diff --git a/README-CN.md b/README-CN.md index 0b7e42d4fa..627b35698c 100644 --- a/README-CN.md +++ b/README-CN.md @@ -39,9 +39,9 @@ TDengine 是一款开源、高性能、云原生的时序数据库 (Time-Series # 构建 -TDengine 目前可以在 Linux、 Windows 等平台上安装和运行。任何 OS 的应用也可以选择 taosAdapter 的 RESTful 接口连接服务端 taosd。CPU 支持 X64/ARM64,后续会支持 MIPS64、Alpha64、ARM32、RISC-V 等 CPU 架构。 +TDengine 目前可以在 Linux、 Windows、macOS 等平台上安装和运行。任何 OS 的应用也可以选择 taosAdapter 的 RESTful 接口连接服务端 taosd。CPU 支持 X64/ARM64,后续会支持 MIPS64、Alpha64、ARM32、RISC-V 等 CPU 架构。 -用户可根据需求选择通过源码、[容器](https://docs.taosdata.com/get-started/docker/)、[安装包](https://docs.taosdata.com/get-started/package/)或[Kubenetes](https://docs.taosdata.com/deployment/k8s/)来安装。本快速指南仅适用于通过源码安装。 +用户可根据需求选择通过源码、[容器](https://docs.taosdata.com/get-started/docker/)、[安装包](https://docs.taosdata.com/get-started/package/)或[Kubernetes](https://docs.taosdata.com/deployment/k8s/)来安装。本快速指南仅适用于通过源码安装。 TDengine 还提供一组辅助工具软件 taosTools,目前它包含 taosBenchmark(曾命名为 taosdemo)和 taosdump 两个软件。默认 TDengine 编译不包含 taosTools, 您可以在编译 TDengine 时使用`cmake .. -DBUILD_TOOLS=true` 来同时编译 taosTools。 @@ -104,6 +104,12 @@ sudo yum install -y zlib-devel xz-devel snappy-devel jansson jansson-devel pkgco sudo yum config-manager --set-enabled Powertools ``` +### macOS + +``` +sudo brew install argp-standalone pkgconfig +``` + ### 设置 golang 开发环境 TDengine 包含数个使用 Go 语言开发的组件,比如taosAdapter, 请参考 golang.org 官方文档设置 go 开发环境。 @@ -210,14 +216,14 @@ cmake .. -G "NMake Makefiles" nmake ``` - +``` # 安装 @@ -263,6 +269,24 @@ nmake install sudo make install ``` +用户可以在[文件目录结构](https://docs.taosdata.com/reference/directory/)中了解更多在操作系统中生成的目录或文件。 + +从源代码安装也会为 TDengine 配置服务管理 ,用户也可以选择[从安装包中安装](https://docs.taosdata.com/get-started/package/)。 + +安装成功后,可以在应用程序中双击 TDengine 图标启动服务,或者在终端中启动 TDengine 服务: + +```bash +launchctl start taosd +``` + +用户可以使用 TDengine CLI 来连接 TDengine 服务,在终端中,输入: + +```bash +taos +``` + +如果 TDengine CLI 连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印出错误消息。 + ## 快速运行 如果不希望以服务方式运行 TDengine,也可以在终端中直接运行它。也即在生成完成后,执行以下命令(在 Windows 下,生成的可执行文件会带有 .exe 后缀,例如会名为 taosd.exe ): diff --git a/README.md b/README.md index fe9bb49ed8..67ca560130 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ English | [简体中文](README-CN.md) | [Learn more about TSDB](https://tdengin # What is TDengine? -TDengine is an open source, high-performance, cloud native [time-series database](https://tdengine.com/tsdb/) optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. It enables efficient, real-time data ingestion, processing, and monitoring of TB and even PB scale data per day, generated by billions of sensors and data collectors. TDengine differentiates itself from other time-seires databases with the following advantages: +TDengine is an open source, high-performance, cloud native [time-series database](https://tdengine.com/tsdb/) optimized for Internet of Things (IoT), Connected Cars, and Industrial IoT. It enables efficient, real-time data ingestion, processing, and monitoring of TB and even PB scale data per day, generated by billions of sensors and data collectors. TDengine differentiates itself from other time-series databases with the following advantages: - **[High Performance](https://tdengine.com/tdengine/high-performance-time-series-database/)**: TDengine is the only time-series database to solve the high cardinality issue to support billions of data collection points while out performing other time-series databases for data ingestion, querying and data compression. @@ -41,7 +41,7 @@ For user manual, system design and architecture, please refer to [TDengine Docum # Building -At the moment, TDengine server supports running on Linux and Windows systems. Any application can also choose the RESTful interface provided by taosAdapter to connect the taosd service . TDengine supports X64/ARM64 CPU, and it will support MIPS64, Alpha64, ARM32, RISC-V and other CPU architectures in the future. +At the moment, TDengine server supports running on Linux/Windows/macOS systems. Any application can also choose the RESTful interface provided by taosAdapter to connect the taosd service . TDengine supports X64/ARM64 CPU, and it will support MIPS64, Alpha64, ARM32, RISC-V and other CPU architectures in the future. You can choose to install through source code, [container](https://docs.tdengine.com/get-started/docker/), [installation package](https://docs.tdengine.com/get-started/package/) or [Kubernetes](https://docs.tdengine.com/deployment/k8s/). This quick guide only applies to installing from source. @@ -105,6 +105,12 @@ If the PowerTools installation fails, you can try to use: sudo yum config-manager --set-enabled powertools ``` +### macOS + +``` +sudo brew install argp-standalone pkgconfig +``` + ### Setup golang environment TDengine includes a few components like taosAdapter developed by Go language. Please refer to golang.org official documentation for golang environment setup. @@ -213,14 +219,14 @@ cmake .. -G "NMake Makefiles" nmake ``` - +``` # Installing @@ -258,7 +264,7 @@ After building successfully, TDengine can be installed by: nmake install ``` - + +Users can find more information about directories installed on the system in the [directory and files](https://docs.tdengine.com/reference/directory/) section. + +Installing from source code will also configure service management for TDengine.Users can also choose to [install from packages](https://docs.tdengine.com/get-started/package/) for it. + +To start the service after installation, double-click the /applications/TDengine to start the program, or in a terminal, use: + +```bash +launchctl start taosd +``` + +Then users can use the TDengine CLI to connect the TDengine server. In a terminal, use: + +```bash +taos +``` + +If TDengine CLI connects the server successfully, welcome messages and version info are printed. Otherwise, an error message is shown. ## Quick Run diff --git a/cmake/taostools_CMakeLists.txt.in b/cmake/taostools_CMakeLists.txt.in index 5d2fcf27b2..2d90d8c49f 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 70f5a1c + GIT_TAG 85179e9 SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools" BINARY_DIR "" #BUILD_IN_SOURCE TRUE diff --git a/docs/en/05-get-started/01-docker.md b/docs/en/05-get-started/01-docker.md index d0874c331e..39fdfeeb06 100644 --- a/docs/en/05-get-started/01-docker.md +++ b/docs/en/05-get-started/01-docker.md @@ -50,7 +50,7 @@ taos> After your TDengine Server is running normally, you can run the taosBenchmark utility to test its performance: -Start TDengine service and execute `taosBenchmark` (formerly named `taosdemo`) in a Linux or Windows terminal. +Start TDengine service and execute `taosBenchmark` (formerly named `taosdemo`) in a terminal. ```bash taosBenchmark diff --git a/docs/en/05-get-started/03-package.md b/docs/en/05-get-started/03-package.md index 25a92573fa..4dadbb0151 100644 --- a/docs/en/05-get-started/03-package.md +++ b/docs/en/05-get-started/03-package.md @@ -7,7 +7,7 @@ import Tabs from "@theme/Tabs"; import TabItem from "@theme/TabItem"; import PkgListV3 from "/components/PkgListV3"; -This document describes how to install TDengine on Linux and Windows and perform queries and inserts. +This document describes how to install TDengine on Linux/Windows/macOS and perform queries and inserts. - The easiest way to explore TDengine is through [TDengine Cloud](http://cloud.tdengine.com). - To get started with TDengine on Docker, see [Quick Install on Docker](../../get-started/docker). @@ -17,7 +17,7 @@ The full package of TDengine includes the TDengine Server (`taosd`), TDengine Cl The standard server installation package includes `taos`, `taosd`, `taosAdapter`, `taosBenchmark`, and sample code. You can also download the Lite package that includes only `taosd` and the C/C++ connector. -The TDengine Community Edition is released as Deb and RPM packages. The Deb package can be installed on Debian, Ubuntu, and derivative systems. The RPM package can be installed on CentOS, RHEL, SUSE, and derivative systems. A .tar.gz package is also provided for enterprise customers, and you can install TDengine over `apt-get` as well. The .tar.tz package includes `taosdump` and the TDinsight installation script. If you want to use these utilities with the Deb or RPM package, download and install taosTools separately. TDengine can also be installed on 64-bit Windows. +The TDengine Community Edition is released as Deb and RPM packages. The Deb package can be installed on Debian, Ubuntu, and derivative systems. The RPM package can be installed on CentOS, RHEL, SUSE, and derivative systems. A .tar.gz package is also provided for enterprise customers, and you can install TDengine over `apt-get` as well. The .tar.tz package includes `taosdump` and the TDinsight installation script. If you want to use these utilities with the Deb or RPM package, download and install taosTools separately. TDengine can also be installed on x64 Windows and x64/m1 macOS. ## Installation @@ -111,6 +111,13 @@ Note: TDengine only supports Windows Server 2016/2019 and Windows 10/11 on the W 2. Run the downloaded package to install TDengine. + + + +1. Download the macOS installation package. + +2. Run the downloaded package to install TDengine. + @@ -178,12 +185,33 @@ The following `systemctl` commands can help you manage TDengine service: After the installation is complete, run `C:\TDengine\taosd.exe` to start TDengine Server. + + + + +After the installation is complete, double-click the /applications/TDengine to start the program, or run `launchctl start taosd` to start TDengine Server. + +The following `launchctl` commands can help you manage TDengine service: + +- Start TDengine Server: `launchctl start taosd` + +- Stop TDengine Server: `launchctl stop taosd` + +- Check TDengine Server status: `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. + +::: + ## Command Line Interface (CLI) -You can use the TDengine CLI to monitor your TDengine deployment and execute ad hoc queries. To open the CLI, you can execute `taos` in the Linux terminal where TDengine is installed, or you can run `taos.exe` in the `C:\TDengine` directory of the Windows terminal where TDengine is installed to start the TDengine command line. +You can use the TDengine CLI to monitor your TDengine deployment and execute ad hoc queries. To open the CLI, you can execute `taos` in the Linux/macOS terminal where TDengine is installed, or you can run `taos.exe` in the `C:\TDengine` directory of the Windows terminal where TDengine is installed to start the TDengine command line. ```bash taos @@ -213,13 +241,13 @@ SELECT * FROM t; Query OK, 2 row(s) in set (0.003128s) ``` -You can also can monitor the deployment status, add and remove user accounts, and manage running instances. You can run the TDengine CLI on either Linux or Windows machines. For more information, see [TDengine CLI](../../reference/taos-shell/). +You can also can monitor the deployment status, add and remove user accounts, and manage running instances. You can run the TDengine CLI on either machines. For more information, see [TDengine CLI](../../reference/taos-shell/). ## Test data insert performance After your TDengine Server is running normally, you can run the taosBenchmark utility to test its performance: -Start TDengine service and execute `taosBenchmark` (formerly named `taosdemo`) in a Linux or Windows terminal. +Start TDengine service and execute `taosBenchmark` (formerly named `taosdemo`) in a terminal. ```bash taosBenchmark diff --git a/docs/en/05-get-started/index.md b/docs/en/05-get-started/index.md index 09875362f4..a6b6721383 100644 --- a/docs/en/05-get-started/index.md +++ b/docs/en/05-get-started/index.md @@ -3,7 +3,7 @@ title: Get Started description: This article describes how to install TDengine and test its performance. --- -You can install and run TDengine on Linux and Windows machines as well as Docker containers. You can also deploy TDengine as a managed service with TDengine Cloud. +You can install and run TDengine on Linux/Windows/macOS machines as well as Docker containers. You can also deploy TDengine as a managed service with TDengine Cloud. The full package of TDengine includes the TDengine Server (`taosd`), TDengine Client (`taosc`), taosAdapter for connecting with third-party systems and providing a RESTful interface, a command-line interface, and some tools. In addition to connectors for multiple languages, TDengine also provides a [RESTful interface](/reference/rest-api) through [taosAdapter](/reference/taosadapter). diff --git a/docs/en/12-taos-sql/06-select.md b/docs/en/12-taos-sql/06-select.md index c065245827..570defe1a7 100644 --- a/docs/en/12-taos-sql/06-select.md +++ b/docs/en/12-taos-sql/06-select.md @@ -11,7 +11,7 @@ SELECT {DATABASE() | CLIENT_VERSION() | SERVER_VERSION() | SERVER_STATUS() | NOW SELECT [DISTINCT] select_list from_clause [WHERE condition] - [PARTITION BY tag_list] + [partition_by_clause] [window_clause] [group_by_clause] [order_by_clasue] @@ -52,6 +52,9 @@ window_clause: { | STATE_WINDOW(col) | INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [WATERMARK(watermark_val)] [FILL(fill_mod_and_val)] +partition_by_clause: + PARTITION BY expr [, expr] ... + group_by_clause: GROUP BY expr [, expr] ... HAVING condition diff --git a/docs/en/13-operation/17-diagnose.md b/docs/en/13-operation/17-diagnose.md index d01d12e831..fa202a23ea 100644 --- a/docs/en/13-operation/17-diagnose.md +++ b/docs/en/13-operation/17-diagnose.md @@ -6,7 +6,7 @@ title: Problem Diagnostics When a TDengine client is unable to access a TDengine server, the network connection between the client side and the server side must be checked to find the root cause and resolve problems. -Diagnostics for network connections can be executed between Linux and Linux or between Linux and Windows. +Diagnostics for network connections can be executed between Linux/Windows/macOS. Diagnostic steps: diff --git a/docs/en/14-reference/03-connector/03-cpp.mdx b/docs/en/14-reference/03-connector/03-cpp.mdx index 02d7df48db..906d56ab15 100644 --- a/docs/en/14-reference/03-connector/03-cpp.mdx +++ b/docs/en/14-reference/03-connector/03-cpp.mdx @@ -13,11 +13,13 @@ After TDengine server or client installation, `taos.h` is located at - Linux:`/usr/local/taos/include` - Windows:`C:\TDengine\include` +- macOS:`/usr/local/include` The dynamic libraries for the TDengine client driver are located in. - Linux: `/usr/local/taos/driver/libtaos.so` - Windows: `C:\TDengine\taos.dll` +- macOS: `/usr/local/lib/libtaos.dylib` ## Supported platforms @@ -119,7 +121,7 @@ This section shows sample code for standard access methods to TDengine clusters :::info More example code and downloads are available at [GitHub](https://github.com/taosdata/TDengine/tree/develop/examples/c). -You can find it in the installation directory under the `examples/c` path. This directory has a makefile and can be compiled under Linux by executing `make` directly. +You can find it in the installation directory under the `examples/c` path. This directory has a makefile and can be compiled under Linux/macOS by executing `make` directly. **Hint:** When compiling in an ARM environment, please remove `-msse4.2` from the makefile. This option is only supported on the x64/x86 hardware platforms. ::: diff --git a/docs/en/14-reference/03-connector/04-java.mdx b/docs/en/14-reference/03-connector/04-java.mdx index c032687d0f..ecf632c624 100644 --- a/docs/en/14-reference/03-connector/04-java.mdx +++ b/docs/en/14-reference/03-connector/04-java.mdx @@ -120,13 +120,13 @@ Connection conn = DriverManager.getConnection(jdbcUrl); In the above example, TSDBDriver, which uses a JDBC native connection, establishes a connection to a hostname `taosdemo.com`, port `6030` (the default port for TDengine), and a database named `test`. In this URL, the user name `user` is specified as `root`, and the `password` is `taosdata`. -Note: With JDBC native connections, taos-jdbcdriver relies on the client driver (`libtaos.so` on Linux; `taos.dll` on Windows). +Note: With JDBC native connections, taos-jdbcdriver relies on the client driver (`libtaos.so` on Linux; `taos.dll` on Windows; `libtaos.dylib` on macOS). The configuration parameters in the URL are as follows: - user: Log in to the TDengine username. The default value is 'root'. - password: User login password, the default value is 'taosdata'. -- cfgdir: client configuration file directory path, default '/etc/taos' on Linux OS, 'C:/TDengine/cfg' on Windows OS. +- cfgdir: client configuration file directory path, default '/etc/taos' on Linux OS, 'C:/TDengine/cfg' on Windows OS, '/etc/taos' on macOS. - charset: The character set used by the client, the default value is the system character set. - locale: Client locale, by default, use the system's current locale. - timezone: The time zone used by the client, the default value is the system's current time zone. @@ -172,7 +172,7 @@ In the above example, JDBC uses the client's configuration file to establish a c In TDengine, as long as one node in firstEp and secondEp is valid, the connection to the cluster can be established normally. -The configuration file here refers to the configuration file on the machine where the application that calls the JDBC Connector is located, the default path is `/etc/taos/taos.cfg` on Linux, and the default path is `C://TDengine/cfg/taos.cfg` on Windows. +The configuration file here refers to the configuration file on the machine where the application that calls the JDBC Connector is located, the default path is `/etc/taos/taos.cfg` on Linux, the default path is `C://TDengine/cfg/taos.cfg` on Windows, and the default path is `/etc/taos/taos.cfg` on macOS. @@ -261,7 +261,7 @@ The configuration parameters in properties are as follows. - TSDBDriver.PROPERTY_KEY_PASSWORD: user login password, default value 'taosdata'. - TSDBDriver.PROPERTY_KEY_BATCH_LOAD: true: pull the result set in batch when executing query; false: pull the result set row by row. The default value is: false. - TSDBDriver.PROPERTY_KEY_BATCH_ERROR_IGNORE: true: when executing executeBatch of Statement, if there is a SQL execution failure in the middle, continue to execute the following sql. false: no longer execute any statement after the failed SQL. The default value is: false. -- TSDBDriver.PROPERTY_KEY_CONFIG_DIR: only works when using JDBC native connection. Client configuration file directory path, default value `/etc/taos` on Linux OS, default value `C:/TDengine/cfg` on Windows OS. +- TSDBDriver.PROPERTY_KEY_CONFIG_DIR: only works when using JDBC native connection. Client configuration file directory path, default value `/etc/taos` on Linux OS, default value `C:/TDengine/cfg` on Windows OS, default value `/etc/taos` on macOS. - TSDBDriver.PROPERTY_KEY_CHARSET: In the character set used by the client, the default value is the system character set. - TSDBDriver.PROPERTY_KEY_LOCALE: this only takes effect when using JDBC native connection. Client language environment, the default value is system current locale. - TSDBDriver.PROPERTY_KEY_TIME_ZONE: only takes effect when using JDBC native connection. In the time zone used by the client, the default value is the system's current time zone. @@ -896,7 +896,7 @@ The source code of the sample application is under `TDengine/examples/JDBC`: **Cause**: The program did not find the dependent native library `taos`. - **Solution**: On Windows you can copy `C:\TDengine\driver\taos.dll` to the `C:\Windows\System32` directory, on Linux the following soft link will be created `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` will work. + **Solution**: On Windows you can copy `C:\TDengine\driver\taos.dll` to the `C:\Windows\System32` directory, on Linux the following soft link will be created `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` will work, on macOS the lib soft link will be `/usr/local/lib/libtaos.dylib`. 3. java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform diff --git a/docs/en/14-reference/03-connector/07-python.mdx b/docs/en/14-reference/03-connector/07-python.mdx index 1e7945bfd2..8f92d5076a 100644 --- a/docs/en/14-reference/03-connector/07-python.mdx +++ b/docs/en/14-reference/03-connector/07-python.mdx @@ -186,7 +186,7 @@ All arguments of the `connect()` function are optional keyword arguments. The fo - `user` : The TDengine user name. The default value is `root`. - `password` : TDengine user password. The default value is `taosdata`. - `port` : The starting port of the data node to connect to, i.e., the serverPort configuration. The default value is 6030, which will only take effect if the host parameter is provided. -- `config` : The path to the client configuration file. On Windows systems, the default is `C:\TDengine\cfg`. The default is `/etc/taos/` on Linux systems. +- `config` : The path to the client configuration file. On Windows systems, the default is `C:\TDengine\cfg`. The default is `/etc/taos/` on Linux/macOS. - `timezone` : The timezone used to convert the TIMESTAMP data in the query results to python `datetime` objects. The default is the local timezone. :::warning diff --git a/docs/en/14-reference/03-connector/10-php.mdx b/docs/en/14-reference/03-connector/10-php.mdx index 820f703759..87f8616f9e 100644 --- a/docs/en/14-reference/03-connector/10-php.mdx +++ b/docs/en/14-reference/03-connector/10-php.mdx @@ -13,11 +13,13 @@ After TDengine client or server is installed, `taos.h` is located at: - Linux:`/usr/local/taos/include` - Windows:`C:\TDengine\include` +- macOS:`/usr/local/include` TDengine client driver is located at: - Linux: `/usr/local/taos/driver/libtaos.so` - Windows: `C:\TDengine\taos.dll` +- macOS:`/usr/local/lib/libtaos.dylib` ## Supported Platforms diff --git a/docs/en/14-reference/03-connector/_preparation.mdx b/docs/en/14-reference/03-connector/_preparation.mdx index c6e42ce023..25b78ec134 100644 --- a/docs/en/14-reference/03-connector/_preparation.mdx +++ b/docs/en/14-reference/03-connector/_preparation.mdx @@ -6,5 +6,6 @@ Since the TDengine client driver is written in C, using the native connection re - libtaos.so: After successful installation of TDengine on a Linux system, the dependent Linux version of the client driver `libtaos.so` file will be automatically linked to `/usr/lib/libtaos.so`, which is included in the Linux scannable path and does not need to be specified separately. - taos.dll: After installing the client on Windows, the dependent Windows version of the client driver taos.dll file will be automatically copied to the system default search path C:/Windows/System32, again without the need to specify it separately. +- libtaos.dylib: After successful installation of TDengine on a mac system, the dependent macOS version of the client driver `libtaos.dylib` file will be automatically linked to `/usr/local/lib/libtaos.dylib`, which is included in the macOS scannable path and does not need to be specified separately. ::: diff --git a/docs/en/14-reference/03-connector/index.mdx b/docs/en/14-reference/03-connector/index.mdx index 5dc54f0934..675a019cc1 100644 --- a/docs/en/14-reference/03-connector/index.mdx +++ b/docs/en/14-reference/03-connector/index.mdx @@ -8,13 +8,15 @@ TDengine provides a rich set of APIs (application development interface). To fac ## Supported platforms -Currently, TDengine's native interface connectors can support platforms such as x64 and ARM hardware platforms and Linux and Windows development environments. The comparison matrix is as follows. +Currently, TDengine's native interface connectors can support platforms such as x64 and ARM hardware platforms and Linux/Windows/macOS development environments. The comparison matrix is as follows. | **CPU** | **OS** | **Java** | **Python** | **Go** | **Node.js** | **C#** | **Rust** | C/C++ | | -------------- | --------- | -------- | ---------- | ------ | ----------- | ------ | -------- | ----- | | **X86 64bit** | **Linux** | ● | ● | ● | ● | ● | ● | ● | | **X86 64bit** | **Win64** | ● | ● | ● | ● | ● | ● | ● | +| **X86 64bit** | **macOS** | ○ | ● | ● | ○ | ○ | ● | ● | | **ARM64** | **Linux** | ● | ● | ● | ● | ○ | ○ | ● | +| **ARM64** | **macOS** | ○ | ● | ● | ○ | ○ | ● | ● | Where ● means the official test verification passed, ○ means the unofficial test verification passed, -- means no assurance. diff --git a/docs/en/14-reference/04-taosadapter.md b/docs/en/14-reference/04-taosadapter.md index 78c4febb92..ad00584360 100644 --- a/docs/en/14-reference/04-taosadapter.md +++ b/docs/en/14-reference/04-taosadapter.md @@ -196,7 +196,8 @@ Support InfluxDB query parameters as follows. - `u` TDengine user name - `p` TDengine password -Note: InfluxDB token authorization is not supported at present. Only Basic authorization and query parameter validation are supported. +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" ### OpenTSDB diff --git a/docs/en/14-reference/08-taos-shell.md b/docs/en/14-reference/08-taos-shell.md index 656db1f481..68e2f08765 100644 --- a/docs/en/14-reference/08-taos-shell.md +++ b/docs/en/14-reference/08-taos-shell.md @@ -12,7 +12,7 @@ If executed on the TDengine server-side, there is no need for additional install ## Execution -To access the TDengine CLI, you can execute `taos` command-line utility from a Linux terminal or Windows terminal. +To access the TDengine CLI, you can execute `taos` command-line utility from a terminal. ```bash taos diff --git a/docs/en/14-reference/09-support-platform/index.md b/docs/en/14-reference/09-support-platform/index.md index 19c984898d..fe26860765 100644 --- a/docs/en/14-reference/09-support-platform/index.md +++ b/docs/en/14-reference/09-support-platform/index.md @@ -5,28 +5,28 @@ description: "List of platforms supported by TDengine server, client, and connec ## List of supported platforms for TDengine server -| | **Windows Server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18/20** | -| ------------ | ---------------------------- | ----------------- | ---------------- | ---------------- | -| X64 | ● | ● | ● | ● | -| ARM64 | | | ● | | +| | **Windows Server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18/20** | **macOS** | +| ------------ | ---------------------------- | ----------------- | ---------------- | ---------------- | --------- | +| X64 | ● | ● | ● | ● | ● | +| ARM64 | | | ● | | ● | Note: ● means officially tested and verified, ○ means unofficially tested and verified. ## List of supported platforms for TDengine clients and connectors -TDengine's connector can support a wide range of platforms, including X64/X86/ARM64/ARM32/MIPS/Alpha hardware platforms and Linux/Win64/Win32 development environments. +TDengine's connector can support a wide range of platforms, including X64/X86/ARM64/ARM32/MIPS/Alpha hardware platforms and Linux/Win64/Win32/macOS development environments. The comparison matrix is as follows. -| **CPU** | **X64 64bit** | **X64 64bit** | **ARM64** | -| ----------- | ------------- | ------------- | --------- | -| **OS** | **Linux** | **Win64** | **Linux** | -| **C/C++** | ● | ● | ● | -| **JDBC** | ● | ● | ● | -| **Python** | ● | ● | ● | -| **Go** | ● | ● | ● | -| **NodeJs** | ● | ● | ● | -| **C#** | ● | ● | ○ | -| **RESTful** | ● | ● | ● | +| **CPU** | **X64 64bit** | **X64 64bit** | **ARM64** | **X64 64bit** | **ARM64** | +| ----------- | ------------- | ------------- | --------- | ------------- | --------- | +| **OS** | **Linux** | **Win64** | **Linux** | **macOS** | **macOS** | +| **C/C++** | ● | ● | ● | ● | ● | +| **JDBC** | ● | ● | ● | ○ | ○ | +| **Python** | ● | ● | ● | ● | ● | +| **Go** | ● | ● | ● | ● | ● | +| **NodeJs** | ● | ● | ● | ○ | ○ | +| **C#** | ● | ● | ○ | ○ | ○ | +| **RESTful** | ● | ● | ● | ● | ● | Note: ● means the official test is verified, ○ means the unofficial test is verified, -- means not verified. diff --git a/docs/en/14-reference/12-config/index.md b/docs/en/14-reference/12-config/index.md index 726a1ccd69..d91675a0ab 100644 --- a/docs/en/14-reference/12-config/index.md +++ b/docs/en/14-reference/12-config/index.md @@ -205,7 +205,7 @@ The parameters described in this document by the effect that they have on the sy :::info To handle the data insertion and data query from multiple timezones, Unix Timestamp is used and stored in TDengine. The timestamp generated from any timezones at same time is same in Unix timestamp. Note that Unix timestamps are converted and recorded on the client side. To make sure the time on client side can be converted to Unix timestamp correctly, the timezone must be set properly. -On Linux system, TDengine clients automatically obtain timezone from the host. Alternatively, the timezone can be configured explicitly in configuration file `taos.cfg` like below. For example: +On Linux/macOS, TDengine clients automatically obtain timezone from the host. Alternatively, the timezone can be configured explicitly in configuration file `taos.cfg` like below. For example: ``` timezone UTC-8 @@ -248,9 +248,9 @@ To avoid the problems of using time strings, Unix timestamp can be used directly :::info A specific type "nchar" is provided in TDengine to store non-ASCII characters such as Chinese, Japanese, and Korean. The characters to be stored in nchar type are firstly encoded in UCS4-LE before sending to server side. Note that the correct encoding is determined by the user. To store non-ASCII characters correctly, the encoding format of the client side needs to be set properly. -The characters input on the client side are encoded using the default system encoding, which is UTF-8 on Linux, or GB18030 or GBK on some systems in Chinese, POSIX in docker, CP936 on Windows in Chinese. The encoding of the operating system in use must be set correctly so that the characters in nchar type can be converted to UCS4-LE. +The characters input on the client side are encoded using the default system encoding, which is UTF-8 on Linux/macOS, or GB18030 or GBK on some systems in Chinese, POSIX in docker, CP936 on Windows in Chinese. The encoding of the operating system in use must be set correctly so that the characters in nchar type can be converted to UCS4-LE. -The locale definition standard on Linux is: \_., for example, in "zh_CN.UTF-8", "zh" means Chinese, "CN" means China mainland, "UTF-8" means charset. The charset indicates how to display the characters. On Linux and Mac OSX, the charset can be set by locale in the system. On Windows system another configuration parameter `charset` must be used to configure charset because the locale used on Windows is not POSIX standard. Of course, `charset` can also be used on Linux to specify the charset. +The locale definition standard on Linux/macOS is: \_., for example, in "zh_CN.UTF-8", "zh" means Chinese, "CN" means China mainland, "UTF-8" means charset. The charset indicates how to display the characters. On Linux/macOS, the charset can be set by locale in the system. On Windows system another configuration parameter `charset` must be used to configure charset because the locale used on Windows is not POSIX standard. Of course, `charset` can also be used on Linux/macOS to specify the charset. ::: @@ -263,9 +263,9 @@ The locale definition standard on Linux is: \_., f | Default Value | charset set in the system | :::info -On Linux, if `charset` is not set in `taos.cfg`, when `taos` is started, the charset is obtained from system locale. If obtaining charset from system locale fails, `taos` would fail to start. +On Linux/macOS, if `charset` is not set in `taos.cfg`, when `taos` is started, the charset is obtained from system locale. If obtaining charset from system locale fails, `taos` would fail to start. -So on Linux system, if system locale is set properly, it's not necessary to set `charset` in `taos.cfg`. For example: +So on Linux/macOS, if system locale is set properly, it's not necessary to set `charset` in `taos.cfg`. For example: ``` locale zh_CN.UTF-8 @@ -279,7 +279,7 @@ charset CP936 Refer to the documentation for your operating system before changing the charset. -On a Linux system, if the charset contained in `locale` is not consistent with that set by `charset`, the later setting in the configuration file takes precedence. +On a Linux/macOS, if the charset contained in `locale` is not consistent with that set by `charset`, the later setting in the configuration file takes precedence. ``` locale zh_CN.UTF-8 @@ -675,7 +675,7 @@ To prevent system resource from being exhausted by multiple concurrent streams, | Meaning | Whether to generate core file when server crashes | | Value Range | 0: false, 1: true | | Default Value | 1 | -| Note | The core file is generated under root directory `systemctl start taosd` is used to start, or under the working directory if `taosd` is started directly on Linux Shell. | +| Note | The core file is generated under root directory `systemctl/launchctl start taosd` is used to start, or under the working directory if `taosd` is started directly on Linux/macOS Shell. | ### udf diff --git a/docs/en/27-train-faq/01-faq.md b/docs/en/27-train-faq/01-faq.md index 733b418474..78794c1ca3 100644 --- a/docs/en/27-train-faq/01-faq.md +++ b/docs/en/27-train-faq/01-faq.md @@ -55,14 +55,16 @@ This error indicates that the client could not connect to the server. Perform th 7. If you are using the Python, Java, Go, Rust, C#, or Node.js connector on Linux to connect to the server, verify that `libtaos.so` is in the `/usr/local/taos/driver` directory and `/usr/local/taos/driver` is in the `LD_LIBRARY_PATH` environment variable. -8. If you are using Windows, verify that `C:\TDengine\driver\taos.dll` is in the `PATH` environment variable. If possible, move `taos.dll` to the `C:\Windows\System32` directory. +8. If you are using macOS, verify that `libtaos.dylib` is in the `/usr/local/lib` directory and `/usr/local/lib` is in the `LD_LIBRARY_PATH` environment variable.. -9. On Linux systems, you can use the `nc` tool to check whether a port is accessible: +9. If you are using Windows, verify that `C:\TDengine\driver\taos.dll` is in the `PATH` environment variable. If possible, move `taos.dll` to the `C:\Windows\System32` directory. + +10. On Linux/macOS, you can use the `nc` tool to check whether a port is accessible: - To check whether a UDP port is open, run `nc -vuz {hostIP} {port}`. - To check whether a TCP port on the server side is open, run `nc -l {port}`. - To check whether a TCP port on client side is open, run `nc {hostIP} {port}`. -10. On Windows systems, you can run `Test-NetConnection -ComputerName {fqdn} -Port {port}` in PowerShell to check whether a port on the server side is accessible. + On Windows systems, you can run `Test-NetConnection -ComputerName {fqdn} -Port {port}` in PowerShell to check whether a port on the server side is accessible. 11. You can also use the TDengine CLI to diagnose network issues. For more information, see [Problem Diagnostics](https://docs.tdengine.com/operation/diagnose/). diff --git a/docs/zh/05-get-started/01-docker.md b/docs/zh/05-get-started/01-docker.md index 0f004581b5..c65e00384d 100644 --- a/docs/zh/05-get-started/01-docker.md +++ b/docs/zh/05-get-started/01-docker.md @@ -46,7 +46,7 @@ taos> 可以使用 TDengine 的自带工具 taosBenchmark 快速体验 TDengine 的写入速度。 -启动 TDengine 的服务,在 Linux 或 Windows 终端执行 `taosBenchmark`(曾命名为 `taosdemo`): +启动 TDengine 的服务,在终端执行 `taosBenchmark`(曾命名为 `taosdemo`): ```bash $ taosBenchmark diff --git a/docs/zh/05-get-started/03-package.md b/docs/zh/05-get-started/03-package.md index 2c857d37f3..50ee721386 100644 --- a/docs/zh/05-get-started/03-package.md +++ b/docs/zh/05-get-started/03-package.md @@ -10,11 +10,11 @@ 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)和一些工具软件。目前 taosAdapter 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../../reference/taosadapter/) 提供 [RESTful 接口](../../connector/rest-api/)。 +TDengine 完整的软件包包括服务端(taosd)、应用驱动(taosc)、用于与第三方系统对接并提供 RESTful 接口的 taosAdapter、命令行程序(CLI,taos)和一些工具软件。目前 taosdump、TDinsight 仅在 Linux 系统上安装和运行,后续将支持 Windows、macOS 等系统。TDengine 除了提供多种语言的连接器之外,还通过 [taosAdapter](../../reference/taosadapter/) 提供 [RESTful 接口](../../connector/rest-api/)。 为方便使用,标准的服务端安装包包含了 taosd、taosAdapter、taosc、taos、taosdump、taosBenchmark、TDinsight 安装脚本和示例代码;如果您只需要用到服务端程序和客户端连接的 C/C++ 语言支持,也可以仅下载 Lite 版本的安装包。 -在 Linux 系统上,TDengine 社区版提供 Deb 和 RPM 格式安装包,用户可以根据自己的运行环境选择合适的安装包。其中 Deb 支持 Debian/Ubuntu 及其衍生系统,RPM 支持 CentOS/RHEL/SUSE 及其衍生系统。同时我们也为企业用户提供 tar.gz 格式安装包,也支持通过 `apt-get` 工具从线上进行安装。需要注意的是,RPM 和 Deb 包不含 `taosdump` 和 TDinsight 安装脚本,这些工具需要通过安装 taosTool 包获得。TDengine 也提供 Windows x64 平台的安装包。 +在 Linux 系统上,TDengine 社区版提供 Deb 和 RPM 格式安装包,用户可以根据自己的运行环境选择合适的安装包。其中 Deb 支持 Debian/Ubuntu 及其衍生系统,RPM 支持 CentOS/RHEL/SUSE 及其衍生系统。同时我们也为企业用户提供 tar.gz 格式安装包,也支持通过 `apt-get` 工具从线上进行安装。需要注意的是,RPM 和 Deb 包不含 `taosdump` 和 TDinsight 安装脚本,这些工具需要通过安装 taosTools 包获得。TDengine 也提供 Windows x64 平台和 macOS x64/m1 平台的安装包。 ## 安装 @@ -110,6 +110,13 @@ apt-get 方式只适用于 Debian 或 Ubuntu 系统。 2. 运行可执行程序来安装 TDengine。 + + + +1. 从列表中下载获得 pkg 安装程序; + +2. 运行可执行程序来安装 TDengine。 + @@ -177,12 +184,33 @@ Active: inactive (dead) 安装后,在 `C:\TDengine` 目录下,运行 `taosd.exe` 来启动 TDengine 服务进程。 + + + + +安装后,在应用程序目录下,双击 TDengine 图标来启动程序,也可以运行 `launchctl start taosd` 来启动 TDengine 服务进程。 + +如下 `launchctl` 命令可以帮助你管理 TDengine 服务: + +- 启动服务进程:`launchctl start taosd` + +- 停止服务进程:`launchctl stop taosd` + +- 查看服务状态:`launchctl list | grep taosd` + +:::info + +- `launchctl` 命令不需要管理员权限,请不要在前面加 `sudo`。 +- `launchctl list | grep taosd` 指令返回的第一个内容是程序的 PID,若为 `-` 则说明 TDengine 服务未运行。 + +::: + ## TDengine 命令行(CLI) -为便于检查 TDengine 的状态,执行数据库(Database)的各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI)taos。要进入 TDengine 命令行,您只要在安装有 TDengine 的 Linux 终端执行 `taos` 即可,也可以在安装有 TDengine 的 Windows 终端的 C:\TDengine 目录下,运行 taos.exe 来启动 TDengine 命令行。 +为便于检查 TDengine 的状态,执行数据库(Database)的各种即席(Ad Hoc)查询,TDengine 提供一命令行应用程序(以下简称为 TDengine CLI)taos。要进入 TDengine 命令行,您只要在安装有 TDengine 的 Linux、macOS 终端执行 `taos` 即可,也可以在安装有 TDengine 的 Windows 终端的 C:\TDengine 目录下,运行 taos.exe 来启动 TDengine 命令行。 ```bash taos @@ -212,13 +240,13 @@ SELECT * FROM t; Query OK, 2 row(s) in set (0.003128s) ``` -除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。TDengine CLI 连同应用驱动也可以独立安装在 Linux 或 Windows 机器上运行,更多细节请参考 [TDengine 命令行](../../reference/taos-shell/)。 +除执行 SQL 语句外,系统管理员还可以从 TDengine CLI 进行检查系统运行状态、添加删除用户账号等操作。TDengine CLI 连同应用驱动也可以独立安装在机器上运行,更多细节请参考 [TDengine 命令行](../../reference/taos-shell/)。 ## 使用 taosBenchmark 体验写入速度 可以使用 TDengine 的自带工具 taosBenchmark 快速体验 TDengine 的写入速度。 -启动 TDengine 的服务,在 Linux 或 Windows 终端执行 `taosBenchmark`(曾命名为 `taosdemo`): +启动 TDengine 服务,然后在终端执行 `taosBenchmark`(曾命名为 `taosdemo`): ```bash $ taosBenchmark @@ -249,7 +277,7 @@ SELECT AVG(current), MAX(voltage), MIN(phase) FROM test.meters; 查询 location = "California.SanFrancisco" 的记录总条数: ```sql -SELECT COUNT(*) FROM test.meters WHERE location = "Calaifornia.SanFrancisco"; +SELECT COUNT(*) FROM test.meters WHERE location = "California.SanFrancisco"; ``` 查询 groupId = 10 的所有记录的平均值、最大值、最小值等: diff --git a/docs/zh/07-develop/03-insert-data/02-influxdb-line.mdx b/docs/zh/07-develop/03-insert-data/02-influxdb-line.mdx index a107ffb1b6..95155c3144 100644 --- a/docs/zh/07-develop/03-insert-data/02-influxdb-line.mdx +++ b/docs/zh/07-develop/03-insert-data/02-influxdb-line.mdx @@ -67,6 +67,10 @@ meters,location=California.LosAngeles,groupid=2 current=13.4,voltage=223,phase=0 -## 查询示例 -比如查询 location=California.LosAngeles,groupid=2 子表的数据可以通过如下sql: -select * from meters where location=California.LosAngeles and groupid=2 +## SQL查询示例 +- meters 是插入数据的超级表名 +- 可以通过超级表的tag来过滤数据,比如查询 `location=California.LosAngeles,groupid=2` 可以通过如下sql: + +``` cmd +select * from meters where location="California.LosAngeles" and groupid=2 +``` diff --git a/docs/zh/07-develop/03-insert-data/03-opentsdb-telnet.mdx b/docs/zh/07-develop/03-insert-data/03-opentsdb-telnet.mdx index 8d097e3f65..b008953c0b 100644 --- a/docs/zh/07-develop/03-insert-data/03-opentsdb-telnet.mdx +++ b/docs/zh/07-develop/03-insert-data/03-opentsdb-telnet.mdx @@ -81,6 +81,10 @@ taos> select tbname, * from `meters.current`; t_7e7b26dd860280242c6492a16... | 2022-03-28 09:56:51.250 | 12.600000000 | 2 | California.SanFrancisco | Query OK, 4 row(s) in set (0.005399s) ``` -## 查询示例: -想要查询 location=California.LosAngeles groupid=3 的数据,可以通过如下sql: -select * from `meters.voltage` where location="California.LosAngeles" and groupid=3 + +## SQL查询示例 +- `meters.current` 是插入数据的超级表名 +- 可以通过超级表的tag来过滤数据,比如查询 `location=California.LosAngeles groupid=3` 可以通过如下sql: +``` cmd +select * from `meters.current` where location="California.LosAngeles" and groupid=3 +``` diff --git a/docs/zh/07-develop/03-insert-data/04-opentsdb-json.mdx b/docs/zh/07-develop/03-insert-data/04-opentsdb-json.mdx index e2e7d7c8fa..1795d8edde 100644 --- a/docs/zh/07-develop/03-insert-data/04-opentsdb-json.mdx +++ b/docs/zh/07-develop/03-insert-data/04-opentsdb-json.mdx @@ -96,6 +96,9 @@ taos> select * from `meters.current`; Query OK, 2 row(s) in set (0.004076s) ``` -## 查询示例 -想要查询"tags": {"location": "California.LosAngeles", "groupid": 1} 的数据,可以通过如下sql: +## SQL查询示例 +- `meters.voltage` 是插入数据的超级表名 +- 可以通过超级表的tag来过滤数据,比如查询 `location=California.LosAngeles groupid=1` 可以通过如下sql: +``` cmd select * from `meters.voltage` where location="California.LosAngeles" and groupid=1 +``` diff --git a/docs/zh/07-develop/06-stream.md b/docs/zh/07-develop/06-stream.md index c9f1b1d43a..a2e1d1a1da 100644 --- a/docs/zh/07-develop/06-stream.md +++ b/docs/zh/07-develop/06-stream.md @@ -70,7 +70,7 @@ insert into d1004 values("2018-10-03 14:38:06.500", 11.50000, 221, 0.35000); ### 查询以观察结果 ```sql -taos> select start, end, max_current from current_stream_output_stb; +taos> select start, wend, max_current from current_stream_output_stb; start | wend | max_current | =========================================================================== 2018-10-03 14:38:05.000 | 2018-10-03 14:38:10.000 | 10.30000 | diff --git a/docs/zh/08-connector/02-rest-api.mdx b/docs/zh/08-connector/02-rest-api.mdx index a8e1682301..68d73ff32f 100644 --- a/docs/zh/08-connector/02-rest-api.mdx +++ b/docs/zh/08-connector/02-rest-api.mdx @@ -74,7 +74,7 @@ http://:/rest/sql/[db_name] 参数说明: -- fqnd: 集群中的任一台主机 FQDN 或 IP 地址。 +- fqdn: 集群中的任一台主机 FQDN 或 IP 地址。 - port: 配置文件中 httpPort 配置项,缺省为 6041。 - db_name: 可选参数,指定本次所执行的 SQL 语句的默认数据库库名。 diff --git a/docs/zh/08-connector/10-cpp.mdx b/docs/zh/08-connector/10-cpp.mdx index c0bd33f129..cc7991da74 100644 --- a/docs/zh/08-connector/10-cpp.mdx +++ b/docs/zh/08-connector/10-cpp.mdx @@ -13,11 +13,13 @@ TDengine 服务端或客户端安装后,`taos.h` 位于: - Linux:`/usr/local/taos/include` - Windows:`C:\TDengine\include` +- macOS:`/usr/local/include` TDengine 客户端驱动的动态库位于: - Linux: `/usr/local/taos/driver/libtaos.so` - Windows: `C:\TDengine\taos.dll` +- macOS: `/usr/local/lib/libtaos.dylib` ## 支持的平台 @@ -119,7 +121,7 @@ TDengine 客户端驱动的安装请参考 [安装指南](../#安装步骤) :::info 更多示例代码及下载请见 [GitHub](https://github.com/taosdata/TDengine/tree/develop/examples/c)。 -也可以在安装目录下的 `examples/c` 路径下找到。 该目录下有 makefile,在 Linux 环境下,直接执行 make 就可以编译得到执行文件。 +也可以在安装目录下的 `examples/c` 路径下找到。 该目录下有 makefile,在 Linux/macOS 环境下,直接执行 make 就可以编译得到执行文件。 **提示:**在 ARM 环境下编译时,请将 makefile 中的 `-msse4.2` 去掉,这个选项只有在 x64/x86 硬件平台上才能支持。 ::: diff --git a/docs/zh/08-connector/14-java.mdx b/docs/zh/08-connector/14-java.mdx index d78da52aaa..acdebac57d 100644 --- a/docs/zh/08-connector/14-java.mdx +++ b/docs/zh/08-connector/14-java.mdx @@ -120,7 +120,7 @@ Connection conn = DriverManager.getConnection(jdbcUrl); 以上示例,使用了 JDBC 原生连接的 TSDBDriver,建立了到 hostname 为 taosdemo.com,端口为 6030(TDengine 的默认端口),数据库名为 test 的连接。这个 URL 中指定用户名(user)为 root,密码(password)为 taosdata。 -**注意**:使用 JDBC 原生连接,taos-jdbcdriver 需要依赖客户端驱动(Linux 下是 libtaos.so;Windows 下是 taos.dll)。 +**注意**:使用 JDBC 原生连接,taos-jdbcdriver 需要依赖客户端驱动(Linux 下是 libtaos.so;Windows 下是 taos.dll;macOS 下是 libtaos.dylib)。 url 中的配置参数如下: @@ -898,7 +898,7 @@ public static void main(String[] args) throws Exception { **原因**:程序没有找到依赖的本地函数库 taos。 - **解决方法**:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可。 + **解决方法**:Windows 下可以将 C:\TDengine\driver\taos.dll 拷贝到 C:\Windows\System32\ 目录下,Linux 下将建立如下软链 `ln -s /usr/local/taos/driver/libtaos.so.x.x.x.x /usr/lib/libtaos.so` 即可,macOS 下需要建立软链 `ln -s /usr/local/lib/libtaos.dylib`。 3. java.lang.UnsatisfiedLinkError: taos.dll Can't load AMD 64 bit on a IA 32-bit platform diff --git a/docs/zh/08-connector/30-python.mdx b/docs/zh/08-connector/30-python.mdx index c70677f816..082f70ed47 100644 --- a/docs/zh/08-connector/30-python.mdx +++ b/docs/zh/08-connector/30-python.mdx @@ -186,7 +186,7 @@ curl -u root:taosdata http://:/rest/sql -d "select server_version()" - `user` :TDengine 用户名。 默认值是 root。 - `password` : TDengine 用户密码。 默认值是 taosdata。 - `port` : 要连接的数据节点的起始端口,即 serverPort 配置。默认值是 6030。只有在提供了 host 参数的时候,这个参数才生效。 -- `config` : 客户端配置文件路径。 在 Windows 系统上默认是 `C:\TDengine\cfg`。 在 Linux 系统上默认是 `/etc/taos/`。 +- `config` : 客户端配置文件路径。 在 Windows 系统上默认是 `C:\TDengine\cfg`。 在 Linux/macOS 系统上默认是 `/etc/taos/`。 - `timezone` : 查询结果中 TIMESTAMP 类型的数据,转换为 python 的 datetime 对象时使用的时区。默认为本地时区。 :::warning diff --git a/docs/zh/08-connector/45-php.mdx b/docs/zh/08-connector/45-php.mdx index 5e32c709de..a5c3a1a400 100644 --- a/docs/zh/08-connector/45-php.mdx +++ b/docs/zh/08-connector/45-php.mdx @@ -13,11 +13,13 @@ TDengine 服务端或客户端安装后,`taos.h` 位于: - Linux:`/usr/local/taos/include` - Windows:`C:\TDengine\include` +- macOS:`/usr/local/include` TDengine 客户端驱动的动态库位于: - Linux: `/usr/local/taos/driver/libtaos.so` - Windows: `C:\TDengine\taos.dll` +- macOS:`/usr/local/lib/libtaos.dylib` ## 支持的平台 diff --git a/docs/zh/08-connector/_preparition.mdx b/docs/zh/08-connector/_preparition.mdx index 87538ebfd8..a0140e15b3 100644 --- a/docs/zh/08-connector/_preparition.mdx +++ b/docs/zh/08-connector/_preparition.mdx @@ -6,5 +6,6 @@ - libtaos.so: 在 Linux 系统中成功安装 TDengine 后,依赖的 Linux 版客户端驱动 libtaos.so 文件会被自动拷贝至 /usr/lib/libtaos.so,该目录包含在 Linux 自动扫描路径上,无需单独指定。 - taos.dll: 在 Windows 系统中安装完客户端之后,依赖的 Windows 版客户端驱动 taos.dll 文件会自动拷贝到系统默认搜索路径 C:/Windows/System32 下,同样无需要单独指定。 +- libtaos.dylib: 在 macOS 系统中成功安装 TDengine 后,依赖的 macOS 版客户端驱动 libtaos.dylib 文件会被自动拷贝至 /usr/local/lib/libtaos.dylib,该目录包含在 macOS 自动扫描路径上,无需单独指定。 ::: diff --git a/docs/zh/12-taos-sql/06-select.md b/docs/zh/12-taos-sql/06-select.md index b3b8ef3887..3ffc081cd7 100644 --- a/docs/zh/12-taos-sql/06-select.md +++ b/docs/zh/12-taos-sql/06-select.md @@ -12,7 +12,7 @@ SELECT {DATABASE() | CLIENT_VERSION() | SERVER_VERSION() | SERVER_STATUS() | NOW SELECT [DISTINCT] select_list from_clause [WHERE condition] - [PARTITION BY tag_list] + [partition_by_clause] [window_clause] [group_by_clause] [order_by_clasue] @@ -53,6 +53,9 @@ window_clause: { | STATE_WINDOW(col) | INTERVAL(interval_val [, interval_offset]) [SLIDING (sliding_val)] [WATERMARK(watermark_val)] [FILL(fill_mod_and_val)] +partition_by_clause: + PARTITION BY expr [, expr] ... + group_by_clause: GROUP BY expr [, expr] ... HAVING condition diff --git a/docs/zh/12-taos-sql/12-distinguished.md b/docs/zh/12-taos-sql/12-distinguished.md index 861ef4ebb7..ee8e8e15ca 100644 --- a/docs/zh/12-taos-sql/12-distinguished.md +++ b/docs/zh/12-taos-sql/12-distinguished.md @@ -4,9 +4,9 @@ title: 特色查询 description: TDengine 提供的时序数据特有的查询功能 --- -TDengine 是专为时序数据而研发的大数据平台,存储和计算都针对时序数据的特定进行了量身定制,在支持标准 SQL 的基础之上,还提供了一系列贴合时序业务场景的特色查询语法,极大的方便时序场景的应用开发。 +TDengine 在支持标准 SQL 的基础之上,还提供了一系列满足时序业务场景需求的特色查询语法,这些语法能够为时序场景的应用的开发带来极大的便利。 -TDengine 提供的特色查询包括数据切分查询和窗口切分查询。 +TDengine 提供的特色查询包括数据切分查询和时间窗口切分查询。 ## 数据切分查询 @@ -31,7 +31,7 @@ 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)三种窗口。其中时间窗口又可划分为滑动时间窗口和翻转时间窗口。窗口切分查询语法如下: ```sql SELECT select_list FROM tb_name @@ -132,6 +132,10 @@ SELECT * FROM (SELECT COUNT(*) AS cnt, FIRST(ts) AS fst, status FROM temp_tb_1 S SELECT COUNT(*), FIRST(ts) FROM temp_tb_1 SESSION(ts, tol_val); ``` +### 时间戳伪列 + +窗口聚合查询结果中,如果 SQL 语句中没有指定输出查询结果中的时间戳列,那么最终结果中不会自动包含窗口的时间列信息。如果需要在结果中输出聚合结果所对应的时间窗口信息,需要在 SELECT 子句中使用时间戳相关的伪列: 时间窗口起始时间 (\_WSTART), 时间窗口结束时间 (\_WEND), 时间窗口持续时间 (\_WDURATION), 以及查询整体窗口相关的伪列: 查询窗口起始时间(\_QSTART) 和查询窗口结束时间(\_QEND)。需要注意的是时间窗口起始时间和结束时间均是闭区间,时间窗口持续时间是数据当前时间分辨率下的数值。例如,如果当前数据库的时间分辨率是毫秒,那么结果中 500 就表示当前时间窗口的持续时间是 500毫秒 (500 ms)。 + ### 示例 智能电表的建表语句如下: @@ -143,8 +147,10 @@ CREATE TABLE meters (ts TIMESTAMP, current FLOAT, voltage INT, phase FLOAT) TAGS 针对智能电表采集的数据,以 10 分钟为一个阶段,计算过去 24 小时的电流数据的平均值、最大值、电流的中位数。如果没有计算值,用前一个非 NULL 值填充。使用的查询语句如下: ``` -SELECT AVG(current), MAX(current), APERCENTILE(current, 50) FROM meters +SELECT _WSTART, _WEND, AVG(current), MAX(current), APERCENTILE(current, 50) FROM meters WHERE ts>=NOW-1d and ts<=now INTERVAL(10m) FILL(PREV); ``` + + diff --git a/docs/zh/14-reference/04-taosadapter.md b/docs/zh/14-reference/04-taosadapter.md index 82efcab06f..ec023afd71 100644 --- a/docs/zh/14-reference/04-taosadapter.md +++ b/docs/zh/14-reference/04-taosadapter.md @@ -189,7 +189,7 @@ AllowWebSockets /influxdb/v1/write ``` -支持 InfluxDB 查询参数如下: +支持 InfluxDB 参数如下: - `db` 指定 TDengine 使用的数据库名 - `precision` TDengine 使用的时间精度 @@ -197,7 +197,7 @@ AllowWebSockets - `p` TDengine 密码 注意: 目前不支持 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" ### OpenTSDB 您可以使用任何支持 http 协议的客户端访问 Restful 接口地址 `http://:6041/` 来写入 OpenTSDB 兼容格式的数据到 TDengine。EndPoint 如下: diff --git a/docs/zh/14-reference/08-taos-shell.md b/docs/zh/14-reference/08-taos-shell.md index 5804549878..5ac5f6f479 100644 --- a/docs/zh/14-reference/08-taos-shell.md +++ b/docs/zh/14-reference/08-taos-shell.md @@ -12,7 +12,7 @@ TDengine 命令行程序(以下简称 TDengine CLI)是用户操作 TDengine ## 执行 -要进入 TDengine CLI,您只要在 Linux 终端或 Windows 终端执行 `taos` 即可。 +要进入 TDengine CLI,您只要在终端执行 `taos` 即可。 ```bash taos diff --git a/docs/zh/14-reference/09-support-platform/index.md b/docs/zh/14-reference/09-support-platform/index.md index ddacdd369a..7292ca4814 100644 --- a/docs/zh/14-reference/09-support-platform/index.md +++ b/docs/zh/14-reference/09-support-platform/index.md @@ -5,29 +5,30 @@ description: "TDengine 服务端、客户端和连接器支持的平台列表" ## TDengine 服务端支持的平台列表 -| | **Windows server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18/20** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | -| ------------ | ---------------------------- | ----------------- | ---------------- | ---------------- | ------------ | ----------------- | ---------------- | -| X64 | ● | ● | ● | ● | ● | ● | ● | -| 树莓派 ARM64 | | | ● | | | | | -| 华为云 ARM64 | | | | ● | | | | +| | **Windows server 2016/2019** | **Windows 10/11** | **CentOS 7.9/8** | **Ubuntu 18/20** | **统信 UOS** | **银河/中标麒麟** | **凝思 V60/V80** | **macOS** | +| ------------ | ---------------------------- | ----------------- | ---------------- | ---------------- | ------------ | ----------------- | ---------------- | --------- | +| X64 | ● | ● | ● | ● | ● | ● | ● | ● | +| 树莓派 ARM64 | | | ● | | | | | | +| 华为云 ARM64 | | | | ● | | | | | +| M1 | | | | | | | | ● | 注: ● 表示经过官方测试验证, ○ 表示非官方测试验证。 ## TDengine 客户端和连接器支持的平台列表 -目前 TDengine 的连接器可支持的平台广泛,目前包括:X64/X86/ARM64/ARM32/MIPS/Alpha 等硬件平台,以及 Linux/Win64/Win32 等开发环境。 +目前 TDengine 的连接器可支持的平台广泛,目前包括:X64/X86/ARM64/ARM32/MIPS/Alpha 等硬件平台,以及 Linux/Win64/Win32/macOS 等开发环境。 对照矩阵如下: -| **CPU** | **X64 64bit** | **X64 64bit** | **ARM64** | -| ----------- | ------------- | ------------- | --------- | -| **OS** | **Linux** | **Win64** | **Linux** | -| **C/C++** | ● | ● | ● | -| **JDBC** | ● | ● | ● | -| **Python** | ● | ● | ● | -| **Go** | ● | ● | ● | -| **NodeJs** | ● | ● | ● | -| **C#** | ● | ● | ○ | -| **RESTful** | ● | ● | ● | +| **CPU** | **X64 64bit** | **X64 64bit** | **ARM64** | **X64 64bit** | **ARM64** | +| ----------- | ------------- | ------------- | --------- | ------------- | --------- | +| **OS** | **Linux** | **Win64** | **Linux** | **macOS** | **macOS** | +| **C/C++** | ● | ● | ● | ● | ● | +| **JDBC** | ● | ● | ● | ○ | ○ | +| **Python** | ● | ● | ● | ● | ● | +| **Go** | ● | ● | ● | ● | ● | +| **NodeJs** | ● | ● | ● | ○ | ○ | +| **C#** | ● | ● | ○ | ○ | ○ | +| **RESTful** | ● | ● | ● | ● | ● | 注:● 表示官方测试验证通过,○ 表示非官方测试验证通过,-- 表示未经验证。 diff --git a/docs/zh/14-reference/12-config/index.md b/docs/zh/14-reference/12-config/index.md index 6f26878cdd..8c19ac78f5 100644 --- a/docs/zh/14-reference/12-config/index.md +++ b/docs/zh/14-reference/12-config/index.md @@ -205,7 +205,7 @@ taos --dump-config :::info 为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix 时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。 -在 Linux 系统中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如: +在 Linux/macOS 中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如: ``` timezone UTC-8 @@ -248,9 +248,9 @@ SELECT count(*) FROM table_name WHERE TS<1554984068000; :::info TDengine 为存储中文、日文、韩文等非 ASCII 编码的宽字符,提供一种专门的字段类型 nchar。写入 nchar 字段的数据将统一采用 UCS4-LE 格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用 nchar 字段来存储诸如中文、日文、韩文等非 ASCII 字符,需要正确设置客户端的编码格式。 -客户端的输入的字符均采用操作系统当前默认的编码格式,在 Linux 系统上多为 UTF-8,部分中文系统编码则可能是 GB18030 或 GBK 等。在 docker 环境中默认的编码是 POSIX。在中文版 Windows 系统中,编码则是 CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证 nchar 中的数据正确转换为 UCS4-LE 编码格式。 +客户端的输入的字符均采用操作系统当前默认的编码格式,在 Linux/macOS 系统上多为 UTF-8,部分中文系统编码则可能是 GB18030 或 GBK 等。在 docker 环境中默认的编码是 POSIX。在中文版 Windows 系统中,编码则是 CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证 nchar 中的数据正确转换为 UCS4-LE 编码格式。 -在 Linux 中 locale 的命名规则为: <语言>\_<地区>.<字符集编码> 如:zh_CN.UTF-8,zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux 系统与 Mac OSX 系统可以通过设置 locale 来确定系统的字符编码,由于 Windows 使用的 locale 中不是 POSIX 标准的 locale 格式,因此在 Windows 下需要采用另一个配置参数 charset 来指定字符编码。在 Linux 系统中也可以使用 charset 来指定字符编码。 +在 Linux/macOS 中 locale 的命名规则为: <语言>\_<地区>.<字符集编码> 如:zh_CN.UTF-8,zh 代表中文,CN 代表大陆地区,UTF-8 表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux/macOS 可以通过设置 locale 来确定系统的字符编码,由于 Windows 使用的 locale 中不是 POSIX 标准的 locale 格式,因此在 Windows 下需要采用另一个配置参数 charset 来指定字符编码。在 Linux/macOS 中也可以使用 charset 来指定字符编码。 ::: @@ -263,9 +263,9 @@ TDengine 为存储中文、日文、韩文等非 ASCII 编码的宽字符,提 | 缺省值 | 系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过 API 设置 | :::info -如果配置文件中不设置 charset,在 Linux 系统中,taos 在启动时候,自动读取系统当前的 locale 信息,并从 locale 信息中解析提取 charset 编码格式。如果自动读取 locale 信息失败,则尝试读取 charset 配置,如果读取 charset 配置也失败,则中断启动过程。 +如果配置文件中不设置 charset,在 Linux/macOS 中,taos 在启动时候,自动读取系统当前的 locale 信息,并从 locale 信息中解析提取 charset 编码格式。如果自动读取 locale 信息失败,则尝试读取 charset 配置,如果读取 charset 配置也失败,则中断启动过程。 -在 Linux 系统中,locale 信息包含了字符编码信息,因此正确设置了 Linux 系统 locale 以后可以不用再单独设置 charset。例如: +在 Linux/macOS 中,locale 信息包含了字符编码信息,因此正确设置了 Linux/macOS 的 locale 以后可以不用再单独设置 charset。例如: ``` locale zh_CN.UTF-8 @@ -279,7 +279,7 @@ charset CP936 如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。 -在 Linux 系统中,如果用户同时设置了 locale 和字符集编码 charset,并且 locale 和 charset 的不一致,后设置的值将覆盖前面设置的值。 +在 Linux/macOS 中,如果用户同时设置了 locale 和字符集编码 charset,并且 locale 和 charset 的不一致,后设置的值将覆盖前面设置的值。 ``` locale zh_CN.UTF-8 diff --git a/docs/zh/17-operation/17-diagnose.md b/docs/zh/17-operation/17-diagnose.md index ec529096a7..ef9923969e 100644 --- a/docs/zh/17-operation/17-diagnose.md +++ b/docs/zh/17-operation/17-diagnose.md @@ -7,7 +7,7 @@ description: 一些常见问题的诊断技巧 当出现客户端应用无法访问服务端时,需要确认客户端与服务端之间网络的各端口连通情况,以便有针对性地排除故障。 -目前网络连接诊断支持在:Linux 与 Linux,Linux 与 Windows 之间进行诊断测试。 +目前网络连接诊断支持在:Linux/Windows/macOS 之间进行诊断测试。 诊断步骤: diff --git a/docs/zh/27-train-faq/01-faq.md b/docs/zh/27-train-faq/01-faq.md index 0a46db4a28..c84cda81a7 100644 --- a/docs/zh/27-train-faq/01-faq.md +++ b/docs/zh/27-train-faq/01-faq.md @@ -56,7 +56,7 @@ description: 一些常见问题的解决方法汇总 3. 在服务器,执行 `systemctl status taosd` 检查*taosd*运行状态。如果没有运行,启动*taosd* -4. 确认客户端连接时指定了正确的服务器 FQDN (Fully Qualified Domain Name —— 可在服务器上执行 Linux 命令 hostname -f 获得),FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 +4. 确认客户端连接时指定了正确的服务器 FQDN (Fully Qualified Domain Name —— 可在服务器上执行 Linux/macOS 命令 hostname -f 获得),FQDN 配置参考:[一篇文章说清楚 TDengine 的 FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。 5. ping 服务器 FQDN,如果没有反应,请检查你的网络,DNS 设置,或客户端所在计算机的系统 hosts 文件。如果部署的是 TDengine 集群,客户端需要能 ping 通所有集群节点的 FQDN。 @@ -64,18 +64,20 @@ description: 一些常见问题的解决方法汇总 7. 对于 Linux 上的 JDBC(ODBC, Python, Go 等接口类似)连接, 确保*libtaos.so*在目录*/usr/local/taos/driver*里, 并且*/usr/local/taos/driver*在系统库函数搜索路径*LD_LIBRARY_PATH*里 -8. 对于 Windows 上的 JDBC, ODBC, Python, Go 等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 _C:\Windows\System32_) +8. 对于 macOS 上的 JDBC(ODBC, Python, Go 等接口类似)连接, 确保*libtaos.dylib*在目录*/usr/local/lib*里, 并且*/usr/local/lib*在系统库函数搜索路径*LD_LIBRARY_PATH*里 -9. 如果仍不能排除连接故障 +9. 对于 Windows 上的 JDBC, ODBC, Python, Go 等连接,确保*C:\TDengine\driver\taos.dll*在你的系统库函数搜索目录里 (建议*taos.dll*放在目录 _C:\Windows\System32_) - - Linux 系统请使用命令行工具 nc 来分别判断指定端口的 TCP 和 UDP 连接是否通畅 +10. 如果仍不能排除连接故障 + + - Linux/macOS 系统请使用命令行工具 nc 来分别判断指定端口的 TCP 和 UDP 连接是否通畅 检查 UDP 端口连接是否工作:`nc -vuz {hostIP} {port} ` 检查服务器侧 TCP 端口连接是否工作:`nc -l {port}` 检查客户端侧 TCP 端口连接是否工作:`nc {hostIP} {port}` - Windows 系统请使用 PowerShell 命令 Test-NetConnection -ComputerName {fqdn} -Port {port} 检测服务段端口是否访问 -10. 也可以使用 taos 程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅:[诊断及其他](https://docs.taosdata.com/3.0-preview/operation/diagnose/)。 +11. 也可以使用 taos 程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅:[诊断及其他](https://docs.taosdata.com/3.0-preview/operation/diagnose/)。 ### 5. 遇到错误 Unable to resolve FQDN” 怎么办? diff --git a/include/common/tcommon.h b/include/common/tcommon.h index 670ce29a2d..3109bc49a2 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -49,7 +49,7 @@ typedef struct { TSKEY ts; } SWinKey; -static inline int SWinKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { +static inline int sWinKeyCmprImpl(const void* pKey1, const void* pKey2) { SWinKey* pWin1 = (SWinKey*)pKey1; SWinKey* pWin2 = (SWinKey*)pKey2; @@ -68,6 +68,10 @@ static inline int SWinKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, i return 0; } +static inline int winKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { + return sWinKeyCmprImpl(pKey1, pKey2); +} + typedef struct { uint64_t groupId; TSKEY ts; diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 10cb72f5d0..a1fefa6902 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -27,6 +27,7 @@ extern "C" { #endif +typedef struct SBuffer SBuffer; typedef struct SSchema SSchema; typedef struct STColumn STColumn; typedef struct STSchema STSchema; @@ -56,6 +57,18 @@ const static uint8_t BIT2_MAP[4][4] = {{0b00000000, 0b00000001, 0b00000010, 0}, #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)) +// SBuffer ================================ +struct SBuffer { + int64_t nBuf; + uint8_t *pBuf; +}; + +#define tBufferCreate() \ + (SBuffer) { .nBuf = 0, .pBuf = NULL } +void tBufferDestroy(SBuffer *pBuffer); +int32_t tBufferInit(SBuffer *pBuffer, int64_t size); +int32_t tBufferPut(SBuffer *pBuffer, const void *pData, int64_t nData); + // STSchema ================================ int32_t tTSchemaCreate(int32_t sver, SSchema *pSchema, int32_t nCols, STSchema **ppTSchema); void tTSchemaDestroy(STSchema *pTSchema); diff --git a/include/os/osDir.h b/include/os/osDir.h index 95b1a6ee1d..2bdc99d268 100644 --- a/include/os/osDir.h +++ b/include/os/osDir.h @@ -38,9 +38,9 @@ extern "C" { #define TD_LOG_DIR_PATH "C:\\TDengine\\log\\" #elif defined(_TD_DARWIN_64) #define TD_TMP_DIR_PATH "/tmp/taosd/" -#define TD_CFG_DIR_PATH "/usr/local/etc/taos/" -#define TD_DATA_DIR_PATH "/usr/local/var/lib/taos/" -#define TD_LOG_DIR_PATH "/usr/local/var/log/taos/" +#define TD_CFG_DIR_PATH "/etc/taos/" +#define TD_DATA_DIR_PATH "/var/lib/taos/" +#define TD_LOG_DIR_PATH "/var/log/taos/" #else #define TD_TMP_DIR_PATH "/tmp/" #define TD_CFG_DIR_PATH "/etc/taos/" diff --git a/include/util/tarray.h b/include/util/tarray.h index 7c1bc34d71..99f09dc769 100644 --- a/include/util/tarray.h +++ b/include/util/tarray.h @@ -288,6 +288,13 @@ void* taosDecodeArray(const void* buf, SArray** pArray, FDecode decode, int32_ char* taosShowStrArray(const SArray* pArray); +/** + * swap array + * @param a + * @param b + * @return + */ +void taosArraySwap(SArray* a, SArray* b); #ifdef __cplusplus } #endif diff --git a/include/util/tthread.h b/include/util/tthread.h index 2215add062..7afed98839 100644 --- a/include/util/tthread.h +++ b/include/util/tthread.h @@ -23,7 +23,7 @@ extern "C" { #endif TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param); -bool taosDestoryThread(TdThread* pthread); +bool taosDestroyThread(TdThread* pthread); bool taosThreadRunning(TdThread* pthread); typedef void *(*ThreadFp)(void *param); diff --git a/packaging/tools/TDengine b/packaging/tools/TDengine new file mode 100755 index 0000000000..3025a5639f --- /dev/null +++ b/packaging/tools/TDengine @@ -0,0 +1,28 @@ +#!/usr/bin/env bash + + +function showAlertMessage(){ +osascript < + + + + Label + taosd + ProgramArguments + + /usr/local/bin/taosd + + ProcessType + Interactive + Disabled + + RunAtLoad + + LaunchOnlyOnce + + SessionCreate + + ExitTimeOut + 600 + KeepAlive + + SuccessfulExit + + AfterInitialDemand + + + Program + /usr/local/bin/taosd + + \ No newline at end of file diff --git a/packaging/tools/logo.png b/packaging/tools/logo.png new file mode 100644 index 0000000000..e739e5dd8c Binary files /dev/null and b/packaging/tools/logo.png differ diff --git a/packaging/tools/mac_before_install.txt b/packaging/tools/mac_before_install.txt new file mode 100644 index 0000000000..f70ea7161f --- /dev/null +++ b/packaging/tools/mac_before_install.txt @@ -0,0 +1,5 @@ +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. + +To configure TDengine : edit /etc/taos/taos.cfg +To start service : launchctl start taosd +To access TDengine : use taos in shell \ No newline at end of file diff --git a/packaging/tools/make_install.sh b/packaging/tools/make_install.sh index 58b4385001..a71614ad6e 100755 --- a/packaging/tools/make_install.sh +++ b/packaging/tools/make_install.sh @@ -30,36 +30,31 @@ productName="TDengine" emailName="taosdata.com" uninstallScript="rmtaos" +data_dir=${dataDir} +log_dir=${logDir} +cfg_install_dir=${configDir} + if [ "$osType" != "Darwin" ]; then - data_dir=${dataDir} - log_dir=${logDir} - - cfg_install_dir=${configDir} - bin_link_dir="/usr/bin" lib_link_dir="/usr/lib" lib64_link_dir="/usr/lib64" inc_link_dir="/usr/include" - - install_main_dir=${installDir} - - bin_dir="${installDir}/bin" else - data_dir="/usr/local${dataDir}" - log_dir="/usr/local${logDir}" - - cfg_install_dir="/usr/local${configDir}" - bin_link_dir="/usr/local/bin" lib_link_dir="/usr/local/lib" inc_link_dir="/usr/local/include" - install_main_dir="/usr/local/Cellar/tdengine/${verNumber}" - install_main_2_dir="/usr/local/Cellar/tdengine@${verNumber}/${verNumber}" - - bin_dir="/usr/local/Cellar/tdengine/${verNumber}/bin" - bin_2_dir="/usr/local/Cellar/tdengine@${verNumber}/${verNumber}/bin" + if [ -d "/usr/local/Cellar/" ];then + installDir="/usr/local/Cellar/tdengine/${verNumber}" + elif [ -d "/opt/homebrew/Cellar/" ];then + installDir="/opt/homebrew/Cellar/tdengine/${verNumber}" + else + installDir="/usr/local/taos" + fi fi +install_main_dir=${installDir} +bin_dir="${installDir}/bin" +cfg_dir="${installDir}/cfg" service_config_dir="/etc/systemd/system" @@ -71,14 +66,16 @@ GREEN_UNDERLINE='\033[4;32m' NC='\033[0m' csudo="" +csudouser="" +if command -v sudo >/dev/null; then + csudo="sudo " + csudouser="sudo -u ${USER} " +fi service_mod=2 os_type=0 if [ "$osType" != "Darwin" ]; then - if command -v sudo >/dev/null; then - csudo="sudo " - fi initd_mod=0 if pidof systemd &>/dev/null; then service_mod=0 @@ -142,28 +139,16 @@ function kill_taosd() { function install_main_path() { #create install main dir and all sub dir - if [ "$osType" != "Darwin" ]; then - ${csudo}rm -rf ${install_main_dir} || : - ${csudo}mkdir -p ${install_main_dir} - ${csudo}mkdir -p ${install_main_dir}/cfg - ${csudo}mkdir -p ${install_main_dir}/bin - # ${csudo}mkdir -p ${install_main_dir}/connector - ${csudo}mkdir -p ${install_main_dir}/driver - ${csudo}mkdir -p ${install_main_dir}/examples - ${csudo}mkdir -p ${install_main_dir}/include - ${csudo}mkdir -p ${install_main_dir}/share - # ${csudo}mkdir -p ${install_main_dir}/init.d - else - ${csudo}rm -rf ${install_main_dir} || ${csudo}rm -rf ${install_main_2_dir} || : - ${csudo}mkdir -p ${install_main_dir} || ${csudo}mkdir -p ${install_main_2_dir} - ${csudo}mkdir -p ${install_main_dir}/cfg || ${csudo}mkdir -p ${install_main_2_dir}/cfg - ${csudo}mkdir -p ${install_main_dir}/bin || ${csudo}mkdir -p ${install_main_2_dir}/bin - # ${csudo}mkdir -p ${install_main_dir}/connector || ${csudo}mkdir -p ${install_main_2_dir}/connector - ${csudo}mkdir -p ${install_main_dir}/driver || ${csudo}mkdir -p ${install_main_2_dir}/driver - ${csudo}mkdir -p ${install_main_dir}/examples || ${csudo}mkdir -p ${install_main_2_dir}/examples - ${csudo}mkdir -p ${install_main_dir}/include || ${csudo}mkdir -p ${install_main_2_dir}/include - ${csudo}mkdir -p ${install_main_dir}/share || ${csudo}mkdir -p ${install_main_2_dir}/share - fi + ${csudo}rm -rf ${install_main_dir} || : + ${csudo}mkdir -p ${install_main_dir} + ${csudo}mkdir -p ${install_main_dir}/cfg + ${csudo}mkdir -p ${install_main_dir}/bin + # ${csudo}mkdir -p ${install_main_dir}/connector + ${csudo}mkdir -p ${install_main_dir}/driver + ${csudo}mkdir -p ${install_main_dir}/examples + ${csudo}mkdir -p ${install_main_dir}/include + ${csudo}mkdir -p ${install_main_dir}/share + # ${csudo}mkdir -p ${install_main_dir}/init.d } function install_bin() { @@ -175,11 +160,11 @@ function install_bin() { ${csudo}rm -f ${bin_link_dir}/taosdemo || : ${csudo}rm -f ${bin_link_dir}/taosdump || : ${csudo}rm -f ${bin_link_dir}/taosx || : + ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : if [ "$osType" != "Darwin" ]; then ${csudo}rm -f ${bin_link_dir}/perfMonitor || : ${csudo}rm -f ${bin_link_dir}/set_core || : - ${csudo}rm -f ${bin_link_dir}/${uninstallScript} || : ${csudo}cp -r ${binary_dir}/build/bin/${clientName} ${install_main_dir}/bin || : [ -f ${binary_dir}/build/bin/taosBenchmark ] && ${csudo}cp -r ${binary_dir}/build/bin/taosBenchmark ${install_main_dir}/bin || : @@ -209,18 +194,26 @@ function install_bin() { [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || : else - ${csudo}cp -r ${binary_dir}/build/bin/* ${install_main_dir}/bin || ${csudo}cp -r ${binary_dir}/build/bin/* ${install_main_2_dir}/bin || : - ${csudo}cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_dir}/bin || ${csudo}cp -r ${script_dir}/taosd-dump-cfg.gdb ${install_main_2_dir} || : - ${csudo}cp -r ${script_dir}/remove_client.sh ${install_main_dir}/bin || ${csudo}cp -r ${script_dir}/remove_client.sh ${install_main_2_dir}/bin || : - ${csudo}chmod 0555 ${install_main_dir}/bin/* || ${csudo}chmod 0555 ${install_main_2_dir}/bin/* + ${csudo}cp -r ${binary_dir}/build/bin/${clientName} ${install_main_dir}/bin || : + [ -f ${binary_dir}/build/bin/taosBenchmark ] && ${csudo}cp -r ${binary_dir}/build/bin/taosBenchmark ${install_main_dir}/bin || : + [ -f ${install_main_dir}/bin/taosBenchmark ] && ${csudo}ln -sf ${install_main_dir}/bin/taosBenchmark ${install_main_dir}/bin/taosdemo || : + [ -f ${binary_dir}/build/bin/taosdump ] && ${csudo}cp -r ${binary_dir}/build/bin/taosdump ${install_main_dir}/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 || : + ${csudo}cp -r ${binary_dir}/build/bin/${serverName} ${install_main_dir}/bin || : + + ${csudo}cp -r ${script_dir}/remove.sh ${install_main_dir}/bin || : + ${csudo}chmod 0555 ${install_main_dir}/bin/* #Make link - [ -x ${install_main_dir}/bin/${clientName} ] || [ -x ${install_main_2_dir}/bin/${clientName} ] && ${csudo}ln -s ${install_main_dir}/bin/${clientName} ${bin_link_dir}/${clientName} || ${csudo}ln -s ${install_main_2_dir}/bin/${clientName} || : - [ -x ${install_main_dir}/bin/${serverName} ] || [ -x ${install_main_2_dir}/bin/${serverName} ] && ${csudo}ln -s ${install_main_dir}/bin/${serverName} ${bin_link_dir}/${serverName} || ${csudo}ln -s ${install_main_2_dir}/bin/${serverName} || : - [ -x ${install_main_dir}/bin/taosadapter ] || [ -x ${install_main_2_dir}/bin/taosadapter ] && ${csudo}ln -s ${install_main_dir}/bin/taosadapter ${bin_link_dir}/taosadapter || ${csudo}ln -s ${install_main_2_dir}/bin/taosadapter || : - [ -x ${install_main_dir}/bin/udfd ] || [ -x ${install_main_2_dir}/bin/udfd ] && ${csudo}ln -s ${install_main_dir}/bin/udfd ${bin_link_dir}/udfd || ${csudo}ln -s ${install_main_2_dir}/bin/udfd || : - [ -x ${install_main_dir}/bin/taosdump ] || [ -x ${install_main_2_dir}/bin/taosdump ] && ${csudo}ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || ln -s ${install_main_2_dir}/bin/taosdump ${bin_link_dir}/taosdump || : - [ -x ${install_main_dir}/bin/taosdemo ] || [ -x ${install_main_2_dir}/bin/taosdemo ] && ${csudo}ln -s ${install_main_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || ln -s ${install_main_2_dir}/bin/taosdemo ${bin_link_dir}/taosdemo || : - [ -x ${install_main_dir}/bin/taosx ] || [ -x ${install_main_2_dir}/bin/taosx ] && ${csudo}ln -s ${install_main_dir}/bin/taosx ${bin_link_dir}/taosx || ln -s ${install_main_2_dir}/bin/taosx ${bin_link_dir}/taosx || : + [ -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/taosadapter ] && ${csudo}ln -s ${install_main_dir}/bin/taosadapter ${bin_link_dir}/taosadapter || : + [ -x ${install_main_dir}/bin/udfd ] && ${csudo}ln -s ${install_main_dir}/bin/udfd ${bin_link_dir}/udfd || : + [ -x ${install_main_dir}/bin/taosdump ] && ${csudo}ln -s ${install_main_dir}/bin/taosdump ${bin_link_dir}/taosdump || : + [ -f ${install_main_dir}/bin/taosBenchmark ] && ${csudo}ln -sf ${install_main_dir}/bin/taosBenchmark ${install_main_dir}/bin/taosdemo || : + [ -x ${install_main_dir}/bin/taosx ] && ${csudo}ln -s ${install_main_dir}/bin/taosx ${bin_link_dir}/taosx || : + [ -x ${install_main_dir}/bin/remove.sh ] && ${csudo}ln -s ${install_main_dir}/bin/remove.sh ${bin_link_dir}/${uninstallScript} || : fi } @@ -331,28 +324,20 @@ function install_lib() { fi else ${csudo}cp -Rf ${binary_dir}/build/lib/libtaos.${verNumber}.dylib \ - ${install_main_dir}/driver || - ${csudo}cp -Rf ${binary_dir}/build/lib/libtaos.${verNumber}.dylib \ - ${install_main_2_dir}/driver && - ${csudo}chmod 777 ${install_main_dir}/driver/* || - ${csudo}chmod 777 ${install_main_2_dir}/driver/* - - ${csudo}ln -sf ${install_main_dir}/driver/libtaos.* \ - ${install_main_dir}/driver/libtaos.1.dylib || - ${csudo}ln -sf ${install_main_2_dir}/driver/libtaos.* \ - ${install_main_2_dir}/driver/libtaos.1.dylib || : - - ${csudo}ln -sf ${install_main_dir}/driver/libtaos.1.dylib \ - ${install_main_dir}/driver/libtaos.dylib || - ${csudo}ln -sf ${install_main_2_dir}/driver/libtaos.1.dylib \ - ${install_main_2_dir}/driver/libtaos.dylib || : + ${install_main_dir}/driver && ${csudo}chmod 777 ${install_main_dir}/driver/* ${csudo}ln -sf ${install_main_dir}/driver/libtaos.${verNumber}.dylib \ - ${lib_link_dir}/libtaos.1.dylib || - ${csudo}ln -sf ${install_main_2_dir}/driver/libtaos.${verNumber}.dylib \ - ${lib_link_dir}/libtaos.1.dylib || : + ${lib_link_dir}/libtaos.1.dylib || : ${csudo}ln -sf ${lib_link_dir}/libtaos.1.dylib ${lib_link_dir}/libtaos.dylib || : + + if [ -f ${binary_dir}/build/lib/libtaosws.dylib ]; then + ${csudo}cp ${binary_dir}/build/lib/libtaosws.dylib \ + ${install_main_dir}/driver && + ${csudo}chmod 777 ${install_main_dir}/driver/libtaosws.dylib ||: + + ${csudo}ln -sf ${install_main_dir}/driver/libtaosws.dylib ${lib_link_dir}/libtaosws.dylib || : + fi fi install_jemalloc @@ -365,37 +350,30 @@ function install_lib() { } function install_header() { + ${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 ||: + ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \ + ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/* - if [ "$osType" != "Darwin" ]; then - ${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 ||: - ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \ - ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/* - - if [ -f ${binary_dir}/build/include/taosws.h ]; then - ${csudo}cp -f ${binary_dir}/build/include/taosws.h ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/taosws.h ||: - ${csudo}ln -sf ${install_main_dir}/include/taosws.h ${inc_link_dir}/taosws.h ||: - fi - - ${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 - - else - ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \ - ${install_main_dir}/include || - ${csudo}cp -f ${source_dir}/include/client/taos.h ${source_dir}/include/common/taosdef.h ${source_dir}/include/util/taoserror.h ${source_dir}/include/libs/function/taosudf.h \ - ${install_main_2_dir}/include && - ${csudo}chmod 644 ${install_main_dir}/include/* || ${csudo}chmod 644 ${install_main_2_dir}/include/* + if [ -f ${binary_dir}/build/include/taosws.h ]; then + ${csudo}cp -f ${binary_dir}/build/include/taosws.h ${install_main_dir}/include && ${csudo}chmod 644 ${install_main_dir}/include/taosws.h ||: + ${csudo}ln -sf ${install_main_dir}/include/taosws.h ${inc_link_dir}/taosws.h ||: fi + + ${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}chmod 644 ${install_main_dir}/include/* } function install_config() { if [ ! -f ${cfg_install_dir}/${configFile} ]; then ${csudo}mkdir -p ${cfg_install_dir} [ -f ${script_dir}/../cfg/${configFile} ] && - ${csudo}cp ${script_dir}/../cfg/${configFile} ${cfg_install_dir} + ${csudo}cp ${script_dir}/../cfg/${configFile} ${cfg_install_dir} && + ${csudo}cp ${script_dir}/../cfg/${configFile} ${cfg_dir} ${csudo}chmod 644 ${cfg_install_dir}/${configFile} ${csudo}cp -f ${script_dir}/../cfg/${configFile} \ ${cfg_install_dir}/${configFile}.${verNumber} @@ -404,6 +382,7 @@ function install_config() { else ${csudo}cp -f ${script_dir}/../cfg/${configFile} \ ${cfg_install_dir}/${configFile}.${verNumber} + ${csudo}cp -f ${script_dir}/../cfg/${configFile} ${cfg_dir} fi } @@ -411,7 +390,8 @@ function install_taosadapter_config() { if [ ! -f "${cfg_install_dir}/taosadapter.toml" ]; then ${csudo}mkdir -p ${cfg_install_dir} || : [ -f ${binary_dir}/test/cfg/taosadapter.toml ] && - ${csudo}cp ${binary_dir}/test/cfg/taosadapter.toml ${cfg_install_dir} || : + ${csudo}cp ${binary_dir}/test/cfg/taosadapter.toml ${cfg_install_dir} && + ${csudo}cp ${binary_dir}/test/cfg/taosadapter.toml ${cfg_dir} || : [ -f ${cfg_install_dir}/taosadapter.toml ] && ${csudo}chmod 644 ${cfg_install_dir}/taosadapter.toml || : [ -f ${binary_dir}/test/cfg/taosadapter.toml ] && @@ -424,6 +404,7 @@ function install_taosadapter_config() { if [ -f "${binary_dir}/test/cfg/taosadapter.toml" ]; then ${csudo}cp -f ${binary_dir}/test/cfg/taosadapter.toml \ ${cfg_install_dir}/taosadapter.toml.${verNumber} || : + ${csudo}cp -f ${binary_dir}/test/cfg/taosadapter.toml ${cfg_dir} || : fi fi } @@ -431,20 +412,12 @@ function install_taosadapter_config() { function install_log() { ${csudo}rm -rf ${log_dir} || : ${csudo}mkdir -p ${log_dir} && ${csudo}chmod 777 ${log_dir} - if [ "$osType" != "Darwin" ]; then - ${csudo}ln -s ${log_dir} ${install_main_dir}/log - else - ${csudo}ln -s ${log_dir} ${install_main_dir}/log || ${csudo}ln -s ${log_dir} ${install_main_2_dir}/log - fi + ${csudo}ln -s ${log_dir} ${install_main_dir}/log } function install_data() { - ${csudo}mkdir -p ${data_dir} - if [ "$osType" != "Darwin" ]; then - ${csudo}ln -s ${data_dir} ${install_main_dir}/data - else - ${csudo}ln -s ${data_dir} ${install_main_dir}/data || ${csudo}ln -s ${data_dir} ${install_main_2_dir}/data - fi + ${csudo}mkdir -p ${data_dir} && ${csudo}chmod 777 ${data_dir} + ${csudo}ln -s ${data_dir} ${install_main_dir}/data } function install_connector() { @@ -453,31 +426,17 @@ function install_connector() { else echo "WARNING: go connector not found, please check if want to use it!" fi - if [ "$osType" != "Darwin" ]; then - ${csudo}cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector || : - ${csudo}cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &>/dev/null && ${csudo}chmod 777 ${install_main_dir}/connector/*.jar || echo &>/dev/null || : - else - ${csudo}cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector || ${csudo}cp -rf ${source_dir}/src/connector/python ${install_main_2_dir}/connector || : - ${csudo}cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &>/dev/null && ${csudo}chmod 777 ${install_main_dir}/connector/*.jar || echo &>/dev/null || : - ${csudo}cp ${binary_dir}/build/lib/*.jar ${install_main_2_dir}/connector &>/dev/null && ${csudo}chmod 777 ${install_main_2_dir}/connector/*.jar || echo &>/dev/null || : - fi + ${csudo}cp -rf ${source_dir}/src/connector/python ${install_main_dir}/connector || : + ${csudo}cp ${binary_dir}/build/lib/*.jar ${install_main_dir}/connector &>/dev/null && ${csudo}chmod 777 ${install_main_dir}/connector/*.jar || echo &>/dev/null || : } function install_examples() { - if [ "$osType" != "Darwin" ]; then - ${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples || : - else - ${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples || ${csudo}cp -rf ${source_dir}/examples/* ${install_main_2_dir}/examples || : - fi + ${csudo}cp -rf ${source_dir}/examples/* ${install_main_dir}/examples || : } function install_web() { if [ -d "${binary_dir}/build/share" ]; then - if [ "$osType" != "Darwin" ]; then - ${csudo}cp -rf ${binary_dir}/build/share/* ${install_main_dir}/share || : - else - ${csudo}cp -rf ${binary_dir}/build/share/* ${install_main_dir}/share || ${csudo}cp -rf ${binary_dir}/build/share/* ${install_main_2_dir}/share || : - fi + ${csudo}cp -rf ${binary_dir}/build/share/* ${install_main_dir}/share || : fi } @@ -575,13 +534,36 @@ function install_taosadapter_service() { fi } +function install_service_on_launchctl() { + ${csudouser}launchctl unload -w /Library/LaunchDaemons/com.taosdata.taosd.plist > /dev/null 2>&1 || : + ${csudo}cp ${script_dir}/com.taosdata.taosd.plist /Library/LaunchDaemons/com.taosdata.taosd.plist + ${csudouser}launchctl load -w /Library/LaunchDaemons/com.taosdata.taosd.plist || : +} + function install_service() { - if ((${service_mod} == 0)); then - install_service_on_systemd - elif ((${service_mod} == 1)); then - install_service_on_sysvinit + if [ "$osType" != "Darwin" ]; then + if ((${service_mod} == 0)); then + install_service_on_systemd + elif ((${service_mod} == 1)); then + install_service_on_sysvinit + else + kill_taosd + fi else - kill_taosd + install_service_on_launchctl + fi +} +function install_app() { + if [ "$osType" = "Darwin" ]; then + ${csudo}rm -rf /Applications/TDengine.app && + ${csudo}mkdir -p /Applications/TDengine.app/Contents/MacOS/ && + ${csudo}cp ${script_dir}/TDengine /Applications/TDengine.app/Contents/MacOS/ && + echo "" | ${csudo}tee /Applications/TDengine.app/Contents/Info.plist > /dev/null && + ${csudo}sips -i ${script_dir}/logo.png > /dev/null && + DeRez -only icns ${script_dir}/logo.png | ${csudo}tee /Applications/TDengine.app/mac_logo.rsrc > /dev/null && + ${csudo}rez -append /Applications/TDengine.app/mac_logo.rsrc -o $'/Applications/TDengine.app/Icon\r' && + ${csudo}SetFile -a C /Applications/TDengine.app/ && + ${csudo}rm /Applications/TDengine.app/mac_logo.rsrc fi } @@ -610,6 +592,7 @@ function update_TDengine() { install_examples install_web install_bin + install_app install_service install_taosadapter_service @@ -633,7 +616,11 @@ function update_TDengine() { [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" + if [ "$osType" != "Darwin" ]; then + echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" + else + echo -e "${GREEN_DARK}To start service ${NC}: launchctl start ${serverName}${NC}" + fi [ -f ${installDir}/bin/taosadapter ] && \ echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi @@ -656,6 +643,7 @@ function install_TDengine() { # install_connector install_examples install_bin + install_app install_service install_taosadapter_service @@ -679,7 +667,11 @@ function install_TDengine() { [ -f ${service_config_dir}/taosadapter.service ] && [ -f ${installDir}/bin/taosadapter ] && \ echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: ${csudo}service taosadapter start${NC}" else - echo -e "${GREEN_DARK}To start ${productName} ${NC}: ./${serverName}${NC}" + if [ "$osType" != "Darwin" ]; then + echo -e "${GREEN_DARK}To start ${productName} ${NC}: ${serverName}${NC}" + else + echo -e "${GREEN_DARK}To start service ${NC}: launchctl start ${serverName}${NC}" + fi [ -f ${installDir}/bin/taosadapter ] && \ echo -e "${GREEN_DARK}To start Taos Adapter ${NC}: taosadapter &${NC}" fi @@ -694,16 +686,10 @@ echo source directory: $1 echo binary directory: $2 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" -elif [ "$osType" != "Darwin" ]; then +else if [ -x ${bin_dir}/${clientName} ]; then update_TDengine else install_TDengine fi -else - if [ -x ${bin_dir}/${clientName} ] || [ -x ${bin_2_dir}/${clientName} ]; then - update_TDengine - else - install_TDengine - fi fi diff --git a/packaging/tools/post.sh b/packaging/tools/post.sh index fcc8a2a942..29d4ac017c 100755 --- a/packaging/tools/post.sh +++ b/packaging/tools/post.sh @@ -7,27 +7,52 @@ iplist="" serverFqdn="" -# -----------------------Variables definition--------------------- -script_dir=$(dirname $(readlink -f "$0")) +osType=`uname` + # Dynamic directory data_dir="/var/lib/taos" log_dir="/var/log/taos" -data_link_dir="/usr/local/taos/data" -log_link_dir="/usr/local/taos/log" -install_main_dir="/usr/local/taos" +cfg_install_dir="/etc/taos" + +if [ "$osType" != "Darwin" ]; then + script_dir=$(dirname $(readlink -f "$0")) + verNumber="" + lib_file_ext="so" + + bin_link_dir="/usr/bin" + lib_link_dir="/usr/lib" + lib64_link_dir="/usr/lib64" + inc_link_dir="/usr/include" + + install_main_dir="/usr/local/taos" +else + script_dir=${source_dir}/packaging/tools + verNumber=`ls tdengine/driver | grep -E "libtaos\.[0-9]\.[0-9]" | sed "s/libtaos.//g" | sed "s/.dylib//g" | head -n 1` + lib_file_ext="dylib" + + bin_link_dir="/usr/local/bin" + lib_link_dir="/usr/local/lib" + lib64_link_dir="/usr/local/lib" + inc_link_dir="/usr/local/include" + + if [ -d "/usr/local/Cellar/" ];then + install_main_dir="/usr/local/Cellar/tdengine/${verNumber}" + elif [ -d "/opt/homebrew/Cellar/" ];then + install_main_dir="/opt/homebrew/Cellar/tdengine/${verNumber}" + else + install_main_dir="/usr/local/taos" + fi +fi + +data_link_dir="${install_main_dir}/data" +log_link_dir="${install_main_dir}/log" # static directory -cfg_dir="/usr/local/taos/cfg" -bin_dir="/usr/local/taos/bin" -lib_dir="/usr/local/taos/driver" -init_d_dir="/usr/local/taos/init.d" -inc_dir="/usr/local/taos/include" - -cfg_install_dir="/etc/taos" -bin_link_dir="/usr/bin" -lib_link_dir="/usr/lib" -lib64_link_dir="/usr/lib64" -inc_link_dir="/usr/include" +cfg_dir="${install_main_dir}/cfg" +bin_dir="${install_main_dir}/bin" +lib_dir="${install_main_dir}/driver" +init_d_dir="${install_main_dir}/init.d" +inc_dir="${install_main_dir}/include" service_config_dir="/etc/systemd/system" @@ -40,8 +65,10 @@ GREEN_UNDERLINE='\033[4;32m' NC='\033[0m' csudo="" +csudouser="" if command -v sudo > /dev/null; then csudo="sudo " + csudouser="sudo -u ${USER} " fi initd_mod=0 @@ -63,6 +90,14 @@ elif $(which service &> /dev/null); then else service_mod=2 fi +if [ "$osType" = "Darwin" ]; then + if [ -d "${install_main_dir}" ];then + ${csudo}rm -rf ${install_main_dir} + fi + ${csudo}mkdir -p ${install_main_dir} + ${csudo}rm -rf ${install_main_dir} + ${csudo}cp -rf tdengine ${install_main_dir} +fi function kill_taosadapter() { # ${csudo}pkill -f taosadapter || : @@ -96,22 +131,24 @@ function install_lib() { ${csudo}rm -f ${lib_link_dir}/libtaos* || : ${csudo}rm -f ${lib64_link_dir}/libtaos* || : - [ -f ${lib_link_dir}/libtaosws.so ] && ${csudo}rm -f ${lib_link_dir}/libtaosws.so || : - [ -f ${lib64_link_dir}/libtaosws.so ] && ${csudo}rm -f ${lib64_link_dir}/libtaosws.so || : + [ -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.so.1 ${csudo}ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so - [ -f ${lib_dir}/libtaosws.so ] && ${csudo}ln -sf ${lib_dir}/libtaosws.so ${lib_link_dir}/libtaosws.so ||: + [ -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.so ]]; then ${csudo}ln -s ${lib_dir}/libtaos.* ${lib64_link_dir}/libtaos.so.1 || : ${csudo}ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || : - [ -f ${lib_dir}/libtaosws.so ] && ${csudo}ln -sf ${lib_dir}/libtaosws.so ${lib64_link_dir}/libtaosws.so || : + [ -f ${lib_dir}/libtaosws.${lib_file_ext} ] && ${csudo}ln -sf ${lib_dir}/libtaosws.${lib_file_ext} ${lib64_link_dir}/libtaosws.${lib_file_ext} || : fi - ${csudo}ldconfig + if [ "$osType" != "Darwin" ]; then + ${csudo}ldconfig + fi } function install_bin() { @@ -138,6 +175,7 @@ function install_bin() { [ -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 || : } function add_newHostname_to_hosts() { @@ -466,6 +504,14 @@ function install_service_on_systemd() { ${csudo}systemctl enable taosd } +function install_service_on_launchctl() { + if [ -f ${install_main_dir}/service/com.taosdata.taosd.plist ]; then + ${csudouser}launchctl unload -w /Library/LaunchDaemons/com.taosdata.taosd.plist > /dev/null 2>&1 || : + ${csudo}cp ${install_main_dir}/service/com.taosdata.taosd.plist /Library/LaunchDaemons/com.taosdata.taosd.plist || : + ${csudouser}launchctl load -w /Library/LaunchDaemons/com.taosdata.taosd.plist || : + fi +} + function install_taosadapter_service() { if ((${service_mod}==0)); then [ -f ${script_dir}/../cfg/taosadapter.service ] &&\ @@ -476,6 +522,7 @@ function install_taosadapter_service() { } function install_service() { + if [ "$osType" != "Darwin" ]; then if ((${service_mod}==0)); then install_service_on_systemd elif ((${service_mod}==1)); then @@ -485,6 +532,25 @@ function install_service() { kill_taosadapter kill_taosd fi + else + install_service_on_launchctl + fi +} + +function install_app() { + if [ "$osType" = "Darwin" ]; then + if [ -f ${install_main_dir}/service/TDengine ]; then + ${csudo}rm -rf /Applications/TDengine.app && + ${csudo}mkdir -p /Applications/TDengine.app/Contents/MacOS/ && + ${csudo}cp ${install_main_dir}/service/TDengine /Applications/TDengine.app/Contents/MacOS/ && + echo "" | ${csudo}tee /Applications/TDengine.app/Contents/Info.plist > /dev/null && + ${csudo}sips -i ${install_main_dir}/service/logo.png > /dev/null && + DeRez -only icns ${install_main_dir}/service/logo.png | ${csudo}tee /Applications/TDengine.app/mac_logo.rsrc > /dev/null && + ${csudo}rez -append /Applications/TDengine.app/mac_logo.rsrc -o $'/Applications/TDengine.app/Icon\r' && + ${csudo}SetFile -a C /Applications/TDengine.app/ && + ${csudo}rm /Applications/TDengine.app/mac_logo.rsrc + fi + fi } function install_TDengine() { @@ -492,7 +558,7 @@ function install_TDengine() { #install log and data dir , then ln to /usr/local/taos ${csudo}mkdir -p ${log_dir} && ${csudo}chmod 777 ${log_dir} - ${csudo}mkdir -p ${data_dir} + ${csudo}mkdir -p ${data_dir} && ${csudo}chmod 777 ${data_dir} ${csudo}rm -rf ${log_link_dir} || : ${csudo}rm -rf ${data_link_dir} || : @@ -508,6 +574,7 @@ function install_TDengine() { install_taosadapter_config install_taosadapter_service install_service + install_app # Ask if to start the service #echo diff --git a/packaging/tools/remove.sh b/packaging/tools/remove.sh index a648750904..6172fc9bc8 100755 --- a/packaging/tools/remove.sh +++ b/packaging/tools/remove.sh @@ -6,12 +6,31 @@ set -e #set -x verMode=edge +osType=`uname` RED='\033[0;31m' GREEN='\033[1;32m' NC='\033[0m' -installDir="/usr/local/taos" +if [ "$osType" != "Darwin" ]; then + installDir="/usr/local/taos" + bin_link_dir="/usr/bin" + lib_link_dir="/usr/lib" + lib64_link_dir="/usr/lib64" + inc_link_dir="/usr/include" +else + if [ -d "/usr/local/Cellar/" ];then + installDir="/usr/local/Cellar/tdengine/${verNumber}" + elif [ -d "/opt/homebrew/Cellar/" ];then + installDir="/opt/homebrew/Cellar/tdengine/${verNumber}" + else + installDir="/usr/local/taos" + fi + bin_link_dir="/usr/local/bin" + lib_link_dir="/usr/local/lib" + lib64_link_dir="/usr/local/lib" + inc_link_dir="/usr/local/include" +fi serverName="taosd" clientName="taos" uninstallScript="rmtaos" @@ -22,11 +41,8 @@ install_main_dir=${installDir} data_link_dir=${installDir}/data log_link_dir=${installDir}/log cfg_link_dir=${installDir}/cfg -bin_link_dir="/usr/bin" local_bin_link_dir="/usr/local/bin" -lib_link_dir="/usr/lib" -lib64_link_dir="/usr/lib64" -inc_link_dir="/usr/include" + service_config_dir="/etc/systemd/system" taos_service_name=${serverName} @@ -82,6 +98,7 @@ function clean_bin() { # Remove link ${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 || : @@ -103,7 +120,7 @@ function clean_lib() { [ -f ${lib_link_dir}/libtaosws.so ] && ${csudo}rm -f ${lib_link_dir}/libtaosws.so || : ${csudo}rm -f ${lib64_link_dir}/libtaos.* || : - [ -f ${lib64_link_dir}/libtaosws.so ] && ${csudo}rm -f ${lib64_link_dir}/libtaosws.so || : + [ -f ${lib64_link_dir}/libtaosws.* ] && ${csudo}rm -f ${lib64_link_dir}/libtaosws.* || : #${csudo}rm -rf ${v15_java_app_dir} || : } @@ -195,12 +212,20 @@ function clean_service_on_sysvinit() { fi } +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 || : +} + function clean_service() { if ((${service_mod} == 0)); then clean_service_on_systemd elif ((${service_mod} == 1)); then clean_service_on_sysvinit else + if [ "$osType" = "Darwin" ]; then + clean_service_on_launchctl + fi kill_taosadapter kill_taosd kill_tarbitrator @@ -241,6 +266,9 @@ elif echo $osinfo | grep -qwi "centos"; then # echo "this is centos system" ${csudo}rpm -e --noscripts tdengine >/dev/null 2>&1 || : fi +if [ "$osType" = "Darwin" ]; then + ${csudo}rm -rf /Applications/TDengine.app +fi echo -e "${GREEN}${productName} is removed successfully!${NC}" echo diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index e461e06158..110c3bc8f4 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -20,6 +20,30 @@ #include "tdatablock.h" #include "tlog.h" +// SBuffer ================================ +void tBufferDestroy(SBuffer *pBuffer) { + tFree(pBuffer->pBuf); + pBuffer->pBuf = NULL; +} + +int32_t tBufferInit(SBuffer *pBuffer, int64_t size) { + pBuffer->nBuf = 0; + return tRealloc(&pBuffer->pBuf, size); +} + +int32_t tBufferPut(SBuffer *pBuffer, const void *pData, int64_t nData) { + int32_t code = 0; + + code = tRealloc(&pBuffer->pBuf, pBuffer->nBuf + nData); + if (code) return code; + + memcpy(pBuffer->pBuf + pBuffer->nBuf, pData, nData); + pBuffer->nBuf += nData; + + return code; +} + +// ================================ static int32_t tGetTagVal(uint8_t *p, STagVal *pTagVal, int8_t isJson); #pragma pack(push, 1) diff --git a/source/common/src/tglobal.c b/source/common/src/tglobal.c index c0203dadb8..ce9a9a7b50 100644 --- a/source/common/src/tglobal.c +++ b/source/common/src/tglobal.c @@ -374,8 +374,8 @@ static int32_t taosAddServerCfg(SConfig *pCfg) { tsNumOfVnodeStreamThreads = TMAX(tsNumOfVnodeStreamThreads, 4); if (cfgAddInt32(pCfg, "numOfVnodeStreamThreads", tsNumOfVnodeStreamThreads, 4, 1024, 0) != 0) return -1; - tsNumOfVnodeFetchThreads = 1; - if (cfgAddInt32(pCfg, "numOfVnodeFetchThreads", tsNumOfVnodeFetchThreads, 1, 1024, 0) != 0) return -1; +// tsNumOfVnodeFetchThreads = 1; +// if (cfgAddInt32(pCfg, "numOfVnodeFetchThreads", tsNumOfVnodeFetchThreads, 1, 1, 0) != 0) return -1; tsNumOfVnodeWriteThreads = tsNumOfCores; tsNumOfVnodeWriteThreads = TMAX(tsNumOfVnodeWriteThreads, 1); @@ -497,6 +497,7 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) { pItem->stype = stype; } +/* pItem = cfgGetItem(tsCfg, "numOfVnodeFetchThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { tsNumOfVnodeFetchThreads = numOfCores / 4; @@ -504,6 +505,7 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) { pItem->i32 = tsNumOfVnodeFetchThreads; pItem->stype = stype; } +*/ pItem = cfgGetItem(tsCfg, "numOfVnodeWriteThreads"); if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) { @@ -703,7 +705,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) { tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32; tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32; tsNumOfVnodeStreamThreads = cfgGetItem(pCfg, "numOfVnodeStreamThreads")->i32; - tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32; +// tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32; tsNumOfVnodeWriteThreads = cfgGetItem(pCfg, "numOfVnodeWriteThreads")->i32; tsNumOfVnodeSyncThreads = cfgGetItem(pCfg, "numOfVnodeSyncThreads")->i32; tsNumOfVnodeRsmaThreads = cfgGetItem(pCfg, "numOfVnodeRsmaThreads")->i32; @@ -953,8 +955,10 @@ int32_t taosSetCfg(SConfig *pCfg, char *name) { tsNumOfMnodeReadThreads = cfgGetItem(pCfg, "numOfMnodeReadThreads")->i32; } else if (strcasecmp("numOfVnodeQueryThreads", name) == 0) { tsNumOfVnodeQueryThreads = cfgGetItem(pCfg, "numOfVnodeQueryThreads")->i32; +/* } else if (strcasecmp("numOfVnodeFetchThreads", name) == 0) { tsNumOfVnodeFetchThreads = cfgGetItem(pCfg, "numOfVnodeFetchThreads")->i32; +*/ } else if (strcasecmp("numOfVnodeWriteThreads", name) == 0) { tsNumOfVnodeWriteThreads = cfgGetItem(pCfg, "numOfVnodeWriteThreads")->i32; } else if (strcasecmp("numOfVnodeSyncThreads", name) == 0) { diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmFile.c b/source/dnode/mgmt/mgmt_vnode/src/vmFile.c index 82fc286a94..2ae9faf7df 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmFile.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmFile.c @@ -135,7 +135,7 @@ _OVER: if (content != NULL) taosMemoryFree(content); if (root != NULL) cJSON_Delete(root); if (pFile != NULL) taosCloseFile(&pFile); - if (*ppCfgs == NULL && pCfgs != NULL) taosMemoryFree(pCfgs); + if (code != 0) taosMemoryFree(pCfgs); terrno = code; return code; @@ -157,6 +157,11 @@ int32_t vmWriteVnodeListToFile(SVnodeMgmt *pMgmt) { int32_t numOfVnodes = 0; SVnodeObj **pVnodes = vmGetVnodeListFromHash(pMgmt, &numOfVnodes); + if (pVnodes == NULL) { + terrno = TSDB_CODE_OUT_OF_MEMORY; + ret = -1; + goto _OVER; + } int32_t len = 0; int32_t maxLen = MAX_CONTENT_LEN; diff --git a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c index 19ed2cbc88..bcc2e358d6 100644 --- a/source/dnode/mgmt/mgmt_vnode/src/vmInt.c +++ b/source/dnode/mgmt/mgmt_vnode/src/vmInt.c @@ -384,7 +384,7 @@ static int32_t vmStartVnodes(SVnodeMgmt *pMgmt) { for (int32_t v = 0; v < numOfVnodes; ++v) { int32_t t = v % threadNum; SVnodeThread *pThread = &threads[t]; - if (pThread->ppVnodes != NULL) { + if (pThread->ppVnodes != NULL && ppVnodes != NULL) { pThread->ppVnodes[pThread->vnodeNum++] = ppVnodes[v]; } } diff --git a/source/dnode/mnode/impl/src/mndAcct.c b/source/dnode/mnode/impl/src/mndAcct.c index 65857367f9..ffa5dc6d0b 100644 --- a/source/dnode/mnode/impl/src/mndAcct.c +++ b/source/dnode/mnode/impl/src/mndAcct.c @@ -77,7 +77,7 @@ static int32_t mndCreateDefaultAcct(SMnode *pMnode) { SSdbRaw *pRaw = mndAcctActionEncode(&acctObj); if (pRaw == NULL) return -1; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); mInfo("acct:%s, will be created when deploying, raw:%p", acctObj.acct, pRaw); diff --git a/source/dnode/mnode/impl/src/mndCluster.c b/source/dnode/mnode/impl/src/mndCluster.c index 3502ecf604..348c8f4cb8 100644 --- a/source/dnode/mnode/impl/src/mndCluster.c +++ b/source/dnode/mnode/impl/src/mndCluster.c @@ -231,7 +231,7 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { SSdbRaw *pRaw = mndClusterActionEncode(&clusterObj); if (pRaw == NULL) return -1; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); mInfo("cluster:%" PRId64 ", will be created when deploying, raw:%p", clusterObj.id, pRaw); @@ -248,7 +248,7 @@ static int32_t mndCreateDefaultCluster(SMnode *pMnode) { mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -326,7 +326,7 @@ static int32_t mndProcessUptimeTimer(SRpcMsg *pReq) { mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); diff --git a/source/dnode/mnode/impl/src/mndDb.c b/source/dnode/mnode/impl/src/mndDb.c index 1d70f43834..9f0cb0b510 100644 --- a/source/dnode/mnode/impl/src/mndDb.c +++ b/source/dnode/mnode/impl/src/mndDb.c @@ -730,7 +730,7 @@ static int32_t mndSetAlterDbRedoLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pOl return -1; } - sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRedoRaw, SDB_STATUS_READY); return 0; } @@ -742,7 +742,7 @@ static int32_t mndSetAlterDbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *p return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); return 0; } @@ -938,7 +938,7 @@ static int32_t mndSetDropDbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pD sdbRelease(pSdb, pVgroup); return -1; } - sdbSetRawStatus(pVgRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pVgRaw, SDB_STATUS_DROPPED); } sdbRelease(pSdb, pVgroup); @@ -956,7 +956,7 @@ static int32_t mndSetDropDbCommitLogs(SMnode *pMnode, STrans *pTrans, SDbObj *pD sdbRelease(pSdb, pStbRaw); return -1; } - sdbSetRawStatus(pStbRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pStbRaw, SDB_STATUS_DROPPED); } sdbRelease(pSdb, pStb); @@ -1052,7 +1052,7 @@ static int32_t mndDropDb(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb) { mError("trans:%d, failed to append redo log since %s", pTrans->id, terrstr()); goto _OVER; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); } int32_t rspLen = 0; diff --git a/source/dnode/mnode/impl/src/mndDnode.c b/source/dnode/mnode/impl/src/mndDnode.c index c8995eb6bc..94317f7ac8 100644 --- a/source/dnode/mnode/impl/src/mndDnode.c +++ b/source/dnode/mnode/impl/src/mndDnode.c @@ -101,7 +101,8 @@ static int32_t mndCreateDefaultDnode(SMnode *pMnode) { dnodeObj.createdTime = taosGetTimestampMs(); dnodeObj.updateTime = dnodeObj.createdTime; dnodeObj.port = tsServerPort; - memcpy(&dnodeObj.fqdn, tsLocalFqdn, TSDB_FQDN_LEN); + tstrncpy(dnodeObj.fqdn, tsLocalFqdn, TSDB_FQDN_LEN); + dnodeObj.fqdn[TSDB_FQDN_LEN - 1] = 0; snprintf(dnodeObj.ep, TSDB_EP_LEN - 1, "%s:%u", dnodeObj.fqdn, dnodeObj.port); pTrans = mndTransCreate(pMnode, TRN_POLICY_RETRY, TRN_CONFLICT_GLOBAL, NULL, "create-dnode"); @@ -110,7 +111,7 @@ static int32_t mndCreateDefaultDnode(SMnode *pMnode) { pRaw = mndDnodeActionEncode(&dnodeObj); if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; @@ -190,7 +191,10 @@ _OVER: static int32_t mndDnodeActionInsert(SSdb *pSdb, SDnodeObj *pDnode) { mTrace("dnode:%d, perform insert action, row:%p", pDnode->id, pDnode); pDnode->offlineReason = DND_REASON_STATUS_NOT_RECEIVED; - snprintf(pDnode->ep, TSDB_EP_LEN - 1, "%s:%u", pDnode->fqdn, pDnode->port); + + char ep[TSDB_EP_LEN] = {0}; + snprintf(ep, TSDB_EP_LEN - 1, "%s:%u", pDnode->fqdn, pDnode->port); + tstrncpy(pDnode->ep, ep, TSDB_EP_LEN); return 0; } @@ -275,7 +279,7 @@ void mndGetDnodeData(SMnode *pMnode, SArray *pDnodeEps) { SDnodeEp dnodeEp = {0}; dnodeEp.id = pDnode->id; dnodeEp.ep.port = pDnode->port; - memcpy(dnodeEp.ep.fqdn, pDnode->fqdn, TSDB_FQDN_LEN); + tstrncpy(dnodeEp.ep.fqdn, pDnode->fqdn, TSDB_FQDN_LEN); sdbRelease(pSdb, pDnode); dnodeEp.isMnode = 0; @@ -485,7 +489,7 @@ static int32_t mndCreateDnode(SMnode *pMnode, SRpcMsg *pReq, SCreateDnodeReq *pC dnodeObj.createdTime = taosGetTimestampMs(); dnodeObj.updateTime = dnodeObj.createdTime; dnodeObj.port = pCreate->port; - memcpy(dnodeObj.fqdn, pCreate->fqdn, TSDB_FQDN_LEN); + tstrncpy(dnodeObj.fqdn, pCreate->fqdn, TSDB_FQDN_LEN); snprintf(dnodeObj.ep, TSDB_EP_LEN - 1, "%s:%u", dnodeObj.fqdn, dnodeObj.port); pTrans = mndTransCreate(pMnode, TRN_POLICY_ROLLBACK, TRN_CONFLICT_GLOBAL, pReq, "create-dnode"); @@ -494,7 +498,7 @@ static int32_t mndCreateDnode(SMnode *pMnode, SRpcMsg *pReq, SCreateDnodeReq *pC pRaw = mndDnodeActionEncode(&dnodeObj); if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; @@ -675,13 +679,13 @@ static int32_t mndDropDnode(SMnode *pMnode, SRpcMsg *pReq, SDnodeObj *pDnode, SM pRaw = mndDnodeActionEncode(pDnode); if (pRaw == NULL) goto _OVER; if (mndTransAppendRedolog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_DROPPING); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_DROPPING); pRaw = NULL; pRaw = mndDnodeActionEncode(pDnode); if (pRaw == NULL) goto _OVER; if (mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_DROPPED); pRaw = NULL; if (pMObj != NULL) { diff --git a/source/dnode/mnode/impl/src/mndFunc.c b/source/dnode/mnode/impl/src/mndFunc.c index ccab4774e2..c9b22fad3a 100644 --- a/source/dnode/mnode/impl/src/mndFunc.c +++ b/source/dnode/mnode/impl/src/mndFunc.c @@ -259,17 +259,17 @@ static int32_t mndDropFunc(SMnode *pMnode, SRpcMsg *pReq, SFuncObj *pFunc) { SSdbRaw *pRedoRaw = mndFuncActionEncode(pFunc); if (pRedoRaw == NULL) goto _OVER; if (mndTransAppendRedolog(pTrans, pRedoRaw) != 0) goto _OVER; - sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING); + (void)sdbSetRawStatus(pRedoRaw, SDB_STATUS_DROPPING); SSdbRaw *pUndoRaw = mndFuncActionEncode(pFunc); if (pUndoRaw == NULL) goto _OVER; if (mndTransAppendUndolog(pTrans, pUndoRaw) != 0) goto _OVER; - sdbSetRawStatus(pUndoRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pUndoRaw, SDB_STATUS_READY); SSdbRaw *pCommitRaw = mndFuncActionEncode(pFunc); if (pCommitRaw == NULL) goto _OVER; if (mndTransAppendCommitlog(pTrans, pCommitRaw) != 0) goto _OVER; - sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); if (mndTransPrepare(pMnode, pTrans) != 0) goto _OVER; diff --git a/source/dnode/mnode/impl/src/mndOffset.c b/source/dnode/mnode/impl/src/mndOffset.c index 797aa88670..2ada3e00bb 100644 --- a/source/dnode/mnode/impl/src/mndOffset.c +++ b/source/dnode/mnode/impl/src/mndOffset.c @@ -161,7 +161,7 @@ int32_t mndCreateOffsets(STrans *pTrans, const char *cgroup, const char *topicNa if (pOffsetRaw == NULL) { return -1; } - sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY); // commit log or redo log? if (mndTransAppendRedolog(pTrans, pOffsetRaw) < 0) { return -1; @@ -208,7 +208,7 @@ static int32_t mndProcessCommitOffsetReq(SRpcMsg *pMsg) { } pOffsetObj->offset = pOffset->offset; SSdbRaw *pOffsetRaw = mndOffsetActionEncode(pOffsetObj); - sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pOffsetRaw, SDB_STATUS_READY); mndTransAppendCommitlog(pTrans, pOffsetRaw); if (create) { taosMemoryFree(pOffsetObj); diff --git a/source/dnode/mnode/impl/src/mndStream.c b/source/dnode/mnode/impl/src/mndStream.c index eb6730e217..fa291177c9 100644 --- a/source/dnode/mnode/impl/src/mndStream.c +++ b/source/dnode/mnode/impl/src/mndStream.c @@ -420,7 +420,7 @@ int32_t mndPersistStream(SMnode *pMnode, STrans *pTrans, SStreamObj *pStream) { mError("trans:%d, failed to append commit log since %s", pTrans->id, terrstr()); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); return 0; } @@ -431,7 +431,7 @@ int32_t mndPersistDropStreamLog(SMnode *pMnode, STrans *pTrans, SStreamObj *pStr mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); return 0; } @@ -447,7 +447,7 @@ static int32_t mndSetStreamRecover(SMnode *pMnode, STrans *pTrans, const SStream mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); return 0; } diff --git a/source/dnode/mnode/impl/src/mndTopic.c b/source/dnode/mnode/impl/src/mndTopic.c index ce195454f8..5d3a2be79a 100644 --- a/source/dnode/mnode/impl/src/mndTopic.c +++ b/source/dnode/mnode/impl/src/mndTopic.c @@ -459,7 +459,7 @@ static int32_t mndCreateTopic(SMnode *pMnode, SRpcMsg *pReq, SCMCreateTopicReq * mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); if (topicObj.ntbUid != 0) { STqCheckInfo info; @@ -596,7 +596,7 @@ static int32_t mndDropTopic(SMnode *pMnode, STrans *pTrans, SRpcMsg *pReq, SMqTo mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -777,7 +777,7 @@ static int32_t mndRetrieveTopic(SRpcMsg *pReq, SShowObj *pShow, SSDataBlock *pBl int32_t cols = 0; char topicName[TSDB_TOPIC_NAME_LEN + VARSTR_HEADER_SIZE + 5] = {0}; - strcpy(varDataVal(topicName), mndGetDbStr(pTopic->name)); + 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))); diff --git a/source/dnode/mnode/impl/src/mndTrans.c b/source/dnode/mnode/impl/src/mndTrans.c index 455b71ace9..d30cc8f9ca 100644 --- a/source/dnode/mnode/impl/src/mndTrans.c +++ b/source/dnode/mnode/impl/src/mndTrans.c @@ -17,9 +17,9 @@ #include "mndTrans.h" #include "mndConsumer.h" #include "mndDb.h" -#include "mndStb.h" #include "mndPrivilege.h" #include "mndShow.h" +#include "mndStb.h" #include "mndSync.h" #include "mndUser.h" @@ -138,6 +138,7 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT32(pRaw, dataPos, undoActionNum, _OVER) SDB_SET_INT32(pRaw, dataPos, commitActionNum, _OVER) + int8_t unused = 0; for (int32_t i = 0; i < redoActionNum; ++i) { STransAction *pAction = taosArrayGet(pTrans->redoActions, i); SDB_SET_INT32(pRaw, dataPos, pAction->id, _OVER) @@ -149,14 +150,14 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER) if (pAction->actionType == TRANS_ACTION_RAW) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); - SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->rawWritten*/, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) SDB_SET_BINARY(pRaw, dataPos, (void *)pAction->pRaw, len, _OVER) } else if (pAction->actionType == TRANS_ACTION_MSG) { SDB_SET_BINARY(pRaw, dataPos, (void *)&pAction->epSet, sizeof(SEpSet), _OVER) SDB_SET_INT16(pRaw, dataPos, pAction->msgType, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgSent, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgReceived, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgSent*/, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgReceived*/, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->contLen, _OVER) SDB_SET_BINARY(pRaw, dataPos, pAction->pCont, pAction->contLen, _OVER) } else { @@ -175,14 +176,14 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER) if (pAction->actionType == TRANS_ACTION_RAW) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); - SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->rawWritten*/, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) SDB_SET_BINARY(pRaw, dataPos, (void *)pAction->pRaw, len, _OVER) } else if (pAction->actionType == TRANS_ACTION_MSG) { SDB_SET_BINARY(pRaw, dataPos, (void *)&pAction->epSet, sizeof(SEpSet), _OVER) SDB_SET_INT16(pRaw, dataPos, pAction->msgType, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgSent, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgReceived, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgSent*/, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgReceived*/, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->contLen, _OVER) SDB_SET_BINARY(pRaw, dataPos, pAction->pCont, pAction->contLen, _OVER) } else { @@ -201,14 +202,14 @@ static SSdbRaw *mndTransActionEncode(STrans *pTrans) { SDB_SET_INT8(pRaw, dataPos, pAction->reserved, _OVER) if (pAction->actionType == TRANS_ACTION_RAW) { int32_t len = sdbGetRawTotalSize(pAction->pRaw); - SDB_SET_INT8(pRaw, dataPos, pAction->rawWritten, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->rawWritten*/, _OVER) SDB_SET_INT32(pRaw, dataPos, len, _OVER) SDB_SET_BINARY(pRaw, dataPos, (void *)pAction->pRaw, len, _OVER) } else if (pAction->actionType == TRANS_ACTION_MSG) { SDB_SET_BINARY(pRaw, dataPos, (void *)&pAction->epSet, sizeof(SEpSet), _OVER) SDB_SET_INT16(pRaw, dataPos, pAction->msgType, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgSent, _OVER) - SDB_SET_INT8(pRaw, dataPos, pAction->msgReceived, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgSent*/, _OVER) + SDB_SET_INT8(pRaw, dataPos, unused /*pAction->msgReceived*/, _OVER) SDB_SET_INT32(pRaw, dataPos, pAction->contLen, _OVER) SDB_SET_BINARY(pRaw, dataPos, pAction->pCont, pAction->contLen, _OVER) } else { @@ -305,6 +306,7 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { if (pTrans->undoActions == NULL) goto _OVER; if (pTrans->commitActions == NULL) goto _OVER; + int8_t unused = 0; for (int32_t i = 0; i < redoActionNum; ++i) { memset(&action, 0, sizeof(action)); SDB_GET_INT32(pRaw, dataPos, &action.id, _OVER) @@ -317,7 +319,7 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { action.stage = stage; SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER) if (action.actionType == TRANS_ACTION_RAW) { - SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.rawWritten*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); if (action.pRaw == NULL) goto _OVER; @@ -328,8 +330,8 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { } else if (action.actionType == TRANS_ACTION_MSG) { SDB_GET_BINARY(pRaw, dataPos, (void *)&action.epSet, sizeof(SEpSet), _OVER); SDB_GET_INT16(pRaw, dataPos, &action.msgType, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgSent, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgReceived, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgSent*/, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgReceived*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.contLen, _OVER) action.pCont = taosMemoryMalloc(action.contLen); if (action.pCont == NULL) goto _OVER; @@ -353,7 +355,7 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { action.stage = stage; SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER) if (action.actionType == TRANS_ACTION_RAW) { - SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.rawWritten*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); if (action.pRaw == NULL) goto _OVER; @@ -364,8 +366,8 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { } else if (action.actionType == TRANS_ACTION_MSG) { SDB_GET_BINARY(pRaw, dataPos, (void *)&action.epSet, sizeof(SEpSet), _OVER); SDB_GET_INT16(pRaw, dataPos, &action.msgType, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgSent, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgReceived, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgSent*/, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgReceived*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.contLen, _OVER) action.pCont = taosMemoryMalloc(action.contLen); if (action.pCont == NULL) goto _OVER; @@ -389,7 +391,7 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { action.stage = stage; SDB_GET_INT8(pRaw, dataPos, &action.reserved, _OVER) if (action.actionType) { - SDB_GET_INT8(pRaw, dataPos, &action.rawWritten, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.rawWritten*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &dataLen, _OVER) action.pRaw = taosMemoryMalloc(dataLen); if (action.pRaw == NULL) goto _OVER; @@ -400,8 +402,8 @@ static SSdbRow *mndTransActionDecode(SSdbRaw *pRaw) { } else if (action.actionType == TRANS_ACTION_MSG) { SDB_GET_BINARY(pRaw, dataPos, (void *)&action.epSet, sizeof(SEpSet), _OVER); SDB_GET_INT16(pRaw, dataPos, &action.msgType, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgSent, _OVER) - SDB_GET_INT8(pRaw, dataPos, &action.msgReceived, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgSent*/, _OVER) + SDB_GET_INT8(pRaw, dataPos, &unused /*&action.msgReceived*/, _OVER) SDB_GET_INT32(pRaw, dataPos, &action.contLen, _OVER) action.pCont = taosMemoryMalloc(action.contLen); if (action.pCont == NULL) goto _OVER; @@ -435,7 +437,9 @@ _OVER: return NULL; } - mTrace("trans:%d, decode from raw:%p, row:%p", pTrans->id, pRaw, pTrans); + if (pTrans != NULL) { + mTrace("trans:%d, decode from raw:%p, row:%p", pTrans->id, pRaw, pTrans); + } return pRow; } @@ -769,7 +773,7 @@ static int32_t mndTransSync(SMnode *pMnode, STrans *pTrans) { mError("trans:%d, failed to encode while sync trans since %s", pTrans->id, terrstr()); return -1; } - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); mInfo("trans:%d, sync to other mnodes, stage:%s", pTrans->id, mndTransStr(pTrans->stage)); int32_t code = mndSyncPropose(pMnode, pRaw, pTrans->id); @@ -816,7 +820,7 @@ static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { if (mndCheckDbConflict(pNew->stbname, pTrans)) conflict = true; } if (pTrans->conflict == TRN_CONFLICT_DB_INSIDE) { - if (mndCheckDbConflict(pNew->stbname, pTrans)) conflict = true; // for stb + if (mndCheckDbConflict(pNew->stbname, pTrans)) conflict = true; // for stb } } @@ -825,9 +829,8 @@ static bool mndCheckTransConflict(SMnode *pMnode, STrans *pNew) { pNew->id, pNew->dbname, pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, pTrans->conflict); } else { - mInfo("trans:%d, db:%s stb:%s type:%d, not conflict with trans:%d db:%s stb:%s type:%d", pNew->id, - pNew->dbname, pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, - pTrans->conflict); + mInfo("trans:%d, db:%s stb:%s type:%d, not conflict with trans:%d db:%s stb:%s type:%d", pNew->id, pNew->dbname, + pNew->stbname, pNew->conflict, pTrans->id, pTrans->dbname, pTrans->stbname, pTrans->conflict); } sdbRelease(pMnode->pSdb, pTrans); } @@ -930,7 +933,7 @@ static void mndTransSendRpcRsp(SMnode *pMnode, STrans *pTrans) { SRpcHandleInfo *pInfo = taosArrayGet(pTrans->pRpcArray, i); if (pInfo->handle != NULL) { mInfo("trans:%d, send rsp, code:0x%x stage:%s app:%p", pTrans->id, code, mndTransStr(pTrans->stage), - pInfo->ahandle); + pInfo->ahandle); if (code == TSDB_CODE_RPC_NETWORK_UNAVAIL) { code = TSDB_CODE_MND_TRANS_NETWORK_UNAVAILL; } @@ -1013,8 +1016,8 @@ int32_t mndTransProcessRsp(SRpcMsg *pRsp) { pAction->errCode = 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); + 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); _OVER: @@ -1030,7 +1033,7 @@ static void mndTransResetAction(SMnode *pMnode, STrans *pTrans, STransAction *pA pAction->errCode == TSDB_CODE_SYN_INTERNAL_ERROR || pAction->errCode == TSDB_CODE_SYN_NOT_LEADER) { pAction->epSet.inUse = (pAction->epSet.inUse + 1) % pAction->epSet.numOfEps; mInfo("trans:%d, %s:%d execute status is reset and set epset inuse:%d", pTrans->id, mndTransStr(pAction->stage), - pAction->id, pAction->epSet.inUse); + pAction->id, pAction->epSet.inUse); } else { mInfo("trans:%d, %s:%d execute status is reset", pTrans->id, mndTransStr(pAction->stage), pAction->id); } @@ -1060,7 +1063,7 @@ static int32_t mndTransWriteSingleLog(SMnode *pMnode, STrans *pTrans, STransActi pAction->errCode = 0; code = 0; mInfo("trans:%d, %s:%d write to sdb, type:%s status:%s", pTrans->id, mndTransStr(pAction->stage), pAction->id, - sdbTableName(pAction->pRaw->type), sdbStatusName(pAction->pRaw->status)); + sdbTableName(pAction->pRaw->type), sdbStatusName(pAction->pRaw->status)); mndSetTransLastAction(pTrans, pAction); } else { @@ -1261,7 +1264,7 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans) pTrans->code = 0; pTrans->redoActionPos++; mInfo("trans:%d, %s:%d is executed and need sync to other mnodes", pTrans->id, mndTransStr(pAction->stage), - pAction->id); + pAction->id); code = mndTransSync(pMnode, pTrans); if (code != 0) { pTrans->code = terrno; @@ -1280,7 +1283,7 @@ static int32_t mndTransExecuteRedoActionsSerial(SMnode *pMnode, STrans *pTrans) terrno = code; pTrans->code = code; mInfo("trans:%d, %s:%d receive code:0x%x and wait another schedule, failedTimes:%d", pTrans->id, - mndTransStr(pAction->stage), pAction->id, code, pTrans->failedTimes); + mndTransStr(pAction->stage), pAction->id, code, pTrans->failedTimes); break; } } @@ -1431,7 +1434,7 @@ static bool mndTransPerfromFinishedStage(SMnode *pMnode, STrans *pTrans) { mError("trans:%d, failed to encode while finish trans since %s", pTrans->id, terrstr()); return false; } - sdbSetRawStatus(pRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_DROPPED); int32_t code = sdbWrite(pMnode->pSdb, pRaw); if (code != 0) { diff --git a/source/dnode/mnode/impl/src/mndUser.c b/source/dnode/mnode/impl/src/mndUser.c index fecdfb12ba..9f4b9fc2de 100644 --- a/source/dnode/mnode/impl/src/mndUser.c +++ b/source/dnode/mnode/impl/src/mndUser.c @@ -77,7 +77,7 @@ static int32_t mndCreateDefaultUser(SMnode *pMnode, char *acct, char *user, char SSdbRaw *pRaw = mndUserActionEncode(&userObj); if (pRaw == NULL) return -1; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); mInfo("user:%s, will be created when deploying, raw:%p", userObj.user, pRaw); @@ -94,7 +94,7 @@ static int32_t mndCreateDefaultUser(SMnode *pMnode, char *acct, char *user, char mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -313,7 +313,7 @@ static int32_t mndCreateUser(SMnode *pMnode, char *acct, SCreateUserReq *pCreate mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -397,7 +397,7 @@ static int32_t mndAlterUser(SMnode *pMnode, SUserObj *pOld, SUserObj *pNew, SRpc mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_READY); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); @@ -612,7 +612,7 @@ static int32_t mndDropUser(SMnode *pMnode, SRpcMsg *pReq, SUserObj *pUser) { mndTransDrop(pTrans); return -1; } - sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); + (void)sdbSetRawStatus(pCommitRaw, SDB_STATUS_DROPPED); if (mndTransPrepare(pMnode, pTrans) != 0) { mError("trans:%d, failed to prepare since %s", pTrans->id, terrstr()); diff --git a/source/dnode/mnode/impl/src/mndVgroup.c b/source/dnode/mnode/impl/src/mndVgroup.c index a0f01f41d8..a31bf6b8e2 100644 --- a/source/dnode/mnode/impl/src/mndVgroup.c +++ b/source/dnode/mnode/impl/src/mndVgroup.c @@ -1115,14 +1115,14 @@ int32_t mndSetMoveVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, { SSdbRaw *pRaw = mndVgroupActionEncode(&newVg); if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) return -1; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; } { SSdbRaw *pRaw = mndVgroupActionEncode(&newVg); if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) return -1; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; } @@ -1304,14 +1304,14 @@ static int32_t mndRedistributeVgroup(SMnode *pMnode, SRpcMsg *pReq, SDbObj *pDb, { pRaw = mndVgroupActionEncode(&newVg); if (pRaw == NULL || mndTransAppendRedolog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; } { pRaw = mndVgroupActionEncode(&newVg); if (pRaw == NULL || mndTransAppendCommitlog(pTrans, pRaw) != 0) goto _OVER; - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); pRaw = NULL; } @@ -1579,7 +1579,7 @@ int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, S sdbFreeRaw(pVgRaw); return -1; } - sdbSetRawStatus(pVgRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pVgRaw, SDB_STATUS_READY); } { @@ -1589,7 +1589,7 @@ int32_t mndBuildAlterVgroupAction(SMnode *pMnode, STrans *pTrans, SDbObj *pDb, S sdbFreeRaw(pVgRaw); return -1; } - sdbSetRawStatus(pVgRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pVgRaw, SDB_STATUS_READY); } } @@ -1704,7 +1704,7 @@ static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SD sdbFreeRaw(pRaw); return -1; } - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); } { @@ -1713,7 +1713,7 @@ static int32_t mndSetBalanceVgroupInfoToTrans(SMnode *pMnode, STrans *pTrans, SD sdbFreeRaw(pRaw); return -1; } - sdbSetRawStatus(pRaw, SDB_STATUS_READY); + (void)sdbSetRawStatus(pRaw, SDB_STATUS_READY); } mInfo("vgId:%d, vgroup info after balance, replica:%d", newVg.vgId, newVg.replica); diff --git a/source/dnode/mnode/sdb/src/sdbFile.c b/source/dnode/mnode/sdb/src/sdbFile.c index b5cfa7b0f6..3df0fcee17 100644 --- a/source/dnode/mnode/sdb/src/sdbFile.c +++ b/source/dnode/mnode/sdb/src/sdbFile.c @@ -619,8 +619,8 @@ int32_t sdbStopWrite(SSdb *pSdb, SSdbIter *pIter, bool isApply, int64_t index, i int32_t code = 0; if (!isApply) { - sdbCloseIter(pIter); mInfo("sdbiter:%p, not apply to sdb", pIter); + sdbCloseIter(pIter); return 0; } diff --git a/source/dnode/vnode/inc/vnode.h b/source/dnode/vnode/inc/vnode.h index 4d228f742a..ba16bad7cf 100644 --- a/source/dnode/vnode/inc/vnode.h +++ b/source/dnode/vnode/inc/vnode.h @@ -96,11 +96,11 @@ void metaReaderClear(SMetaReader *pReader); int32_t metaGetTableEntryByUid(SMetaReader *pReader, tb_uid_t uid); int metaGetTableEntryByName(SMetaReader *pReader, const char *name); int32_t metaGetTableTags(SMeta *pMeta, uint64_t suid, SArray *uidList, SHashObj *tags); -int32_t metaGetTableTagsByUids(SMeta *pMeta, uint64_t suid, SArray *uidList, SHashObj *tags); +int32_t metaGetTableTagsByUids(SMeta *pMeta, int64_t suid, SArray *uidList, SHashObj *tags); int32_t metaReadNext(SMetaReader *pReader); const void *metaGetTableTagVal(void *tag, int16_t type, STagVal *tagVal); int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName); -int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid); +int metaGetTableUidByName(void *meta, char *tbName, int64_t *uid); int metaGetTableTypeByName(void *meta, char *tbName, ETableType *tbType); bool metaIsTableExist(SMeta *pMeta, tb_uid_t uid); diff --git a/source/dnode/vnode/src/meta/metaQuery.c b/source/dnode/vnode/src/meta/metaQuery.c index 3c9f964ff6..07e917931b 100644 --- a/source/dnode/vnode/src/meta/metaQuery.c +++ b/source/dnode/vnode/src/meta/metaQuery.c @@ -202,7 +202,7 @@ int metaGetTableNameByUid(void *meta, uint64_t uid, char *tbName) { return 0; } -int metaGetTableUidByName(void *meta, char *tbName, uint64_t *uid) { +int metaGetTableUidByName(void *meta, char *tbName, int64_t *uid) { int code = 0; SMetaReader mr = {0}; metaReaderInit(&mr, (SMeta *)meta, 0); @@ -1134,7 +1134,7 @@ END: return ret; } -static int32_t metaGetTableTagByUid(SMeta *pMeta, uint64_t suid, uint64_t uid, void **tag, int32_t *len, bool lock) { +static int32_t metaGetTableTagByUid(SMeta *pMeta, int64_t suid, int64_t uid, void **tag, int32_t *len, bool lock) { int ret = 0; if (lock) { metaRLock(pMeta); @@ -1148,7 +1148,7 @@ static int32_t metaGetTableTagByUid(SMeta *pMeta, uint64_t suid, uint64_t uid, v return ret; } -int32_t metaGetTableTagsByUids(SMeta *pMeta, uint64_t suid, SArray *uidList, SHashObj *tags) { +int32_t metaGetTableTagsByUids(SMeta *pMeta, int64_t suid, SArray *uidList, SHashObj *tags) { const int32_t LIMIT = 128; int32_t isLock = false; @@ -1169,6 +1169,9 @@ int32_t metaGetTableTagsByUids(SMeta *pMeta, uint64_t suid, SArray *uidList, SHa if (metaGetTableTagByUid(pMeta, suid, *id, &val, &len, false) == 0) { taosHashPut(tags, id, sizeof(tb_uid_t), val, len); tdbFree(val); + } else { + metaError("vgId:%d, failed to table IDs, suid: %" PRId64 ", uid: %" PRId64 "", TD_VID(pMeta->pVnode), suid, + *id); } } } diff --git a/source/libs/executor/inc/executorimpl.h b/source/libs/executor/inc/executorimpl.h index 4edb4a1f97..ecb04bf5bc 100644 --- a/source/libs/executor/inc/executorimpl.h +++ b/source/libs/executor/inc/executorimpl.h @@ -608,8 +608,6 @@ typedef struct SStreamIntervalOperatorInfo { SArray* pDelWins; // SWinRes int32_t delIndex; SSDataBlock* pDelRes; - SSDataBlock* pUpdateRes; - bool returnUpdate; SPhysiNode* pPhyNode; // create new child SHashObj* pPullDataMap; SArray* pPullWins; // SPullWindowInfo diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 9ce6275d84..2f6b737f79 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -26,7 +26,8 @@ #include "executorimpl.h" #include "tcompression.h" -static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond); +static int32_t removeInvalidTable(SArray* list, SHashObj* tags); +static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond, SHashObj* tags); static int32_t optimizeTbnameInCondImpl(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond); void initResultRowInfo(SResultRowInfo* pResultRowInfo) { @@ -373,7 +374,7 @@ static int32_t createResultData(SDataType* pType, int32_t numOfRows, SScalarPara return TSDB_CODE_SUCCESS; } -static SColumnInfoData* getColInfoResult(void* metaHandle, uint64_t suid, SArray* uidList, SNode* pTagCond) { +static SColumnInfoData* getColInfoResult(void* metaHandle, int64_t suid, SArray* uidList, SNode* pTagCond) { int32_t code = TSDB_CODE_SUCCESS; SArray* pBlockList = NULL; SSDataBlock* pResBlock = NULL; @@ -411,7 +412,7 @@ static SColumnInfoData* getColInfoResult(void* metaHandle, uint64_t suid, SArray // int64_t stt = taosGetTimestampUs(); tags = taosHashInit(32, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), false, HASH_NO_LOCK); - int32_t filter = optimizeTbnameInCond(metaHandle, suid, uidList, pTagCond); + int32_t filter = optimizeTbnameInCond(metaHandle, suid, uidList, pTagCond, tags); if (filter == -1) { code = metaGetTableTags(metaHandle, suid, uidList, tags); if (code != TSDB_CODE_SUCCESS) { @@ -419,10 +420,17 @@ static SColumnInfoData* getColInfoResult(void* metaHandle, uint64_t suid, SArray terrno = code; goto end; } - } else { - metaGetTableTagsByUids(metaHandle, suid, uidList, tags); - qInfo("succ to get table from meta idx, suid:%" PRIu64, suid); } + /*else { + code = metaGetTableTagsByUids(metaHandle, suid, uidList, tags); + if (code != 0) { + terrno = code; + qError("failed to get table from meta idx, reason: %s, suid:%" PRId64, tstrerror(code), suid); + goto end; + } else { + qInfo("succ to get table from meta idx, suid:%" PRId64, suid); + } + }*/ int32_t rows = taosArrayGetSize(uidList); if (rows == 0) { @@ -760,13 +768,18 @@ static int tableUidCompare(const void* a, const void* b) { } return u1 < u2 ? -1 : 1; } -static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* cond) { +static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list, SNode* cond, SHashObj* tags) { + int32_t ret = -1; if (nodeType(cond) == QUERY_NODE_OPERATOR) { - return optimizeTbnameInCondImpl(metaHandle, suid, list, cond); + ret = optimizeTbnameInCondImpl(metaHandle, suid, list, cond); + if (ret != -1) { + metaGetTableTagsByUids(metaHandle, suid, list, tags); + removeInvalidTable(list, tags); + } } if (nodeType(cond) != QUERY_NODE_LOGIC_CONDITION || ((SLogicConditionNode*)cond)->condType != LOGIC_COND_TYPE_AND) { - return -1; + return ret; } bool hasTbnameCond = false; @@ -774,20 +787,44 @@ static int32_t optimizeTbnameInCond(void* metaHandle, int64_t suid, SArray* list SNodeList* pList = (SNodeList*)pNode->pParameterList; int32_t len = LIST_LENGTH(pList); - if (len <= 0) return -1; + if (len <= 0) return ret; SListCell* cell = pList->pHead; for (int i = 0; i < len; i++) { if (cell == NULL) break; if (optimizeTbnameInCondImpl(metaHandle, suid, list, cell->pNode) == 0) { hasTbnameCond = true; + break; } cell = cell->pNext; } taosArraySort(list, tableUidCompare); taosArrayRemoveDuplicate(list, tableUidCompare, NULL); - return hasTbnameCond == true ? 0 : -1; + if (hasTbnameCond) { + ret = metaGetTableTagsByUids(metaHandle, suid, list, tags); + removeInvalidTable(list, tags); + } + return ret; +} + +/* + * handle invalid uid + */ +static int32_t removeInvalidTable(SArray* uids, SHashObj* tags) { + if (taosArrayGetSize(uids) <= 0) return 0; + + SArray* validUid = taosArrayInit(taosArrayGetSize(uids), sizeof(int64_t)); + + for (int32_t i = 0; i < taosArrayGetSize(uids); i++) { + int64_t* uid = taosArrayGet(uids, i); + if (taosHashGet(tags, uid, sizeof(int64_t)) != NULL) { + taosArrayPush(validUid, uid); + } + } + taosArraySwap(uids, validUid); + taosArrayDestroy(validUid); + return 0; } static int32_t optimizeTbnameInCondImpl(void* metaHandle, int64_t suid, SArray* list, SNode* pTagCond) { if (nodeType(pTagCond) != QUERY_NODE_OPERATOR) { diff --git a/source/libs/executor/src/scanoperator.c b/source/libs/executor/src/scanoperator.c index 3752a9f211..e43a6011de 100644 --- a/source/libs/executor/src/scanoperator.c +++ b/source/libs/executor/src/scanoperator.c @@ -1311,8 +1311,8 @@ void appendOneRow(SSDataBlock* pBlock, TSKEY* pStartTs, TSKEY* pEndTs, uint64_t* 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); - colDataAppendNULL(pCalStartCol, pBlock->info.rows); - colDataAppendNULL(pCalEndCol, pBlock->info.rows); + colDataAppend(pCalStartCol, pBlock->info.rows, (const char*)pStartTs, false); + colDataAppend(pCalEndCol, pBlock->info.rows, (const char*)pEndTs, false); pBlock->info.rows++; } @@ -1356,7 +1356,7 @@ static void checkUpdateData(SStreamScanInfo* pInfo, bool invertible, SSDataBlock } } -static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock) { +static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock, bool filter) { SDataBlockInfo* pBlockInfo = &pInfo->pRes->info; SOperatorInfo* pOperator = pInfo->pStreamScanOp; SExecTaskInfo* pTaskInfo = pOperator->pTaskInfo; @@ -1410,7 +1410,9 @@ static int32_t setBlockIntoRes(SStreamScanInfo* pInfo, const SSDataBlock* pBlock } } - doFilter(pInfo->pCondition, pInfo->pRes, NULL); + if (filter) { + doFilter(pInfo->pCondition, pInfo->pRes, NULL); + } blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); blockDataFreeRes((SSDataBlock*)pBlock); return 0; @@ -1446,7 +1448,7 @@ static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) { continue; } - setBlockIntoRes(pInfo, &block); + setBlockIntoRes(pInfo, &block, true); if (pBlockInfo->rows > 0) { return pInfo->pRes; @@ -1487,7 +1489,7 @@ static SSDataBlock* doQueueScan(SOperatorInfo* pOperator) { tqNextBlock(pInfo->tqReader, &ret); if (ret.fetchType == FETCH_TYPE__DATA) { blockDataCleanup(pInfo->pRes); - if (setBlockIntoRes(pInfo, &ret.data) < 0) { + if (setBlockIntoRes(pInfo, &ret.data, true) < 0) { ASSERT(0); } if (pInfo->pRes->info.rows > 0) { @@ -1751,6 +1753,7 @@ FETCH_NEXT_BLOCK: // printDataBlock(pSDB, "stream scan update"); return pSDB; } + blockDataCleanup(pInfo->pUpdateDataRes); pInfo->scanMode = STREAM_SCAN_FROM_READERHANDLE; } break; default: @@ -1801,7 +1804,7 @@ FETCH_NEXT_BLOCK: continue; } - setBlockIntoRes(pInfo, &block); + setBlockIntoRes(pInfo, &block, false); if (updateInfoIgnore(pInfo->pUpdateInfo, &pInfo->pRes->info.window, pInfo->pRes->info.groupId, pInfo->pRes->info.version)) { @@ -1810,11 +1813,30 @@ FETCH_NEXT_BLOCK: continue; } - if (pBlockInfo->rows > 0) { + 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; + } + } + } + + doFilter(pInfo->pCondition, pInfo->pRes, NULL); + blockDataUpdateTsWindow(pInfo->pRes, pInfo->primaryTsIndex); + + if (pBlockInfo->rows > 0 || pInfo->pUpdateDataRes->info.rows > 0) { break; } } - if (pBlockInfo->rows > 0) { + if (pBlockInfo->rows > 0 || pInfo->pUpdateDataRes->info.rows > 0) { break; } else { pInfo->tqReader->pMsg = NULL; @@ -1828,32 +1850,16 @@ FETCH_NEXT_BLOCK: pOperator->resultInfo.totalRows += pBlockInfo->rows; // printDataBlock(pInfo->pRes, "stream scan"); - if (pBlockInfo->rows == 0) { - updateInfoDestoryColseWinSBF(pInfo->pUpdateInfo); - /*pOperator->status = OP_EXEC_DONE;*/ - } else 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; - } - } - } - qDebug("scan rows: %d", pBlockInfo->rows); if (pBlockInfo->rows > 0) { return pInfo->pRes; - } else { - goto NEXT_SUBMIT_BLK; } - /*return (pBlockInfo->rows == 0) ? NULL : pInfo->pRes;*/ + + if (pInfo->pUpdateDataRes->info.rows > 0) { + goto FETCH_NEXT_BLOCK; + } + + goto NEXT_SUBMIT_BLK; } else { ASSERT(0); return NULL; @@ -3077,6 +3083,7 @@ static SSDataBlock* doTagScan(SOperatorInfo* pOperator) { STagScanInfo* pInfo = pOperator->info; SExprInfo* pExprInfo = &pOperator->exprSupp.pExprInfo[0]; SSDataBlock* pRes = pInfo->pRes; + blockDataCleanup(pRes); int32_t size = taosArrayGetSize(pInfo->pTableList->pTableList); if (size == 0) { diff --git a/source/libs/executor/src/tfill.c b/source/libs/executor/src/tfill.c index f6fd8c8920..34997a5dd8 100644 --- a/source/libs/executor/src/tfill.c +++ b/source/libs/executor/src/tfill.c @@ -584,7 +584,7 @@ int64_t getNumOfResultsAfterFillGap(SFillInfo* pFillInfo, TSKEY ekey, int32_t ma 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))) { + (ekey1 >= pFillInfo->currentKey && !FILL_IS_ASC_FILL(pFillInfo))) { return 0; } numOfRes = taosTimeCountInterval(ekey1, pFillInfo->currentKey, pFillInfo->interval.sliding, @@ -706,6 +706,9 @@ void* destroyStreamFillSupporter(SStreamFillSupporter* pFillSup) { pFillSup->pAllColInfo = destroyFillColumnInfo(pFillSup->pAllColInfo, pFillSup->numOfFillCols, pFillSup->numOfAllCols); tSimpleHashCleanup(pFillSup->pResMap); pFillSup->pResMap = NULL; + streamStateReleaseBuf(NULL, NULL, pFillSup->cur.pRowVal); + pFillSup->cur.pRowVal = NULL; + taosMemoryFree(pFillSup); return NULL; } @@ -722,6 +725,7 @@ void* destroyStreamFillInfo(SStreamFillInfo* pFillInfo) { taosMemoryFreeClear(pFillInfo->pResRow); } pFillInfo->pLinearInfo = destroyStreamFillLinearInfo(pFillInfo->pLinearInfo); + taosArrayDestroy(pFillInfo->delRanges); taosMemoryFree(pFillInfo); return NULL; } @@ -732,6 +736,8 @@ void destroyStreamFillOperatorInfo(void* param) { pInfo->pFillSup = destroyStreamFillSupporter(pInfo->pFillSup); pInfo->pRes = blockDataDestroy(pInfo->pRes); pInfo->pSrcBlock = blockDataDestroy(pInfo->pSrcBlock); + pInfo->pPrevSrcBlock = blockDataDestroy(pInfo->pPrevSrcBlock); + pInfo->pDelRes = blockDataDestroy(pInfo->pDelRes); pInfo->pColMatchColInfo = taosArrayDestroy(pInfo->pColMatchColInfo); taosMemoryFree(pInfo); } @@ -743,6 +749,7 @@ static void resetFillWindow(SResultRowData* pRowData) { void resetPrevAndNextWindow(SStreamFillSupporter* pFillSup, SStreamState* pState) { resetFillWindow(&pFillSup->prev); + streamStateReleaseBuf(NULL, NULL, pFillSup->cur.pRowVal); resetFillWindow(&pFillSup->cur); resetFillWindow(&pFillSup->next); resetFillWindow(&pFillSup->nextNext); @@ -753,12 +760,12 @@ void getCurWindowFromDiscBuf(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupI resetPrevAndNextWindow(pFillSup, pState); SWinKey key = {.ts = ts, .groupId = groupId}; - void* curVal = NULL; + // void* curVal = NULL; int32_t curVLen = 0; - int32_t code = streamStateFillGet(pState, &key, (void**)&curVal, &curVLen); + int32_t code = streamStateFillGet(pState, &key, (void**)&pFillSup->cur.pRowVal, &curVLen); ASSERT(code == TSDB_CODE_SUCCESS); pFillSup->cur.key = key.ts; - pFillSup->cur.pRowVal = curVal; + // pFillSup->cur.pRowVal = curVal; } void getWindowFromDiscBuf(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId, SStreamFillSupporter* pFillSup) { @@ -777,11 +784,9 @@ void getWindowFromDiscBuf(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId, SWinKey preKey = {.groupId = groupId}; void* preVal = NULL; int32_t preVLen = 0; - if (pCur) { - code = streamStateGetGroupKVByCur(pCur, &preKey, (const void**)&preVal, &preVLen); - } + code = streamStateGetGroupKVByCur(pCur, &preKey, (const void**)&preVal, &preVLen); - if (pCur && code == TSDB_CODE_SUCCESS) { + if (code == TSDB_CODE_SUCCESS) { pFillSup->prev.key = preKey.ts; pFillSup->prev.pRowVal = preVal; @@ -790,35 +795,36 @@ void getWindowFromDiscBuf(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId, code = streamStateCurNext(pState, pCur); if (code != TSDB_CODE_SUCCESS) { + streamStateFreeCur(pCur); pCur = NULL; } } else { + streamStateFreeCur(pCur); pCur = streamStateFillSeekKeyNext(pState, &key); } - if (pCur) { - SWinKey nextKey = {.groupId = groupId}; - void* nextVal = NULL; - int32_t nextVLen = 0; - code = streamStateGetGroupKVByCur(pCur, &nextKey, (const void**)&nextVal, &nextVLen); - if (code == TSDB_CODE_SUCCESS) { - pFillSup->next.key = nextKey.ts; - pFillSup->next.pRowVal = nextVal; - if (pFillSup->type == TSDB_FILL_PREV || pFillSup->type == TSDB_FILL_NEXT) { - code = streamStateCurNext(pState, pCur); + SWinKey nextKey = {.groupId = groupId}; + void* nextVal = NULL; + int32_t nextVLen = 0; + code = streamStateGetGroupKVByCur(pCur, &nextKey, (const void**)&nextVal, &nextVLen); + if (code == TSDB_CODE_SUCCESS) { + pFillSup->next.key = nextKey.ts; + pFillSup->next.pRowVal = nextVal; + if (pFillSup->type == TSDB_FILL_PREV || pFillSup->type == TSDB_FILL_NEXT) { + code = streamStateCurNext(pState, pCur); + if (code == TSDB_CODE_SUCCESS) { + SWinKey nextNextKey = {.groupId = groupId}; + void* nextNextVal = NULL; + int32_t nextNextVLen = 0; + code = streamStateGetGroupKVByCur(pCur, &nextNextKey, (const void**)&nextNextVal, &nextNextVLen); if (code == TSDB_CODE_SUCCESS) { - SWinKey nextNextKey = {.groupId = groupId}; - void* nextNextVal = NULL; - int32_t nextNextVLen = 0; - code = streamStateGetGroupKVByCur(pCur, &nextNextKey, (const void**)&nextNextVal, &nextNextVLen); - if (code == TSDB_CODE_SUCCESS) { - pFillSup->nextNext.key = nextNextKey.ts; - pFillSup->nextNext.pRowVal = nextNextVal; - } + pFillSup->nextNext.key = nextNextKey.ts; + pFillSup->nextNext.pRowVal = nextNextVal; } } } } + streamStateFreeCur(pCur); } static bool hasPrevWindow(SStreamFillSupporter* pFillSup) { return pFillSup->prev.key != INT64_MIN; } @@ -1388,6 +1394,7 @@ static void doDeleteFillResult(SOperatorInfo* pOperator) { } pInfo->srcDelRowIndex++; } + streamStateFreeCur(pCur); doDeleteFillResultImpl(pOperator, ts, endTs, groupId); } pFillInfo->current = pFillInfo->end + 1; @@ -1538,9 +1545,12 @@ static int32_t initResultBuf(SStreamFillSupporter* pFillSup) { pFillSup->next.key = INT64_MIN; pFillSup->nextNext.key = INT64_MIN; pFillSup->prev.key = INT64_MIN; + pFillSup->cur.key = INT64_MIN; pFillSup->next.pRowVal = NULL; pFillSup->nextNext.pRowVal = NULL; pFillSup->prev.pRowVal = NULL; + pFillSup->cur.pRowVal = NULL; + return TSDB_CODE_SUCCESS; } diff --git a/source/libs/executor/src/timewindowoperator.c b/source/libs/executor/src/timewindowoperator.c index ab72ad97ca..e0a5bbffa4 100644 --- a/source/libs/executor/src/timewindowoperator.c +++ b/source/libs/executor/src/timewindowoperator.c @@ -414,14 +414,17 @@ static bool setTimeWindowInterpolationEndTs(SIntervalAggOperatorInfo* pInfo, SEx return true; } -bool inSlidingWindow(SInterval* pInterval, STimeWindow* pWin, SDataBlockInfo* pBlockInfo) { - if (pInterval->interval != pInterval->sliding && - (pWin->ekey < pBlockInfo->calWin.skey || pWin->skey > pBlockInfo->calWin.ekey)) { +bool inCalSlidingWindow(SInterval* pInterval, STimeWindow* pWin, TSKEY calStart, TSKEY calEnd) { + if (pInterval->interval != pInterval->sliding && (pWin->ekey < calStart || pWin->skey > calEnd)) { return false; } return true; } +bool inSlidingWindow(SInterval* pInterval, STimeWindow* pWin, SDataBlockInfo* pBlockInfo) { + return inCalSlidingWindow(pInterval, pWin, pBlockInfo->calWin.skey, pBlockInfo->calWin.ekey); +} + static int32_t getNextQualifiedWindow(SInterval* pInterval, STimeWindow* pNext, SDataBlockInfo* pDataBlockInfo, TSKEY* primaryKeys, int32_t prevPosition, int32_t order) { bool ascQuery = (order == TSDB_ORDER_ASC); @@ -879,7 +882,12 @@ static void removeResults(SArray* pWins, SHashObj* pUpdatedMap) { int32_t size = taosArrayGetSize(pWins); for (int32_t i = 0; i < size; i++) { SWinKey* pW = taosArrayGet(pWins, i); - taosHashRemove(pUpdatedMap, pW, sizeof(SWinKey)); + void* tmp = taosHashGet(pUpdatedMap, pW, sizeof(SWinKey)); + if (tmp) { + void* value = *(void**)tmp; + taosMemoryFree(value); + taosHashRemove(pUpdatedMap, pW, sizeof(SWinKey)); + } } } @@ -907,6 +915,8 @@ int32_t compareWinRes(void* pKey, void* data, int32_t index) { } static void removeDeleteResults(SHashObj* pUpdatedMap, SArray* pDelWins) { + taosArraySort(pDelWins, sWinKeyCmprImpl); + taosArrayRemoveDuplicate(pDelWins, sWinKeyCmprImpl, NULL); int32_t delSize = taosArrayGetSize(pDelWins); if (taosHashGetSize(pUpdatedMap) == 0 || delSize == 0) { return; @@ -1382,7 +1392,7 @@ static bool doClearWindow(SAggSupporter* pAggSup, SExprSupp* pSup, char* pData, return true; } -static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId, int32_t numOfOutput) { +static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId) { SStreamIntervalOperatorInfo* pInfo = pOperator->info; SWinKey key = {.ts = ts, .groupId = groupId}; tSimpleHashRemove(pInfo->aggSup.pResultRowHashTable, &key, sizeof(SWinKey)); @@ -1390,27 +1400,48 @@ static bool doDeleteWindow(SOperatorInfo* pOperator, TSKEY ts, uint64_t groupId, return true; } -static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, int32_t numOfOutput, SSDataBlock* pBlock, - SArray* pUpWins, SHashObj* pUpdatedMap) { - SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX); - TSKEY* startTsCols = (TSKEY*)pStartTsCol->pData; - SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX); - TSKEY* endTsCols = (TSKEY*)pEndTsCol->pData; - SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX); - uint64_t* pGpDatas = (uint64_t*)pGpCol->pData; +static void doDeleteWindows(SOperatorInfo* pOperator, SInterval* pInterval, SSDataBlock* pBlock, SArray* pUpWins, + SHashObj* pUpdatedMap) { + SStreamIntervalOperatorInfo* pInfo = pOperator->info; + SColumnInfoData* pStartTsCol = taosArrayGet(pBlock->pDataBlock, START_TS_COLUMN_INDEX); + TSKEY* startTsCols = (TSKEY*)pStartTsCol->pData; + SColumnInfoData* pEndTsCol = taosArrayGet(pBlock->pDataBlock, END_TS_COLUMN_INDEX); + TSKEY* endTsCols = (TSKEY*)pEndTsCol->pData; + SColumnInfoData* pCalStTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_START_TS_COLUMN_INDEX); + TSKEY* calStTsCols = (TSKEY*)pCalStTsCol->pData; + SColumnInfoData* pCalEnTsCol = taosArrayGet(pBlock->pDataBlock, CALCULATE_END_TS_COLUMN_INDEX); + TSKEY* calEnTsCols = (TSKEY*)pCalEnTsCol->pData; + SColumnInfoData* pGpCol = taosArrayGet(pBlock->pDataBlock, GROUPID_COLUMN_INDEX); + uint64_t* pGpDatas = (uint64_t*)pGpCol->pData; for (int32_t i = 0; i < pBlock->info.rows; i++) { SResultRowInfo dumyInfo; dumyInfo.cur.pageId = -1; - STimeWindow win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC); + STimeWindow win = {0}; + if (IS_FINAL_OP(pInfo)) { + win.skey = startTsCols[i]; + win.ekey = endTsCols[i]; + } else { + win = getActiveTimeWindow(NULL, &dumyInfo, startTsCols[i], pInterval, TSDB_ORDER_ASC); + } + do { + if (!inCalSlidingWindow(pInterval, &win, calStTsCols[i], calEnTsCols[i])) { + getNextTimeWindow(pInterval, pInterval->precision, TSDB_ORDER_ASC, &win); + continue; + } uint64_t winGpId = pGpDatas[i]; - bool res = doDeleteWindow(pOperator, win.skey, winGpId, numOfOutput); + bool res = doDeleteWindow(pOperator, win.skey, winGpId); SWinKey winRes = {.ts = win.skey, .groupId = winGpId}; if (pUpWins && res) { taosArrayPush(pUpWins, &winRes); } if (pUpdatedMap) { - taosHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey)); + void* tmp = taosHashGet(pUpdatedMap, &winRes, sizeof(SWinKey)); + if (tmp) { + void* value = *(void**)tmp; + taosMemoryFree(value); + taosHashRemove(pUpdatedMap, &winRes, sizeof(SWinKey)); + } } getNextTimeWindow(pInterval, pInterval->precision, TSDB_ORDER_ASC, &win); } while (win.ekey <= endTsCols[i]); @@ -1501,16 +1532,43 @@ 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* pos = taosArrayGet(res, index); + SWinKey* pData = (SWinKey*)pKey; + if (pData->ts == pos->ts) { + if (pData->groupId > pos->groupId) { + return 1; + } else if (pData->groupId < pos->groupId) { + return -1; + } + return 0; + } else if (pData->ts > pos->ts) { + return 1; + } + return -1; +} + static int32_t closeStreamIntervalWindow(SSHashObj* pHashMap, STimeWindowAggSupp* pTwSup, SInterval* pInterval, - SHashObj* pPullDataMap, SHashObj* closeWins, SOperatorInfo* pOperator) { + SHashObj* pPullDataMap, SHashObj* 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); - SWinKey* pWinKey = (SWinKey*)key; + void* key = tSimpleHashGetKey(pIte, &keyLen); + SWinKey* pWinKey = (SWinKey*)key; + if (delSize > 0) { + int32_t index = binarySearchCom(pDelWins, delSize, pWinKey, TSDB_ORDER_DESC, compareWinKey); + if (index >= 0 && 0 == compareWinKey(pWinKey, pDelWins, index)) { + taosArrayRemove(pDelWins, index); + delSize = taosArrayGetSize(pDelWins); + } + } + void* chIds = taosHashGet(pPullDataMap, pWinKey, sizeof(SWinKey)); STimeWindow win = { .skey = pWinKey->ts, @@ -1615,7 +1673,7 @@ static void closeChildIntervalWindow(SOperatorInfo* pOperator, SArray* pChildren ASSERT(pChInfo->twAggSup.calTrigger == STREAM_TRIGGER_AT_ONCE); pChInfo->twAggSup.maxTs = TMAX(pChInfo->twAggSup.maxTs, maxTs); closeStreamIntervalWindow(pChInfo->aggSup.pResultRowHashTable, &pChInfo->twAggSup, &pChInfo->interval, NULL, NULL, - pOperator); + NULL, pOperator); } } @@ -1685,7 +1743,6 @@ void destroyStreamFinalIntervalOperatorInfo(void* param) { taosHashCleanup(pInfo->pPullDataMap); taosArrayDestroy(pInfo->pPullWins); blockDataDestroy(pInfo->pPullDataRes); - blockDataDestroy(pInfo->pUpdateRes); taosArrayDestroy(pInfo->pDelWins); blockDataDestroy(pInfo->pDelRes); taosMemoryFreeClear(pInfo->pState); @@ -2853,11 +2910,7 @@ static void rebuildIntervalWindow(SOperatorInfo* pOperator, SExprSupp* pSup, SAr isCloseWindow(&parentWin, &pInfo->twAggSup)) { continue; } - int32_t code = setOutputBuf(pInfo->pState, &parentWin, &pCurResult, pWinRes->groupId, pSup->pCtx, numOfOutput, - pSup->rowEntryInfoOffset, &pInfo->aggSup); - if (code != TSDB_CODE_SUCCESS || pCurResult == NULL) { - T_LONG_JMP(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY); - } + int32_t numOfChildren = taosArrayGetSize(pInfo->pChildren); int32_t num = 0; for (int32_t j = 0; j < numOfChildren; j++) { @@ -2867,6 +2920,13 @@ static void rebuildIntervalWindow(SOperatorInfo* pOperator, SExprSupp* pSup, SAr if (!hasIntervalWindow(pChInfo->pState, pWinRes)) { continue; } + if (num == 0) { + int32_t code = setOutputBuf(pInfo->pState, &parentWin, &pCurResult, pWinRes->groupId, pSup->pCtx, numOfOutput, + pSup->rowEntryInfoOffset, &pInfo->aggSup); + if (code != TSDB_CODE_SUCCESS || pCurResult == NULL) { + T_LONG_JMP(pTaskInfo->env, TSDB_CODE_QRY_OUT_OF_MEMORY); + } + } num++; SResultRow* pChResult = NULL; setOutputBuf(pChInfo->pState, &parentWin, &pChResult, pWinRes->groupId, pChildSup->pCtx, pChildSup->numOfExprs, @@ -2892,9 +2952,7 @@ bool isDeletedWindow(STimeWindow* pWin, uint64_t groupId, SAggSupporter* pSup) { 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}; - void* pVal = NULL; - int32_t size = 0; - if (streamStateGet(pState, &key, &pVal, &size) == TSDB_CODE_SUCCESS) { + if (streamStateGet(pState, &key, NULL, 0) == TSDB_CODE_SUCCESS) { return false; } return true; @@ -3206,25 +3264,19 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { return NULL; } else { if (!IS_FINAL_OP(pInfo)) { + doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes); + if (pInfo->pDelRes->info.rows != 0) { + // process the rest of the data + printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); + return pInfo->pDelRes; + } + doBuildResult(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; } } - if (pInfo->pUpdateRes->info.rows != 0 && pInfo->returnUpdate) { - pInfo->returnUpdate = false; - ASSERT(!IS_FINAL_OP(pInfo)); - printDataBlock(pInfo->pUpdateRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); - // process the rest of the data - return pInfo->pUpdateRes; - } - doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes); - if (pInfo->pDelRes->info.rows != 0) { - // process the rest of the data - printDataBlock(pInfo->pDelRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); - return pInfo->pDelRes; - } } SArray* pUpdated = taosArrayInit(4, POINTER_BYTES); @@ -3233,50 +3285,25 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { while (1) { SSDataBlock* pBlock = downstream->fpSet.getNextFn(downstream); if (pBlock == NULL) { - clearSpecialDataBlock(pInfo->pUpdateRes); - removeDeleteResults(pUpdatedMap, pInfo->pDelWins); pOperator->status = OP_RES_TO_RETURN; qDebug("%s return data", IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); break; } printDataBlock(pBlock, IS_FINAL_OP(pInfo) ? "interval final recv" : "interval semi recv"); - if (pBlock->info.parTbName[0]) { - taosHashPut(pInfo->pGroupIdTbNameMap, &pBlock->info.groupId, sizeof(int64_t), &pBlock->info.parTbName, - TSDB_TABLE_NAME_LEN); - } - ASSERT(pBlock->info.type != STREAM_INVERT); if (pBlock->info.type == STREAM_NORMAL || pBlock->info.type == STREAM_PULL_DATA) { pInfo->binfo.pRes->info.type = pBlock->info.type; - } else if (pBlock->info.type == STREAM_CLEAR) { - SArray* pUpWins = taosArrayInit(8, sizeof(SWinKey)); - doDeleteWindows(pOperator, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, pUpWins, NULL); - 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, pChildOp->exprSupp.numOfExprs, pBlock, NULL, NULL); - rebuildIntervalWindow(pOperator, pSup, pUpWins, pUpdatedMap); - taosArrayDestroy(pUpWins); - continue; - } - removeResults(pUpWins, pUpdatedMap); - copyDataBlock(pInfo->pUpdateRes, pBlock); - pInfo->returnUpdate = true; - taosArrayDestroy(pUpWins); - break; - } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT) { + } 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, pOperator->exprSupp.numOfExprs, pBlock, delWins, pUpdatedMap); + doDeleteWindows(pOperator, &pInfo->interval, pBlock, delWins, 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, pChildOp->exprSupp.numOfExprs, pBlock, NULL, NULL); + doDeleteWindows(pChildOp, &pChildInfo->interval, pBlock, NULL, NULL); rebuildIntervalWindow(pOperator, pSup, delWins, pUpdatedMap); addRetriveWindow(delWins, pInfo); taosArrayAddAll(pInfo->pDelWins, delWins); @@ -3291,7 +3318,7 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdatedMap); continue; } else if (pBlock->info.type == STREAM_RETRIEVE && !IS_FINAL_OP(pInfo)) { - doDeleteWindows(pOperator, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, NULL, pUpdatedMap); + doDeleteWindows(pOperator, &pInfo->interval, pBlock, NULL, pUpdatedMap); if (taosArrayGetSize(pUpdated) > 0) { break; } @@ -3331,11 +3358,12 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { minTs = TMIN(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); if (IS_FINAL_OP(pInfo)) { closeStreamIntervalWindow(pInfo->aggSup.pResultRowHashTable, &pInfo->twAggSup, &pInfo->interval, - pInfo->pPullDataMap, pUpdatedMap, pOperator); + pInfo->pPullDataMap, pUpdatedMap, pInfo->pDelWins, pOperator); closeChildIntervalWindow(pOperator, pInfo->pChildren, pInfo->twAggSup.maxTs); } pInfo->binfo.pRes->info.watermark = pInfo->twAggSup.maxTs; @@ -3371,13 +3399,6 @@ static SSDataBlock* doStreamFinalIntervalAgg(SOperatorInfo* pOperator) { return pInfo->binfo.pRes; } - if (pInfo->pUpdateRes->info.rows != 0 && pInfo->returnUpdate) { - pInfo->returnUpdate = false; - ASSERT(!IS_FINAL_OP(pInfo)); - printDataBlock(pInfo->pUpdateRes, IS_FINAL_OP(pInfo) ? "interval final" : "interval semi"); - // process the rest of the data - return pInfo->pUpdateRes; - } return NULL; } @@ -3452,9 +3473,6 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, goto _error; } } - pInfo->pUpdateRes = createSpecialDataBlock(STREAM_CLEAR); - blockDataEnsureCapacity(pInfo->pUpdateRes, 128); - pInfo->returnUpdate = false; pInfo->pPhyNode = (SPhysiNode*)nodesCloneNode((SNode*)pPhyNode); @@ -3483,9 +3501,6 @@ SOperatorInfo* createStreamFinalIntervalOperatorInfo(SOperatorInfo* downstream, pInfo->delKey.ts = INT64_MAX; pInfo->delKey.groupId = 0; - pInfo->pGroupIdTbNameMap = - taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK); - pOperator->operatorType = pPhyNode->type; pOperator->blocking = true; pOperator->status = OP_NOT_OPENED; @@ -4276,23 +4291,6 @@ static void removeSessionResults(SHashObj* pHashMap, SArray* pWins) { } } -int32_t compareWinKey(void* pKey, void* data, int32_t index) { - SArray* res = (SArray*)data; - SResKeyPos* pos = taosArrayGetP(res, index); - SWinKey* pData = (SWinKey*)pKey; - if (pData->ts == *(int64_t*)pos->key) { - if (pData->groupId > pos->groupId) { - return 1; - } else if (pData->groupId < pos->groupId) { - return -1; - } - return 0; - } else if (pData->ts > *(int64_t*)pos->key) { - return 1; - } - return -1; -} - static void removeSessionDeleteResults(SArray* update, SHashObj* pStDeleted) { int32_t size = taosHashGetSize(pStDeleted); if (size == 0) { @@ -5668,18 +5666,9 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { } printDataBlock(pBlock, "single interval recv"); - if (pBlock->info.parTbName[0]) { - taosHashPut(pInfo->pGroupIdTbNameMap, &pBlock->info.groupId, sizeof(int64_t), &pBlock->info.parTbName, - TSDB_TABLE_NAME_LEN); - } - - if (pBlock->info.type == STREAM_CLEAR) { - doDeleteWindows(pOperator, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, NULL, NULL); - qDebug("%s clear existed time window results for updates checked", GET_TASKID(pTaskInfo)); - continue; - } else if (pBlock->info.type == STREAM_DELETE_DATA || pBlock->info.type == STREAM_DELETE_RESULT) { - doDeleteWindows(pOperator, &pInfo->interval, pOperator->exprSupp.numOfExprs, pBlock, pInfo->pDelWins, - pUpdatedMap); + 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); continue; } else if (pBlock->info.type == STREAM_GET_ALL) { getAllIntervalWindow(pInfo->aggSup.pResultRowHashTable, pUpdatedMap); @@ -5711,8 +5700,9 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { 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, - pOperator); + pInfo->pDelWins, pOperator); void* pIte = NULL; while ((pIte = taosHashIterate(pUpdatedMap, pIte)) != NULL) { @@ -5722,7 +5712,6 @@ static SSDataBlock* doStreamIntervalAgg(SOperatorInfo* pOperator) { initMultiResInfoFromArrayList(&pInfo->groupResInfo, pUpdated); blockDataEnsureCapacity(pInfo->binfo.pRes, pOperator->resultInfo.capacity); - removeDeleteResults(pUpdatedMap, pInfo->pDelWins); taosHashCleanup(pUpdatedMap); doBuildDeleteResult(pInfo->pDelWins, &pInfo->delIndex, pInfo->pDelRes); @@ -5808,8 +5797,6 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhys *(pInfo->pState) = *(pTaskInfo->streamInfo.pState); streamStateSetNumber(pInfo->pState, -1); - pInfo->pUpdateRes = NULL; - pInfo->returnUpdate = false; pInfo->pPhyNode = NULL; // create new child pInfo->pPullDataMap = NULL; pInfo->pPullWins = NULL; // SPullWindowInfo @@ -5820,9 +5807,6 @@ SOperatorInfo* createStreamIntervalOperatorInfo(SOperatorInfo* downstream, SPhys pInfo->delKey.ts = INT64_MAX; pInfo->delKey.groupId = 0; - pInfo->pGroupIdTbNameMap = - taosHashInit(1024, taosGetDefaultHashFunction(TSDB_DATA_TYPE_UBIGINT), false, HASH_NO_LOCK); - pOperator->name = "StreamIntervalOperator"; pOperator->operatorType = QUERY_NODE_PHYSICAL_PLAN_STREAM_INTERVAL; pOperator->blocking = true; diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 42512d3a11..d91423ab5c 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -1251,12 +1251,12 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { } } } else if (type == TSDB_DATA_TYPE_FLOAT) { - double prev = 0; - GET_TYPED_DATA(prev, double, type, &pBuf->v); + float prev = 0; + GET_TYPED_DATA(prev, float, type, &pBuf->v); - double val = GET_DOUBLE_VAL(tval); + float val = GET_DOUBLE_VAL(tval); if ((prev < val) ^ isMinFunc) { - *(double*)&pBuf->v = val; + *(float*)&pBuf->v = val; } if (pCtx->subsidiaries.num > 0) { diff --git a/source/libs/function/src/udfd.c b/source/libs/function/src/udfd.c index 8ff0dc15a5..14e358ea00 100644 --- a/source/libs/function/src/udfd.c +++ b/source/libs/function/src/udfd.c @@ -959,8 +959,8 @@ int32_t udfdInitResidentFuncs() { char* pSave = tsUdfdResFuncs; char* token; while ((token = strtok_r(pSave, ",", &pSave)) != NULL) { - char func[TSDB_FUNC_NAME_LEN] = {0}; - strncpy(func, token, sizeof(func)); + char func[TSDB_FUNC_NAME_LEN+1] = {0}; + strncpy(func, token, TSDB_FUNC_NAME_LEN); taosArrayPush(global.residentFuncs, func); } diff --git a/source/libs/stream/src/streamMeta.c b/source/libs/stream/src/streamMeta.c index 1442ed2e05..63a28e17ed 100644 --- a/source/libs/stream/src/streamMeta.c +++ b/source/libs/stream/src/streamMeta.c @@ -32,7 +32,7 @@ SStreamMeta* streamMetaOpen(const char* path, void* ahandle, FTaskExpand expandF } sprintf(streamPath, "%s/%s", pMeta->path, "checkpoints"); - mkdir(streamPath, 0755); + taosMulModeMkDir(streamPath, 0755); taosMemoryFree(streamPath); if (tdbTbOpen("task.db", sizeof(int32_t), -1, NULL, pMeta->db, &pMeta->pTaskDb) < 0) { diff --git a/source/libs/stream/src/streamState.c b/source/libs/stream/src/streamState.c index 8c851127dd..24c5defee5 100644 --- a/source/libs/stream/src/streamState.c +++ b/source/libs/stream/src/streamState.c @@ -24,7 +24,7 @@ typedef struct SStateKey { int64_t opNum; } SStateKey; -static inline int SStateKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { +static inline int stateKeyCmpr(const void* pKey1, int kLen1, const void* pKey2, int kLen2) { SStateKey* pWin1 = (SStateKey*)pKey1; SStateKey* pWin2 = (SStateKey*)pKey2; @@ -68,12 +68,12 @@ SStreamState* streamStateOpen(char* path, SStreamTask* pTask, bool specPath) { } // open state storage backend - if (tdbTbOpen("state.db", sizeof(SStateKey), -1, SStateKeyCmpr, pState->db, &pState->pStateDb) < 0) { + if (tdbTbOpen("state.db", sizeof(SStateKey), -1, stateKeyCmpr, pState->db, &pState->pStateDb) < 0) { goto _err; } // todo refactor - if (tdbTbOpen("func.state.db", sizeof(SWinKey), -1, SWinKeyCmpr, pState->db, &pState->pFillStateDb) < 0) { + if (tdbTbOpen("func.state.db", sizeof(SWinKey), -1, winKeyCmpr, pState->db, &pState->pFillStateDb) < 0) { goto _err; } @@ -197,6 +197,7 @@ int32_t streamStateClear(SStreamState* pState) { SStreamStateCur* pCur = streamStateSeekKeyNext(pState, &key); SWinKey delKey = {0}; int32_t code = streamStateGetKVByCur(pCur, &delKey, NULL, 0); + streamStateFreeCur(pCur); if (code == 0) { streamStateDel(pState, &delKey); } else { @@ -226,6 +227,9 @@ int32_t streamStateAddIfNotExist(SStreamState* pState, const SWinKey* key, void* int32_t streamStateReleaseBuf(SStreamState* pState, const SWinKey* key, void* pVal) { // todo refactor + if (!pVal) { + return 0; + } streamFreeVal(pVal); return 0; } @@ -237,7 +241,7 @@ SStreamStateCur* streamStateGetCur(SStreamState* pState, const SWinKey* key) { int32_t c; SStateKey sKey = {.key = *key, .opNum = pState->number}; - tdbTbcMoveTo(pCur->pCur, key, sizeof(SWinKey), &c); + tdbTbcMoveTo(pCur->pCur, &sKey, sizeof(SStateKey), &c); if (c != 0) { taosMemoryFree(pCur); return NULL; @@ -254,7 +258,7 @@ SStreamStateCur* streamStateFillGetCur(SStreamState* pState, const SWinKey* key) int32_t c; tdbTbcMoveTo(pCur->pCur, key, sizeof(SWinKey), &c); if (c != 0) { - taosMemoryFree(pCur); + streamStateFreeCur(pCur); return NULL; } return pCur; @@ -267,6 +271,7 @@ SStreamStateCur* streamStateGetAndCheckCur(SStreamState* pState, SWinKey* key) { if (code == 0) { return pCur; } + streamStateFreeCur(pCur); } return NULL; } @@ -301,6 +306,9 @@ int32_t streamStateFillGetKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const vo } int32_t streamStateGetGroupKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen) { + if (!pCur) { + return -1; + } uint64_t groupId = pKey->groupId; int32_t code = streamStateFillGetKVByCur(pCur, pKey, pVal, pVLen); if (code == 0) { @@ -361,7 +369,7 @@ SStreamStateCur* streamStateSeekKeyNext(SStreamState* pState, const SWinKey* key SStreamStateCur* streamStateFillSeekKeyNext(SStreamState* pState, const SWinKey* key) { SStreamStateCur* pCur = taosMemoryCalloc(1, sizeof(SStreamStateCur)); - if (pCur == NULL) { + if (!pCur) { return NULL; } if (tdbTbcOpen(pState->pFillStateDb, &pCur->pCur, NULL) < 0) { @@ -412,6 +420,9 @@ SStreamStateCur* streamStateFillSeekKeyPrev(SStreamState* pState, const SWinKey* } int32_t streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur) { + if (!pCur) { + return -1; + } // return tdbTbcMoveToNext(pCur->pCur); } diff --git a/source/libs/tdb/src/db/tdbDb.c b/source/libs/tdb/src/db/tdbDb.c index cc8bdca75d..42aeeae19a 100644 --- a/source/libs/tdb/src/db/tdbDb.c +++ b/source/libs/tdb/src/db/tdbDb.c @@ -62,7 +62,7 @@ int32_t tdbOpen(const char *dbname, int32_t szPage, int32_t pages, TDB **ppDb) { } memset(pDb->pgrHash, 0, tsize); - mkdir(dbname, 0755); + taosMulModeMkDir(dbname, 0755); #ifdef USE_MAINDB // open main db diff --git a/source/os/src/osDir.c b/source/os/src/osDir.c index cf74525543..0cc946ac21 100644 --- a/source/os/src/osDir.c +++ b/source/os/src/osDir.c @@ -121,6 +121,8 @@ int32_t taosMkDir(const char *dirname) { if (taosDirExist(dirname)) return 0; #ifdef WINDOWS int32_t code = _mkdir(dirname, 0755); +#elif defined(DARWIN) + int32_t code = mkdir(dirname, 0777); #else int32_t code = mkdir(dirname, 0755); #endif @@ -156,6 +158,8 @@ int32_t taosMulMkDir(const char *dirname) { *pos = '\0'; #ifdef WINDOWS code = _mkdir(temp, 0755); +#elif defined(DARWIN) + code = mkdir(dirname, 0777); #else code = mkdir(temp, 0755); #endif @@ -170,6 +174,8 @@ int32_t taosMulMkDir(const char *dirname) { if (*(pos - 1) != TD_DIRSEP[0]) { #ifdef WINDOWS code = _mkdir(temp, 0755); +#elif defined(DARWIN) + code = mkdir(dirname, 0777); #else code = mkdir(temp, 0755); #endif @@ -179,7 +185,6 @@ int32_t taosMulMkDir(const char *dirname) { } } - // int32_t code = mkdir(dirname, 0755); if (code < 0 && errno == EEXIST) { return 0; } @@ -215,6 +220,8 @@ int32_t taosMulModeMkDir(const char *dirname, int mode) { *pos = '\0'; #ifdef WINDOWS code = _mkdir(temp, mode); +#elif defined(DARWIN) + code = mkdir(dirname, 0777); #else code = mkdir(temp, mode); #endif @@ -229,6 +236,8 @@ int32_t taosMulModeMkDir(const char *dirname, int mode) { if (*(pos - 1) != TD_DIRSEP[0]) { #ifdef WINDOWS code = _mkdir(temp, mode); +#elif defined(DARWIN) + code = mkdir(dirname, 0777); #else code = mkdir(temp, mode); #endif diff --git a/source/os/src/osEnv.c b/source/os/src/osEnv.c index 8f6800c7be..9511230f8d 100644 --- a/source/os/src/osEnv.c +++ b/source/os/src/osEnv.c @@ -59,34 +59,18 @@ void osDefaultInit() { if (tmpDir != NULL) { strcpy(tsTempDir, tmpDir); } - - if (configDir[0] == 0) { - strcpy(configDir, "C:\\TDengine\\cfg"); - } - strcpy(tsDataDir, "C:\\TDengine\\data"); - strcpy(tsLogDir, "C:\\TDengine\\log"); - strcpy(tsTempDir, "C:\\Windows\\Temp"); strcpy(tsOsName, "Windows"); - #elif defined(_TD_DARWIN_64) - if (configDir[0] == 0) { - strcpy(configDir, "/usr/local/etc/taos"); - } - strcpy(tsDataDir, "/usr/local/var/lib/taos"); - strcpy(tsLogDir, "/usr/local/var/log/taos"); - strcpy(tsTempDir, "/tmp/taosd"); strcpy(tsOsName, "Darwin"); - #else - if (configDir[0] == 0) { - strcpy(configDir, "/etc/taos"); - } - strcpy(tsDataDir, "/var/lib/taos"); - strcpy(tsLogDir, "/var/log/taos"); - strcpy(tsTempDir, "/tmp"); strcpy(tsOsName, "Linux"); - #endif + if (configDir[0] == 0) { + strcpy(configDir, TD_CFG_DIR_PATH); + } + strcpy(tsDataDir, TD_DATA_DIR_PATH); + strcpy(tsLogDir, TD_LOG_DIR_PATH); + strcpy(tsTempDir, TD_TMP_DIR_PATH); } void osUpdate() { diff --git a/source/os/src/osSysinfo.c b/source/os/src/osSysinfo.c index a57bd4ee63..f5f02676af 100644 --- a/source/os/src/osSysinfo.c +++ b/source/os/src/osSysinfo.c @@ -154,8 +154,8 @@ static int32_t taosGetSysCpuInfo(SysCpuInfo *cpuInfo) { return -1; } - char *line = NULL; - ssize_t _bytes = taosGetLineFile(pFile, &line); + char line[1024]; + ssize_t _bytes = taosGetsFile(pFile, sizeof(line), line); if ((_bytes < 0) || (line == NULL)) { taosCloseFile(&pFile); return -1; @@ -165,7 +165,6 @@ static int32_t taosGetSysCpuInfo(SysCpuInfo *cpuInfo) { sscanf(line, "%s %" PRIu64 " %" PRIu64 " %" PRIu64 " %" PRIu64, cpu, &cpuInfo->user, &cpuInfo->nice, &cpuInfo->system, &cpuInfo->idle); - if (line != NULL) taosMemoryFreeClear(line); taosCloseFile(&pFile); #endif return 0; @@ -194,8 +193,8 @@ static int32_t taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) { return -1; } - char *line = NULL; - ssize_t _bytes = taosGetLineFile(pFile, &line); + char line[1024]; + ssize_t _bytes = taosGetsFile(pFile, sizeof(line), line); if ((_bytes < 0) || (line == NULL)) { taosCloseFile(&pFile); return -1; @@ -210,7 +209,6 @@ static int32_t taosGetProcCpuInfo(ProcCpuInfo *cpuInfo) { } } - if (line != NULL) taosMemoryFreeClear(line); taosCloseFile(&pFile); #endif return 0; @@ -286,14 +284,14 @@ int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { snprintf(releaseName, maxLen, "Windows"); return 0; #elif defined(_TD_DARWIN_64) - char *line = NULL; + char line[1024]; size_t size = 0; int32_t code = -1; TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) return false; - while ((size = taosGetLineFile(pFile, &line)) != -1) { + while ((size = taosGetsFile(pFile, sizeof(line), line)) != -1) { line[size - 1] = '\0'; if (strncmp(line, "PRETTY_NAME", 11) == 0) { const char *p = strchr(line, '=') + 1; @@ -307,18 +305,17 @@ int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { } } - if (line != NULL) taosMemoryFree(line); taosCloseFile(&pFile); return code; #else - char *line = NULL; + char line[1024]; size_t size = 0; int32_t code = -1; TdFilePtr pFile = taosOpenFile("/etc/os-release", TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) return false; - while ((size = taosGetLineFile(pFile, &line)) != -1) { + while ((size = taosGetsFile(pFile, sizeof(line), line)) != -1) { line[size - 1] = '\0'; if (strncmp(line, "PRETTY_NAME", 11) == 0) { const char *p = strchr(line, '=') + 1; @@ -332,7 +329,6 @@ int32_t taosGetOsReleaseName(char *releaseName, int32_t maxLen) { } } - if (line != NULL) taosMemoryFree(line); taosCloseFile(&pFile); return code; #endif @@ -374,7 +370,7 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { return code; #else - char *line = NULL; + char line[1024]; size_t size = 0; int32_t done = 0; int32_t code = -1; @@ -383,7 +379,7 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { TdFilePtr pFile = taosOpenFile("/proc/cpuinfo", TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) return code; - while (done != 3 && (size = taosGetLineFile(pFile, &line)) != -1) { + while (done != 3 && (size = taosGetsFile(pFile, sizeof(line), line)) != -1) { line[size - 1] = '\0'; if (((done & 1) == 0) && strncmp(line, "model name", 10) == 0) { const char *v = strchr(line, ':') + 2; @@ -398,7 +394,6 @@ int32_t taosGetCpuInfo(char *cpuModel, int32_t maxLen, float *numOfCores) { if (strncmp(line, "processor", 9) == 0) coreCount += 1; } - if (line != NULL) taosMemoryFree(line); taosCloseFile(&pFile); if (code != 0 && (done & 1) == 0) { @@ -517,9 +512,9 @@ int32_t taosGetProcMemory(int64_t *usedKB) { } ssize_t _bytes = 0; - char *line = NULL; + char line[1024]; while (!taosEOFFile(pFile)) { - _bytes = taosGetLineFile(pFile, &line); + _bytes = taosGetsFile(pFile, sizeof(line), line); if ((_bytes < 0) || (line == NULL)) { break; } @@ -537,7 +532,6 @@ int32_t taosGetProcMemory(int64_t *usedKB) { char tmp[10]; sscanf(line, "%s %" PRId64, tmp, usedKB); - if (line != NULL) taosMemoryFreeClear(line); taosCloseFile(&pFile); return 0; #endif @@ -631,12 +625,12 @@ int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int if (pFile == NULL) return -1; ssize_t _bytes = 0; - char *line = NULL; + char line[1024]; char tmp[24]; int readIndex = 0; while (!taosEOFFile(pFile)) { - _bytes = taosGetLineFile(pFile, &line); + _bytes = taosGetsFile(pFile, sizeof(line), line); if (_bytes < 10 || line == NULL) { break; } @@ -658,7 +652,6 @@ int32_t taosGetProcIO(int64_t *rchars, int64_t *wchars, int64_t *read_bytes, int if (readIndex >= 4) break; } - if (line != NULL) taosMemoryFreeClear(line); taosCloseFile(&pFile); if (readIndex < 4) { @@ -709,7 +702,7 @@ int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { if (pFile == NULL) return -1; ssize_t _bytes = 0; - char *line = NULL; + char line[1024]; while (!taosEOFFile(pFile)) { int64_t o_rbytes = 0; @@ -724,7 +717,7 @@ int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { int64_t nouse6 = 0; char nouse0[200] = {0}; - _bytes = taosGetLineFile(pFile, &line); + _bytes = taosGetsFile(pFile, sizeof(line), line); if (_bytes < 0) { break; } @@ -743,7 +736,6 @@ int32_t taosGetCardInfo(int64_t *receive_bytes, int64_t *transmit_bytes) { *transmit_bytes = o_tbytes; } - if (line != NULL) taosMemoryFreeClear(line); taosCloseFile(&pFile); return 0; diff --git a/source/util/src/tarray.c b/source/util/src/tarray.c index 4f170c203c..4e9ac0e0de 100644 --- a/source/util/src/tarray.c +++ b/source/util/src/tarray.c @@ -468,12 +468,11 @@ static int32_t taosArrayPartition(SArray* pArray, int32_t i, int32_t j, __ext_co return i; } -static void taosArrayQuicksortHelper(SArray* pArray, int32_t low, int32_t high, __ext_compar_fn_t fn, - const void* param) { +static void taosArrayQuicksortImpl(SArray* pArray, int32_t low, int32_t high, __ext_compar_fn_t fn, const void* param) { if (low < high) { int32_t idx = taosArrayPartition(pArray, low, high, fn, param); - taosArrayQuicksortHelper(pArray, low, idx - 1, fn, param); - taosArrayQuicksortHelper(pArray, idx + 1, high, fn, param); + taosArrayQuicksortImpl(pArray, low, idx - 1, fn, param); + taosArrayQuicksortImpl(pArray, idx + 1, high, fn, param); } } @@ -481,7 +480,7 @@ static void taosArrayQuickSort(SArray* pArray, __ext_compar_fn_t fn, const void* if (pArray->size <= 1) { return; } - taosArrayQuicksortHelper(pArray, 0, (int32_t)(taosArrayGetSize(pArray) - 1), fn, param); + taosArrayQuicksortImpl(pArray, 0, (int32_t)(taosArrayGetSize(pArray) - 1), fn, param); } static void taosArrayInsertSort(SArray* pArray, __ext_compar_fn_t fn, const void* param) { @@ -564,3 +563,21 @@ char* taosShowStrArray(const SArray* pArray) { } return res; } +void taosArraySwap(SArray* a, SArray* b) { + if (a == NULL || b == NULL) return; + size_t t = a->size; + a->size = b->size; + b->size = t; + + uint32_t cap = a->capacity; + a->capacity = b->capacity; + b->capacity = cap; + + uint32_t elem = a->elemSize; + a->elemSize = b->elemSize; + b->elemSize = elem; + + void* data = a->pData; + a->pData = b->pData; + b->pData = data; +} diff --git a/source/util/src/tconfig.c b/source/util/src/tconfig.c index 2a28ec66d2..58f90b68c9 100644 --- a/source/util/src/tconfig.c +++ b/source/util/src/tconfig.c @@ -714,7 +714,7 @@ int32_t cfgLoadFromEnvCmd(SConfig *pConfig, const char **envCmd) { } int32_t cfgLoadFromEnvFile(SConfig *pConfig, const char *envFile) { - char *line = NULL, *name, *value, *value2, *value3; + char line[1024], *name, *value, *value2, *value3; int32_t olen, vlen, vlen2, vlen3; int32_t code = 0; ssize_t _bytes = 0; @@ -743,7 +743,7 @@ int32_t cfgLoadFromEnvFile(SConfig *pConfig, const char *envFile) { name = value = value2 = value3 = NULL; olen = vlen = vlen2 = vlen3 = 0; - _bytes = taosGetLineFile(pFile, &line); + _bytes = taosGetsFile(pFile, sizeof(line), line); if (_bytes <= 0) { break; } @@ -775,14 +775,13 @@ int32_t cfgLoadFromEnvFile(SConfig *pConfig, const char *envFile) { } taosCloseFile(&pFile); - if (line != NULL) taosMemoryFreeClear(line); uInfo("load from env cfg file %s success", filepath); return 0; } int32_t cfgLoadFromCfgFile(SConfig *pConfig, const char *filepath) { - char *line = NULL, *name, *value, *value2, *value3; + char line[1024], *name, *value, *value2, *value3; int32_t olen, vlen, vlen2, vlen3; ssize_t _bytes = 0; int32_t code = 0; @@ -804,7 +803,7 @@ int32_t cfgLoadFromCfgFile(SConfig *pConfig, const char *filepath) { name = value = value2 = value3 = NULL; olen = vlen = vlen2 = vlen3 = 0; - _bytes = taosGetLineFile(pFile, &line); + _bytes = taosGetsFile(pFile, sizeof(line), line); if (_bytes <= 0) { break; } @@ -836,7 +835,6 @@ int32_t cfgLoadFromCfgFile(SConfig *pConfig, const char *filepath) { } taosCloseFile(&pFile); - if (line != NULL) taosMemoryFreeClear(line); if (code == 0 || (code != 0 && terrno == TSDB_CODE_CFG_NOT_FOUND)) { uInfo("load from cfg file %s success", filepath); diff --git a/source/util/src/tthread.c b/source/util/src/tthread.c index 3a22478729..5c409935ff 100644 --- a/source/util/src/tthread.c +++ b/source/util/src/tthread.c @@ -31,7 +31,7 @@ TdThread* taosCreateThread(void* (*__start_routine)(void*), void* param) { return pthread; } -bool taosDestoryThread(TdThread* pthread) { +bool taosDestroyThread(TdThread* pthread) { if (pthread == NULL) return false; if (taosThreadRunning(pthread)) { taosThreadCancel(*pthread); diff --git a/source/util/src/tuuid.c b/source/util/src/tuuid.c index d192b1229d..8652652024 100644 --- a/source/util/src/tuuid.c +++ b/source/util/src/tuuid.c @@ -39,8 +39,8 @@ int32_t tGenIdPI32(void) { int64_t tGenIdPI64(void) { if (tUUIDHashId == 0) { - char uid[64]; - int32_t code = taosGetSystemUUID(uid, tListLen(uid)); + char uid[65] = {0}; + int32_t code = taosGetSystemUUID(uid, 64); if (code != TSDB_CODE_SUCCESS) { terrno = TAOS_SYSTEM_ERROR(errno); } else { 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 18b22b51ce..0a835ec564 100644 --- a/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py +++ b/tests/develop-test/5-taos-tools/taosbenchmark/default_json.py @@ -19,10 +19,9 @@ from util.dnodes import * class TDTestCase: def caseDescription(self): - ''' + """ [TD-11510] taosBenchmark test cases - ''' - return + """ def init(self, conn, logSql): tdLog.debug("start to execute %s" % __file__) @@ -31,19 +30,19 @@ class TDTestCase: def getPath(self, tool="taosBenchmark"): selfPath = os.path.dirname(os.path.realpath(__file__)) - if ("community" in selfPath): - projPath = selfPath[:selfPath.find("community")] + 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: @@ -52,14 +51,15 @@ class TDTestCase: def run(self): binPath = self.getPath() - cmd = "%s -f ./5-taos-tools/taosbenchmark/json/default.json" %binPath + cmd = "%s -f ./5-taos-tools/taosbenchmark/json/default.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.stb)") tdSql.checkData(0, 0, 10) tdSql.query("select count(*) from db.stb") - tdSql.checkData(0, 0, 100) + if len(tdSql.queryResult): + tdLog.exit("query result is %d" % len(tdSql.queryResult)) def stop(self): tdSql.close() diff --git a/tests/script/tsim/parser/fill.sim b/tests/script/tsim/parser/fill.sim index 4892345e12..ea0311ebde 100644 --- a/tests/script/tsim/parser/fill.sim +++ b/tests/script/tsim/parser/fill.sim @@ -795,12 +795,34 @@ if $data81 != 4 then endi # desc fill query -print desc fill query -sql select count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10); +print asc fill query +sql select _wstart,count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10) order by _wstart asc; if $rows != 12 then return -1 endi +if $data00 != @18-09-17 09:00:00.000@ then + return -1 +endi + +if $data01 != 1 then + return -1 +endi + +print desc fill query +sql select _wstart,count(*) from m_fl_tb0 where ts>='2018-9-17 9:0:0' and ts<='2018-9-17 9:11:00' interval(1m) fill(value,10) order by _wstart desc; +if $rows != 12 then + return -1 +endi + +if $data00 != @18-09-17 09:11:00.000@ then + return -1 +endi + +if $data01 != 10 then + return -1 +endi + print =====================> aggregation + arithmetic + fill, need to add cases TODO #sql select avg(cpu_taosd) - first(cpu_taosd) from dn1 where ts<'2020-11-13 11:00:00' and ts>'2020-11-13 10:50:00' interval(10s) fill(value, 99) #sql select count(*), first(k), avg(k), avg(k)-first(k) from tm0 where ts>'2020-1-1 1:1:1' and ts<'2020-1-1 1:02:59' interval(10s) fill(value, 99); diff --git a/tests/script/tsim/stream/basic1.sim b/tests/script/tsim/stream/basic1.sim index 8942f7f702..b20e2e3592 100644 --- a/tests/script/tsim/stream/basic1.sim +++ b/tests/script/tsim/stream/basic1.sim @@ -622,4 +622,56 @@ if $data12 != 2 then goto loop3 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 insert into t1 values(1648791213000,1,2,3,1.0); + +sleep 200 +sql select * from streamt4; + +# row 0 +if $rows != 0 then + print =====rows=$rows + return -1 +endi + +sql insert into t1 values(1648791213000,6,2,3,1.0); + +$loop_count = 0 +loop4: +sleep 200 +sql select * from streamt4; + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +if $data01 != 1 then + print =====data01=$data01 + goto loop4 +endi + +sql insert into t1 values(1648791213000,2,2,3,1.0); + +$loop_count = 0 +loop5: +sleep 200 +sql select * from streamt4; + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +if $rows != 0 then + print =====rows=$rows + goto loop5 +endi + + + system sh/exec.sh -n dnode1 -s stop -x SIGINT diff --git a/tests/script/tsim/stream/distributeIntervalRetrive0.sim b/tests/script/tsim/stream/distributeIntervalRetrive0.sim index 79edea2a3c..bea70b1639 100644 --- a/tests/script/tsim/stream/distributeIntervalRetrive0.sim +++ b/tests/script/tsim/stream/distributeIntervalRetrive0.sim @@ -3,12 +3,15 @@ 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 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 @@ -232,4 +235,41 @@ endi print loop3 over + + + + +#==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 + + + +#==system sh/exec.sh -n dnode2 -s stop -x SIGINT +#==print =============== check +#==$null= + +#==system_content sh/checkValgrind.sh -n dnode2 +#==print cmd return result ----> [ $system_content ] +#==if $system_content > 0 then +#== return -1 +#==endi + +#==if $system_content == $null then +#== return -1 +#==endi +#==return 1 + + + system sh/stop_dnodes.sh diff --git a/tests/script/tsim/stream/fillIntervalDelete1.sim b/tests/script/tsim/stream/fillIntervalDelete1.sim index 8e6972975e..e14062e830 100644 --- a/tests/script/tsim/stream/fillIntervalDelete1.sim +++ b/tests/script/tsim/stream/fillIntervalDelete1.sim @@ -4,6 +4,8 @@ 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 @@ -353,6 +355,22 @@ 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; diff --git a/tests/script/tsim/stream/fillIntervalLinear.sim b/tests/script/tsim/stream/fillIntervalLinear.sim index 46ff785fd3..4d0f101b6c 100644 --- a/tests/script/tsim/stream/fillIntervalLinear.sim +++ b/tests/script/tsim/stream/fillIntervalLinear.sim @@ -4,6 +4,8 @@ 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 @@ -671,6 +673,22 @@ 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; diff --git a/tests/script/tsim/stream/fillIntervalPrevNext.sim b/tests/script/tsim/stream/fillIntervalPrevNext.sim index 5eab5fdac1..4eadd7e7b1 100644 --- a/tests/script/tsim/stream/fillIntervalPrevNext.sim +++ b/tests/script/tsim/stream/fillIntervalPrevNext.sim @@ -4,6 +4,8 @@ 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 @@ -1011,6 +1013,21 @@ 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 diff --git a/tests/script/tsim/stream/fillIntervalValue.sim b/tests/script/tsim/stream/fillIntervalValue.sim index 113eae9270..49e68ae9f2 100644 --- a/tests/script/tsim/stream/fillIntervalValue.sim +++ b/tests/script/tsim/stream/fillIntervalValue.sim @@ -4,6 +4,7 @@ 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 @@ -463,6 +464,20 @@ 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 diff --git a/tests/script/tsim/stream/partitionbyColumnInterval.sim b/tests/script/tsim/stream/partitionbyColumnInterval.sim index fd1d796fdb..8375df5064 100644 --- a/tests/script/tsim/stream/partitionbyColumnInterval.sim +++ b/tests/script/tsim/stream/partitionbyColumnInterval.sim @@ -587,8 +587,6 @@ sleep 300 sql delete from st where ts = 1648791223000; -sql select * from test.streamt5; - $loop_count = 0 loop15: @@ -604,11 +602,10 @@ if $rows != 4 then print =====rows=$rows print =====rows=$rows print =====rows=$rows -# goto loop15 + #goto loop15 endi - $loop_all = $loop_all + 1 print ============loop_all=$loop_all diff --git a/tests/script/tsim/stream/sliding.sim b/tests/script/tsim/stream/sliding.sim index b7477fe36c..49e22db1b1 100644 --- a/tests/script/tsim/stream/sliding.sim +++ b/tests/script/tsim/stream/sliding.sim @@ -5,15 +5,15 @@ sleep 50 sql connect print =============== create database -sql create database test vgroups 1 -sql select * from information_schema.ins_databases +sql create database test vgroups 1; +sql select * from information_schema.ins_databases; if $rows != 3 then return -1 endi print $data00 $data01 $data02 -sql use test +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); @@ -48,8 +48,9 @@ if $loop_count == 10 then return -1 endi +print step 0 -sql select * from streamt +sql select * from streamt; # row 0 if $data01 != 1 then @@ -97,7 +98,7 @@ endi print step 1 -sql select * from streamt2 +sql select * from streamt2; # row 0 if $data01 != 1 then @@ -239,6 +240,67 @@ if $data32 != 6 then goto loop0 endi +print step 3.1 + +sql insert into t1 values(1648791216001,2,2,3,1.1); + +$loop_count = 0 + +loop00: +sleep 300 + +$loop_count = $loop_count + 1 +if $loop_count == 10 then + return -1 +endi + +sql select * from streamt2; + +# row 0 +if $data01 != 1 then + print =====data01=$data01 + goto loop00 +endi + +if $data02 != 1 then + print =====data02=$data02 + goto loop00 +endi + +# row 1 +if $data11 != 3 then + print =====data11=$data11 + goto loop00 +endi + +if $data12 != 5 then + print =====data12=$data12 + goto loop00 +endi + +# row 2 +if $data21 != 3 then + print =====data21=$data21 + goto loop00 +endi + +if $data22 != 7 then + print =====data22=$data22 + goto loop00 +endi + +# row 3 +if $data31 != 1 then + print =====data31=$data31 + goto loop00 +endi + +if $data32 != 3 then + print =====data32=$data32 + goto loop00 +endi + + print step 4 sql create database test1 vgroups 1 @@ -513,6 +575,8 @@ endi $loop_count = 0 +print step 7 + loop4: sleep 100 diff --git a/tests/system-test/7-tmq/tmqDnodeRestart.py b/tests/system-test/7-tmq/tmqDnodeRestart.py index 1902945bf6..bcc6725848 100644 --- a/tests/system-test/7-tmq/tmqDnodeRestart.py +++ b/tests/system-test/7-tmq/tmqDnodeRestart.py @@ -64,7 +64,7 @@ class TDTestCase: 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") + tdLog.info("flush database to ensure that the data falls into the disk") # tdDnodes.stop(1) # tdDnodes.start(1) tdSql.query("flush database %s"%(paraDict['dbName'])) @@ -87,7 +87,7 @@ class TDTestCase: 'rowsPerTbl': 1000, 'batchNum': 100, 'startTs': 1640966400000, # 2022-01-01 00:00:00.000 - 'pollDelay': 5, + 'pollDelay': 10, 'showMsg': 1, 'showRow': 1, 'snapshot': 0} diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 03097e31b9..98d21a4f2c 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -1,6 +1,11 @@ IF (TD_WEBSOCKET) + IF (TD_LINUX) + SET(websocket_lib_file "libtaosws.so") + ELSEIF (TD_DARWIN) + SET(websocket_lib_file "libtaosws.dylib") + ENDIF () MESSAGE("${Green} use libtaos-ws${ColourReset}") - IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs/target/release/libtaosws.so" OR "${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs/target/release/libtaosws.so" IS_NEWER_THAN "${CMAKE_SOURCE_DIR}/.git/modules/tools/taosws-rs/FETCH_HEAD") + IF (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs/target/release/${websocket_lib_file}" OR "${CMAKE_CURRENT_SOURCE_DIR}/taosws-rs/target/release/${websocket_lib_file}" IS_NEWER_THAN "${CMAKE_SOURCE_DIR}/.git/modules/tools/taosws-rs/FETCH_HEAD") include(ExternalProject) ExternalProject_Add(taosws-rs PREFIX "taosws-rs" @@ -15,7 +20,7 @@ IF (TD_WEBSOCKET) COMMAND cargo build --release -p taos-ws-sys COMMAND ./taos-ws-sys/ci/package.sh INSTALL_COMMAND - COMMAND cmake -E copy target/libtaosws/libtaosws.so ${CMAKE_BINARY_DIR}/build/lib + COMMAND cmake -E copy target/libtaosws/${websocket_lib_file} ${CMAKE_BINARY_DIR}/build/lib COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build/include COMMAND cmake -E copy target/libtaosws/taosws.h ${CMAKE_BINARY_DIR}/build/include ) @@ -34,7 +39,7 @@ IF (TD_WEBSOCKET) COMMAND cargo build --release -p taos-ws-sys COMMAND ./taos-ws-sys/ci/package.sh INSTALL_COMMAND - COMMAND cmake -E copy target/libtaosws/libtaosws.so ${CMAKE_BINARY_DIR}/build/lib + COMMAND cmake -E copy target/libtaosws/${websocket_lib_file} ${CMAKE_BINARY_DIR}/build/lib COMMAND cmake -E make_directory ${CMAKE_BINARY_DIR}/build/include COMMAND cmake -E copy target/libtaosws/taosws.h ${CMAKE_BINARY_DIR}/build/include ) diff --git a/tools/shell/CMakeLists.txt b/tools/shell/CMakeLists.txt index 488b623f89..45a6f8c16f 100644 --- a/tools/shell/CMakeLists.txt +++ b/tools/shell/CMakeLists.txt @@ -6,6 +6,10 @@ IF (TD_LINUX AND TD_WEBSOCKET) ADD_DEFINITIONS(-DWEBSOCKET -I${CMAKE_BINARY_DIR}/build/include -ltaosws) SET(LINK_WEBSOCKET "-L${CMAKE_BINARY_DIR}/build/lib -ltaosws") ADD_DEPENDENCIES(shell taosws-rs) +ELSEIF (TD_DARWIN AND TD_WEBSOCKET) + ADD_DEFINITIONS(-DWEBSOCKET -I${CMAKE_BINARY_DIR}/build/include) + SET(LINK_WEBSOCKET "${CMAKE_BINARY_DIR}/build/lib/libtaosws.dylib") + ADD_DEPENDENCIES(shell taosws-rs) ELSE () SET(LINK_WEBSOCKET "") ENDIF () diff --git a/tools/shell/inc/shellAuto.h b/tools/shell/inc/shellAuto.h new file mode 100644 index 0000000000..2cfab41f26 --- /dev/null +++ b/tools/shell/inc/shellAuto.h @@ -0,0 +1,42 @@ +/* + * 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 __SHELL_AUTO__ +#define __SHELL_AUTO__ + +#define TAB_KEY 0x09 + +// press tab key +void pressTabKey(SShellCmd* cmd); + +// press othr key +void pressOtherKey(char c); + +// init shell auto funciton , shell start call once +bool shellAutoInit(); + +// set conn +void shellSetConn(TAOS* conn); + +// exit shell auto funciton, shell exit call once +void shellAutoExit(); + +// callback autotab module +void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb); + +// introduction +void printfIntroduction(); + +#endif diff --git a/tools/shell/inc/shellInt.h b/tools/shell/inc/shellInt.h index 15f6f6dc6a..af724c1533 100644 --- a/tools/shell/inc/shellInt.h +++ b/tools/shell/inc/shellInt.h @@ -102,6 +102,16 @@ typedef struct { #endif } SShellObj; +typedef struct { + char *buffer; + char *command; + uint32_t commandSize; + uint32_t bufferSize; + uint32_t cursorOffset; + uint32_t screenOffset; + uint32_t endOffset; +} SShellCmd; + // shellArguments.c int32_t shellParseArgs(int32_t argc, char* argv[]); diff --git a/tools/shell/inc/shellTire.h b/tools/shell/inc/shellTire.h new file mode 100644 index 0000000000..88bae54809 --- /dev/null +++ b/tools/shell/inc/shellTire.h @@ -0,0 +1,92 @@ +/* + * 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 __TRIE__ +#define __TRIE__ + +// +// 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 LAST_ASCII 122 // last visilbe char is 'z' + +// capacity save char is 95 +#define CHAR_CNT (LAST_ASCII - FIRST_ASCII + 1) +#define MAX_WORD_LEN 256 // max insert word length + +// define STire +#define TIRE_TREE 0 +#define TIRE_LIST 1 + +typedef struct STireNode { + struct STireNode** d; + bool end; // record end flag +}STireNode; + +typedef struct StrName { + char * name; + struct StrName * next; +}StrName; + + +typedef struct STire { + char type; // see define TIRE_ + STireNode root; + + StrName * head; + StrName * tail; + + int count; // all count + int ref; +}STire; + +typedef struct SMatchNode { + char* word; + struct SMatchNode* next; +}SMatchNode; + + +typedef struct SMatch { + SMatchNode* head; + SMatchNode* tail; // append node to tail + int count; + char pre[MAX_WORD_LEN]; +}SMatch; + + +// ----------- interface ------------- + +// create prefix search tree, return value call freeTire to free +STire* createTire(char type); + +// destroy prefix search tree +void freeTire(STire* tire); + +// add a new word +bool insertWord(STire* tire, char* word); + +// add a new word +bool deleteWord(STire* tire, char* word); + +// match prefix words, if match is not NULL , put all item to match and return match +SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match); + +// get all items from tires tree +SMatch* enumAll(STire* tire); + +// free match result +void freeMatch(SMatch* match); + +#endif diff --git a/tools/shell/src/shellAuto.c b/tools/shell/src/shellAuto.c new file mode 100644 index 0000000000..c648b6932b --- /dev/null +++ b/tools/shell/src/shellAuto.c @@ -0,0 +1,2052 @@ +/* + * 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 __USE_XOPEN + +#include "shellInt.h" +#include "shellAuto.h" +#include "shellTire.h" +#include "tthread.h" + +// +// ------------- define area --------------- +// +#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); +bool appendAfterSelect(TAOS * con, SShellCmd * cmd, char* p, int32_t len); + + +typedef struct SAutoPtr { + STire* p; + int ref; +}SAutoPtr; + +typedef struct SWord{ + int type ; // word type , see WT_ define + char * word; + int32_t len; + struct SWord * next; + bool free; // if true need free +}SWord; + +typedef struct { + char * source; + int32_t source_len; // valid data length in source + int32_t count; + SWord* head; + // matched information + int32_t matchIndex; // matched word index in words + int32_t matchLen; // matched length at matched word +}SWords; + +SWords shellCommands[] = { + {"alter database ;", 0, 0, NULL}, + {"alter dnode balance ", 0, 0, NULL}, + {"alter dnode resetlog;", 0, 0, NULL}, + {"alter dnode debugFlag 141;", 0, 0, NULL}, + {"alter dnode monitor 1;", 0, 0, NULL}, + {"alter all dnodes monitor ", 0, 0, NULL}, + {"alter alldnodes balance ", 0, 0, NULL}, + {"alter alldnodes resetlog;", 0, 0, NULL}, + {"alter alldnodes debugFlag 141;", 0, 0, NULL}, + {"alter alldnodes monitor 1;", 0, 0, NULL}, + {"alter table ;", 0, 0, NULL}, + {"alter table modify column", 0, 0, NULL}, + {"alter local resetlog;", 0, 0, NULL}, + {"alter local DebugFlag 143;", 0, 0, NULL}, + {"alter local cDebugFlag 143;", 0, 0, NULL}, + {"alter local uDebugFlag 143;", 0, 0, NULL}, + {"alter local rpcDebugFlag 143;", 0, 0, NULL}, + {"alter local tmrDebugFlag 143;", 0, 0, NULL}, + {"alter topic", 0, 0, NULL}, + {"alter user ;", 0, 0, NULL}, + // 20 + {"create table using tags(", 0, 0, NULL}, + {"create database ;", 0, 0, NULL}, + {"create dnode ", 0, 0, NULL}, + {"create index ", 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 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 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 consumer group on ", 0, 0, NULL}, + {"drop topic ;", 0, 0, NULL}, + {"drop stream ;", 0, 0, NULL}, + {"explain select", 0, 0, NULL}, // 44 append sub sql + {"grant all on to ;", 0, 0, NULL}, + {"grant read on to ;", 0, 0, NULL}, + {"grant write on to ;", 0, 0, NULL}, + {"kill connection ;", 0, 0, NULL}, + {"kill query ", 0, 0, NULL}, + {"kill transaction ", 0, 0, NULL}, + {"merge vgroup ", 0, 0, NULL}, + {"reset query cache;", 0, 0, NULL}, + {"revoke all on from ;", 0, 0, NULL}, + {"revoke read on from ;", 0, 0, NULL}, + {"revoke write on from ;", 0, 0, NULL}, + {"select * from ", 0, 0, NULL}, + {"select _block_dist() from \\G;", 0, 0, NULL}, + {"select client_version();", 0, 0, NULL}, + // 60 + {"select current_user();", 0, 0, NULL}, + {"select database();", 0, 0, NULL}, + {"select server_version();", 0, 0, NULL}, + {"select server_status();", 0, 0, NULL}, + {"select now();", 0, 0, NULL}, + {"select today();", 0, 0, NULL}, + {"select timezone();", 0, 0, NULL}, + {"set max_binary_display_width ", 0, 0, NULL}, + {"show apps;", 0, 0, NULL}, + {"show create database \\G;", 0, 0, NULL}, + {"show create stable \\G;", 0, 0, NULL}, + {"show create table \\G;", 0, 0, NULL}, + {"show connections;", 0, 0, NULL}, + {"show cluster;", 0, 0, NULL}, + {"show databases;", 0, 0, NULL}, + {"show dnodes;", 0, 0, NULL}, + {"show dnode variables;", 0, 0, NULL}, + {"show functions;", 0, 0, NULL}, + {"show mnodes;", 0, 0, NULL}, + {"show queries;", 0, 0, NULL}, + // 80 + {"show query ;", 0, 0, NULL}, + {"show qnodes;", 0, 0, NULL}, + {"show snodes;", 0, 0, NULL}, + {"show stables;", 0, 0, NULL}, + {"show stables like ", 0, 0, NULL}, + {"show streams;", 0, 0, NULL}, + {"show scores;", 0, 0, NULL}, + {"show subscriptions;", 0, 0, NULL}, + {"show tables;", 0, 0, NULL}, + {"show tables like", 0, 0, NULL}, + {"show table distributed ", 0, 0, NULL}, + {"show tags from ", 0, 0, NULL}, + {"show tags from ", 0, 0, NULL}, + {"show topics;", 0, 0, NULL}, + {"show transactions;", 0, 0, NULL}, + {"show users;", 0, 0, NULL}, + {"show variables;", 0, 0, NULL}, + {"show local variables;", 0, 0, NULL}, + {"show vnodes ", 0, 0, NULL}, + {"show vgroups;", 0, 0, NULL}, + {"show consumers;", 0, 0, NULL}, + {"show grants;", 0, 0, NULL}, + {"split vgroup ", 0, 0, NULL}, + {"insert into values(", 0, 0, NULL}, + {"insert into using tags(", 0, 0, NULL}, + {"insert into using values(", 0, 0, NULL}, + {"insert into file ", 0, 0, NULL}, + {"trim database ", 0, 0, NULL}, + {"use ", 0, 0, NULL}, + {"quit", 0, 0, NULL} +}; + +char * keywords[] = { + "and ", + "asc ", + "desc ", + "from ", + "fill(", + "limit ", + "where ", + "interval(", + "order by ", + "order by ", + "offset ", + "or ", + "group by ", + "now()", + "session(", + "sliding ", + "slimit ", + "soffset ", + "state_window(", + "today() ", + "union all select ", + "partition by " +}; + +char * functions[] = { + "count(", + "sum(", + "avg(", + "last(", + "last_row(", + "top(", + "interp(", + "max(", + "min(", + "now()", + "today()", + "percentile(", + "tail(", + "pow(", + "abs(", + "atan(", + "acos(", + "asin(", + "apercentile(", + "bottom(", + "cast(", + "ceil(", + "char_length(", + "cos(", + "concat(", + "concat_ws(", + "csum(", + "diff(", + "derivative(", + "elapsed(", + "first(", + "floor(", + "hyperloglog(", + "histogram(", + "irate(", + "leastsquares(", + "length(", + "log(", + "lower(", + "ltrim(", + "mavg(", + "mode(", + "tan(", + "round(", + "rtrim(", + "sample(", + "sin(", + "spread(", + "substr(", + "statecount(", + "stateduration(", + "stddev(", + "sqrt(", + "timediff(", + "timezone(", + "timetruncate(", + "twa(", + "to_unixtimestamp(", + "unique(", + "upper(", +}; + +char * tb_actions[] = { + "add column ", + "modify column ", + "drop column ", + "rename column ", + "add tag ", + "modify tag ", + "drop tag ", + "rename tag ", + "set tag ", +}; + +char * user_actions[] = { + "pass ", + "enable ", + "sysinfo " +}; + +char * tb_options[] = { + "comment ", + "watermark ", + "max_delay ", + "ttl ", + "rollup(", + "sma(" +}; + +char * db_options[] = { + "keep ", + "replica ", + "precision ", + "strict ", + "buffer ", + "cachemodel ", + "cachesize ", + "comp ", + "duration ", + "wal_fsync_period", + "maxrows ", + "minrows ", + "pages ", + "pagesize ", + "retentions ", + "wal_level ", + "vgroups ", + "single_stable ", + "wal_retention_period ", + "wal_roll_period ", + "wal_retention_size ", + "wal_segment_size " +}; + +char * alter_db_options[] = { + "keep ", + "cachemodel ", + "cachesize ", + "wal_fsync_period ", + "wal_level " +}; + +char * data_types[] = { + "timestamp", + "int", + "int unsigned", + "varchar(16)", + "float", + "double", + "binary(16)", + "nchar(16)", + "bigint", + "bigint unsigned", + "smallint", + "smallint unsigned", + "tinyint", + "tinyint unsigned", + "bool", + "json" +}; + +char * key_tags[] = { + "tags(" +}; + +char * key_select[] = { + "select " +}; + +// +// ------- gobal variant define --------- +// +int32_t firstMatchIndex = -1; // first match shellCommands index +int32_t lastMatchIndex = -1; // last match shellCommands index +int32_t curMatchIndex = -1; // current match shellCommands index +int32_t lastWordBytes = -1; // printShow last word length +bool waitAutoFill = false; + + +// +// ----------- global var array define ----------- +// +#define WT_VAR_DBNAME 0 +#define WT_VAR_STABLE 1 +#define WT_VAR_TABLE 2 +#define WT_VAR_DNODEID 3 +#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_CNT 19 + +#define WT_FROM_DB_MAX 6 // max get content from db +#define WT_FROM_DB_CNT (WT_FROM_DB_MAX + 1) + +#define WT_TEXT 0xFF + +char dbName[256] = ""; // save use database name; +// tire array +STire* tires[WT_VAR_CNT]; +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 varSqls[WT_FROM_DB_CNT][64] = { + "show databases;", + "show stables;", + "show tables;", + "show dnodes;", + "show users;", + "show topics;", + "show streams;" +}; + + +// var words current cursor, if user press any one key except tab, cursorVar can be reset to -1 +int cursorVar = -1; +bool varMode = false; // enter var names list mode + + +TAOS* varCon = NULL; +SShellCmd* varCmd = NULL; +SMatch* lastMatch = NULL; // save last match result +int cntDel = 0; // delete byte count after next press tab + + +// show auto tab introduction +void printfIntroduction() { + printf(" **************************** How To Use TAB Key ********************************\n"); + printf(" * TDengine Command Line supports pressing TAB key to complete word, *\n"); + printf(" * including database name, table name, function name and keywords. *\n"); + printf(" * Press TAB key anywhere, you'll get surprise. *\n"); + printf(" * KEYBOARD SHORTCUT: *\n"); + printf(" * [ TAB ] ...... Complete the word or show help if no input *\n"); + printf(" * [ Ctrl + A ] ...... move cursor to [A]head of line *\n"); + printf(" * [ Ctrl + E ] ...... move cursor to [E]nd of line *\n"); + printf(" * [ Ctrl + W ] ...... move cursor to line of middle *\n"); + printf(" * [ Ctrl + L ] ...... clean screen *\n"); + printf(" * [ Ctrl + K ] ...... clean after cursor *\n"); + printf(" * [ Ctrl + U ] ...... clean before cursor *\n"); + printf(" * *\n"); + printf(" **********************************************************************************\n\n"); +} + +void showHelp() { + printf("\nThe following are supported commands for TDengine Command Line:"); + printf("\n\ + ----- A ----- \n\ + alter database \n\ + alter dnode balance \n\ + alter dnode resetlog;\n\ + alter all dnodes monitor \n\ + alter alldnodes balance \n\ + alter alldnodes resetlog;\n\ + alter alldnodes debugFlag \n\ + alter alldnodes monitor \n\ + alter table ;\n\ + alter table modify column\n\ + alter local resetlog;\n\ + alter local DebugFlag 143;\n\ + alter topic\n\ + alter user ...\n\ + ----- C ----- \n\ + create table using tags ...\n\ + create database ...\n\ + create dnode ...\n\ + create index ...\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 user pass ...\n\ + ----- D ----- \n\ + describe \n\ + delete from where ...\n\ + drop database ;\n\ + drop table ;\n\ + drop dnode ;\n\ + drop mnode on dnode ;\n\ + drop qnode on dnode ;\n\ + drop user ;\n\ + drop function ;\n\ + drop consumer group ... \n\ + drop topic ;\n\ + drop stream ;\n\ + ----- E ----- \n\ + explain select clause ...\n\ + ----- I ----- \n\ + insert into values(...) ;\n\ + insert into using tags(...) values(...) ;\n\ + ----- G ----- \n\ + grant all on to ;\n\ + grant read on to ;\n\ + grant write on to ;\n\ + ----- K ----- \n\ + kill connection ; \n\ + kill query ; \n\ + kill transaction ;\n\ + ----- M ----- \n\ + merge vgroup ...\n\ + ----- R ----- \n\ + reset query cache;\n\ + revoke all on from ;\n\ + revoke read on from ;\n\ + revoke write on from ;\n\ + ----- S ----- \n\ + select * from where ... \n\ + select _block_dist() from ;\n\ + select client_version();\n\ + select current_user();\n\ + select database();\n\ + select server_version();\n\ + select server_status();\n\ + select now();\n\ + select today();\n\ + select timezone();\n\ + set max_binary_display_width ...\n\ + show apps;\n\ + show create database ;\n\ + show create stable ;\n\ + show create table ;\n\ + show connections;\n\ + show cluster;\n\ + show databases;\n\ + show dnodes;\n\ + show dnode variables;\n\ + show functions;\n\ + show mnodes;\n\ + show queries;\n\ + show query ;\n\ + show qnodes;\n\ + show snodes;\n\ + show stables;\n\ + show stables like \n\ + show streams;\n\ + show scores;\n\ + show subscriptions;\n\ + show tables;\n\ + show tables like\n\ + show table distributed ;\n\ + show tags from \n\ + show tags from \n\ + show topics;\n\ + show transactions;\n\ + show users;\n\ + show variables;\n\ + show local variables;\n\ + show vnodes \n\ + show vgroups;\n\ + show consumers;\n\ + show grants;\n\ + split vgroup ...\n\ + ----- T ----- \n\ + trim database ;\n\ + ----- U ----- \n\ + use ;"); + + printf("\n\n"); + + //define in getDuration() function + printf("\ + Timestamp expression Format:\n\ + b - nanosecond \n\ + u - microsecond \n\ + a - millisecond \n\ + s - second \n\ + m - minute \n\ + h - hour \n\ + d - day \n\ + w - week \n\ + now - current time \n\ + Example : \n\ + select * from t1 where ts > now - 2w + 3d and ts <= now - 1w -2h ;\n"); + printf("\n"); +} + +// +// ------------------- parse words -------------------------- +// + +#define SHELL_COMMAND_COUNT() (sizeof(shellCommands) / sizeof(SWords)) + +// get at +SWord * atWord(SWords * command, int32_t index) { + SWord * word = command->head; + for (int32_t i = 0; i < index; i++) { + if (word == NULL) + return NULL; + word = word->next; + } + + return word; +} + +#define MATCH_WORD(x) atWord(x, x->matchIndex) + +int wordType(const char* p, int32_t len) { + for (int i = 0; i < WT_VAR_CNT; i++) { + if (strncmp(p, varTypes[i], len) == 0) + return i; + } + return WT_TEXT; +} + +// add word +SWord * addWord(const char* p, int32_t len, bool pattern) { + SWord* word = (SWord *) taosMemoryMalloc(sizeof(SWord)); + memset(word, 0, sizeof(SWord)); + word->word = (char* )p; + word->len = len; + + // check format + if (pattern) { + word->type = wordType(p, len); + } else { + word->type = WT_TEXT; + } + + return word; +} + +// parse one command +void parseCommand(SWords * command, bool pattern) { + char * p = command->source; + int32_t start = 0; + int32_t size = command->source_len > 0 ? command->source_len : strlen(p); + + bool lastBlank = false; + for (int i = 0; i <= size; i++) { + if (p[i] == ' ' || i == size) { + // check continue blank like ' ' + if (p[i] == ' ') { + if (lastBlank) { + start ++; + continue; + } + if (i == 0) { // first blank + lastBlank = true; + start ++; + continue; + } + lastBlank = true; + } + + // found split or string end , append word + if (command->head == NULL) { + command->head = addWord(p + start, i - start, pattern); + command->count = 1; + } else { + SWord * word = command->head; + while (word->next) { + word = word->next; + } + word->next = addWord(p + start, i - start, pattern); + command->count ++; + } + start = i + 1; + } else { + lastBlank = false; + } + } +} + +// free SShellCmd +void freeCommand(SWords * command) { + SWord * word = command->head; + if (word == NULL) { + return ; + } + + // loop + while (word->next) { + SWord * tmp = word; + word = word->next; + // if malloc need free + if(tmp->free && tmp->word) + taosMemoryFree(tmp->word); + taosMemoryFree(tmp); + } + + // if malloc need free + if(word->free && word->word) + taosMemoryFree(word->word); + taosMemoryFree(word); +} + +void GenerateVarType(int type, char** p, int count) { + STire* tire = createTire(TIRE_LIST); + for (int i = 0; i < count; i++) { + insertWord(tire, p[i]); + } + + taosThreadMutexLock(&tiresMutex); + tires[type] = tire; + taosThreadMutexUnlock(&tiresMutex); +} + +// +// -------------------- shell auto ---------------- +// + + +// init shell auto funciton , shell start call once +bool shellAutoInit() { + // command + int32_t count = SHELL_COMMAND_COUNT(); + for (int32_t i = 0; i < count; i ++) { + parseCommand(shellCommands + i, true); + } + + // tires + memset(tires, 0, sizeof(STire*) * WT_VAR_CNT); + taosThreadMutexInit(&tiresMutex, NULL); + + // threads + memset(threads, 0, sizeof(TdThread*) * WT_FROM_DB_CNT); + + // generate varType + GenerateVarType(WT_VAR_FUNC, functions, sizeof(functions) /sizeof(char *)); + GenerateVarType(WT_VAR_KEYWORD, keywords, sizeof(keywords) /sizeof(char *)); + GenerateVarType(WT_VAR_DBOPTION, db_options, sizeof(db_options) /sizeof(char *)); + GenerateVarType(WT_VAR_ALTER_DBOPTION, alter_db_options, sizeof(alter_db_options) /sizeof(char *)); + GenerateVarType(WT_VAR_TBACTION, tb_actions, sizeof(tb_actions) /sizeof(char *)); + GenerateVarType(WT_VAR_DATATYPE, data_types, sizeof(data_types) /sizeof(char *)); + GenerateVarType(WT_VAR_KEYTAGS, key_tags, sizeof(key_tags) /sizeof(char *)); + GenerateVarType(WT_VAR_TBOPTION, tb_options, sizeof(tb_options) /sizeof(char *)); + GenerateVarType(WT_VAR_USERACTION, user_actions, sizeof(user_actions) /sizeof(char *)); + GenerateVarType(WT_VAR_KEYSELECT,key_select, sizeof(key_select) /sizeof(char *)); + + return true; +} + +// set conn +void shellSetConn(TAOS* conn) { + varCon = conn; +} + +// exit shell auto funciton, shell exit call once +void shellAutoExit() { + // free command + int32_t count = SHELL_COMMAND_COUNT(); + for (int32_t i = 0; i < count; i ++) { + freeCommand(shellCommands + i); + } + + // free tires + taosThreadMutexLock(&tiresMutex); + for (int32_t i = 0; i < WT_VAR_CNT; i++) { + if (tires[i]) { + freeTire(tires[i]); + tires[i] = NULL; + } + } + taosThreadMutexUnlock(&tiresMutex); + // destory + taosThreadMutexDestroy(&tiresMutex); + + // free threads + for (int32_t i = 0; i < WT_FROM_DB_CNT; i++) { + if (threads[i]) { + taosDestroyThread(threads[i]); + threads[i] = NULL; + } + } + + // free lastMatch + if (lastMatch) { + freeMatch(lastMatch); + lastMatch = NULL; + } +} + +// +// ------------------- auto ptr for tires -------------------------- +// +bool setNewAuotPtr(int type, STire* pNew) { + if (pNew == NULL) + return false; + + taosThreadMutexLock(&tiresMutex); + STire* pOld = tires[type]; + if (pOld != NULL) { + // previous have value, release self ref count + if (--pOld->ref == 0) { + freeTire(pOld); + } + } + + // set new + tires[type] = pNew; + tires[type]->ref = 1; + taosThreadMutexUnlock(&tiresMutex); + + return true; +} + +// get ptr +STire* getAutoPtr(int type) { + if (tires[type] == NULL) { + return NULL; + } + + taosThreadMutexLock(&tiresMutex); + tires[type]->ref++; + taosThreadMutexUnlock(&tiresMutex); + + return tires[type]; +} + +// put back tire to tires[type], if tire not equal tires[type].p, need free tire +void putBackAutoPtr(int type, STire* tire) { + if (tire == NULL) { + return ; + } + + taosThreadMutexLock(&tiresMutex); + if (tires[type] != tire) { + //update by out, can't put back , so free + if (--tire->ref == 1) { + // support multi thread getAuotPtr + freeTire(tire); + } + + } else { + tires[type]->ref--; + assert(tires[type]->ref > 0); + } + taosThreadMutexUnlock(&tiresMutex); + + return ; +} + + + +// +// ------------------- var Word -------------------------- +// + +#define MAX_CACHED_CNT 100000 // max cached rows 10w +// write sql result to var name, return write rows cnt +int writeVarNames(int type, TAOS_RES* tres) { + // fetch row + TAOS_ROW row = taos_fetch_row(tres); + if (row == NULL) { + return 0; + } + + TAOS_FIELD *fields = taos_fetch_fields(tres); + // create new tires + char tireType = type == WT_VAR_TABLE ? TIRE_TREE : TIRE_LIST; + STire* tire = createTire(tireType); + + // enum rows + char name[1024]; + int numOfRows = 0; + do { + int32_t* lengths = taos_fetch_lengths(tres); + int32_t bytes = lengths[0]; + if(fields[0].type == TSDB_DATA_TYPE_INT) { + sprintf(name,"%d", *(int16_t*)row[0]); + } else { + memcpy(name, row[0], bytes); + } + + name[bytes] = 0; //set string end + // insert to tire + insertWord(tire, name); + + if (++numOfRows > MAX_CACHED_CNT ) { + break; + } + + row = taos_fetch_row(tres); + } while (row != NULL); + + // replace old tire + setNewAuotPtr(type, tire); + + return numOfRows; +} + +bool firstMatchCommand(TAOS * con, SShellCmd * cmd); +// +// thread obtain var thread from db server +// +void* varObtainThread(void* param) { + int type = *(int* )param; + taosMemoryFree(param); + + if (varCon == NULL || type > WT_FROM_DB_MAX) { + return NULL; + } + + TAOS_RES* pSql = taos_query(varCon, varSqls[type]); + if (taos_errno(pSql)) { + taos_free_result(pSql); + return NULL; + } + + // write var names from pSql + int cnt = writeVarNames(type, pSql); + + // free sql + taos_free_result(pSql); + + // check need call auto tab + if (cnt > 0 && waitAutoFill) { + // press tab key by program + firstMatchCommand(varCon, varCmd); + } + + return NULL; +} + +// only match next one word from all match words, return valuue must free by caller +char* matchNextPrefix(STire* tire, char* pre) { + SMatch* match = NULL; + + // re-use last result + if (lastMatch) { + if (strcmp(pre, lastMatch->pre) == 0) { + // same pre + match = lastMatch; + } + } + + if (match == NULL) { + // not same with last result + if (pre[0] == 0) { + // EMPTY PRE + match = enumAll(tire); + } else { + // NOT EMPTY + match = matchPrefix(tire, pre, NULL); + } + + // save to lastMatch + if (match) { + if (lastMatch) + freeMatch(lastMatch); + lastMatch = match; + } + } + + // check valid + if (match == NULL || match->head == NULL) { + // no one matched + return false; + } + + if (cursorVar == -1) { + // first + cursorVar = 0; + return strdup(match->head->word); + } + + // according to cursorVar , calculate next one + int i = 0; + SMatchNode* item = match->head; + while (item) { + if (i == cursorVar + 1) { + // found next position ok + if (item->next == NULL) { + // match last item, reset cursorVar to head + cursorVar = -1; + } else { + cursorVar = i; + } + + return strdup(item->word); + } + + // check end item + if (item->next == NULL) { + // if cursorVar > var list count, return last and reset cursorVar + cursorVar = -1; + + return strdup(item->word); + } + + // move next + item = item->next; + i++; + } + + return NULL; +} + +// search pre word from tire tree, return value must free by caller +char* tireSearchWord(int type, char* pre) { + if (type == WT_TEXT) { + return NULL; + } + + if(type > WT_FROM_DB_MAX) { + // NOT FROM DB , tires[type] alwary not null + STire* tire = tires[type]; + if (tire == NULL) + return NULL; + return matchNextPrefix(tire, pre); + } + + // TYPE CONTEXT GET FROM DB + taosThreadMutexLock(&tiresMutex); + + // check need obtain from server + if (tires[type] == NULL) { + waitAutoFill = true; + // need async obtain var names from db sever + if (threads[type] != NULL) { + if (taosThreadRunning(threads[type])) { + // thread running , need not obtain again, return + taosThreadMutexUnlock(&tiresMutex); + return NULL; + } + // destroy previous thread handle for new create thread handle + taosDestroyThread(threads[type]); + threads[type] = NULL; + } + + // create new + void * param = taosMemoryMalloc(sizeof(int)); + *((int* )param) = type; + threads[type] = taosCreateThread(varObtainThread, param); + taosThreadMutexUnlock(&tiresMutex); + return NULL; + } + taosThreadMutexUnlock(&tiresMutex); + + // can obtain var names from local + STire* tire = getAutoPtr(type); + if (tire == NULL) { + return NULL; + } + + char* str = matchNextPrefix(tire, pre); + // used finish, put back pointer to autoptr array + putBackAutoPtr(type, tire); + + return str; +} + +// match var word, word1 is pattern , word2 is input from shell +bool matchVarWord(SWord* word1, SWord* word2) { + // search input word from tire tree + char pre[512]; + memcpy(pre, word2->word, word2->len); + pre[word2->len] = 0; + + char* str = NULL; + if (word1->type == WT_VAR_ALLTABLE) { + // ALL_TABLE + str = tireSearchWord(WT_VAR_STABLE, pre); + if (str == NULL) { + str = tireSearchWord(WT_VAR_TABLE, pre); + if(str == NULL) + return false; + } + } else { + // OTHER + str = tireSearchWord(word1->type, pre); + if (str == NULL) { + // not found or word1->type variable list not obtain from server, return not match + return false; + } + } + + // free previous malloc + if(word1->free && word1->word) { + taosMemoryFree(word1->word); + } + + // save + word1->word = str; + word1->len = strlen(str); + word1->free = true; // need free + + return true; +} + +// +// ------------------- match words -------------------------- +// + + +// compare command cmd1 come from shellCommands , cmd2 come from user input +int32_t compareCommand(SWords * cmd1, SWords * cmd2) { + SWord * word1 = cmd1->head; + SWord * word2 = cmd2->head; + + if (word1 == NULL || word2 == NULL) { + return -1; + } + + for (int32_t i = 0; i < cmd1->count; i++) { + if (word1->type == WT_TEXT) { + // WT_TEXT match + if (word1->len == word2->len) { + if (strncasecmp(word1->word, word2->word, word1->len) != 0) + return -1; + } else if (word1->len < word2->len) { + return -1; + } else { + // word1->len > word2->len + if (strncasecmp(word1->word, word2->word, word2->len) == 0) { + cmd1->matchIndex = i; + cmd1->matchLen = word2->len; + return i; + } else { + return -1; + } + } + } else { + // WT_VAR auto match any one word + if (word2->next == NULL) { // input words last one + if (matchVarWord(word1, word2)) { + cmd1->matchIndex = i; + cmd1->matchLen = word2->len; + varMode = true; + return i; + } + return -1; + } + } + + // move next + word1 = word1->next; + word2 = word2->next; + if (word1 == NULL || word2 == NULL) { + return -1; + } + } + + return -1; +} + +// match command +SWords * matchCommand(SWords * input, bool continueSearch) { + int32_t count = SHELL_COMMAND_COUNT(); + for (int32_t i = 0; i < count; i ++) { + SWords * shellCommand = shellCommands + i; + if (continueSearch && lastMatchIndex != -1 && i <= lastMatchIndex) { + // new match must greate than lastMatchIndex + if (varMode && i == lastMatchIndex) { + // do nothing, var match on lastMatchIndex + } else { + continue; + } + } + + // command is large + if (input->count > shellCommand->count ) { + continue; + } + + // compare + int32_t index = compareCommand(shellCommand, input); + if (index != -1) { + if (firstMatchIndex == -1) + firstMatchIndex = i; + curMatchIndex = i; + return &shellCommands[i]; + } + } + + // not match + return NULL; +} + +// +// ------------------- print screen -------------------------- +// + +// delete char count +void deleteCount(SShellCmd * cmd, int count) { + int size = 0; + int width = 0; + int prompt_size = 6; + shellClearScreen(cmd->endOffset + prompt_size, cmd->screenOffset + prompt_size); + + // loop delete + while (--count >= 0 && cmd->cursorOffset > 0) { + shellGetPrevCharSize(cmd->command, cmd->cursorOffset, &size, &width); + memmove(cmd->command + cmd->cursorOffset - size, cmd->command + cmd->cursorOffset, + cmd->commandSize - cmd->cursorOffset); + cmd->commandSize -= size; + cmd->cursorOffset -= size; + cmd->screenOffset -= width; + cmd->endOffset -= width; + } +} + +// show screen +void printScreen(TAOS * con, SShellCmd * cmd, SWords * match) { + // modify SShellCmd + if (firstMatchIndex == -1 || curMatchIndex == -1) { + // no match + return ; + } + + // first tab press + const char * str = NULL; + int strLen = 0; + + if (firstMatchIndex == curMatchIndex && lastWordBytes == -1) { + // first press tab + SWord * word = MATCH_WORD(match); + str = word->word + match->matchLen; + strLen = word->len - match->matchLen; + lastMatchIndex = firstMatchIndex; + lastWordBytes = word->len; + } else { + if (lastWordBytes == -1) + return ; + deleteCount(cmd, lastWordBytes); + + SWord * word = MATCH_WORD(match); + str = word->word; + strLen = word->len; + // set current to last + lastMatchIndex = curMatchIndex; + lastWordBytes = word->len; + } + + // insert new + shellInsertChar(cmd, (char *)str, strLen); +} + + +// main key press tab , matched return true else false +bool firstMatchCommand(TAOS * con, SShellCmd * cmd) { + // parse command + SWords* input = (SWords *)taosMemoryMalloc(sizeof(SWords)); + memset(input, 0, sizeof(SWords)); + input->source = cmd->command; + input->source_len = cmd->commandSize; + parseCommand(input, false); + + // if have many , default match first, if press tab again , switch to next + curMatchIndex = -1; + lastMatchIndex = -1; + SWords * match = matchCommand(input, true); + if (match == NULL) { + // not match , nothing to do + freeCommand(input); + taosMemoryFree(input); + return false; + } + + // print to screen + printScreen(con, cmd, match); + freeCommand(input); + taosMemoryFree(input); + return true; +} + +// create input source +void createInputFromFirst(SWords* input, SWords * firstMatch) { + // + // if next pressTabKey , input context come from firstMatch, set matched length with source_len + // + input->source = (char*)taosMemoryMalloc(1024); + memset((void* )input->source, 0, 1024); + + SWord * word = firstMatch->head; + + // source_len = full match word->len + half match with firstMatch->matchLen + 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 + input->source_len += word->len + 1; // 1 is blank length + // move next + word = word->next; + } + // appand half matched word for last + if (word) { + strncpy(input->source + input->source_len, word->word, firstMatch->matchLen); + input->source_len += firstMatch->matchLen; + } +} + +// user press Tabkey again is named next , matched return true else false +bool nextMatchCommand(TAOS * con, SShellCmd * cmd, SWords * firstMatch) { + if (firstMatch == NULL || firstMatch->head == NULL) { + return false; + } + SWords* input = (SWords *)taosMemoryMalloc(sizeof(SWords)); + memset(input, 0, sizeof(SWords)); + + // create input from firstMatch + createInputFromFirst(input, firstMatch); + + // parse input + parseCommand(input, false); + + // if have many , default match first, if press tab again , switch to next + SWords * match = matchCommand(input, true); + if (match == NULL) { + // if not match , reset all index + firstMatchIndex = -1; + curMatchIndex = -1; + match = matchCommand(input, false); + if (match == NULL) { + freeCommand(input); + if (input->source) + taosMemoryFree(input->source); + taosMemoryFree(input); + return false; + } + } + + // print to screen + printScreen(con, cmd, match); + + // free + if (input->source) { + taosMemoryFree(input->source); + input->source = NULL; + } + freeCommand(input); + taosMemoryFree(input); + + return true; +} + +// fill with type +bool fillWithType(TAOS * con, SShellCmd * cmd, char* pre, int type) { + // get type + STire* tire = tires[type]; + char* str = matchNextPrefix(tire, pre); + if (str == NULL) { + return false; + } + + // need insert part string + char * part = str + strlen(pre); + + // show + int count = strlen(part); + shellInsertChar(cmd, part, count); + cntDel = count; // next press tab delete current append count + + taosMemoryFree(str); + return true; +} + +// fill with type +bool fillTableName(TAOS * con, SShellCmd * cmd, char* pre) { + // search stable and table + char * str = tireSearchWord(WT_VAR_STABLE, pre); + if (str == NULL) { + str = tireSearchWord(WT_VAR_TABLE, pre); + if(str == NULL) + return false; + } + + // need insert part string + char * part = str + strlen(pre); + + // delete autofill count last append + if(cntDel > 0) { + deleteCount(cmd, cntDel); + cntDel = 0; + } + + // show + int count = strlen(part); + shellInsertChar(cmd, part, count); + cntDel = count; // next press tab delete current append count + + taosMemoryFree(str); + return true; +} + +// +// find last word from sql select clause +// example : +// 1 select cou -> press tab select count( +// 2 select count(*),su -> select count(*), sum( +// 3 select count(*), su -> select count(*), sum( +// +char * lastWord(char * p) { + // get near from end revert find ' ' and ',' + char * p1 = strrchr(p, ' '); + char * p2 = strrchr(p, ','); + + if (p1 && p2) { + return p1 > p2 ? p1 : p2 + 1; + } else if (p1) { + return p1 + 1; + } else if(p2) { + return p2 + 1; + } else { + return p; + } +} + +bool fieldsInputEnd(char* sql) { + // not in '()' + char* p1 = strrchr(sql, '('); + char* p2 = strrchr(sql, ')'); + if (p1 && p2 == NULL) { + // like select count( ' ' + return false; + } else if (p1 && p2 && p1 > p2) { + // like select sum(age), count( ' ' + return false; + } + + // not in ',' + char * p3 = strrchr(sql, ','); + char * p = p3; + // like select ts, age,' ' + if (p) { + ++p; + bool allBlank = true; // after last ',' all char is blank + int cnt = 0; // blank count , like ' ' as one blank + char * plast = NULL; // last blank position + while(*p) { + if (*p == ' ') { + plast = p; + cnt ++; + } else { + allBlank = false; + } + ++p; + } + + // any one word is not blank + if(allBlank) { + return false; + } + + // like 'select count(*),sum(age) fr' need return true + if (plast && plast > p3 && p2 > p1 && plast > p2 && p1 > p3) { + return true; + } + + // if last char not ' ', then not end field, like 'select count(*), su' can fill sum( + if(sql[strlen(sql)-1] != ' ' && cnt <= 1) { + return false; + } + } + + char * p4 = strrchr(sql, ' '); + if(p4 == NULL) { + // only one word + return false; + } + + return true; +} + +// need insert from +bool needInsertFrom(char * sql, int len) { + // last is blank + if(sql[len-1] != ' ') { + // insert from keyword + return false; + } + + // select fields input is end + if (!fieldsInputEnd(sql)) { + return false; + } + + // can insert from keyword + return true; +} + +// p is string following select keyword +bool appendAfterSelect(TAOS * con, SShellCmd * cmd, char* sql, int32_t len) { + char* p = strndup(sql, len); + + // union all + char * p1; + do { + p1 = strstr(p, UNION_ALL); + if(p1) { + p = p1 + strlen(UNION_ALL); + } + } while (p1); + + char * from = strstr(p, " from "); + //last word , maybe empty string or some letters of a string + char * last = lastWord(p); + bool ret = false; + if (from == NULL) { + bool fieldEnd = fieldsInputEnd(p); + // cheeck fields input end then insert from keyword + if (fieldEnd && p[len-1] == ' ') { + shellInsertChar(cmd, "from", 4); + taosMemoryFree(p); + return true; + } + + // fill funciton + if(fieldEnd) { + // fields is end , need match keyword + ret = fillWithType(con, cmd, last, WT_VAR_KEYWORD); + } else { + ret = fillWithType(con, cmd, last, WT_VAR_FUNC); + } + + taosMemoryFree(p); + return ret; + } + + // have from + char * blank = strstr(from + 6, " "); + if (blank == NULL) { + // no table name, need fill + ret = fillTableName(con, cmd, last); + } else { + ret = fillWithType(con, cmd, last, WT_VAR_KEYWORD); + } + + taosMemoryFree(p); + return ret; +} + +int32_t searchAfterSelect(char* p, int32_t len) { + // select * from st; + if(strncasecmp(p, "select ", 7) == 0) { + // check nest query + char *p1 = p + 7; + while(1) { + char *p2 = strstr(p1, "select "); + if(p2 == NULL) + break; + p1 = p2 + 7; + } + + return p1 - p; + } + + // explain as select * from st; + if(strncasecmp(p, "explain select ", 15) == 0) { + return 15; + } + + char* as_pos_end = strstr(p, " as select "); + if (as_pos_end == NULL) + return -1; + as_pos_end += 11; + + // create stream as select + if(strncasecmp(p, "create stream ", 14) == 0) { + return as_pos_end - p;; + } + + // create topic as select + if(strncasecmp(p, "create topic ", 13) == 0) { + return as_pos_end - p; + } + + return -1; +} + +bool matchSelectQuery(TAOS * con, SShellCmd * cmd) { + // if continue press Tab , delete bytes by previous autofill + if (cntDel > 0) { + deleteCount(cmd, cntDel); + cntDel = 0; + } + + // match select ... + int len = cmd->commandSize; + char * p = cmd->command; + + // remove prefix blank + while (p[0] == ' ' && len > 0) { + p++; + len--; + } + + // special range + if(len < 7 || len > 512) { + return false; + } + + // search + char* sql_cp = strndup(p, len); + int32_t n = searchAfterSelect(sql_cp, len); + taosMemoryFree(sql_cp); + if(n == -1 || n > len) + return false; + p += n; + len -= n; + + // append + return appendAfterSelect(con, cmd, p, len); +} + +// if is input create fields or tags area, return true +bool isCreateFieldsArea(char * p) { + char * left = strrchr(p, '('); + if (left == NULL) { + // like 'create table st' + return false; + } + + char * right = strrchr(p, ')'); + if(right == NULL) { + // like 'create table st( ' + return true; + } + + if (left > right) { + // like 'create table st( ts timestamp, age int) tags(area ' + return true; + } + + return false; +} + +bool matchCreateTable(TAOS * con, SShellCmd * cmd) { + // if continue press Tab , delete bytes by previous autofill + if (cntDel > 0) { + deleteCount(cmd, cntDel); + cntDel = 0; + } + + // match select ... + int len = cmd->commandSize; + char * p = cmd->command; + + // remove prefix blank + while (p[0] == ' ' && len > 0) { + p++; + len--; + } + + // special range + if(len < 7 || len > 1024) { + return false; + } + + // select and from + if(strncasecmp(p, "create table ", 13) != 0) { + // not select query clause + return false; + } + p += 13; + len -= 13; + + char* ps = strndup(p, len); + bool ret = false; + char * last = lastWord(ps); + + // check in create fields or tags input area + if (isCreateFieldsArea(ps)) { + ret = fillWithType(con, cmd, last, WT_VAR_DATATYPE); + } + + // tags + if (!ret) { + // find only one ')' , can insert tags + char * p1 = strchr(ps, ')'); + if (p1) { + if(strchr(p1 + 1, ')') == NULL && strstr(p1 + 1, "tags") == NULL) { + // can insert tags keyword + ret = fillWithType(con, cmd, last, WT_VAR_KEYTAGS); + } + } + } + + // tb options + if (!ret) { + // find like create talbe st (...) tags(..) + char * p1 = strchr(ps, ')'); // first ')' end + if (p1) { + if(strchr(p1 + 1, ')')) { // second ')' end + // here is tb options area, can insert option + ret = fillWithType(con, cmd, last, WT_VAR_TBOPTION); + } + } + } + + taosMemoryFree(ps); + return ret; +} + +bool matchOther(TAOS * con, SShellCmd * cmd) { + int len = cmd->commandSize; + char* p = cmd->command; + + // '\\' + if (p[len - 1] == '\\') { + // append '\G' + char a[] = "G;"; + shellInsertChar(cmd, a, 2); + return true; + } + + // too small + if(len < 8) + return false; + + // like 'from ( ' + char* sql = strndup(p, len); + char* last = lastWord(sql); + + if (strcmp(last, "from(") == 0) { + fillWithType(con, cmd, "", WT_VAR_KEYSELECT); + taosMemoryFree(sql); + return true; + } + if (strncmp(last, "(", 1) == 0) { + last += 1; + } + + char* from = strstr(sql, " from"); + // find last ' from' + while (from) { + char* p1 = strstr(from + 5, " from"); + if (p1 == NULL) + break; + from = p1; + } + + if (from) { + // find next is '(' + char * p2 = from + 5; + bool found = false; // found 'from ... ( ...' ... is any count of blank + bool found1 = false; // found '(' + while (1) { + if ( p2 == last || *p2 == '\0') { + // last word or string end + if (found1) { + found = true; + } + break; + } else if(*p2 == '(') { + found1 = true; + } else if(*p2 == ' ') { + // do nothing + } else { + // have any other char + break; + } + + // move next + p2++; + } + + if (found) { + fillWithType(con, cmd, last, WT_VAR_KEYSELECT); + taosMemoryFree(sql); + return true; + } + } + + // INSERT + + + taosMemoryFree(sql); + + return false; +} + + +// main key press tab +void pressTabKey(SShellCmd * cmd) { + // check + if (cmd->commandSize == 0) { + // empty + showHelp(); + shellShowOnScreen(cmd); + return ; + } + + // save connection to global + varCmd = cmd; + bool matched = false; + + // manual match like create table st( ... + matched = matchCreateTable(varCon, cmd); + if (matched) + return ; + + // shellCommands match + if (firstMatchIndex == -1) { + matched = firstMatchCommand(varCon, cmd); + } else { + matched = nextMatchCommand(varCon, cmd, &shellCommands[firstMatchIndex]); + } + if (matched) + return ; + + // NOT MATCHED ANYONE + // match other like '\G' ... + matched = matchOther(varCon, cmd); + if (matched) + return ; + + // manual match like select * from ... + matched = matchSelectQuery(varCon, cmd); + if (matched) + return ; + + return ; +} + +// press othr key +void pressOtherKey(char c) { + // reset global variant + firstMatchIndex = -1; + lastMatchIndex = -1; + curMatchIndex = -1; + lastWordBytes = -1; + + // var names + cursorVar = -1; + varMode = false; + waitAutoFill = false; + cntDel = 0; + + if (lastMatch) { + freeMatch(lastMatch); + lastMatch = NULL; + } +} + +// put name into name, return name length +int getWordName(char* p, char * name, int nameLen) { + //remove prefix blank + while (*p == ' ') { + p++; + } + + // get databases name; + int i = 0; + while(p[i] != 0 && i < nameLen - 1) { + name[i] = p[i]; + i++; + if(p[i] == ' ' || p[i] == ';'|| p[i] == '(') { + // name end + break; + } + } + name[i] = 0; + + return i; +} + +// deal use db, if have 'use' return true +bool dealUseDB(char * sql) { + // check use keyword + if(strncasecmp(sql, "use ", 4) != 0) { + return false; + } + + char db[256]; + char *p = sql + 4; + if (getWordName(p, db, sizeof(db)) == 0) { + // no name , return + return true; + } + + // dbName is previous use open db name + if (strcasecmp(db, dbName) == 0) { + // same , no need switch + return true; + } + + // switch new db + taosThreadMutexLock(&tiresMutex); + // STABLE set null + STire* tire = tires[WT_VAR_STABLE]; + tires[WT_VAR_STABLE] = NULL; + if(tire) { + freeTire(tire); + } + // TABLE set null + tire = tires[WT_VAR_TABLE]; + tires[WT_VAR_TABLE] = NULL; + if(tire) { + freeTire(tire); + } + // save + strcpy(dbName, db); + taosThreadMutexUnlock(&tiresMutex); + + return true; +} + +// deal create, if have 'create' return true +bool dealCreateCommand(char * sql) { + // check keyword + if(strncasecmp(sql, "create ", 7) != 0) { + return false; + } + + char name[1024]; + char *p = sql + 7; + if (getWordName(p, name, sizeof(name)) == 0) { + // no name , return + return true; + } + + int type = -1; + // dbName is previous use open db name + if (strcasecmp(name, "database") == 0) { + type = WT_VAR_DBNAME; + } else if (strcasecmp(name, "table") == 0) { + if(strstr(sql, " tags") != NULL && strstr(sql, " using ") == NULL) + type = WT_VAR_STABLE; + else + type = WT_VAR_TABLE; + } else if (strcasecmp(name, "user") == 0) { + type = WT_VAR_USERNAME; + } else if (strcasecmp(name, "topic") == 0) { + type = WT_VAR_TOPIC; + } else if (strcasecmp(name, "stream") == 0) { + type = WT_VAR_STREAM; + } else { + // no match , return + return true; + } + + // move next + p += strlen(name); + + // get next word , that is table name + if (getWordName(p, name, sizeof(name)) == 0) { + // no name , return + return true; + } + + // switch new db + taosThreadMutexLock(&tiresMutex); + // STABLE set null + STire* tire = tires[type]; + if(tire) { + insertWord(tire, name); + } + taosThreadMutexUnlock(&tiresMutex); + + return true; +} + +// deal create, if have 'drop' return true +bool dealDropCommand(char * sql) { + // check keyword + if(strncasecmp(sql, "drop ", 5) != 0) { + return false; + } + + char name[1024]; + char *p = sql + 5; + if (getWordName(p, name, sizeof(name)) == 0) { + // no name , return + return true; + } + + int type = -1; + // dbName is previous use open db name + if (strcasecmp(name, "database") == 0) { + type = WT_VAR_DBNAME; + } else if (strcasecmp(name, "table") == 0) { + type = WT_VAR_ALLTABLE; + } else if (strcasecmp(name, "dnode") == 0) { + type = WT_VAR_DNODEID; + } else if (strcasecmp(name, "user") == 0) { + type = WT_VAR_USERNAME; + } else if (strcasecmp(name, "topic") == 0) { + type = WT_VAR_TOPIC; + } else if (strcasecmp(name, "stream") == 0) { + type = WT_VAR_STREAM; + } else { + // no match , return + return true; + } + + // move next + p += strlen(name); + + // get next word , that is table name + if (getWordName(p, name, sizeof(name)) == 0) { + // no name , return + return true; + } + + // switch new db + taosThreadMutexLock(&tiresMutex); + // STABLE set null + if(type == WT_VAR_ALLTABLE) { + bool del = false; + // del in stable + STire* tire = tires[WT_VAR_STABLE]; + if(tire) + del = deleteWord(tire, name); + // del in table + if(!del) { + tire = tires[WT_VAR_TABLE]; + if(tire) + del = deleteWord(tire, name); + } + } else { + // OTHER TYPE + STire* tire = tires[type]; + if(tire) + deleteWord(tire, name); + } + taosThreadMutexUnlock(&tiresMutex); + + return true; +} + +// callback autotab module after shell sql execute +void callbackAutoTab(char* sqlstr, TAOS* pSql, bool usedb) { + char * sql = sqlstr; + // remove prefix blank + while (*sql == ' ') { + sql++; + } + + if(dealUseDB(sql)) { + // change to new db + return ; + } + + // create command add name to autotab + if(dealCreateCommand(sql)) { + return ; + } + + // drop command remove name from autotab + if(dealDropCommand(sql)) { + return ; + } + + return ; +} diff --git a/tools/shell/src/shellCommand.c b/tools/shell/src/shellCommand.c index b73317e991..cffa02824e 100644 --- a/tools/shell/src/shellCommand.c +++ b/tools/shell/src/shellCommand.c @@ -15,6 +15,7 @@ #define __USE_XOPEN #include "shellInt.h" +#include "shellAuto.h" #define LEFT 1 #define RIGHT 2 @@ -23,20 +24,11 @@ #define PSIZE shell.info.promptSize #define SHELL_INPUT_MAX_COMMAND_SIZE 10000 -typedef struct { - char *buffer; - char *command; - uint32_t commandSize; - uint32_t bufferSize; - uint32_t cursorOffset; - uint32_t screenOffset; - uint32_t endOffset; -} SShellCmd; static int32_t shellCountPrefixOnes(uint8_t c); -static void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width); + static void shellGetNextCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width); -static void shellInsertChar(SShellCmd *cmd, char *c, int size); + static void shellBackspaceChar(SShellCmd *cmd); static void shellClearLineBefore(SShellCmd *cmd); static void shellClearLineAfter(SShellCmd *cmd); @@ -51,8 +43,10 @@ static void shellUpdateBuffer(SShellCmd *cmd); static int32_t shellIsReadyGo(SShellCmd *cmd); static void shellGetMbSizeInfo(const char *str, int32_t *size, int32_t *width); static void shellResetCommand(SShellCmd *cmd, const char s[]); -static void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); -static void shellShowOnScreen(SShellCmd *cmd); +void shellClearScreen(int32_t ecmd_pos, int32_t cursor_pos); +void shellShowOnScreen(SShellCmd *cmd); +void shellGetPrevCharSize(const char *str, int32_t pos, int32_t *size, int32_t *width); +void shellInsertChar(SShellCmd *cmd, char *c, int size); int32_t shellCountPrefixOnes(uint8_t c) { uint8_t mask = 127; @@ -107,8 +101,11 @@ void shellInsertChar(SShellCmd *cmd, char *c, int32_t size) { /* update the values */ cmd->commandSize += size; cmd->cursorOffset += size; - cmd->screenOffset += taosWcharWidth(wc); - cmd->endOffset += taosWcharWidth(wc); + for (int i = 0; i < size; i++) { + taosMbToWchar(&wc, c + i, size); + cmd->screenOffset += taosWcharWidth(wc); + cmd->endOffset += taosWcharWidth(wc); + } #ifdef WINDOWS #else shellShowOnScreen(cmd); @@ -209,6 +206,15 @@ void shellPositionCursorHome(SShellCmd *cmd) { } } +void positionCursorMiddle(SShellCmd *cmd) { + if (cmd->endOffset > 0) { + shellClearScreen(cmd->endOffset + PSIZE, cmd->screenOffset + PSIZE); + cmd->cursorOffset = cmd->commandSize/2; + cmd->screenOffset = cmd->endOffset/2; + shellShowOnScreen(cmd); + } +} + void shellPositionCursorEnd(SShellCmd *cmd) { assert(cmd->cursorOffset <= cmd->commandSize && cmd->endOffset >= cmd->screenOffset); @@ -464,7 +470,12 @@ int32_t shellReadCommand(char *command) { utf8_array[k] = c; } shellInsertChar(&cmd, utf8_array, count); + pressOtherKey(c); + } else if (c == TAB_KEY) { + // press TAB key + pressTabKey(&cmd); } else if (c < '\033') { + pressOtherKey(c); // Ctrl keys. TODO: Implement ctrl combinations switch (c) { case 0: @@ -519,8 +530,12 @@ int32_t shellReadCommand(char *command) { case 21: // Ctrl + U; shellClearLineBefore(&cmd); break; + case 23: // Ctrl + W; + positionCursorMiddle(&cmd); + break; } } else if (c == '\033') { + pressOtherKey(c); c = taosGetConsoleChar(); switch (c) { case '[': @@ -597,9 +612,11 @@ int32_t shellReadCommand(char *command) { break; } } else if (c == 0x7f) { + pressOtherKey(c); // press delete key shellBackspaceChar(&cmd); } else { + pressOtherKey(c); shellInsertChar(&cmd, &c, 1); } } diff --git a/tools/shell/src/shellEngine.c b/tools/shell/src/shellEngine.c index 45d5489803..abb6cf84d5 100644 --- a/tools/shell/src/shellEngine.c +++ b/tools/shell/src/shellEngine.c @@ -19,6 +19,7 @@ #define _XOPEN_SOURCE #define _DEFAULT_SOURCE #include "shellInt.h" +#include "shellAuto.h" static bool shellIsEmptyCommand(const char *cmd); static int32_t shellRunSingleCommand(char *command); @@ -87,9 +88,15 @@ int32_t shellRunSingleCommand(char *command) { if (shellRegexMatch(command, "^[ \t]*source[\t ]+[^ ]+[ \t;]*$", REG_EXTENDED | REG_ICASE)) { /* If source file. */ char *c_ptr = strtok(command, " ;"); - assert(c_ptr != NULL); + if (c_ptr == NULL) { + shellRunSingleCommandImp(command); + return 0; + } c_ptr = strtok(NULL, " ;"); - assert(c_ptr != NULL); + if (c_ptr == NULL) { + shellRunSingleCommandImp(command); + return 0; + } shellSourceFile(c_ptr); return 0; } @@ -193,6 +200,9 @@ void shellRunSingleCommandImp(char *command) { fprintf(stdout, "Database changed.\r\n\r\n"); fflush(stdout); + // call back auto tab module + callbackAutoTab(command, pSql, true); + taos_free_result(pSql); return; @@ -217,6 +227,9 @@ void shellRunSingleCommandImp(char *command) { taos_free_result(pSql); et = taosGetTimestampUs(); printf("Query OK, %d of %d rows affected (%.6fs)\r\n", num_rows_affacted, num_rows_affacted, (et - st) / 1E6); + + // call auto tab + callbackAutoTab(command, pSql, false); } printf("\r\n"); @@ -774,9 +787,9 @@ void shellReadHistory() { TdFilePtr pFile = taosOpenFile(pHistory->file, TD_FILE_READ | TD_FILE_STREAM); if (pFile == NULL) return; - char *line = NULL; + char *line = taosMemoryMalloc(TSDB_MAX_ALLOWED_SQL_LEN + 1); int32_t read_size = 0; - while ((read_size = taosGetLineFile(pFile, &line)) != -1) { + 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); @@ -788,7 +801,7 @@ void shellReadHistory() { } } - if (line != NULL) taosMemoryFree(line); + taosMemoryFreeClear(line); taosCloseFile(&pFile); int64_t file_size; if (taosStatFile(pHistory->file, &file_size, NULL) == 0 && file_size > SHELL_MAX_COMMAND_SIZE) { @@ -852,7 +865,6 @@ void shellSourceFile(const char *file) { int32_t read_len = 0; char *cmd = taosMemoryCalloc(1, TSDB_MAX_ALLOWED_SQL_LEN + 1); size_t cmd_len = 0; - char *line = NULL; char fullname[PATH_MAX] = {0}; char sourceFileCommand[PATH_MAX + 8] = {0}; @@ -870,7 +882,8 @@ void shellSourceFile(const char *file) { return; } - while ((read_len = taosGetLineFile(pFile, &line)) != -1) { + char *line = taosMemoryMalloc(TSDB_MAX_ALLOWED_SQL_LEN + 1); + while ((read_len = taosGetsFile(pFile, TSDB_MAX_ALLOWED_SQL_LEN, line)) != -1) { if (read_len >= TSDB_MAX_ALLOWED_SQL_LEN) continue; line[--read_len] = '\0'; @@ -897,7 +910,7 @@ void shellSourceFile(const char *file) { } taosMemoryFree(cmd); - if (line != NULL) taosMemoryFree(line); + taosMemoryFreeClear(line); taosCloseFile(&pFile); } @@ -1053,6 +1066,7 @@ int32_t shellExecute() { } #endif + shellSetConn(shell.conn); shellReadHistory(); if (pArgs->commands != NULL || pArgs->file[0] != 0) { @@ -1098,6 +1112,7 @@ int32_t shellExecute() { #ifdef WEBSOCKET if (!shell.args.restful && !shell.args.cloud) { #endif + printfIntroduction(); shellGetGrantInfo(); #ifdef WEBSOCKET } diff --git a/tools/shell/src/shellMain.c b/tools/shell/src/shellMain.c index 964082f3c3..fa3c0f2585 100644 --- a/tools/shell/src/shellMain.c +++ b/tools/shell/src/shellMain.c @@ -15,6 +15,7 @@ #define __USE_XOPEN #include "shellInt.h" +#include "shellAuto.h" SShellObj shell = {0}; @@ -70,5 +71,9 @@ int main(int argc, char *argv[]) { return 0; } - return shellExecute(); + // support port feature + shellAutoInit(); + int32_t ret = shellExecute(); + shellAutoExit(); + return ret; } diff --git a/tools/shell/src/shellTire.c b/tools/shell/src/shellTire.c new file mode 100644 index 0000000000..dc5efa4e8d --- /dev/null +++ b/tools/shell/src/shellTire.c @@ -0,0 +1,435 @@ +/* + * 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 __USE_XOPEN + +#include "os.h" +#include "shellTire.h" + +// ----------- interface ------------- + +// create prefix search tree +STire* createTire(char type) { + STire* tire = taosMemoryMalloc(sizeof(STire)); + memset(tire, 0, sizeof(STire)); + tire->ref = 1; // init is 1 + tire->type = type; + tire->root.d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *)); + return tire; +} + +// free tire node +void freeTireNode(STireNode* node) { + if (node == NULL) + return ; + + // nest free sub node on array d + if(node->d) { + for (int i = 0; i < CHAR_CNT; i++) { + freeTireNode(node->d[i]); + } + taosMemoryFree(node->d); + } + + // free self + taosMemoryFree(node); +} + +// destroy prefix search tree +void freeTire(STire* tire) { + // free nodes + for (int i = 0; i < CHAR_CNT; i++) { + freeTireNode(tire->root.d[i]); + } + taosMemoryFree(tire->root.d); + + // free from list + StrName * item = tire->head; + while (item) { + StrName * next = item->next; + // free string + taosMemoryFree(item->name); + // free node + taosMemoryFree(item); + + // move next + item = next; + } + tire->head = tire->tail = NULL; + + // free tire + taosMemoryFree(tire); +} + +// insert a new word to list +bool insertToList(STire* tire, char* word) { + StrName * p = (StrName *)taosMemoryMalloc(sizeof(StrName)); + p->name = strdup(word); + p->next = NULL; + + if(tire->head == NULL) { + tire->head = p; + tire->tail = p; + }else { + tire->tail->next = p; + tire->tail = p; + } + + return true; +} + +// insert a new word to tree +bool insertToTree(STire* tire, char* word, int len) { + int m = 0; + STireNode ** nodes = tire->root.d; + for (int i = 0; i < len; i++) { + m = word[i] - FIRST_ASCII; + if (m < 0 || m > CHAR_CNT) { + return false; + } + + if (nodes[m] == NULL) { + // no pointer + STireNode* p = (STireNode* )taosMemoryMalloc(sizeof(STireNode)); + memset(p, 0, sizeof(STireNode)); + nodes[m] = p; + if (i == len - 1) { + // is end + p->end = true; + break; + } + } + + if (nodes[m]->d == NULL) { + // malloc d + nodes[m]->d = (STireNode **)taosMemoryCalloc(CHAR_CNT, sizeof(STireNode *)); + } + + // move to next node + nodes = nodes[m]->d; + } + + // add count + tire->count += 1; + return true; +} + +// insert a new word +bool insertWord(STire* tire, char* word) { + int len = strlen(word); + if (len >= MAX_WORD_LEN) { + return false; + } + + switch (tire->type) { + case TIRE_TREE: + return insertToTree(tire, word, len); + case TIRE_LIST: + return insertToList(tire, word); + default: + break; + } + return false; +} + +// delete one word from list +bool deleteFromList(STire* tire, char* word) { + StrName * item = tire->head; + while (item) { + if (strcmp(item->name, word) == 0) { + // found, reset empty to delete + item->name[0] = 0; + } + + // move next + item = item->next; + } + return true; +} + +// delete one word from tree +bool deleteFromTree(STire* tire, char* word, int len) { + int m = 0; + bool del = false; + + STireNode** nodes = tire->root.d; + for (int i = 0; i < len; i++) { + m = word[i] - FIRST_ASCII; + if (m < 0 || m >= CHAR_CNT) { + return false; + } + + if (nodes[m] == NULL) { + // no found + return false; + } else { + // not null + if(i == len - 1) { + // this is last, only set end false , not free node + nodes[m]->end = false; + del = true; + break; + } + } + + if(nodes[m]->d == NULL) + break; + // move to next node + nodes = nodes[m]->d; + } + + // reduce count + if (del) { + tire->count -= 1; + } + + return del; +} + +// insert a new word +bool deleteWord(STire* tire, char* word) { + int len = strlen(word); + if (len >= MAX_WORD_LEN) { + return false; + } + + switch (tire->type) { + case TIRE_TREE: + return deleteFromTree(tire, word, len); + case TIRE_LIST: + return deleteFromList(tire, word); + default: + break; + } + return false; +} + +void addWordToMatch(SMatch* match, char* word){ + // malloc new + SMatchNode* node = (SMatchNode* )taosMemoryMalloc(sizeof(SMatchNode)); + memset(node, 0, sizeof(SMatchNode)); + node->word = strdup(word); + + // append to match + if (match->head == NULL) { + match->head = match->tail = node; + } else { + match->tail->next = node; + match->tail = node; + } + match->count += 1; +} + +// enum all words from node +void enumAllWords(STireNode** nodes, char* prefix, SMatch* match) { + STireNode * c; + char word[MAX_WORD_LEN]; + int len = strlen(prefix); + for (int i = 0; i < CHAR_CNT; i++) { + c = nodes[i]; + + if (c == NULL) { + // chain end node + continue; + } else { + // combine word string + memset(word, 0, sizeof(word)); + strcpy(word, prefix); + word[len] = FIRST_ASCII + i; // append current char + + // chain middle node + if (c->end) { + // have end flag + addWordToMatch(match, word); + } + // nested call next layer + if (c->d) + enumAllWords(c->d, word, match); + } + } +} + +// match prefix from list +void matchPrefixFromList(STire* tire, char* prefix, SMatch* match) { + StrName * item = tire->head; + int len = strlen(prefix); + while (item) { + if ( strncmp(item->name, prefix, len) == 0) { + // prefix matched + addWordToMatch(match, item->name); + } + + // move next + item = item->next; + } +} + +// match prefix words, if match is not NULL , put all item to match and return match +void matchPrefixFromTree(STire* tire, char* prefix, SMatch* match) { + SMatch* root = match; + int m = 0; + STireNode* c = 0; + int len = strlen(prefix); + if (len >= MAX_WORD_LEN) { + return; + } + + STireNode** nodes = tire->root.d; + for (int i = 0; i < len; i++) { + m = prefix[i] - FIRST_ASCII; + if (m < 0 || m > CHAR_CNT) { + return; + } + + // match + c = nodes[m]; + if (c == NULL) { + // arrive end + break; + } + + // previous items already matched + if (i == len - 1) { + // malloc match if not pass by param match + if (root == NULL) { + root = (SMatch* )taosMemoryMalloc(sizeof(SMatch)); + memset(root, 0, sizeof(SMatch)); + strcpy(root->pre, prefix); + } + + // prefix is match to end char + if (c->d) + enumAllWords(c->d, prefix, root); + } else { + // move to next node continue match + if(c->d == NULL) + break; + nodes = c->d; + } + } + + // return + return ; +} + +SMatch* matchPrefix(STire* tire, char* prefix, SMatch* match) { + if(match == NULL) { + match = (SMatch* )taosMemoryMalloc(sizeof(SMatch)); + memset(match, 0, sizeof(SMatch)); + } + + switch (tire->type) { + case TIRE_TREE: + matchPrefixFromTree(tire, prefix, match); + case TIRE_LIST: + matchPrefixFromList(tire, prefix, match); + default: + break; + } + + // return if need + if (match->count == 0) { + freeMatch(match); + match = NULL; + } + + return match; +} + + +// get all items from tires tree +void enumFromList(STire* tire, SMatch* match) { + StrName * item = tire->head; + while (item) { + if (item->name[0] != 0) { + // not delete + addWordToMatch(match, item->name); + } + + // move next + item = item->next; + } +} + +// get all items from tires tree +void enumFromTree(STire* tire, SMatch* match) { + char pre[2] ={0, 0}; + STireNode* c; + + // enum first layer + for (int i = 0; i < CHAR_CNT; i++) { + pre[0] = FIRST_ASCII + i; + + // each node + c = tire->root.d[i]; + if (c == NULL) { + // this branch no data + continue; + } + + // this branch have data + if(c->end) + addWordToMatch(match, pre); + else + matchPrefix(tire, pre, match); + } +} + +// get all items from tires tree +SMatch* enumAll(STire* tire) { + SMatch* match = (SMatch* )taosMemoryMalloc(sizeof(SMatch)); + memset(match, 0, sizeof(SMatch)); + + switch (tire->type) { + case TIRE_TREE: + enumFromTree(tire, match); + case TIRE_LIST: + enumFromList(tire, match); + default: + break; + } + + // return if need + if (match->count == 0) { + freeMatch(match); + match = NULL; + } + + return match; +} + + +// free match result +void freeMatchNode(SMatchNode* node) { + // first free next + if (node->next) + freeMatchNode(node->next); + + // second free self + if (node->word) + taosMemoryFree(node->word); + taosMemoryFree(node); +} + +// free match result +void freeMatch(SMatch* match) { + // first free next + if (match->head) { + freeMatchNode(match->head); + } + + // second free self + taosMemoryFree(match); +} diff --git a/utils/tsim/src/simExe.c b/utils/tsim/src/simExe.c index 5bb53287db..4fe5fdf672 100644 --- a/utils/tsim/src/simExe.c +++ b/utils/tsim/src/simExe.c @@ -237,9 +237,9 @@ int32_t simExecuteExpression(SScript *script, char *exp) { int32_t var3Len = 0; int32_t val0 = 0; int32_t val1 = 0; - char t0[1024] = {0}; - char t1[1024] = {0}; - char t2[1024] = {0}; + char t0[2048] = {0}; + char t1[2048] = {0}; + char t2[2048] = {0}; char t3[2048] = {0}; int32_t result = 0; @@ -256,7 +256,7 @@ int32_t simExecuteExpression(SScript *script, char *exp) { } if (var2[0] == '$') { - tstrncpy(t1, simGetVariable(script, var2 + 1, var2Len - 1), 1024); + tstrncpy(t1, simGetVariable(script, var2 + 1, var2Len - 1), sizeof(t1)); } else { memcpy(t1, var2, var2Len); t1[var2Len] = 0; @@ -266,7 +266,7 @@ int32_t simExecuteExpression(SScript *script, char *exp) { rest = paGetToken(rest, &var3, &var3Len); if (var3[0] == '$') - strcpy(t2, simGetVariable(script, var3 + 1, var3Len - 1)); + tstrncpy(t2, simGetVariable(script, var3 + 1, var3Len - 1), sizeof(t2)); else { memcpy(t2, var3, var3Len); t2[var3Len] = 0; @@ -291,7 +291,7 @@ int32_t simExecuteExpression(SScript *script, char *exp) { sprintf(t3, "%s%s", t1, t2); } } else { - strcpy(t3, t1); + tstrncpy(t3, t1, sizeof(t3)); } result = 0;