Merge remote-tracking branch 'tdengine/3.0' into freemine.lemon.warning.as.error
|
@ -0,0 +1,66 @@
|
|||
name: TDengine Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- 'main'
|
||||
- '3.0'
|
||||
- '3.1'
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
name: Run unit tests
|
||||
|
||||
steps:
|
||||
- name: Checkout the repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: 1.18
|
||||
|
||||
- name: Install system dependencies
|
||||
run: |
|
||||
sudo apt update -y
|
||||
sudo apt install -y build-essential cmake \
|
||||
libgeos-dev libjansson-dev libsnappy-dev liblzma-dev libz-dev \
|
||||
zlib1g pkg-config libssl-dev gawk
|
||||
|
||||
|
||||
- name: Build and install TDengine
|
||||
run: |
|
||||
mkdir debug && cd debug
|
||||
cmake .. -DBUILD_HTTP=false -DBUILD_JDBC=false \
|
||||
-DBUILD_TOOLS=true -DBUILD_TEST=off \
|
||||
-DBUILD_KEEPER=true -DBUILD_DEPENDENCY_TESTS=false
|
||||
make -j 4
|
||||
sudo make install
|
||||
which taosd
|
||||
which taosadapter
|
||||
which taoskeeper
|
||||
|
||||
- name: Start taosd
|
||||
run: |
|
||||
cp /etc/taos/taos.cfg ./
|
||||
sudo echo "supportVnodes 256" >> taos.cfg
|
||||
nohup sudo taosd -c taos.cfg &
|
||||
|
||||
- name: Start taosadapter
|
||||
run: nohup sudo taosadapter &
|
||||
|
||||
- name: Run tests with taosBenchmark
|
||||
run: |
|
||||
taosBenchmark -t 10 -n 10 -y
|
||||
taos -s "select count(*) from test.meters"
|
||||
|
||||
- name: Clean up
|
||||
if: always()
|
||||
run: |
|
||||
if pgrep taosd; then sudo pkill taosd; fi
|
||||
if pgrep taosadapter; then sudo pkill taosadapter; fi
|
|
@ -7,6 +7,9 @@ file_zh_changed = ''
|
|||
file_en_changed = ''
|
||||
file_no_doc_changed = '1'
|
||||
file_only_tdgpt_change_except = '1'
|
||||
tdgpt_file = "forecastoperator.c|anomalywindowoperator.c|tanalytics.h|tanalytics.c|tdgpt_cases.task|analytics"
|
||||
|
||||
|
||||
def abortPreviousBuilds() {
|
||||
def currentJobName = env.JOB_NAME
|
||||
def currentBuildNumber = env.BUILD_NUMBER.toInteger()
|
||||
|
@ -67,7 +70,7 @@ def check_docs(){
|
|||
returnStdout: true
|
||||
)
|
||||
|
||||
file_no_doc_changed = sh (
|
||||
def file_no_doc_changed = sh (
|
||||
script: '''
|
||||
cd ${WKC}
|
||||
git --no-pager diff --name-only FETCH_HEAD `git merge-base FETCH_HEAD ${CHANGE_TARGET}`|grep -v "^docs/en/"|grep -v "^docs/zh/"|grep -v ".md$" || :
|
||||
|
@ -78,7 +81,7 @@ def check_docs(){
|
|||
file_only_tdgpt_change_except = sh (
|
||||
script: '''
|
||||
cd ${WKC}
|
||||
git --no-pager diff --name-only FETCH_HEAD `git merge-base FETCH_HEAD ${CHANGE_TARGET}`|grep -v "^docs/en/"|grep -v "^docs/zh/"|grep -v ".md$" | grep -v "forecastoperator.c\\|anomalywindowoperator.c\\|tanalytics.h\\|tanalytics.c" |grep -v "tsim/analytics" |grep -v "tdgpt_cases.task" || :
|
||||
git --no-pager diff --name-only FETCH_HEAD `git merge-base FETCH_HEAD ${CHANGE_TARGET}`|grep -v "^docs/en/"|grep -v "^docs/zh/"|grep -v ".md$" | grep -Ev "forecastoperator.c|anomalywindowoperator.c|tanalytics.h|tanalytics.c|tdgpt_cases.task|analytics" ||:
|
||||
''',
|
||||
returnStdout: true
|
||||
).trim()
|
||||
|
@ -570,7 +573,7 @@ pipeline {
|
|||
cd ${WKC}/tests/parallel_test
|
||||
./run_scan_container.sh -d ${WKDIR} -b ${BRANCH_NAME}_${BUILD_ID} -f ${WKDIR}/tmp/${BRANCH_NAME}_${BUILD_ID}/docs_changed.txt ''' + extra_param + '''
|
||||
'''
|
||||
if ( file_no_doc_changed =~ /forecastoperator.c|anomalywindowoperator.c|tsim\/analytics|tdgpt_cases.task/ ) {
|
||||
if ( file_no_doc_changed =~ /forecastoperator.c|anomalywindowoperator.c|tanalytics.h|tanalytics.c|tdgpt_cases.task|analytics/ ) {
|
||||
sh '''
|
||||
cd ${WKC}/tests/parallel_test
|
||||
export DEFAULT_RETRY_TIME=2
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
</p>
|
||||
<p>
|
||||
|
||||
[](https://github.com/taosdata/TDengine/actions/workflows/taosd-ci-build.yml)
|
||||
[](https://coveralls.io/github/taosdata/TDengine?branch=3.0)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4201)
|
||||
<br />
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taosadapter
|
||||
ExternalProject_Add(taosadapter
|
||||
GIT_REPOSITORY https://github.com/taosdata/taosadapter.git
|
||||
GIT_TAG main
|
||||
GIT_TAG 3.0
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosadapter"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taos-tools
|
||||
ExternalProject_Add(taos-tools
|
||||
GIT_REPOSITORY https://github.com/taosdata/taos-tools.git
|
||||
GIT_TAG main
|
||||
GIT_TAG 3.0
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taos-tools"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
# taosws-rs
|
||||
ExternalProject_Add(taosws-rs
|
||||
GIT_REPOSITORY https://github.com/taosdata/taos-connector-rust.git
|
||||
GIT_TAG main
|
||||
GIT_TAG 3.0
|
||||
SOURCE_DIR "${TD_SOURCE_DIR}/tools/taosws-rs"
|
||||
BINARY_DIR ""
|
||||
#BUILD_IN_SOURCE TRUE
|
||||
|
|
|
@ -17,7 +17,7 @@ TDengine is designed for various writing scenarios, and many of these scenarios
|
|||
|
||||
```sql
|
||||
COMPACT DATABASE db_name [start with 'XXXX'] [end with 'YYYY'];
|
||||
SHOW COMPACTS [compact_id];
|
||||
SHOW COMPACT [compact_id];
|
||||
KILL COMPACT compact_id;
|
||||
```
|
||||
|
||||
|
|
|
@ -9,13 +9,12 @@ Apache Superset provides an intuitive user interface that makes creating, sharin
|
|||
|
||||
Through the Python connector of TDengine, Superset can support TDengine data sources and provide functions such as data presentation and analysis
|
||||
|
||||
## Install Apache Superset
|
||||
## Prerequisites
|
||||
|
||||
Ensure that Apache Superset v2.1.0 or above is installed. If not, please visit [official website](https://superset.apache.org/) to install
|
||||
|
||||
## Install TDengine
|
||||
|
||||
Both TDengine Enterprise Edition and Community Edition are supported, with version requirements of 3.0 or higher
|
||||
Prepare the following environment:
|
||||
- TDengine is installed and running normally (both Enterprise and Community versions are available)
|
||||
- taosAdapter is running normally, refer to [taosAdapter](../../../reference/components/taosAdapter)
|
||||
- Apache Superset version 2.1.0 or above is already installed, refre to [Apache Superset](https://superset.apache.org/)
|
||||
|
||||
## Install TDengine Python Connector
|
||||
|
||||
|
|
|
@ -190,7 +190,8 @@ The effective value of charset is UTF-8.
|
|||
|Parameter Name |Supported Version |Dynamic Modification|Description|
|
||||
|-----------------------|-------------------------|--------------------|------------|
|
||||
|supportVnodes | |Supported, effective immediately |Maximum number of vnodes supported by a dnode, range 0-4096, default value is twice the number of CPU cores + 5|
|
||||
|numOfCommitThreads | |Supported, effective after restart|Maximum number of commit threads, range 0-1024, default value 4|
|
||||
|numOfCommitThreads | |Supported, effective after restart|Maximum number of commit threads, range 1-1024, default value 4|
|
||||
|numOfCompactThreads | |Supported, effective after restart|Maximum number of commit threads, range 1-16, default value 2|
|
||||
|numOfMnodeReadThreads | |Supported, effective after restart|Number of Read threads for mnode, range 0-1024, default value is one quarter of the CPU cores (not exceeding 4)|
|
||||
|numOfVnodeQueryThreads | |Supported, effective after restart|Number of Query threads for vnode, range 0-1024, default value is twice the number of CPU cores (not exceeding 16)|
|
||||
|numOfVnodeFetchThreads | |Supported, effective after restart|Number of Fetch threads for vnode, range 0-1024, default value is one quarter of the CPU cores (not exceeding 4)|
|
||||
|
|
|
@ -4,22 +4,17 @@ sidebar_label: taosdump
|
|||
slug: /tdengine-reference/tools/taosdump
|
||||
---
|
||||
|
||||
taosdump is a tool application that supports backing up data from a running TDengine cluster and restoring the backed-up data to the same or another running TDengine cluster.
|
||||
|
||||
taosdump can back up data using databases, supertables, or basic tables as logical data units, and can also back up data records within a specified time period from databases, supertables, and basic tables. You can specify the directory path for data backup; if not specified, taosdump defaults to backing up data to the current directory.
|
||||
|
||||
If the specified location already has data files, taosdump will prompt the user and exit immediately to avoid data being overwritten. This means the same path can only be used for one backup.
|
||||
If you see related prompts, please operate carefully.
|
||||
|
||||
taosdump is a logical backup tool, it should not be used to back up any raw data, environment settings, hardware information, server configuration, or cluster topology. taosdump uses [Apache AVRO](https://avro.apache.org/) as the data file format to store backup data.
|
||||
`taosdump` is a TDengine data backup/recovery tool provided for open source users, and the backed up data files adopt the standard [Apache AVRO](https://avro.apache.org/)
|
||||
Format, convenient for exchanging data with the external ecosystem.
|
||||
Taosdump provides multiple data backup and recovery options to meet different data needs, and all supported options can be viewed through --help.
|
||||
|
||||
## Installation
|
||||
|
||||
There are two ways to install taosdump:
|
||||
Taosdump provides two installation methods:
|
||||
|
||||
- Install the official taosTools package, please find taosTools on the [release history page](../../../release-history/taostools/) and download it for installation.
|
||||
- Taosdump is the default installation component in the TDengine installation package, which can be used after installing TDengine. For how to install TDengine, please refer to [TDengine Installation](../../../get-started/)
|
||||
|
||||
- Compile taos-tools separately and install, please refer to the [taos-tools](https://github.com/taosdata/taos-tools) repository for details.
|
||||
- Compile and install taos tools separately, refer to [taos tools](https://github.com/taosdata/taos-tools) .
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
|
@ -30,6 +25,9 @@ There are two ways to install taosdump:
|
|||
3. Backup certain supertables or basic tables in a specified database: use the `dbname stbname1 stbname2 tbname1 tbname2 ...` parameter, note that this input sequence starts with the database name, supports only one database, and the second and subsequent parameters are the names of the supertables or basic tables in that database, separated by spaces;
|
||||
4. Backup the system log database: TDengine clusters usually include a system database named `log`, which contains data for TDengine's own operation, taosdump does not back up the log database by default. If there is a specific need to back up the log database, you can use the `-a` or `--allow-sys` command line parameter.
|
||||
5. "Tolerant" mode backup: Versions after taosdump 1.4.1 provide the `-n` and `-L` parameters, used for backing up data without using escape characters and in "tolerant" mode, which can reduce backup data time and space occupied when table names, column names, and label names do not use escape characters. If unsure whether to use `-n` and `-L`, use the default parameters for "strict" mode backup. For an explanation of escape characters, please refer to the [official documentation](../../sql-manual/escape-characters/).
|
||||
6. If a backup file already exists in the directory specified by the `-o` parameter, to prevent data from being overwritten, taosdump will report an error and exit. Please replace it with another empty directory or clear the original data before backing up.
|
||||
7. Currently, taosdump does not support data breakpoint backup function. Once the data backup is interrupted, it needs to be started from scratch.
|
||||
If the backup takes a long time, it is recommended to use the (-S -E options) method to specify the start/end time for segmented backup.
|
||||
|
||||
:::tip
|
||||
|
||||
|
@ -42,7 +40,8 @@ There are two ways to install taosdump:
|
|||
|
||||
### taosdump Restore Data
|
||||
|
||||
Restore data files from a specified path: use the `-i` parameter along with the data file path. As mentioned earlier, the same directory should not be used to back up different data sets, nor should the same path be used to back up the same data set multiple times, otherwise, the backup data will cause overwriting or multiple backups.
|
||||
- Restore data files from a specified path: use the `-i` parameter along with the data file path. As mentioned earlier, the same directory should not be used to back up different data sets, nor should the same path be used to back up the same data set multiple times, otherwise, the backup data will cause overwriting or multiple backups.
|
||||
- taosdump supports data recovery to a new database name with the parameter `-W`, please refer to the command line parameter description for details.
|
||||
|
||||
:::tip
|
||||
taosdump internally uses the TDengine stmt binding API to write restored data, currently using 16384 as a batch for writing. If there are many columns in the backup data, it may cause a "WAL size exceeds limit" error, in which case you can try adjusting the `-B` parameter to a smaller value.
|
||||
|
@ -105,6 +104,13 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
the table name.(Version 2.5.3)
|
||||
-T, --thread-num=THREAD_NUM Number of thread for dump in file. Default is
|
||||
8.
|
||||
-W, --rename=RENAME-LIST Rename database name with new name during
|
||||
importing data. RENAME-LIST:
|
||||
"db1=newDB1|db2=newDB2" means rename db1 to newDB1
|
||||
and rename db2 to newDB2 (Version 2.5.4)
|
||||
-k, --retry-count=VALUE Set the number of retry attempts for connection or
|
||||
query failures
|
||||
-z, --retry-sleep-ms=VALUE retry interval sleep time, unit ms
|
||||
-C, --cloud=CLOUD_DSN specify a DSN to access TDengine cloud service
|
||||
-R, --restful Use RESTful interface to connect TDengine
|
||||
-t, --timeout=SECONDS The timeout seconds for websocket to interact.
|
||||
|
@ -112,10 +118,6 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
-?, --help Give this help list
|
||||
--usage Give a short usage message
|
||||
-V, --version Print program version
|
||||
-W, --rename=RENAME-LIST Rename database name with new name during
|
||||
importing data. RENAME-LIST:
|
||||
"db1=newDB1|db2=newDB2" means rename db1 to newDB1
|
||||
and rename db2 to newDB2 (Version 2.5.4)
|
||||
|
||||
Mandatory or optional arguments to long options are also mandatory or optional
|
||||
for any corresponding short options.
|
||||
|
|
|
@ -4,35 +4,38 @@ sidebar_label: taosBenchmark
|
|||
slug: /tdengine-reference/tools/taosbenchmark
|
||||
---
|
||||
|
||||
taosBenchmark (formerly known as taosdemo) is a tool for testing the performance of the TDengine product. taosBenchmark can test the performance of TDengine's insert, query, and subscription functions. It can simulate massive data generated by a large number of devices and flexibly control the number of databases, supertables, types and number of tag columns, types and number of data columns, number of subtables, data volume per subtable, data insertion interval, number of working threads in taosBenchmark, whether and how to insert out-of-order data, etc. To accommodate the usage habits of past users, the installation package provides taosdemo as a soft link to taosBenchmark.
|
||||
TaosBenchmark is a performance benchmarking tool for TDengine products, providing insertion, query, and subscription performance testing for TDengine products, and outputting performance indicators.
|
||||
|
||||
## Installation
|
||||
|
||||
There are two ways to install taosBenchmark:
|
||||
taosBenchmark provides two installation methods:
|
||||
|
||||
- taosBenchmark is automatically installed with the official TDengine installation package, for details please refer to [TDengine Installation](../../../get-started/).
|
||||
- taosBenchmark is the default installation component in the TDengine installation package, which can be used after installing TDengine. For how to install TDengine, please refer to [TDengine Installation](../../../get started/)
|
||||
|
||||
- Compile and install taos-tools separately, for details please refer to the [taos-tools](https://github.com/taosdata/taos-tools) repository.
|
||||
- Compile and install taos tools separately, refer to [taos tools](https://github.com/taosdata/taos-tools) .
|
||||
|
||||
## Operation
|
||||
|
||||
### Configuration and Operation Methods
|
||||
|
||||
taosBenchmark needs to be executed in the operating system's terminal, and this tool supports two configuration methods: Command Line Arguments and JSON Configuration File. These two methods are mutually exclusive; when using a configuration file, only one command line argument `-f <json file>` can be used to specify the configuration file. When using command line arguments to run taosBenchmark and control its behavior, the `-f` parameter cannot be used; instead, other parameters must be used for configuration. In addition, taosBenchmark also offers a special mode of operation, which is running without any parameters.
|
||||
|
||||
taosBenchmark supports comprehensive performance testing for TDengine, and the TDengine features it supports are divided into three categories: writing, querying, and subscribing. These three functions are mutually exclusive, and each run of taosBenchmark can only select one of them. It is important to note that the type of function to be tested is not configurable when using the command line configuration method; the command line configuration method can only test writing performance. To test TDengine's query and subscription performance, you must use the configuration file method and specify the type of function to be tested through the `filetype` parameter in the configuration file.
|
||||
taosBbenchmark supports three operating modes:
|
||||
- No parameter mode
|
||||
- Command line mode
|
||||
- JSON configuration file mode
|
||||
The command-line approach is a subset of the functionality of JSON configuration files, which immediately uses the command line and then the configuration file, with the parameters specified by the command line taking precedence.
|
||||
|
||||
**Ensure that the TDengine cluster is running correctly before running taosBenchmark.**
|
||||
|
||||
### Running Without Command Line Arguments
|
||||
|
||||
Execute the following command to quickly experience taosBenchmark performing a write performance test on TDengine based on the default configuration.
|
||||
|
||||
Execute the following command to quickly experience taosBenchmark performing a write performance test on TDengine based on the default configuration.
|
||||
```shell
|
||||
taosBenchmark
|
||||
```
|
||||
|
||||
When running without parameters, taosBenchmark by default connects to the TDengine cluster specified under `/etc/taos`, and creates a database named `test` in TDengine, under which a supertable named `meters` is created, and 10,000 tables are created under the supertable, each table having 10,000 records inserted. Note that if a `test` database already exists, this command will delete the existing database and create a new `test` database.
|
||||
When running without parameters, taosBenchmark defaults to connecting to the TDengine cluster specified in `/etc/taos/taos.cfg `.
|
||||
After successful connection, a smart meter example database test, super meters, and 10000 sub meters will be created, with 10000 records per sub meter. If the test database already exists, it will be deleted before creating a new one.
|
||||
|
||||
### Running Using Command Line Configuration Parameters
|
||||
|
||||
|
@ -46,9 +49,7 @@ The above command `taosBenchmark` will create a database named `test`, establish
|
|||
|
||||
### Running Using a Configuration File
|
||||
|
||||
The taosBenchmark installation package includes examples of configuration files, located in `<install_directory>/examples/taosbenchmark-json`
|
||||
|
||||
Use the following command line to run taosBenchmark and control its behavior through a configuration file.
|
||||
Running in configuration file mode provides all functions, so parameters can be configured to run in the configuration file.
|
||||
|
||||
```shell
|
||||
taosBenchmark -f <json file>
|
||||
|
@ -214,6 +215,61 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
- **-?/--help**:
|
||||
Displays help information and exits. Cannot be used with other parameters.
|
||||
|
||||
|
||||
## Output performance indicators
|
||||
|
||||
#### Write indicators
|
||||
|
||||
After writing is completed, a summary performance metric will be output in the last two lines in the following format:
|
||||
``` bash
|
||||
SUCC: Spent 8.527298 (real 8.117379) seconds to insert rows: 10000000 with 8 thread(s) into test 1172704.41 (real 1231924.74) records/second
|
||||
SUCC: insert delay, min: 19.6780ms, avg: 64.9390ms, p90: 94.6900ms, p95: 105.1870ms, p99: 130.6660ms, max: 157.0830ms
|
||||
```
|
||||
First line write speed statistics:
|
||||
- Spent: Total write time, in seconds, counting from the start of writing the first data to the end of the last data. This indicates that a total of 8.527298 seconds were spent
|
||||
- Real: Total write time (calling the engine), excluding the time spent preparing data for the testing framework. Purely counting the time spent on engine calls, The time spent is 8.117379 seconds. If 8.527298-8.117379=0.409919 seconds, it is the time spent preparing data for the testing framework
|
||||
- Rows: Write the total number of rows, which is 10 million pieces of data
|
||||
- Threads: The number of threads being written, which is 8 threads writing simultaneously
|
||||
- Records/second write speed = `total write time` / `total number of rows written`, real in parentheses is the same as before, indicating pure engine write speed
|
||||
|
||||
Second line single write delay statistics:
|
||||
- min: Write minimum delay
|
||||
- avg: Write normal delay
|
||||
- p90: Write delay p90 percentile delay number
|
||||
- p95: Write delay p95 percentile delay number
|
||||
- p99: Write delay p99 percentile delay number
|
||||
- max: maximum write delay
|
||||
Through this series of indicators, the distribution of write request latency can be observed
|
||||
|
||||
#### Query indicators
|
||||
The query performance test mainly outputs the QPS indicator of query request speed, and the output format is as follows:
|
||||
|
||||
``` bash
|
||||
complete query with 3 threads and 10000 query delay avg: 0.002686s min: 0.001182s max: 0.012189s p90: 0.002977s p95: 0.003493s p99: 0.004645s SQL command: select ...
|
||||
INFO: Total specified queries: 30000
|
||||
INFO: Spend 26.9530 second completed total queries: 30000, the QPS of all threads: 1113.049
|
||||
```
|
||||
|
||||
- The first line represents the percentile distribution of query execution and query request delay for each of the three threads executing 10000 queries. The SQL command is the test query statement
|
||||
- The second line indicates that a total of 10000 * 3 = 30000 queries have been completed
|
||||
- The third line indicates that the total query time is 26.9653 seconds, and the query rate per second (QPS) is 1113.049 times/second
|
||||
|
||||
#### Subscription metrics
|
||||
|
||||
The subscription performance test mainly outputs consumer consumption speed indicators, with the following output format:
|
||||
``` bash
|
||||
INFO: consumer id 0 has poll total msgs: 376, period rate: 37.592 msgs/s, total rows: 3760000, period rate: 375924.815 rows/s
|
||||
INFO: consumer id 1 has poll total msgs: 362, period rate: 36.131 msgs/s, total rows: 3620000, period rate: 361313.504 rows/s
|
||||
INFO: consumer id 2 has poll total msgs: 364, period rate: 36.378 msgs/s, total rows: 3640000, period rate: 363781.731 rows/s
|
||||
INFO: consumerId: 0, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: consumerId: 1, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: consumerId: 2, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: Consumed total msgs: 3000, total rows: 30000000
|
||||
```
|
||||
- Lines 1 to 3 real-time output of the current consumption speed of each consumer, msgs/s represents the number of consumption messages, each message contains multiple rows of data, and rows/s represents the consumption speed calculated by rows
|
||||
- Lines 4 to 6 show the overall statistics of each consumer after the test is completed, including the total number of messages consumed and the total number of lines
|
||||
- The overall statistics of all consumers in line 7, `msgs` represents how many messages were consumed in total, `rows` represents how many rows of data were consumed in total
|
||||
|
||||
## Configuration File Parameters Detailed Explanation
|
||||
|
||||
### General Configuration Parameters
|
||||
|
@ -331,21 +387,6 @@ Parameters related to supertable creation are configured in the `super_tables` s
|
|||
- **repeat_ts_max** : Numeric type, when composite primary key is enabled, specifies the maximum number of records with the same timestamp to be generated
|
||||
- **sqls** : Array of strings type, specifies the array of sql to be executed after the supertable is successfully created, the table name specified in sql must be prefixed with the database name, otherwise an unspecified database error will occur
|
||||
|
||||
#### tsma Configuration Parameters
|
||||
|
||||
Specify the configuration parameters for tsma in `super_tables` under `tsmas`, with the following specific parameters:
|
||||
|
||||
- **name**: Specifies the name of the tsma, mandatory.
|
||||
|
||||
- **function**: Specifies the function of the tsma, mandatory.
|
||||
|
||||
- **interval**: Specifies the time interval for the tsma, mandatory.
|
||||
|
||||
- **sliding**: Specifies the window time shift for the tsma, mandatory.
|
||||
|
||||
- **custom**: Specifies custom configuration appended at the end of the tsma creation statement, optional.
|
||||
|
||||
- **start_when_inserted**: Specifies when to create the tsma after how many rows are inserted, optional, default is 0.
|
||||
|
||||
#### Tag and Data Column Configuration Parameters
|
||||
|
||||
|
@ -423,6 +464,11 @@ For other common parameters, see Common Configuration Parameters.
|
|||
|
||||
Configuration parameters for querying specified tables (can specify supertables, subtables, or regular tables) are set in `specified_table_query`.
|
||||
|
||||
- **mixed_query** "yes": `Mixed Query` "no": `Normal Query`, default is "no"
|
||||
`Mixed Query`: All SQL statements in `sqls` are grouped by the number of threads, with each thread executing one group. Each SQL statement in a thread needs to perform `query_times` queries.
|
||||
`Normal Query `: Each SQL in `sqls` starts `threads` and exits after executing `query_times` times. The next SQL can only be executed after all previous SQL threads have finished executing and exited.
|
||||
Regardless of whether it is a `Normal Query` or `Mixed Query`, the total number of query executions is the same. The total number of queries = `sqls` * `threads` * `query_times`. The difference is that `Normal Query` starts `threads` for each SQL query, while ` Mixed Query` only starts `threads` once to complete all SQL queries. The number of thread startups for the two is different.
|
||||
|
||||
- **query_interval** : Query interval, in seconds, default is 0.
|
||||
|
||||
- **threads** : Number of threads executing the SQL query, default is 1.
|
||||
|
@ -434,6 +480,7 @@ Configuration parameters for querying specified tables (can specify supertables,
|
|||
#### Configuration Parameters for Querying Supertables
|
||||
|
||||
Configuration parameters for querying supertables are set in `super_table_query`.
|
||||
The thread mode of the super table query is the same as the `Normal Query` mode of the specified query statement described above, except that `sqls` is filled all sub tables.
|
||||
|
||||
- **stblname** : The name of the supertable to query, required.
|
||||
|
||||
|
|
|
@ -943,6 +943,7 @@ CHAR(expr1 [, expr2] [, expr3] ...)
|
|||
- NULL values in input parameters will be skipped.
|
||||
- If the input parameters are of string type, they will be converted to numeric type for processing.
|
||||
- If the character corresponding to the input parameter is a non-printable character, the return value will still contain the character corresponding to that parameter, but it may not be displayed.
|
||||
- This function can have at most 2^31 - 1 input parameters.
|
||||
|
||||
**Examples**:
|
||||
|
||||
|
|
|
@ -148,6 +148,7 @@ When using time windows, note:
|
|||
- The window width of the aggregation period is specified by the keyword INTERVAL, with the shortest interval being 10 milliseconds (10a); it also supports an offset (the offset must be less than the interval), which is the offset of the time window division compared to "UTC moment 0". The SLIDING statement is used to specify the forward increment of the aggregation period, i.e., the duration of each window slide forward.
|
||||
- When using the INTERVAL statement, unless in very special cases, it is required to configure the timezone parameter in the taos.cfg configuration files of both the client and server to the same value to avoid frequent cross-time zone conversions by time processing functions, which can cause severe performance impacts.
|
||||
- The returned results have a strictly monotonically increasing time-series.
|
||||
- When using AUTO as the window offset, if the WHERE time condition is complex, such as multiple AND/OR/IN combinations, AUTO may not take effect. In such cases, you can manually specify the window offset to resolve the issue.
|
||||
- When using AUTO as the window offset, if the window width unit is d (day), n (month), w (week), y (year), such as: INTERVAL(1d, AUTO), INTERVAL(3w, AUTO), the TSMA optimization cannot take effect. If TSMA is manually created on the target table, the statement will report an error and exit; in this case, you can explicitly specify the Hint SKIP_TSMA or not use AUTO as the window offset.
|
||||
|
||||
### State Window
|
||||
|
|
|
@ -304,9 +304,10 @@ Displays information about all topics in the current database.
|
|||
|
||||
```sql
|
||||
SHOW TRANSACTIONS;
|
||||
SHOW TRANSACTION [tranaction_id];
|
||||
```
|
||||
|
||||
Displays information about transactions currently being executed in the system (these transactions are only for metadata level, not for regular tables).
|
||||
Displays information about one of or all transaction(s) currently being executed in the system (these transactions are only for metadata level, not for regular tables).
|
||||
|
||||
## SHOW USERS
|
||||
|
||||
|
|
|
@ -328,8 +328,35 @@ In addition to precomputation, TDengine also supports various downsampling stora
|
|||
|
||||
### Multi-Level Storage and Object Storage
|
||||
|
||||
By default, TDengine stores all data in the /var/lib/taos directory. To expand storage capacity, reduce potential bottlenecks caused by file reading, and enhance data throughput, TDengine allows the use of the configuration parameter `dataDir` to enable the cluster to utilize multiple mounted hard drives simultaneously.
|
||||
By default, TDengine saves all data in /var/lib/taos directory, and the data files of each vnode are saved in a different directory under this directory. In order to expand the storage space, minimize the bottleneck of file reading and improve the data throughput rate, TDengine can configure the system parameter "dataDir" to allow multiple mounted hard disks to be used by system at the same time. In addition, TDengine also provides the function of tiered data storage, i.e. storage on different storage media according to the time stamps of data files. For example, the latest data is stored on SSD, the data older than a week is stored on local hard disk, and data older than four weeks is stored on network storage device. This reduces storage costs and ensures efficient data access. The movement of data on different storage media is automatically done by the system and is completely transparent to applications. Tiered storage of data is also configured through the system parameter "dataDir".
|
||||
|
||||
dataDir format is as follows:
|
||||
|
||||
```
|
||||
dataDir data_path [tier_level] [primary] [disable_create_new_file]
|
||||
```
|
||||
|
||||
Where `data_path` is the folder path of mount point, and `tier_level` is the media storage-tier. The higher the media storage-tier, means the older the data file. Multiple hard disks can be mounted at the same storage-tier, and data files on the same storage-tier are distributed on all hard disks within the tier. TDengine supports up to 3 tiers of storage, so tier_level values are 0, 1, and 2. When configuring dataDir, there must be only one mount path without specifying tier_level, which is called special mount disk (path). The mount path defaults to level 0 storage media and contains special file links, which cannot be removed, otherwise it will have a devastating impact on the written data. And `primary` means whether the data dir is the primary mount point. Enter 0 for false or 1 for true. The default value is 1. A TDengine cluster can have only one `primary` mount point, which must be on tier 0. And `disable_create_new_file` means whether to prohibit the creation of new file sets on the specified mount point. Enter 0 for false and 1 for true. The default value is 0. Tier 0 storage must have at least one mount point with disable_create_new_file set to 0. Tier 1 and tier 2 storage do not have this restriction.
|
||||
|
||||
Suppose there is a physical node with six mountable hard disks/mnt/disk1,/mnt/disk2, ..., /mnt/disk6, where disk1 and disk2 need to be designated as level 0 storage media, disk3 and disk4 are level 1 storage media, and disk5 and disk6 are level 2 storage media. Disk1 is a special mount disk, you can configure it in/etc/taos/taos.cfg as follows:
|
||||
|
||||
```
|
||||
dataDir /mnt/disk1/taos 0 1 0
|
||||
dataDir /mnt/disk2/taos 0 0 0
|
||||
dataDir /mnt/disk3/taos 1 0 0
|
||||
dataDir /mnt/disk4/taos 1 0 1
|
||||
dataDir /mnt/disk5/taos 2 0 0
|
||||
dataDir /mnt/disk6/taos 2 0 0
|
||||
```
|
||||
|
||||
Mounted disks can also be a non-local network disk, as long as the system can access it.
|
||||
|
||||
You can use the following command to dynamically modify dataDir to control whether disable_create_new_file is enabled for the current directory.
|
||||
|
||||
```
|
||||
alter dnode 1 "/mnt/disk2/taos 1";
|
||||
```
|
||||
|
||||
Note: Tiered Storage is only supported in Enterprise Edition
|
||||
|
||||
Additionally, TDengine offers tiered data storage functionality, allowing users to store data from different time periods in directories on different storage devices. This facilitates the separation of "hot" data (frequently accessed) and "cold" data (less frequently accessed), making full use of various storage resources while saving costs. For example, data that is recently collected and requires frequent access can be stored on high-performance solid-state drives due to their high read performance requirements. Data that exceeds a certain age and has lower query demands can be stored on mechanically driven hard disks, which are relatively cheaper.
|
||||
|
||||
To further reduce storage costs, TDengine also supports storing time-series data in object storage systems. Through its innovative design, in most cases, the performance of querying time-series data from object storage systems is close to half that of local disks, and in some scenarios, the performance can even be comparable to local disks. Additionally, TDengine allows users to perform delete and update operations on time-series data stored in object storage.
|
||||
|
|
|
@ -166,6 +166,12 @@ json 数据支持 JSONObject 或者 JSONArray,使用 json 解析器可以解
|
|||
|
||||

|
||||
|
||||
### 8. 创建完成
|
||||
### 8. 异常处理策略
|
||||
|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
<Contributing />
|
||||
|
||||
### 9. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 MQTT 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -196,12 +196,16 @@ json 数据支持 JSONObject 或者 JSONArray,使用 json 解析器可以解
|
|||
|
||||
### 8. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||

|
||||
<AdvancedOptions/>
|
||||
|
||||

|
||||
### 9. 异常处理策略
|
||||
|
||||
### 9. 创建完成
|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
<Contributing />
|
||||
|
||||
### 10. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 Kafka 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -75,9 +75,9 @@ InfluxDB 是一种流行的开源时间序列数据库,它针对处理大量
|
|||
|
||||
### 6. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||

|
||||

|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
<AdvancedOptions/>
|
||||
|
||||
### 7. 创建完成
|
||||
|
|
@ -58,9 +58,9 @@ OpenTSDB 是一个架构在 HBase 系统之上的实时监控信息收集和展
|
|||
|
||||
### 5. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||

|
||||

|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
<AdvancedOptions/>
|
||||
|
||||
### 6. 创建完成
|
||||
|
|
@ -107,13 +107,25 @@ sidebar_label: "CSV"
|
|||
|
||||

|
||||
|
||||
### 5. 创建完成
|
||||
### 5. 配置高级选项
|
||||
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
<AdvancedOptions/>
|
||||
|
||||
### 6. 异常处理策略
|
||||
|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
<Contributing />
|
||||
|
||||
### 7. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 CSV 到 TDengine 的数据同步任务,回到数据写入任务列表页面,可查看任务执行情况,也可以进行任务的“启动/停止”操作与“查看/编辑/删除/复制”操作。
|
||||
|
||||

|
||||
|
||||
### 6. 查看运行指标
|
||||
### 8. 查看运行指标
|
||||
|
||||
点击 **查看** 按钮,查看任务的运行指标,同时也可以查看任务中所有文件的处理情况。
|
||||
|
|
@ -134,6 +134,12 @@ split 提取器,seperator 填写分割符 `,`, number 填写 2。
|
|||
|
||||

|
||||
|
||||
### 7. 创建完成
|
||||
### 7. 异常处理策略
|
||||
|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
<Contributing />
|
||||
|
||||
### 8. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建任务。提交任务后,回到**数据写入**页面可以查看任务状态。
|
|
@ -98,14 +98,16 @@ MySQL 是最流行的关系型数据库之一。很多系统都曾经或正在
|
|||
|
||||
### 8. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
<AdvancedOptions/>
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
### 9. 异常处理策略
|
||||
|
||||

|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
### 9. 创建完成
|
||||
<Contributing />
|
||||
|
||||
### 10. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 MySQL 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -99,14 +99,16 @@ TDengine 可以高效地从 PostgreSQL 读取数据并将其写入 TDengine,
|
|||
|
||||
### 8. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
<AdvancedOptions/>
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
### 9. 异常处理策略
|
||||
|
||||

|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
### 9. 创建完成
|
||||
<Contributing />
|
||||
|
||||
### 10. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 PostgreSQL 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -91,14 +91,16 @@ TDengine 可以高效地从 Oracle 读取数据并将其写入 TDengine,以实
|
|||
|
||||
### 7. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
<AdvancedOptions/>
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
### 8. 异常处理策略
|
||||
|
||||

|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
### 8. 创建完成
|
||||
<Contributing />
|
||||
|
||||
### 9. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 Oracle 到 TDengine 的数据同步任务,回到**数据源列表****页面可查看任务执行情况。
|
|
@ -105,14 +105,16 @@ Microsoft SQL Server 是最流行的关系型数据库之一。很多系统都
|
|||
|
||||
### 8. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
<AdvancedOptions/>
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
### 9. 异常处理策略
|
||||
|
||||

|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
### 9. 创建完成
|
||||
<Contributing />
|
||||
|
||||
### 10. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 Microsoft SQL Server 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -122,14 +122,16 @@ MongoDB 是一个介于关系型数据库与非关系型数据库之间的产品
|
|||
|
||||
### 8. 配置高级选项
|
||||
|
||||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
import AdvancedOptions from './_02-advanced_options.mdx'
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
<AdvancedOptions/>
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
### 9. 异常处理策略
|
||||
|
||||

|
||||
import Contributing from './_03-exception-handling-strategy.mdx'
|
||||
|
||||
### 9. 创建完成
|
||||
<Contributing />
|
||||
|
||||
### 10. 创建完成
|
||||
|
||||
点击 **提交** 按钮,完成创建 MongoDB 到 TDengine 的数据同步任务,回到**数据源列表**页面可查看任务执行情况。
|
|
@ -0,0 +1,7 @@
|
|||
**高级选项** 区域是默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
|
||||
**最大读取并发数** 数据源连接数或读取线程数限制,当默认参数不满足需要或需要调整资源使用量时修改此参数。
|
||||
|
||||
**批次大小** 单次发送的最大消息数或行数。默认是 10000。
|
||||
|
||||

|
|
@ -0,0 +1,23 @@
|
|||
异常处理策略区域是对数据异常时的处理策略进行配置,默认折叠的,点击右侧 `>` 可以展开,如下图所示:
|
||||
|
||||

|
||||
|
||||
各异常项说明及相应可选处理策略如下:
|
||||
|
||||
> 通用处理策略说明:
|
||||
> 归档:将异常数据写入归档文件(默认路径为 `${data_dir}/tasks/_id/.datetime`),不写入目标库
|
||||
> 丢弃:将异常数据忽略,不写入目标库
|
||||
> 报错:任务报错
|
||||
|
||||
- **主键时间戳溢出** 检查数据中第一列时间戳是否在正确的时间范围内(now - keep1, now + 100y),可选处理策略:归档、丢弃、报错
|
||||
- **主键时间戳空** 检查数据中第一列时间戳是否为空,可选处理策略:归档、丢弃、报错、使用当前时间
|
||||
> 使用当前时间:使用当前时间填充到空的时间戳字段中
|
||||
- **表名长度溢出** 检查子表表名的长度是否超出限制(最大 192 字符),可选处理策略:归档、丢弃、报错、截断、截断且归档
|
||||
> 截断:截取原始表名的前 192 个字符作为新的表名
|
||||
> 截断且归档:截取原始表名的前 192 个字符作为新的表名,并且将此行记录写入归档文件
|
||||
- **表名非法字符** 检查子表表名中是否包含特殊字符(符号 `.` 等),可选处理策略:归档、丢弃、报错、非法字符替换为指定字符串
|
||||
> 非法字符替换为指定字符串:将原始表名中的特殊字符替换为后方输入框中的指定字符串,例如 `a.b` 替换为 `a_b`
|
||||
- **表名模板变量空值** 检查子表表名模板中的变量是否为空,可选处理策略:丢弃、留空、变量替换为指定字符串
|
||||
> 留空:变量位置不做任何特殊处理,例如 `a_{x}` 转换为 `a_`
|
||||
> 变量替换为指定字符串:变量位置使用后方输入框中的指定字符串,例如 `a_{x}` 转换为 `a_b`
|
||||
- **列名长度溢出** 检查列名的长度是否超出限制(最大 64 字符),可选处理策略:归档、丢弃、报错
|
Before Width: | Height: | Size: 6.7 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 98 KiB |
Before Width: | Height: | Size: 7.2 KiB |
Before Width: | Height: | Size: 97 KiB |
After Width: | Height: | Size: 21 KiB |
After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 31 KiB |
Before Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 31 KiB |
|
@ -66,7 +66,7 @@ pidfile = /usr/local/taos/taosanode/taosanode.pid
|
|||
# uWSGI log files
|
||||
logto = /var/log/taos/taosanode/taosanode.log
|
||||
|
||||
# wWSGI monitor port
|
||||
# uWSGI monitor port
|
||||
stats = 127.0.0.1:8387
|
||||
|
||||
# python virtual environment directory, used by Anode
|
||||
|
@ -86,7 +86,7 @@ log-level = DEBUG
|
|||
|
||||
**提示**
|
||||
请勿设置 `daemonize` 参数,该参数会导致 uWSGI 与 systemctl 冲突,从而导致 Anode 无法正常启动。
|
||||
上面的示例配置文件 `taosanode.ini` 只包含了使用 Anode 提供服务的基础配置参数,对于 uWSGI 的其他配置参数的设置及其说明请参考 [uWSGIS官方文档](https://uwsgi-docs-zh.readthedocs.io/zh-cn/latest/Options.html)。
|
||||
上面的示例配置文件 `taosanode.ini` 只包含了使用 Anode 提供服务的基础配置参数,对于 uWSGI 的其他配置参数的设置及其说明请参考 [uWSGI 官方文档](https://uwsgi-docs-zh.readthedocs.io/zh-cn/latest/Options.html)。
|
||||
|
||||
Anode 运行配置主要是以下:
|
||||
- app-log: Anode 服务运行产生的日志,用户可以调整其到需要的位置
|
||||
|
@ -110,7 +110,7 @@ SHOW ANODES;
|
|||
taos> show anodes;
|
||||
id | url | status | create_time | update_time |
|
||||
==================================================================================================================
|
||||
1 | 192.168.0.1:6090 | ready | 2024-11-28 18:44:27.089 | 2024-11-28 18:44:27.089 |
|
||||
1 | 192.168.0.1:6090 | ready | 2024-11-28 18:44:27.089 | 2024-11-28 18:44:27.089 |
|
||||
Query OK, 1 row(s) in set (0.037205s)
|
||||
|
||||
```
|
||||
|
|
|
@ -41,7 +41,7 @@ algo=expr1
|
|||
"}
|
||||
|
||||
```
|
||||
1. `column_expr`:预测的时序数据列。与异常检测相同,只支持数值类型列输入。
|
||||
1. `column_expr`:预测的时序数据列,只支持数值类型列输入。
|
||||
2. `options`:预测函数的参数。字符串类型,其中使用 K=V 方式调用算法及相关参数。采用逗号分隔的 K=V 字符串表示,其中的字符串不需要使用单引号、双引号、或转义号等符号,不能使用中文及其他宽字符。预测支持 `conf`, `every`, `rows`, `start`, `rows` 几个控制参数,其含义如下:
|
||||
|
||||
### 参数说明
|
||||
|
|
|
@ -99,7 +99,7 @@ def test_myfc(self):
|
|||
s = loader.get_service("myfc")
|
||||
|
||||
# 设置用于预测分析的数据
|
||||
s.set_input_list(self.get_input_list())
|
||||
s.set_input_list(self.get_input_list(), None)
|
||||
# 检查预测结果应该全部为 1
|
||||
r = s.set_params(
|
||||
{"fc_rows": 10, "start_ts": 171000000, "time_step": 86400 * 30, "start_p": 0}
|
||||
|
|
|
@ -44,10 +44,10 @@ class _MyAnomalyDetectionService(AbstractAnomalyDetectionService):
|
|||
|
||||
def set_params(self, params):
|
||||
"""该算法无需任何输入参数,直接重载父类该函数,不处理算法参数设置逻辑"""
|
||||
pass
|
||||
return super().set_params(params)
|
||||
```
|
||||
|
||||
将该文件保存在 `./lib/taosanalytics/algo/ad/` 目录下,然后重启 taosanode 服务。在 TDengine 命令行接口 taos 中执行 `SHOW ANODES FULL` 就能够看到新加入的算法,然后应用就可以通过 SQL 语句调用该检测算法。
|
||||
将该文件保存在 `./lib/taosanalytics/algo/ad/` 目录下,然后重启 taosanode 服务。在 TDengine 命令行接口 taos 中执行 `SHOW ANODES FULL` 就能够看到新加入的算法,然后就可以通过 SQL 语句调用该算法。
|
||||
|
||||
```SQL
|
||||
--- 对 col 列进行异常检测,通过指定 algo 参数为 myad 来调用新添加的异常检测类
|
||||
|
@ -65,7 +65,7 @@ def test_myad(self):
|
|||
s = loader.get_service("myad")
|
||||
|
||||
# 设置需要进行检测的输入数据
|
||||
s.set_input_list(AnomalyDetectionTest.input_list)
|
||||
s.set_input_list(AnomalyDetectionTest.input_list, None)
|
||||
|
||||
r = s.execute()
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ TDengine 面向多种写入场景,而很多写入场景下,TDengine 的存
|
|||
```SQL
|
||||
COMPACT DATABASE db_name [start with 'XXXX'] [end with 'YYYY'];
|
||||
COMPACT [db_name.]VGROUPS IN (vgroup_id1, vgroup_id2, ...) [start with 'XXXX'] [end with 'YYYY'];
|
||||
SHOW COMPACTS [compact_id];
|
||||
SHOW COMPACT [compact_id];
|
||||
KILL COMPACT compact_id;
|
||||
```
|
||||
|
||||
|
|
|
@ -145,3 +145,47 @@ toasX 的配置文件(默认 /etc/taos/taosx.toml) 中与 monitor 相关的配
|
|||
#### 限制
|
||||
|
||||
只有在以 server 模式运行 taosX 时,与监控相关的配置才生效。
|
||||
|
||||
## explorer 集成监控面板
|
||||
|
||||
explorer 支持集成已有的 grafana dashboard。
|
||||
|
||||
### 配置 grafana
|
||||
|
||||
编辑 grafana.ini, 修改以下配置项。配置 root_url, 可能对现有的 grafana 使用习惯有所影响,为了集成到 explorer 是需要如此配置的, 方便通过 explorer 做服务代理。
|
||||
|
||||
``` toml
|
||||
[server]
|
||||
# If you use reverse proxy and sub path specify full url (with sub path)
|
||||
root_url = http://ip:3000/grafana
|
||||
# Serve Grafana from subpath specified in `root_url` setting. By default it is set to `false` for compatibility reasons.
|
||||
serve_from_sub_path = true
|
||||
|
||||
[security]
|
||||
# set to true if you want to allow browsers to render Grafana in a <frame>, <iframe>, <embed> or <object>. default is false.
|
||||
allow_embedding = true
|
||||
```
|
||||
|
||||
### 配置 Explorer
|
||||
|
||||
修改 explorer.toml, 其中 dashboard 配置的 url 中的 ip, 应该配置为可以通过 explorer 服务器能够访问到的 grafana 服务的内网地址。
|
||||
|
||||
``` toml
|
||||
[grafana]
|
||||
# The token of the Grafana server, which is used to access the Grafana server.
|
||||
token = ""
|
||||
|
||||
# The URL of the Grafana dashboard, which is used to display the monitoring data of the TDengine cluster.
|
||||
# You can configure multiple Grafana dashboards.
|
||||
[grafana.dashboards]
|
||||
TDengine3 = "http://ip:3000/d/000000001/tdengine3?theme=light&kiosk=tv"
|
||||
taosX = "http://ip:3000/d/000000002/taosx?theme=light&kiosk=tv"
|
||||
```
|
||||
|
||||
如下图(grafana V-8.5.27),获取 api key, 请注意添加只读权限的 apikey, 否则有安全风险。
|
||||
|
||||

|
||||
|
||||
如下图(grafana V-8.5.27),获取 dashboard url, 获取的 url 请额外加上参数:theme=light&kiosk=tv.
|
||||
|
||||

|
||||
|
|
|
@ -35,119 +35,67 @@ taosdump -i /file/path -h localhost -P 6030
|
|||
|
||||
# 2. 基于 TDengine Enterprise 进行数据备份恢复
|
||||
|
||||
## 2.1. 概念
|
||||
## 2.1. 概述
|
||||
|
||||
基于 TDengine 的数据订阅功能,TDengine Enterprise 实现了数据的增量备份和恢复。用户可以通过 taosExplorer 对 TDengine
|
||||
集群进行备份和恢复。
|
||||
|
||||
TDengine Enterprise 的备份和恢复功能包括以下几个概念:
|
||||
|
||||
1. 备份对象:用户可以对一个数据库,或者一个超级表进行备份。
|
||||
2. 备份计划:用户可以为某个备份对象创建一个备份计划。备份计划从指定的时间点开始,周期性的执行一次备份任务,并生成一组备份文件。
|
||||
3. 备份点:每执行一次备份任务,生成一组备份文件,它们对应一个时间点,称为**备份点**。第一个备份点称为**初始备份点**。
|
||||
4. 备份文件:多个备份点,组成备份计划的备份文件。
|
||||
5. 恢复任务:用户可以选择备份计划的某个备份点,创建一个恢复任务。恢复任务会从初始备份点开始,逐个应用备份点,恢复到指定的备份点。
|
||||
1. 增量数据备份:基于 TDengine 的数据订阅功能,将**备份对象**的所有数据变更(包括:新增、修改、删除、元数据变更等)记录下来,生成备份文件。
|
||||
2. 数据恢复:使用增量数据备份生成的备份文件,将**备份对象**恢复到指定的时间点。
|
||||
3. 备份对象:用户备份的对象,可以是一个**数据库**,也可以是一个**超级表**。
|
||||
4. 备份计划:用户为备份对象创建一个周期性执行的备份任务。备份计划从指定的时间点开始,以**备份周期**为间隔,周期性地执行备份任务。备份任务每次生成一个**备份点**。
|
||||
5. 备份点:每次执行备份任务,生成一组备份文件,它们对应一个时间点,称为**备份点**。第一个备份点称为**初始备份点**。
|
||||
6. 恢复任务:用户选择备份计划的某个备份点,创建一个恢复任务。恢复任务从**初始备份点**开始,逐个回放**备份文件**中的数据变更,直到指定的备份点结束。
|
||||
|
||||

|
||||
|
||||
以上面的图为例:
|
||||
以上图为例:
|
||||
|
||||
1. 用户创建了一个备份计划,从 2024-08-27 00:00:00 开始,每隔 1 天执行一次备份任务。
|
||||
2. 在 2024-08-27 00:00:00 执行了第一次备份任务,生成了一个备份点。
|
||||
3. 之后,每隔 1 天执行一次备份任务,生成了多个备份点,组成了备份文件。
|
||||
4. 用户可以选择某个备份点,创建一个恢复任务,恢复到指定的备份点。
|
||||
1. 用户创建了一个**备份计划**,从 2024-08-27 00:00:00 开始,每隔 1 天执行一次**备份任务**。
|
||||
2. 在 2024-08-27 00:00:00 执行了第一次备份任务,生成了一个**初始备份点**。
|
||||
3. 之后,每隔 1 天执行一次备份任务,生成了多个**备份点**。
|
||||
4. 用户可以选择某个**备份点**,创建一个**恢复任务**。
|
||||
5. 恢复任务会从初始备份点开始,逐个应用备份点,恢复到指定的备份点。
|
||||
|
||||
## 2.2. 备份计划
|
||||
## 2.2. 数据备份
|
||||
|
||||
### 2.1.1. 创建
|
||||
|
||||
1. 通过浏览器访问 taosExplorer 服务,访问地址通常为 TDengine 集群所在 IP 地址的端口 6060,如 http://localhost:6060。
|
||||
2. 在 taosExplorer 服务页面中,进入“系统管理 - 备份”页面,点击“创建备份计划”按钮。
|
||||
|
||||

|
||||
|
||||
3. 在弹出的“创建备份计划”表单中,填写备份计划的相关信息。
|
||||
|
||||

|
||||
通过浏览器访问 taosExplorer 服务,访问地址通常为 TDengine 集群所在 IP 地址的端口 6060,如 http://localhost:6060。 在
|
||||
taosExplorer 服务页面中,进入“系统管理 - 备份”页面,在“备份计划”标签页下,点击“创建备份计划”,填写备份计划的相关信息。
|
||||
|
||||
需要填写的信息包括:
|
||||
|
||||
* 数据库:需要备份的数据库名称。一个备份计划只能备份一个数据库/超级表。
|
||||
* 超级表:需要备份的超级表名称。如果不填写,则备份整个数据库。
|
||||
* 下次执行时间:首次执行备份任务的日期时间。
|
||||
* 备份周期:备份点之间的时间间隔。注意:备份周期必须大于数据库的 WAL_RETENTION_PERIOD 参数值。
|
||||
* 错误重试次数:对于可通过重试解决的错误,系统会按照此次数进行重试。
|
||||
* 错误重试间隔:每次重试之间的时间间隔。
|
||||
* 目录:存储备份文件的目录。
|
||||
* 备份文件大小:备份文件的大小限制。当备份文件大小达到此限制时,会自动创建新的备份文件。
|
||||
* 文件压缩等级:备份文件的压缩等级。支持:最快速度、最佳压缩比、兼具速度和压缩比。
|
||||
1. 数据库:需要备份的数据库名称。一个备份计划只能备份一个数据库/超级表。
|
||||
2. 超级表:需要备份的超级表名称。如果不填写,则备份整个数据库。
|
||||
3. 下次执行时间:首次执行备份任务的日期时间。
|
||||
4. 备份周期:备份点之间的时间间隔。注意:备份周期必须大于数据库的 WAL_RETENTION_PERIOD 参数值。
|
||||
5. 错误重试次数:对于可通过重试解决的错误,系统会按照此次数进行重试。
|
||||
6. 错误重试间隔:每次重试之间的时间间隔。
|
||||
7. 目录:存储备份文件的目录。
|
||||
8. 备份文件大小:备份文件的大小限制。当备份文件大小达到此限制时,会自动创建新的备份文件。
|
||||
9. 文件压缩等级:备份文件的压缩等级。支持:最快速度、最佳压缩比、兼具速度和压缩比。
|
||||
|
||||
创建成功后,备份计划会开始按照配置的参数运行。
|
||||
创建成功后,备份计划会开始按照配置的参数运行。在“备份计划”下的列表中,可以查看已创建的备份计划。
|
||||
|
||||
### 2.1.2. 查看
|
||||
备份计划支持以下操作:
|
||||
|
||||
在“备份计划”下的列表中,可以查看已创建的备份计划。
|
||||
1. 查看:显示备份计划的详细信息。
|
||||
2. 修改:修改备份计划的配置。修改备份计划的配置后,当前运行的备份任务会先停止,然后按照新的配置重新运行。
|
||||
3. 复制:以选中的备份计划为模版,创建新的备份计划。除了数据库和超级表需要用户选择以外,其他配置项和被复制的计划相同。
|
||||
4. 删除:删除备份计划。删除备份计划时,可以选择是否删除关联的备份文件。
|
||||
5. 指标:查看备份计划的统计指标。
|
||||
6. 查看备份点:查看和备份计划关联的所有备份点。
|
||||
|
||||

|
||||
## 2.3. 备份文件
|
||||
|
||||
点击“操作”中的“查看”按钮,可以查看备份计划的详细信息。
|
||||
在“备份文件”列表中,可以查看备份文件的详细信息。
|
||||
|
||||

|
||||
## 2.4. 数据恢复
|
||||
|
||||
### 2.1.3. 修改
|
||||
在“备份文件”列表中,选择一个备份点,可以创建一个恢复任务,数据库恢复到指定的时间。
|
||||
|
||||
点击“操作”中的“修改”按钮,可以修改备份计划的配置。
|
||||
|
||||

|
||||
|
||||
修改备份计划的配置后,当前运行的备份任务会先停止,然后按照新的配置重新运行。
|
||||
|
||||
### 2.1.4. 复制
|
||||
|
||||
点击“操作”中的“复制”按钮,可以复制备份计划。
|
||||
|
||||

|
||||
|
||||
除了数据库和超级表被置为空外,其他配置项和被复制的计划相同。用户点击“确认”后,创建一个新的备份计划。
|
||||
|
||||
### 2.1.5. 删除
|
||||
|
||||
在操作中点击关闭按钮,可以停止当前备份计划。点击“操作”中的“删除”按钮,可以删除备份计划。
|
||||
|
||||

|
||||
|
||||
删除备份计划时,可以选择,是否删除关联的备份文件。
|
||||
|
||||
## 2.2. 备份文件
|
||||
|
||||
### 2.2.1. 查看
|
||||
|
||||
在备份计划列表中,选择要一个备份计划。在“备份文件”列中,点击“查看”按钮。可以查看和备份计划的所有备份点。
|
||||
|
||||

|
||||
|
||||
在备份文件列表中,可以查看备份文件的详细信息。
|
||||
|
||||

|
||||
|
||||
## 2.3. 恢复任务
|
||||
|
||||
### 2.3.1. 创建
|
||||
|
||||
在备份文件列表中,点击“操作”中的“恢复”按钮,可以创建一个恢复任务。
|
||||
|
||||

|
||||
|
||||
在弹出的对话框中,选择使用哪个备份点开始恢复,默认为最早的备份点。点击“确定”后,创建恢复任务,并跳转至“恢复任务”列表。
|
||||
|
||||
### 2.3.2. 查看
|
||||
|
||||
在“恢复任务”列表中,可以查看已创建的恢复任务。
|
||||
|
||||

|
||||
|
||||
恢复任务可以终止。点击“操作”中的开关,可以终止当前恢复任务。
|
||||
在“恢复任务”列表中,可以查看已创建的恢复任务。恢复任务可以终止。
|
||||
|
||||
# 3. 常见错误排查
|
||||
|
||||
|
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 57 KiB |
Before Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 55 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 106 KiB |
Before Width: | Height: | Size: 102 KiB |
Before Width: | Height: | Size: 119 KiB |
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 56 KiB |
After Width: | Height: | Size: 61 KiB |
After Width: | Height: | Size: 109 KiB |
|
@ -4,26 +4,27 @@ title: 与 Superset 集成
|
|||
---
|
||||
Apache Superset 是一个现代的企业级商业智能(BI)Web 应用程序,主要用于数据探索和可视化。它由 Apache 软件基金会支持,是一个开源项目,它拥有活跃的社区和丰富的生态系统。Apache Superset 提供了直观的用户界面,使得创建、分享和可视化数据变得简单,同时支持多种数据源和丰富的可视化选项。
|
||||
|
||||
通过 TDengine 的 Python 连接器, Superset 可支持 TDengine 数据源并提供数据展现、分析等功能
|
||||
通过 TDengine 的 Python 连接器, Apache Superset 可支持 TDengine 数据源并提供数据展现、分析等功能
|
||||
|
||||
## 安装 Apache Superset
|
||||
|
||||
确保已安装 Apache Superset v2.1.0 及以上版本, 如未安装,请到其 [官网](https://superset.apache.org/) 安装
|
||||
## 前置条件
|
||||
|
||||
## 安装 TDengine
|
||||
准备以下环境:
|
||||
- TDengine 集群已部署并正常运行(企业及社区版均可)
|
||||
- taosAdapter 能够正常运行。详细参考 [taosAdapter 使用手册](../../../reference/components/taosadapter)
|
||||
- Apache Superset v2.1.0 或以上版本已安装。安装 Apache Superset 请参考 [官方文档](https://superset.apache.org/)
|
||||
|
||||
TDengine 企业版及社区版均可支持,版本要求在 3.0 及以上
|
||||
|
||||
## 安装 TDengine Python 连接器
|
||||
|
||||
TDengine Python 连接器从 `v2.1.18` 开始自带 Superset 连接驱动,安装程序会把连接驱动安装到 Superset 相应目录下并向 Superset 提供数据源服务
|
||||
Superset 与 TDengine 之间使用 WebSocket 协议连接,所以需另安装支持 WebSocket 连接协议的组件 `taos-ws-py` , 全部安装脚本如下:
|
||||
TDengine Python 连接器从 `v2.1.18` 起带 Superset 连接驱动,会安装至 Superset 相应目录下并向 Superset 提供数据源服务
|
||||
Superset 与 TDengine 之间使用 WebSocket 协议连接,需安装支持此协议的 `taos-ws-py` 组件, 全部安装脚本如下:
|
||||
```bash
|
||||
pip3 install taospy
|
||||
pip3 install taos-ws-py
|
||||
```
|
||||
|
||||
## Superset 中配置 TDengine 连接
|
||||
## 配置 TDengine 数据源
|
||||
|
||||
**第 1 步**,进入新建数据库连接页面 "Superset" → "Setting" → "Database Connections" → "+DATABASE"
|
||||
**第 2 步**,选择 TDengine 数据库连接。"SUPPORTED DATABASES" 下拉列表中选择 "TDengine" 项。
|
||||
|
|
|
@ -185,7 +185,8 @@ charset 的有效值是 UTF-8。
|
|||
|参数名称|支持版本|动态修改|参数含义|
|
||||
|--------------------------|----------|-------------------------|-|
|
||||
|supportVnodes | |支持动态修改 立即生效 |dnode 支持的最大 vnode 数目,取值范围 0-4096,默认值 CPU 核数的 2 倍 + 5|
|
||||
|numOfCommitThreads | |支持动态修改 重启生效 |落盘线程的最大数量,取值范围 0-1024,默认值为 4|
|
||||
|numOfCommitThreads | |支持动态修改 重启生效 |落盘线程的最大数量,取值范围 1-1024,默认值为 4|
|
||||
|numOfCompactThreads | |支持动态修改 重启生效 |落盘线程的最大数量,取值范围 1-16,默认值为 2|
|
||||
|numOfMnodeReadThreads | |支持动态修改 重启生效 |mnode 的 Read 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)|
|
||||
|numOfVnodeQueryThreads | |支持动态修改 重启生效 |vnode 的 Query 线程数目,取值范围 0-1024,默认值为 CPU 核数的两倍(不超过 16)|
|
||||
|numOfVnodeFetchThreads | |支持动态修改 重启生效 |vnode 的 Fetch 线程数目,取值范围 0-1024,默认值为 CPU 核数的四分之一(不超过 4)|
|
||||
|
@ -250,7 +251,7 @@ charset 的有效值是 UTF-8。
|
|||
|minimalLogDirGB | |不支持动态修改 |日志文件夹所在磁盘可用空间大小小于该值时,停止写日志,单位 GB,默认值 1|
|
||||
|numOfLogLines | |支持动态修改 立即生效 |单个日志文件允许的最大行数,默认值 10,000,000|
|
||||
|asyncLog | |支持动态修改 立即生效 |日志写入模式,0:同步,1:异步,默认值 1|
|
||||
|logKeepDays | |支持动态修改 立即生效 |日志文件的最长保存时间,单位:天,默认值 0,意味着无限保存,日志文件不会被重命名,也不会有新的日志文件滚动产生,但日志文件的内容有可能会不断滚动,取决于日志文件大小的设置;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taosdlog.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件|
|
||||
|logKeepDays | |支持动态修改 立即生效 |日志文件的最长保存时间,单位:天,默认值 0,小于等于0意味着只有两个日志文件相互切换保存日志,超过两个文件保存数量的日志会被删除;当设置为大于 0 的值时,当日志文件大小达到设置的上限时会被重命名为 taosdlog.yyy,其中 yyy 为日志文件最后修改的时间戳,并滚动产生新的日志文件|
|
||||
|slowLogThreshold|3.3.3.0 后|支持动态修改 立即生效 |慢查询门限值,大于等于门限值认为是慢查询,单位秒,默认值 3 |
|
||||
|slowLogMaxLen |3.3.3.0 后|支持动态修改 立即生效 |慢查询日志最大长度,取值范围 1-16384,默认值 4096|
|
||||
|slowLogScope |3.3.3.0 后|支持动态修改 立即生效 |慢查询记录类型,取值范围 ALL/QUERY/INSERT/OTHERS/NONE,默认值 QUERY|
|
||||
|
|
|
@ -14,7 +14,7 @@ taosAdapter 是一个 TDengine 的配套工具,是 TDengine 集群和应用程
|
|||
|
||||
taosAdapter 提供以下功能:
|
||||
|
||||
- RESTful 接口
|
||||
- Websocket/RESTful 接口
|
||||
- 兼容 InfluxDB v1 写接口
|
||||
- 兼容 OpenTSDB JSON 和 telnet 格式写入
|
||||
- 无缝连接到 Telegraf
|
||||
|
|
|
@ -4,26 +4,17 @@ sidebar_label: taosdump
|
|||
toc_max_heading_level: 4
|
||||
---
|
||||
|
||||
taosdump 是一个支持从运行中的 TDengine 集群备份数据并将备份的数据恢复到相同或另一个运行中的 TDengine 集群中的工具应用程序。
|
||||
taosdump 是为开源用户提供的 TDengine 数据备份/恢复工具,备份数据文件采用标准 [ Apache AVRO ](https://avro.apache.org/) 格式,方便与外界生态交换数据。taosdump 提供多种数据备份及恢复选项来满足不同需求,可通过 --help 查看支持的全部选项。
|
||||
|
||||
taosdump 可以用数据库、超级表或普通表作为逻辑数据单元进行备份,也可以对数据库、超级
|
||||
表和普通表中指定时间段内的数据记录进行备份。使用时可以指定数据备份的目录路径,如果
|
||||
不指定位置,taosdump 默认会将数据备份到当前目录。
|
||||
|
||||
如果指定的位置已经有数据文件,taosdump 会提示用户并立即退出,避免数据被覆盖。这意味着同一路径只能被用于一次备份。
|
||||
如果看到相关提示,请小心操作。
|
||||
|
||||
taosdump 是一个逻辑备份工具,它不应被用于备份任何原始数据、环境设置、
|
||||
硬件信息、服务端配置或集群的拓扑结构。taosdump 使用
|
||||
[ Apache AVRO ](https://avro.apache.org/)作为数据文件格式来存储备份数据。
|
||||
|
||||
## 安装
|
||||
|
||||
taosdump 有两种安装方式:
|
||||
taosdump 提供两种安装方式:
|
||||
|
||||
- 安装 taosTools 官方安装包, 请从[发布历史页面](https://docs.taosdata.com/releases/tools/)页面找到 taosTools 并下载安装。
|
||||
- taosdump 是 TDengine 安装包中默认安装组件,安装 TDengine 后即可使用,可参考[TDengine 安装](../../../get-started/)
|
||||
|
||||
- 单独编译 taos-tools 并安装, 参考 [taos-tools](https://github.com/taosdata/taos-tools) 仓库。
|
||||
|
||||
- 单独编译 taos-tools 并安装, 详情请参考 [taos-tools](https://github.com/taosdata/taos-tools) 仓库。
|
||||
|
||||
## 常用使用场景
|
||||
|
||||
|
@ -31,9 +22,11 @@ taosdump 有两种安装方式:
|
|||
|
||||
1. 备份所有数据库:指定 `-A` 或 `--all-databases` 参数;
|
||||
2. 备份多个指定数据库:使用 `-D db1,db2,...` 参数;
|
||||
3. 备份指定数据库中的某些超级表或普通表:使用 `dbname stbname1 stbname2 tbname1 tbname2 ...` 参数,注意这种输入序列第一个参数为数据库名称,且只支持一个数据库,第二个和之后的参数为该数据库中的超级表或普通表名称,中间以空格分隔;
|
||||
3. 备份指定数据库中某些超级表或普通表:使用 `dbname stbname1 stbname2 tbname1 tbname2 ...` 参数,注意这种输入序列第一个参数为数据库名称,且只支持一个数据库,第二个和之后的参数为该数据库中的超级表或普通表名称,中间以空格分隔;
|
||||
4. 备份系统 log 库:TDengine 集群通常会包含一个系统数据库,名为 `log`,这个数据库内的数据为 TDengine 自我运行的数据,taosdump 默认不会对 log 库进行备份。如果有特定需求对 log 库进行备份,可以使用 `-a` 或 `--allow-sys` 命令行参数。
|
||||
5. “宽容”模式备份:taosdump 1.4.1 之后的版本提供 `-n` 参数和 `-L` 参数,用于备份数据时不使用转义字符和“宽容”模式,可以在表名、列名、标签名没使用转义字符的情况下减少备份数据时间和备份数据占用空间。如果不确定符合使用 `-n` 和 `-L` 条件时请使用默认参数进行“严格”模式进行备份。转义字符的说明请参考[官方文档](../../taos-sql/escape)。
|
||||
6. `-o` 参数指定的目录下如果已存在备份文件,为防止数据被覆盖,taosdump 会报错并退出,请更换其它空目录或清空原来数据后再备份。
|
||||
7. 目前 taosdump 不支持数据断点继备功能,一旦数据备份中断,需要从头开始。如果备份需要很长时间,建议使用(-S -E 选项)指定开始/结束时间进行分段备份的方法,
|
||||
|
||||
:::tip
|
||||
- taosdump 1.4.1 之后的版本提供 `-I` 参数,用于解析 avro 文件 schema 和数据,如果指定 `-s` 参数将只解析 schema。
|
||||
|
@ -45,7 +38,9 @@ taosdump 有两种安装方式:
|
|||
|
||||
### taosdump 恢复数据
|
||||
|
||||
恢复指定路径下的数据文件:使用 `-i` 参数加上数据文件所在路径。如前面提及,不应该使用同一个目录备份不同数据集合,也不应该在同一路径多次备份同一数据集,否则备份数据会造成覆盖或多次备份。
|
||||
- 恢复指定路径下的数据文件:使用 `-i` 参数加上数据文件所在路径。如前面提及,不应该使用同一个目录备份不同数据集合,也不应该在同一路径多次备份同一数据集,否则备份数据会造成覆盖或多次备份。
|
||||
- taosdump 支持数据恢复至新数据库名下,参数是 -W, 详细见命令行参数说明。
|
||||
|
||||
|
||||
:::tip
|
||||
taosdump 内部使用 TDengine stmt binding API 进行恢复数据的写入,为提高数据恢复性能,目前使用 16384 为一次写入批次。如果备份数据中有比较多列数据,可能会导致产生 "WAL size exceeds limit" 错误,此时可以通过使用 `-B` 参数调整为一个更小的值进行尝试。
|
||||
|
@ -108,6 +103,13 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
the table name.(Version 2.5.3)
|
||||
-T, --thread-num=THREAD_NUM Number of thread for dump in file. Default is
|
||||
8.
|
||||
-W, --rename=RENAME-LIST Rename database name with new name during
|
||||
importing data. RENAME-LIST:
|
||||
"db1=newDB1|db2=newDB2" means rename db1 to newDB1
|
||||
and rename db2 to newDB2 (Version 2.5.4)
|
||||
-k, --retry-count=VALUE Set the number of retry attempts for connection or
|
||||
query failures
|
||||
-z, --retry-sleep-ms=VALUE retry interval sleep time, unit ms
|
||||
-C, --cloud=CLOUD_DSN specify a DSN to access TDengine cloud service
|
||||
-R, --restful Use RESTful interface to connect TDengine
|
||||
-t, --timeout=SECONDS The timeout seconds for websocket to interact.
|
||||
|
@ -115,10 +117,6 @@ Usage: taosdump [OPTION...] dbname [tbname ...]
|
|||
-?, --help Give this help list
|
||||
--usage Give a short usage message
|
||||
-V, --version Print program version
|
||||
-W, --rename=RENAME-LIST Rename database name with new name during
|
||||
importing data. RENAME-LIST:
|
||||
"db1=newDB1|db2=newDB2" means rename db1 to newDB1
|
||||
and rename db2 to newDB2 (Version 2.5.4)
|
||||
|
||||
Mandatory or optional arguments to long options are also mandatory or optional
|
||||
for any corresponding short options.
|
||||
|
|
|
@ -4,59 +4,59 @@ sidebar_label: taosBenchmark
|
|||
toc_max_heading_level: 4
|
||||
---
|
||||
|
||||
taosBenchmark (曾用名 taosdemo ) 是一个用于测试 TDengine 产品性能的工具。taosBenchmark 可以测试 TDengine 的插入、查询和订阅等功能的性能,它可以模拟由大量设备产生的大量数据,还可以灵活地控制数据库、超级表、标签列的数量和类型、数据列的数量和类型、子表的数量、每张子表的数据量、插入数据的时间间隔、taosBenchmark 的工作线程数量、是否以及如何插入乱序数据等。为了兼容过往用户的使用习惯,安装包提供 了 taosdemo 作为 taosBenchmark 的软链接。
|
||||
taosBenchmark 是 TDengine 产品性能基准测试工具,提供对 TDengine 产品写入、查询及订阅性能测试,输出性能指标。
|
||||
|
||||
## 安装
|
||||
|
||||
taosBenchmark 有两种安装方式:
|
||||
taosBenchmark 提供两种安装方式:
|
||||
|
||||
- 安装 TDengine 官方安装包的同时会自动安装 taosBenchmark, 详情请参考[ TDengine 安装](../../../get-started/)。
|
||||
- taosBenchmark 是 TDengine 安装包中默认安装组件,安装 TDengine 后即可使用,参考 [TDengine 安装](../../../get-started/)
|
||||
|
||||
- 单独编译 taos-tools 并安装, 详情请参考 [taos-tools](https://github.com/taosdata/taos-tools) 仓库。
|
||||
- 单独编译 taos-tools 并安装, 参考 [taos-tools](https://github.com/taosdata/taos-tools) 仓库。
|
||||
|
||||
## 运行
|
||||
|
||||
### 配置和运行方式
|
||||
### 运行方式
|
||||
|
||||
taosBenchmark 需要在操作系统的终端执行,该工具支持两种配置方式:[命令行参数](#命令行参数详解) 和 [JSON 配置文件](#配置文件参数详解)。这两种方式是互斥的,在使用配置文件时只能使用一个命令行参数 `-f <json file>` 指定配置文件。在使用命令行参数运行 taosBenchmark 并控制其行为时则不能使用 `-f` 参数而要用其它参数来进行配置。除此之外,taosBenchmark 还提供了一种特殊的运行方式,即无参数运行。
|
||||
taosBenchmark 支持三种运行模式:
|
||||
- 无参数模式
|
||||
- 命令行模式
|
||||
- JSON 配置文件模式
|
||||
`命令行方式` 为 `JSON 配置文件方式` 功能子集,两者都使用时,命令行方式优先。
|
||||
|
||||
taosBenchmark 支持对 TDengine 做完备的性能测试,其所支持的 TDengine 功能分为三大类:写入、查询和订阅。这三种功能之间是互斥的,每次运行 taosBenchmark 只能选择其中之一。值得注意的是,所要测试的功能类型在使用命令行配置方式时是不可配置的,命令行配置方式只能测试写入性能。若要测试 TDengine 的查询和订阅性能,必须使用配置文件的方式,通过配置文件中的参数 `filetype` 指定所要测试的功能类型。
|
||||
|
||||
**在运行 taosBenchmark 之前要确保 TDengine 集群已经在正确运行。**
|
||||
|
||||
### 无命令行参数运行
|
||||
|
||||
执行下列命令即可快速体验 taosBenchmark 对 TDengine 进行基于默认配置的写入性能测试。
|
||||
|
||||
```bash
|
||||
taosBenchmark
|
||||
```
|
||||
|
||||
在无参数运行时,taosBenchmark 默认连接 `/etc/taos` 下指定的 TDengine 集群,并在 TDengine 中创建一个名为 test 的数据库,test 数据库下创建名为 meters 的一张超级表,超级表下创建 10000 张表,每张表中写入 10000 条记录。注意,如果已有 test 数据库,这个命令会先删除该数据库后建立一个全新的 test 数据库。
|
||||
在无参数运行时,taosBenchmark 默认连接 `/etc/taos/taos.cfg` 中指定的 TDengine 集群。
|
||||
连接成功后,会默认创建智能电表示例数据库 test,创建超级表 meters, 创建子表 1 万,每子写入数据 1 万条,若 test 库已存在,默认会先删再建。
|
||||
|
||||
### 使用命令行配置参数运行
|
||||
|
||||
在使用命令行参数运行 taosBenchmark 并控制其行为时,`-f <json file>` 参数不能使用。所有配置参数都必须通过命令行指定。以下是使用命令行方式测试 taosBenchmark 写入性能的一个示例。
|
||||
### 使用命令行参数运行
|
||||
|
||||
命令行支持的参数为写入功能中使用较为频繁的参数,查询与订阅功能不支持命令行方式
|
||||
示例:
|
||||
```bash
|
||||
taosBenchmark -I stmt -n 200 -t 100
|
||||
taosBenchmark -d db -t 100 -n 1000 -T 4 -I stmt -y
|
||||
```
|
||||
|
||||
上面的命令 `taosBenchmark` 将创建一个名为`test`的数据库,在其中建立一张超级表`meters`,在该超级表中建立 100 张子表并使用参数绑定的方式为每张子表插入 200 条记录。
|
||||
此命令表示使用 `taosBenchmark` 将创建一个名为 `db` 的数据库,并建立默认超级表 `meters`,子表 100 ,使用参数绑定(stmt)方式为每张子表写入 1000 条记录。
|
||||
|
||||
### 使用配置文件运行
|
||||
|
||||
taosBenchmark 安装包中提供了配置文件的示例,位于 `<install_directory>/examples/taosbenchmark-json` 下
|
||||
|
||||
使用如下命令行即可运行 taosBenchmark 并通过配置文件控制其行为。
|
||||
配置文件方式运行提供了全部功能,所有命令行参数都可以在配置文件中配置运行
|
||||
|
||||
```bash
|
||||
taosBenchmark -f <json file>
|
||||
```
|
||||
|
||||
**下面是几个配置文件的示例:**
|
||||
**下面为支持的写入、查询、订阅三大功能的配置文件示例:**
|
||||
|
||||
#### 插入场景 JSON 配置文件示例
|
||||
#### 写入场景 JSON 配置文件示例
|
||||
|
||||
<details>
|
||||
<summary>insert.json</summary>
|
||||
|
@ -89,130 +89,102 @@ taosBenchmark -f <json file>
|
|||
|
||||
</details>
|
||||
|
||||
查看更多 json 配置文件示例可 [点击这里](https://github.com/taosdata/taos-tools/tree/main/example)
|
||||
|
||||
## 命令行参数详解
|
||||
| 命令行参数 | 功能说明 |
|
||||
| ---------------------------- | ----------------------------------------------- |
|
||||
| -f/--file \<json file> | 要使用的 JSON 配置文件,由该文件指定所有参数,本参数与命令行其他参数不能同时使用。没有默认值 |
|
||||
| -c/--config-dir \<dir> | TDengine 集群配置文件所在的目录,默认路径是 /etc/taos |
|
||||
| -h/--host \<host> | 指定要连接的 TDengine 服务端的 FQDN,默认值为 localhost |
|
||||
| -P/--port \<port> | 要连接的 TDengine 服务器的端口号,默认值为 6030 |
|
||||
| -I/--interface \<insertMode> | 插入模式,可选项有 taosc, rest, stmt, sml, sml-rest, 分别对应普通写入、restful 接口写入、参数绑定接口写入、schemaless 接口写入、restful schemaless 接口写入 (由 taosAdapter 提供)。默认值为 taosc |
|
||||
| -u/--user \<user> | 用于连接 TDengine 服务端的用户名,默认为 root |
|
||||
| -U/--supplement-insert | 写入数据而不提前建数据库和表,默认关闭 |
|
||||
| -p/--password \<passwd> | 用于连接 TDengine 服务端的密码,默认值为 taosdata |
|
||||
| -o/--output \<file> | 结果输出文件的路径,默认值为 ./output.txt |
|
||||
| -T/--thread \<threadNum> | 插入数据的线程数量,默认为 8 |
|
||||
| -B/--interlace-rows \<rowNum> |启用交错插入模式并同时指定向每个子表每次插入的数据行数。交错插入模式是指依次向每张子表插入由本参数所指定的行数并重复这个过程,直到所有子表的数据都插入完成。默认值为 0, 即向一张子表完成数据插入后才会向下一张子表进行数据插入 |
|
||||
| -i/--insert-interval \<timeInterval> | 指定交错插入模式的插入间隔,单位为 ms,默认值为 0。 只有当 `-B/--interlace-rows` 大于 0 时才起作用 |意味着数据插入线程在为每个子表插入隔行扫描记录后,会等待该值指定的时间间隔后再进行下一轮写入 |
|
||||
| -r/--rec-per-req \<rowNum> | 每次向 TDengine 请求写入的数据行数,默认值为 30000 |
|
||||
| -t/--tables \<tableNum> | 指定子表的数量,默认为 10000 |
|
||||
| -S/--timestampstep \<stepLength> | 每个子表中插入数据的时间戳步长,单位是 ms,默认值是 1 |
|
||||
| -n/--records \<recordNum> | 每个子表插入的记录数,默认值为 10000 |
|
||||
| -d/--database \<dbName> | 所使用的数据库的名称,默认值为 test |
|
||||
| -b/--data-type \<colType> | 指定超级表普通列数据类型, 多个使用逗号分隔,默认值: "FLOAT,INT,FLOAT" 如:`taosBenchmark -b "FLOAT,BINARY(8),NCHAR(16)"`|
|
||||
| -A/--tag-type \<tagType> | 指定超级表标签列数据类型,多个使用逗号分隔,默认值: "INT,BINARY(24)" 如:`taosBenchmark -A "INT,BINARY(8),NCHAR(8)"`|
|
||||
| -l/--columns \<colNum> | 超级表的数据列的总数量。如果同时设置了该参数和 `-b/--data-type`,则最后的结果列数为两者取大。如果本参数指定的数量大于 `-b/--data-type` 指定的列数,则未指定的列类型默认为 INT, 例如: `-l 5 -b float,double`, 那么最后的列为 `FLOAT,DOUBLE,INT,INT,INT`。如果 columns 指定的数量小于或等于 `-b/--data-type` 指定的列数,则结果为 `-b/--data-type` 指定的列和类型,例如: `-l 3 -b float,double,float,bigint`,那么最后的列为 `FLOAT,DOUBLE,FLOAT,BIGINT` |
|
||||
| -L/--partial-col-num \<colNum> | 指定某些列写入数据,其他列数据为 NULL。默认所有列都写入数据 |
|
||||
| -w/--binwidth \<length> | nchar 和 binary 类型的默认长度,默认值为 64 |
|
||||
| -m/--table-prefix \<tablePrefix> | 子表名称的前缀,默认值为 "d" |
|
||||
| -E/--escape-character | 开关参数,指定在超级表和子表名称中是否使用转义字符。默认值为不使用 |
|
||||
| -C/--chinese | 开关参数,指定 nchar 和 binary 是否使用 Unicode 中文字符。默认值为不使用 |
|
||||
| -N/--normal-table | 开关参数,指定只创建普通表,不创建超级表。默认值为 false。仅当插入模式为 taosc, stmt, rest 模式下可以使用 |
|
||||
| -M/--random | 开关参数,插入数据为生成的随机值。默认值为 false。若配置此参数,则随机生成要插入的数据。对于数值类型的 标签列/数据列,其值为该类型取值范围内的随机值。对于 NCHAR 和 BINARY 类型的 标签列/数据列,其值为指定长度范围内的随机字符串 |
|
||||
| -x/--aggr-func | 开关参数,指示插入后查询聚合函数。默认值为 false |
|
||||
| -y/--answer-yes | 开关参数,要求用户在提示后确认才能继续 |默认值为 false 。
|
||||
| -O/--disorder \<Percentage> | 指定乱序数据的百分比概率,其值域为 [0,50]。默认为 0,即没有乱序数据 |
|
||||
| -R/--disorder-range \<timeRange> | 指定乱序数据的时间戳回退范围。所生成的乱序时间戳为非乱序情况下应该使用的时间戳减去这个范围内的一个随机值。仅在 `-O/--disorder` 指定的乱序数据百分比大于 0 时有效|
|
||||
| -F/--prepare_rand \<Num> | 生成的随机数据中唯一值的数量。若为 1 则表示所有数据都相同。默认值为 10000 |
|
||||
| -a/--replica \<replicaNum> | 创建数据库时指定其副本数,默认值为 1 |
|
||||
| -k/--keep-trying \<NUMBER> | 失败后进行重试的次数,默认不重试。需使用 v3.0.9 以上版本|
|
||||
| -z/--trying-interval \<NUMBER> | 失败重试间隔时间,单位为毫秒,仅在 -k 指定重试后有效。需使用 v3.0.9 以上版本 |
|
||||
| -v/--vgroups \<NUMBER> | 创建数据库时指定 vgroups 数,仅对 TDengine v3.0+ 有效|
|
||||
| -V/--version | 显示版本信息并退出。不能与其它参数混用|
|
||||
| -?/--help | 显示帮助信息并退出。不能与其它参数混用|
|
||||
|
||||
- **-f/--file \<json file>** :
|
||||
要使用的 JSON 配置文件,由该文件指定所有参数,本参数与命令行其他参数不能同时使用。没有默认值。
|
||||
|
||||
- **-c/--config-dir \<dir>** :
|
||||
TDengine 集群配置文件所在的目录,默认路径是 /etc/taos 。
|
||||
## 输出性能指标
|
||||
|
||||
- **-h/--host \<host>** :
|
||||
指定要连接的 TDengine 服务端的 FQDN,默认值为 localhost 。
|
||||
|
||||
- **-P/--port \<port>** :
|
||||
要连接的 TDengine 服务器的端口号,默认值为 6030 。
|
||||
|
||||
- **-I/--interface \<insertMode>** :
|
||||
插入模式,可选项有 taosc, rest, stmt, sml, sml-rest, 分别对应普通写入、restful 接口写入、参数绑定接口写入、schemaless 接口写入、restful schemaless 接口写入 (由 taosAdapter 提供)。默认值为 taosc。
|
||||
|
||||
- **-u/--user \<user>** :
|
||||
用于连接 TDengine 服务端的用户名,默认为 root 。
|
||||
|
||||
- **-U/--supplement-insert ** :
|
||||
写入数据而不提前建数据库和表,默认关闭。
|
||||
|
||||
- **-p/--password \<passwd>** :
|
||||
用于连接 TDengine 服务端的密码,默认值为 taosdata。
|
||||
|
||||
- **-o/--output \<file>** :
|
||||
结果输出文件的路径,默认值为 ./output.txt。
|
||||
|
||||
- **-T/--thread \<threadNum>** :
|
||||
插入数据的线程数量,默认为 8 。
|
||||
|
||||
- **-B/--interlace-rows \<rowNum>** :
|
||||
启用交错插入模式并同时指定向每个子表每次插入的数据行数。交错插入模式是指依次向每张子表插入由本参数所指定的行数并重复这个过程,直到所有子表的数据都插入完成。默认值为 0, 即向一张子表完成数据插入后才会向下一张子表进行数据插入。
|
||||
|
||||
- **-i/--insert-interval \<timeInterval>** :
|
||||
指定交错插入模式的插入间隔,单位为 ms,默认值为 0。 只有当 `-B/--interlace-rows` 大于 0 时才起作用。意味着数据插入线程在为每个子表插入隔行扫描记录后,会等待该值指定的时间间隔后再进行下一轮写入。
|
||||
|
||||
- **-r/--rec-per-req \<rowNum>** :
|
||||
每次向 TDengine 请求写入的数据行数,默认值为 30000 。
|
||||
|
||||
- **-t/--tables \<tableNum>** :
|
||||
指定子表的数量,默认为 10000 。
|
||||
|
||||
- **-S/--timestampstep \<stepLength>** :
|
||||
每个子表中插入数据的时间戳步长,单位是 ms,默认值是 1。
|
||||
|
||||
- **-n/--records \<recordNum>** :
|
||||
每个子表插入的记录数,默认值为 10000 。
|
||||
|
||||
- **-d/--database \<dbName>** :
|
||||
所使用的数据库的名称,默认值为 test 。
|
||||
|
||||
- **-b/--data-type \<colType>** :
|
||||
超级表的数据列的类型。如果不使用则默认为有三个数据列,其类型分别为 FLOAT, INT, FLOAT 。
|
||||
|
||||
- **-l/--columns \<colNum>** :
|
||||
超级表的数据列的总数量。如果同时设置了该参数和 `-b/--data-type`,则最后的结果列数为两者取大。如果本参数指定的数量大于 `-b/--data-type` 指定的列数,则未指定的列类型默认为 INT, 例如: `-l 5 -b float,double`, 那么最后的列为 `FLOAT,DOUBLE,INT,INT,INT`。如果 columns 指定的数量小于或等于 `-b/--data-type` 指定的列数,则结果为 `-b/--data-type` 指定的列和类型,例如: `-l 3 -b float,double,float,bigint`,那么最后的列为 `FLOAT,DOUBLE,FLOAT,BIGINT` 。
|
||||
|
||||
- **-L/--partial-col-num \<colNum> **:
|
||||
指定某些列写入数据,其他列数据为 NULL。默认所有列都写入数据。
|
||||
|
||||
- **-A/--tag-type \<tagType>** :
|
||||
超级表的标签列类型。nchar 和 binary 类型可以同时设置长度,例如:
|
||||
#### 写入指标
|
||||
|
||||
写入结束后会在最后两行输出总体性能指标,格式如下:
|
||||
``` bash
|
||||
SUCC: Spent 8.527298 (real 8.117379) seconds to insert rows: 10000000 with 8 thread(s) into test 1172704.41 (real 1231924.74) records/second
|
||||
SUCC: insert delay, min: 19.6780ms, avg: 64.9390ms, p90: 94.6900ms, p95: 105.1870ms, p99: 130.6660ms, max: 157.0830ms
|
||||
```
|
||||
taosBenchmark -A INT,DOUBLE,NCHAR,BINARY(16)
|
||||
第一行写入速度统计:
|
||||
- Spent: 写入总耗时,单位秒,从开始写入第一个数据开始计时到最后一条数据结束,这里表示共花了 8.527298 秒
|
||||
- real : 写入总耗时(调用引擎),此耗时已抛去测试框架准备数据时间,纯统计在引擎调用上花费的时间,示例为 8.117379 秒,8.527298 - 8.117379 = 0.409919 秒则为测试框架准备数据消耗时间
|
||||
- rows : 写入总行数,为 1000 万条数据
|
||||
- threads: 写入线程数,这里是 8 个线程同时写入
|
||||
- records/second 写入速度 = `写入总耗时`/ `写入总行数` , 括号中 `real` 同前,表示纯引擎写入速度
|
||||
第二行单个写入延时统计:
|
||||
- min : 写入最小延时
|
||||
- avg : 写入平时延时
|
||||
- p90 : 写入延时 p90 百分位上的延时数
|
||||
- p95 : 写入延时 p95 百分位上的延时数
|
||||
- p99 : 写入延时 p99 百分位上的延时数
|
||||
- max : 写入最大延时
|
||||
通过此系列指标,可观察到写入请求延时分布情况
|
||||
|
||||
#### 查询指标
|
||||
|
||||
查询性能测试主要输出查询请求速度 QPS 指标, 输出格式如下:
|
||||
``` bash
|
||||
complete query with 3 threads and 10000 query delay avg: 0.002686s min: 0.001182s max: 0.012189s p90: 0.002977s p95: 0.003493s p99: 0.004645s SQL command: select ...
|
||||
INFO: Total specified queries: 30000
|
||||
INFO: Spend 26.9530 second completed total queries: 30000, the QPS of all threads: 1113.049
|
||||
```
|
||||
- 第一行表示 3 个线程每个线程执行 10000 次查询及查询请求延时百分位分布情况,`SQL command` 为测试的查询语句
|
||||
- 第二行表示总共完成了 10000 * 3 = 30000 次查询总数
|
||||
- 第三行表示查询总耗时为 26.9653 秒,每秒查询率(QPS)为:1113.049 次/秒
|
||||
|
||||
如果没有设置标签类型,默认是两个标签,其类型分别为 INT 和 BINARY(16)。
|
||||
注意:在有的 shell 比如 bash 命令里面 “()” 需要转义,则上述指令应为:
|
||||
#### 订阅指标
|
||||
|
||||
订阅性能测试主要输出消费者消费速度指标,输出格式如下:
|
||||
``` bash
|
||||
INFO: consumer id 0 has poll total msgs: 376, period rate: 37.592 msgs/s, total rows: 3760000, period rate: 375924.815 rows/s
|
||||
INFO: consumer id 1 has poll total msgs: 362, period rate: 36.131 msgs/s, total rows: 3620000, period rate: 361313.504 rows/s
|
||||
INFO: consumer id 2 has poll total msgs: 364, period rate: 36.378 msgs/s, total rows: 3640000, period rate: 363781.731 rows/s
|
||||
INFO: consumerId: 0, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: consumerId: 1, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: consumerId: 2, consume msgs: 1000, consume rows: 10000000
|
||||
INFO: Consumed total msgs: 3000, total rows: 30000000
|
||||
```
|
||||
taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
||||
```
|
||||
|
||||
- **-w/--binwidth \<length>**:
|
||||
nchar 和 binary 类型的默认长度,默认值为 64。
|
||||
|
||||
- **-m/--table-prefix \<tablePrefix>** :
|
||||
子表名称的前缀,默认值为 "d"。
|
||||
|
||||
- **-E/--escape-character** :
|
||||
开关参数,指定在超级表和子表名称中是否使用转义字符。默认值为不使用。
|
||||
|
||||
- **-C/--chinese** :
|
||||
开关参数,指定 nchar 和 binary 是否使用 Unicode 中文字符。默认值为不使用。
|
||||
|
||||
- **-N/--normal-table** :
|
||||
开关参数,指定只创建普通表,不创建超级表。默认值为 false。仅当插入模式为 taosc, stmt, rest 模式下可以使用。
|
||||
|
||||
- **-M/--random** :
|
||||
开关参数,插入数据为生成的随机值。默认值为 false。若配置此参数,则随机生成要插入的数据。对于数值类型的 标签列/数据列,其值为该类型取值范围内的随机值。对于 NCHAR 和 BINARY 类型的 标签列/数据列,其值为指定长度范围内的随机字符串。
|
||||
|
||||
- **-x/--aggr-func** :
|
||||
开关参数,指示插入后查询聚合函数。默认值为 false。
|
||||
|
||||
- **-y/--answer-yes** :
|
||||
开关参数,要求用户在提示后确认才能继续。默认值为 false 。
|
||||
|
||||
- **-O/--disorder \<Percentage>** :
|
||||
指定乱序数据的百分比概率,其值域为 [0,50]。默认为 0,即没有乱序数据。
|
||||
|
||||
- **-R/--disorder-range \<timeRange>** :
|
||||
指定乱序数据的时间戳回退范围。所生成的乱序时间戳为非乱序情况下应该使用的时间戳减去这个范围内的一个随机值。仅在 `-O/--disorder` 指定的乱序数据百分比大于 0 时有效。
|
||||
|
||||
- **-F/--prepare_rand \<Num>** :
|
||||
生成的随机数据中唯一值的数量。若为 1 则表示所有数据都相同。默认值为 10000 。
|
||||
|
||||
- **-a/--replica \<replicaNum>** :
|
||||
创建数据库时指定其副本数,默认值为 1 。
|
||||
|
||||
- ** -k/--keep-trying \<NUMBER>** : 失败后进行重试的次数,默认不重试。需使用 v3.0.9 以上版本。
|
||||
|
||||
- ** -z/--trying-interval \<NUMBER>** : 失败重试间隔时间,单位为毫秒,仅在 -k 指定重试后有效。需使用 v3.0.9 以上版本。
|
||||
|
||||
- **-v/--vgroups \<NUMBER>** :
|
||||
创建数据库时指定 vgroups 数,仅对 TDengine v3.0+ 有效。
|
||||
|
||||
- **-V/--version** :
|
||||
显示版本信息并退出。不能与其它参数混用。
|
||||
|
||||
- **-?/--help** :
|
||||
显示帮助信息并退出。不能与其它参数混用。
|
||||
- 1 ~ 3 行实时输出每个消费者当前的消费速度,`msgs/s` 表示消费消息个数,每个消息中包含多行数据,`rows/s` 表示按行数统计的消费速度
|
||||
- 4 ~ 6 行是测试完成后每个消费者总体统计,统计共消费了多少条消息,共计多少行
|
||||
- 第 7 行所有消费者总体统计,`msgs` 表示共消费了多少条消息, `rows` 表示共消费了多少行数据
|
||||
|
||||
## 配置文件参数详解
|
||||
|
||||
|
@ -220,7 +192,7 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
本节所列参数适用于所有功能模式。
|
||||
|
||||
- **filetype** : 要测试的功能,可选值为 `insert`, `query` 和 `subscribe`。分别对应插入、查询和订阅功能。每个配置文件中只能指定其中之一。
|
||||
- **filetype** : 功能分类,可选值为 `insert`, `query` 和 `subscribe`。分别对应插入、查询和订阅功能。每个配置文件中只能指定其中之一。
|
||||
- **cfgdir** : TDengine 客户端配置文件所在的目录,默认路径是 /etc/taos 。
|
||||
|
||||
- **host** : 指定要连接的 TDengine 服务端的 FQDN,默认值为 localhost。
|
||||
|
@ -252,7 +224,7 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
- **name** : 数据库名。
|
||||
|
||||
- **drop** : 插入前是否删除数据库,可选项为 "yes" 或者 "no", 为 "no" 时不创建。默认删除。
|
||||
- **drop** : 数据库已存在时是否删除重建,可选项为 "yes" 或 "no", 默认为 “yes”
|
||||
|
||||
#### 流式计算相关配置参数
|
||||
|
||||
|
@ -331,21 +303,6 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
- **repeat_ts_max** : 数值类型,复合主键开启情况下指定生成相同时间戳记录的最大个数
|
||||
- **sqls** : 字符串数组类型,指定超级表创建成功后要执行的 sql 数组,sql 中指定表名前面要带数据库名,否则会报未指定数据库错误
|
||||
|
||||
#### tsma配置参数
|
||||
|
||||
指定tsma的配置参数在 `super_tables` 中的 `tsmas` 中,具体参数如下。
|
||||
|
||||
- **name** : 指定 tsma 的名字,必选项。
|
||||
|
||||
- **function** : 指定 tsma 的函数,必选项。
|
||||
|
||||
- **interval** : 指定 tsma 的时间间隔,必选项。
|
||||
|
||||
- **sliding** : 指定 tsma 的窗口时间位移,必选项。
|
||||
|
||||
- **custom** : 指定 tsma 的创建语句结尾追加的自定义配置,可选项。
|
||||
|
||||
- **start_when_inserted** : 指定当插入多少行时创建 tsma,可选项,默认为 0。
|
||||
|
||||
#### 标签列与数据列配置参数
|
||||
|
||||
|
@ -415,7 +372,8 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
查询场景下 `filetype` 必须设置为 `query`。
|
||||
`query_times` 指定运行查询的次数,数值类型
|
||||
|
||||
查询场景可以通过设置 `kill_slow_query_threshold` 和 `kill_slow_query_interval` 参数来控制杀掉慢查询语句的执行,threshold 控制如果 exec_usec 超过指定时间的查询将被 taosBenchmark 杀掉,单位为秒;interval 控制休眠时间,避免持续查询慢查询消耗 CPU ,单位为秒。
|
||||
查询场景可以通过设置 `kill_slow_query_threshold` 和 `kill_slow_query_interval` 参数来控制杀掉慢查询语句的执行,threshold 控制如果 exec_usec 超过指定时间的查询将被 taosBenchmark 杀掉,单位为秒;
|
||||
interval 控制休眠时间,避免持续查询慢查询消耗 CPU ,单位为秒。
|
||||
|
||||
其它通用参数详见[通用配置参数](#通用配置参数)。
|
||||
|
||||
|
@ -423,6 +381,11 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
|
||||
查询指定表(可以指定超级表、子表或普通表)的配置参数在 `specified_table_query` 中设置。
|
||||
|
||||
- **mixed_query** : 查询模式,取值 “yes” 为`混合查询`, "no" 为`正常查询` , 默认值为 “no”
|
||||
`混合查询`:`sqls` 中所有 sql 按 `threads` 线程数分组,每个线程执行一组, 线程中每个 sql 都需执行 `query_times` 次查询
|
||||
`正常查询`:`sqls` 中每个 sql 启动 `threads` 个线程,每个线程执行完 `query_times` 次后退出,下个 sql 需等待上个 sql 线程全部执行完退出后方可执行
|
||||
不管 `正常查询` 还是 `混合查询` ,执行查询总次数是相同的 ,查询总次数 = `sqls` 个数 * `threads` * `query_times`, 区别是 `正常查询` 每个 sql 都会启动 `threads` 个线程,而 `混合查询` 只启动一次 `threads` 个线程执行完所有 SQL, 两者启动线程次数不一样。
|
||||
|
||||
- **query_interval** : 查询时间间隔,单位是秒,默认值为 0。
|
||||
|
||||
- **threads** : 执行查询 SQL 的线程数,默认值为 1。
|
||||
|
@ -434,6 +397,7 @@ taosBenchmark -A INT,DOUBLE,NCHAR,BINARY\(16\)
|
|||
#### 查询超级表的配置参数
|
||||
|
||||
查询超级表的配置参数在 `super_table_query` 中设置。
|
||||
超级表查询的线程模式与上面介绍的指定查询语句查询的 `正常查询` 模式相同,不同之处是本 `sqls` 使用所有子表填充。
|
||||
|
||||
- **stblname** : 指定要查询的超级表的名称,必填。
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ description: 对表的各种管理操作
|
|||
|
||||
## 创建表
|
||||
|
||||
`CREATE TABLE` 语句用于创建普通表和以超级表为模板创建子表。
|
||||
`CREATE TABLE` 语句用于创建普通表和以超级表为模板创建子表(也可以通过指定 TAGS 字段创建超级表)。
|
||||
|
||||
```sql
|
||||
CREATE TABLE [IF NOT EXISTS] [db_name.]tb_name (create_definition [, create_definition] ...) [table_options]
|
||||
|
|
|
@ -902,6 +902,7 @@ CHAR(expr1 [, expr2] [, epxr3] ...)
|
|||
- 输入参数的 NULL 值会被跳过。
|
||||
- 输入参数若为字符串类型,会将其转换为数值类型处理。
|
||||
- 若输入的参数对应的字符为不可打印字符,返回值中仍有该参数对应的字符,但是可能无法显示出来。
|
||||
- 输入参数的个数上限为 2^31 - 1 个。
|
||||
|
||||
**举例**:
|
||||
```sql
|
||||
|
|
|
@ -138,6 +138,7 @@ SELECT COUNT(*) FROM meters WHERE _rowts - voltage > 1000000;
|
|||
- 聚合时间段的窗口宽度由关键词 INTERVAL 指定,最短时间间隔 10 毫秒(10a);并且支持偏移 offset(偏移必须小于间隔),也即时间窗口划分与“UTC 时刻 0”相比的偏移量。SLIDING 语句用于指定聚合时间段的前向增量,也即每次窗口向前滑动的时长。
|
||||
- 使用 INTERVAL 语句时,除非极特殊的情况,都要求把客户端和服务端的 taos.cfg 配置文件中的 timezone 参数配置为相同的取值,以避免时间处理函数频繁进行跨时区转换而导致的严重性能影响。
|
||||
- 返回的结果中时间序列严格单调递增。
|
||||
- 使用 AUTO 作为窗口偏移量时,如果 WHERE 时间条件比较复杂,比如多个 AND/OR/IN 互相组合,那么 AUTO 可能不生效,这种情况可以通过手动指定窗口偏移量进行解决。
|
||||
- 使用 AUTO 作为窗口偏移量时,如果窗口宽度的单位是 d (天), n (月), w (周), y (年),比如: INTERVAL(1d, AUTO), INTERVAL(3w, AUTO),此时 TSMA 优化无法生效。如果目标表上手动创建了TSMA,语句会报错退出;这种情况下,可以显式指定 Hint SKIP_TSMA 或者不使用 AUTO 作为窗口偏移量。
|
||||
|
||||
### 状态窗口
|
||||
|
|
|
@ -306,9 +306,10 @@ SHOW TOPICS;
|
|||
|
||||
```sql
|
||||
SHOW TRANSACTIONS;
|
||||
SHOW TRANSACTION [tranaction_id];
|
||||
```
|
||||
|
||||
显示当前系统中正在执行的事务的信息(该事务仅针对除普通表以外的元数据级别)
|
||||
显示当前系统中正在执行的所有或者某一个事务的信息(该事务仅针对除普通表以外的元数据级别)
|
||||
|
||||
## SHOW USERS
|
||||
|
||||
|
|
|
@ -325,8 +325,50 @@ TDengine 采用了一种数据驱动的策略来实现缓存数据的持久化
|
|||
|
||||
### 多级存储与对象存储
|
||||
|
||||
在默认情况下,TDengine 将所有数据存储在 /var/lib/taos 目录中。为了扩展存储容量,减少文件读取可能导致的瓶颈,并提升数据吞吐量,TDengine 允许通过配置参数dataDir,使得集群能够同时利用挂载的多块硬盘。
|
||||
说明:多级存储功能仅企业版支持,从 2.0.16.0 版本开始提供。
|
||||
|
||||
此外,TDengine 还提供了数据分级存储的功能,允许用户将不同时间段的数据存储在不同存储设备的目录中,以此实现将“热”数据和“冷”数据分开存储。这样做可以充分利用各种存储资源,同时节约成本。例如,对于最新采集且需要频繁访问的数据,由于其读取性能要求较高,用户可以配置将这些数据存储在高性能的固态硬盘上。而对于超过一定期限、查询需求较低的数据,则可以将其存储在成本相对较低的机械硬盘上。
|
||||
在默认配置下,TDengine 会将所有数据保存在 /var/lib/taos 目录下,而且每个 vnode 的数据文件保存在该目录下的不同目录。为扩大存储空间,尽量减少文件读取的瓶颈,提高数据吞吐率 TDengine 可通过配置系统参数 dataDir 让多个挂载的硬盘被系统同时使用。
|
||||
|
||||
为了进一步降低存储成本,TDengine 还支持将时序数据存储在对象存储系统中。通过其创新性的设计,在大多数情况下,从对象存储系统中查询时序数据的性能接近本地硬盘的一半,而在某些场景下,性能甚至可以与本地硬盘相媲美。同时,TDengine 还允许用户对存储在对象存储中的时序数据执行删除和更新操作。
|
||||
除此之外,TDengine 也提供了数据分级存储的功能,将不同时间段的数据存储在挂载的不同介质上的目录里,从而实现不同“热度”的数据存储在不同的存储介质上,充分利用存储,节约成本。比如,最新采集的数据需要经常访问,对硬盘的读取性能要求高,那么用户可以配置将这些数据存储在 SSD 盘上。超过一定期限的数据,查询需求量没有那么高,那么可以存储在相对便宜的 HDD 盘上。
|
||||
|
||||
多级存储支持 3 级,每级最多可配置 128 个挂载点。
|
||||
|
||||
TDengine 多级存储配置方式如下(在配置文件/etc/taos/taos.cfg 中):
|
||||
|
||||
```
|
||||
dataDir [path] <level> <primary> <disable_create_new_file>
|
||||
```
|
||||
|
||||
- path: 挂载点的文件夹路径
|
||||
- level: 介质存储等级,取值为 0,1,2。
|
||||
0 级存储最新的数据,1 级存储次新的数据,2 级存储最老的数据,省略默认为 0。
|
||||
各级存储之间的数据流向:0 级存储 -> 1 级存储 -> 2 级存储。
|
||||
同一存储等级可挂载多个硬盘,同一存储等级上的数据文件分布在该存储等级的所有硬盘上。
|
||||
需要说明的是,数据在不同级别的存储介质上的移动,是由系统自动完成的,用户无需干预。
|
||||
- primary: 是否为主挂载点,0(否)或 1(是),省略默认为 1。
|
||||
- disable_create_new_file: 是否禁止创建新文件组,0(否)或 1(是),省略默认为 0。
|
||||
|
||||
在配置中,只允许一个主挂载点的存在(level=0,primary=1),例如采用如下的配置方式:
|
||||
|
||||
```
|
||||
dataDir /mnt/data1 0 1 0
|
||||
dataDir /mnt/data2 0 0 0
|
||||
dataDir /mnt/data3 1 0 0
|
||||
dataDir /mnt/data4 1 0 1
|
||||
dataDir /mnt/data5 2 0 0
|
||||
dataDir /mnt/data6 2 0 0
|
||||
```
|
||||
|
||||
您可以使用以下命令动态修改 dataDir 的 disable 来控制当前目录是否开启 disable_create_new_file 。
|
||||
```
|
||||
alter dnode 1 "/mnt/disk2/taos 1";
|
||||
```
|
||||
|
||||
:::note
|
||||
|
||||
1. 多级存储不允许跨级配置,合法的配置方案有:仅 0 级,仅 0 级+ 1 级,以及 0 级+ 1 级+ 2 级。而不允许只配置 level=0 和 level=2,而不配置 level=1。
|
||||
2. 禁止手动移除使用中的挂载盘,挂载盘目前不支持非本地的网络盘。
|
||||
3. 多级存储目前不支持删除已经挂载的硬盘的功能。
|
||||
4. 0 级存储至少存在一个 disable_create_new_file 为 0 的挂载点,1 级 和 2 级存储没有该限制。
|
||||
|
||||
:::
|
|
@ -63,6 +63,7 @@ extern "C" {
|
|||
#define TSDB_INS_TABLE_TSMAS "ins_tsmas"
|
||||
#define TSDB_INS_DISK_USAGE "ins_disk_usage"
|
||||
#define TSDB_INS_TABLE_FILESETS "ins_filesets"
|
||||
#define TSDB_INS_TABLE_TRANSACTION_DETAILS "ins_transaction_details"
|
||||
|
||||
#define TSDB_PERFORMANCE_SCHEMA_DB "performance_schema"
|
||||
#define TSDB_PERFS_TABLE_SMAS "perf_smas"
|
||||
|
|
|
@ -182,7 +182,7 @@ void tColDataClear(SColData *pColData);
|
|||
void tColDataDeepClear(SColData *pColData);
|
||||
int32_t tColDataAppendValue(SColData *pColData, SColVal *pColVal);
|
||||
int32_t tColDataUpdateValue(SColData *pColData, SColVal *pColVal, bool forward);
|
||||
void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal);
|
||||
int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal);
|
||||
uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal);
|
||||
int32_t tColDataCopy(SColData *pColDataFrom, SColData *pColData, xMallocFn xMalloc, void *arg);
|
||||
void tColDataArrGetRowKey(SColData *aColData, int32_t nColData, int32_t iRow, SRowKey *key);
|
||||
|
|
|
@ -112,9 +112,8 @@ extern int32_t tsNumOfSnodeWriteThreads;
|
|||
extern int64_t tsQueueMemoryAllowed;
|
||||
extern int32_t tsRetentionSpeedLimitMB;
|
||||
|
||||
extern const char *tsAlterCompactTaskKeywords;
|
||||
extern int32_t tsNumOfCompactThreads;
|
||||
extern int32_t tsNumOfRetentionThreads;
|
||||
extern int32_t tsNumOfCompactThreads;
|
||||
extern int32_t tsNumOfRetentionThreads;
|
||||
|
||||
// sync raft
|
||||
extern int32_t tsElectInterval;
|
||||
|
@ -291,8 +290,8 @@ extern int tsStreamAggCnt;
|
|||
extern bool tsFilterScalarMode;
|
||||
extern int32_t tsMaxStreamBackendCache;
|
||||
extern int32_t tsPQSortMemThreshold;
|
||||
extern int32_t tsResolveFQDNRetryTime;
|
||||
extern bool tsStreamCoverage;
|
||||
extern int8_t tsS3EpNum;
|
||||
|
||||
extern bool tsExperimental;
|
||||
// #define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
|
||||
|
|
|
@ -163,6 +163,7 @@ typedef enum _mgmt_table {
|
|||
TSDB_MGMT_TABLE_ANODE_FULL,
|
||||
TSDB_MGMT_TABLE_USAGE,
|
||||
TSDB_MGMT_TABLE_FILESETS,
|
||||
TSDB_MGMT_TABLE_TRANSACTION_DETAIL,
|
||||
TSDB_MGMT_TABLE_MAX,
|
||||
} EShowType;
|
||||
|
||||
|
@ -405,6 +406,7 @@ typedef enum ENodeType {
|
|||
QUERY_NODE_SHOW_CREATE_TSMA_STMT,
|
||||
QUERY_NODE_DROP_TSMA_STMT,
|
||||
QUERY_NODE_SHOW_FILESETS_STMT,
|
||||
QUERY_NODE_SHOW_TRANSACTION_DETAILS_STMT,
|
||||
|
||||
// logic plan node
|
||||
QUERY_NODE_LOGIC_PLAN_SCAN = 1000,
|
||||
|
|
|
@ -389,7 +389,6 @@ typedef struct SStateStore {
|
|||
int32_t (*streamStateFillGetGroupKVByCur)(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
int32_t (*streamStateGetKVByCur)(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
|
||||
void (*streamStateSetFillInfo)(SStreamState* pState);
|
||||
void (*streamStateClearExpiredState)(SStreamState* pState);
|
||||
|
||||
int32_t (*streamStateSessionAddIfNotExist)(SStreamState* pState, SSessionKey* key, TSKEY gap, void** pVal,
|
||||
|
@ -455,7 +454,6 @@ typedef struct SStateStore {
|
|||
int32_t (*streamStateBegin)(SStreamState* pState);
|
||||
void (*streamStateCommit)(SStreamState* pState);
|
||||
void (*streamStateDestroy)(SStreamState* pState, bool remove);
|
||||
int32_t (*streamStateDeleteCheckPoint)(SStreamState* pState, TSKEY mark);
|
||||
void (*streamStateReloadInfo)(SStreamState* pState, TSKEY ts);
|
||||
void (*streamStateCopyBackend)(SStreamState* src, SStreamState* dst);
|
||||
} SStateStore;
|
||||
|
|
|
@ -237,18 +237,20 @@ static FORCE_INLINE int32_t udfColDataSet(SUdfColumn *pColumn, uint32_t currentR
|
|||
(void)memcpy(data->fixLenCol.data + meta->bytes * currentRow, pData, meta->bytes);
|
||||
} else {
|
||||
int32_t dataLen = varDataTLen(pData);
|
||||
if (meta->type == TSDB_DATA_TYPE_JSON) {
|
||||
if (*pData == TSDB_DATA_TYPE_NULL) {
|
||||
dataLen = 0;
|
||||
} else if (*pData == TSDB_DATA_TYPE_NCHAR) {
|
||||
dataLen = varDataTLen(pData + sizeof(char));
|
||||
} else if (*pData == TSDB_DATA_TYPE_BIGINT || *pData == TSDB_DATA_TYPE_DOUBLE) {
|
||||
dataLen = sizeof(int64_t);
|
||||
} else if (*pData == TSDB_DATA_TYPE_BOOL) {
|
||||
dataLen = sizeof(char);
|
||||
}
|
||||
dataLen += sizeof(char);
|
||||
}
|
||||
// This is a piece of code to help users implement udf. It is only called during testing.
|
||||
// Currently, the json type is not supported and will not be called.
|
||||
// if (meta->type == TSDB_DATA_TYPE_JSON) {
|
||||
// if (*pData == TSDB_DATA_TYPE_NULL) {
|
||||
// dataLen = 0;
|
||||
// } else if (*pData == TSDB_DATA_TYPE_NCHAR) {
|
||||
// dataLen = varDataTLen(pData + sizeof(char));
|
||||
// } else if (*pData == TSDB_DATA_TYPE_BIGINT || *pData == TSDB_DATA_TYPE_DOUBLE) {
|
||||
// dataLen = sizeof(int64_t);
|
||||
// } else if (*pData == TSDB_DATA_TYPE_BOOL) {
|
||||
// dataLen = sizeof(char);
|
||||
// }
|
||||
// dataLen += sizeof(char);
|
||||
// }
|
||||
|
||||
if (data->varLenCol.payloadAllocLen < data->varLenCol.payloadLen + dataLen) {
|
||||
uint32_t newSize = data->varLenCol.payloadAllocLen;
|
||||
|
|
|
@ -112,7 +112,7 @@ typedef struct SDatabaseOptions {
|
|||
int8_t s3Compact;
|
||||
int8_t withArbitrator;
|
||||
// for auto-compact
|
||||
int8_t compactTimeOffset; // hours
|
||||
int32_t compactTimeOffset; // hours
|
||||
int32_t compactInterval; // minutes
|
||||
int32_t compactStartTime; // minutes
|
||||
int32_t compactEndTime; // minutes
|
||||
|
@ -439,6 +439,11 @@ typedef struct SShowCompactDetailsStmt {
|
|||
SNode* pCompactId;
|
||||
} SShowCompactDetailsStmt;
|
||||
|
||||
typedef struct SShowTransactionDetailsStmt {
|
||||
ENodeType type;
|
||||
SNode* pTransactionId;
|
||||
} SShowTransactionDetailsStmt;
|
||||
|
||||
typedef enum EIndexType { INDEX_TYPE_SMA = 1, INDEX_TYPE_FULLTEXT, INDEX_TYPE_NORMAL } EIndexType;
|
||||
|
||||
typedef struct SIndexOptions {
|
||||
|
|
|
@ -34,7 +34,6 @@ void streamStateClose(SStreamState* pState, bool remove);
|
|||
int32_t streamStateBegin(SStreamState* pState);
|
||||
void streamStateCommit(SStreamState* pState);
|
||||
void streamStateDestroy(SStreamState* pState, bool remove);
|
||||
int32_t streamStateDeleteCheckPoint(SStreamState* pState, TSKEY mark);
|
||||
int32_t streamStateDelTaskDb(SStreamState* pState);
|
||||
|
||||
int32_t streamStateFuncPut(SStreamState* pState, const SWinKey* key, const void* value, int32_t vLen);
|
||||
|
@ -108,7 +107,6 @@ int32_t streamStateFillGetGroupKVByCur(SStreamStateCur* pCur, SWinKey* pKey, con
|
|||
int32_t streamStateGetKVByCur(SStreamStateCur* pCur, SWinKey* pKey, const void** pVal, int32_t* pVLen);
|
||||
|
||||
// twa
|
||||
void streamStateSetFillInfo(SStreamState* pState);
|
||||
void streamStateClearExpiredState(SStreamState* pState);
|
||||
|
||||
void streamStateCurNext(SStreamState* pState, SStreamStateCur* pCur);
|
||||
|
|
|
@ -67,7 +67,6 @@ SStreamSnapshot* getSnapshot(SStreamFileState* pFileState);
|
|||
void flushSnapshot(SStreamFileState* pFileState, SStreamSnapshot* pSnapshot, bool flushState);
|
||||
int32_t recoverSnapshot(SStreamFileState* pFileState, int64_t ckId);
|
||||
|
||||
int32_t getSnapshotIdList(SStreamFileState* pFileState, SArray* list);
|
||||
int32_t deleteExpiredCheckPoint(SStreamFileState* pFileState, TSKEY mark);
|
||||
int32_t streamFileStateGetSelectRowSize(SStreamFileState* pFileState);
|
||||
void streamFileStateReloadInfo(SStreamFileState* pFileState, TSKEY ts);
|
||||
|
|
|
@ -148,7 +148,7 @@ int32_t tfsMkdirRecur(STfs *pTfs, const char *rname);
|
|||
* @return int32_t 0 for success, -1 for failure.
|
||||
*/
|
||||
int32_t tfsMkdirRecurAt(STfs *pTfs, const char *rname, SDiskID diskId);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief check directories exist in tfs.
|
||||
*
|
||||
|
@ -158,7 +158,7 @@ int32_t tfsMkdirRecurAt(STfs *pTfs, const char *rname, SDiskID diskId);
|
|||
* @return true for exist, false for not exist.
|
||||
*/
|
||||
bool tfsDirExistAt(STfs *pTfs, const char *rname, SDiskID diskId);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @brief Remove directory at all levels in tfs.
|
||||
*
|
||||
|
@ -241,7 +241,7 @@ void tfsBasename(const STfsFile *pFile, char *dest);
|
|||
* @param dest The buffer where dirname will be saved.
|
||||
*/
|
||||
void tfsDirname(const STfsFile *pFile, char *dest);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Get the absolute file name of rname.
|
||||
*
|
||||
|
@ -251,7 +251,7 @@ void tfsDirname(const STfsFile *pFile, char *dest);
|
|||
* @param aname absolute file name
|
||||
*/
|
||||
void tfsAbsoluteName(STfs *pTfs, SDiskID diskId, const char *rname, char *aname);
|
||||
|
||||
#endif
|
||||
/**
|
||||
* @brief Remove file in tfs.
|
||||
*
|
||||
|
|
|
@ -411,6 +411,7 @@ int32_t taosGetErrSize();
|
|||
#define TSDB_CODE_MND_TRANS_CTX_SWITCH TAOS_DEF_ERROR_CODE(0, 0x03D8)
|
||||
#define TSDB_CODE_MND_TRANS_CONFLICT_COMPACT TAOS_DEF_ERROR_CODE(0, 0x03D9)
|
||||
#define TSDB_CODE_MND_TRANS_UNKNOW_ERROR TAOS_DEF_ERROR_CODE(0, 0x03DF)
|
||||
#define TSDB_CODE_MND_TRANS_NOT_ABLE_TO_kILLED TAOS_DEF_ERROR_CODE(0, 0x03D2)
|
||||
|
||||
// mnode-mq
|
||||
#define TSDB_CODE_MND_TOPIC_ALREADY_EXIST TAOS_DEF_ERROR_CODE(0, 0x03E0)
|
||||
|
|
|
@ -329,7 +329,11 @@ typedef enum ELogicConditionType {
|
|||
|
||||
#define TSDB_TRANS_STAGE_LEN 12
|
||||
#define TSDB_TRANS_TYPE_LEN 16
|
||||
#define TSDB_TRANS_ERROR_LEN 512
|
||||
#define TSDB_TRANS_ERROR_LEN 512
|
||||
#define TSDB_TRANS_OBJTYPE_LEN 40
|
||||
#define TSDB_TRANS_RESULT_LEN 100
|
||||
#define TSDB_TRANS_TARGET_LEN 300
|
||||
#define TSDB_TRANS_DETAIL_LEN 100
|
||||
|
||||
#define TSDB_STEP_NAME_LEN 32
|
||||
#define TSDB_STEP_DESC_LEN 128
|
||||
|
|
|
@ -221,11 +221,8 @@ int stmtPrepare2(TAOS_STMT2 *stmt, const char *sql, unsigned long length
|
|||
int stmtSetTbName2(TAOS_STMT2 *stmt, const char *tbName);
|
||||
int stmtSetTbTags2(TAOS_STMT2 *stmt, TAOS_STMT2_BIND *tags);
|
||||
int stmtBindBatch2(TAOS_STMT2 *stmt, TAOS_STMT2_BIND *bind, int32_t colIdx);
|
||||
int stmtGetTagFields2(TAOS_STMT2 *stmt, int *nums, TAOS_FIELD_E **fields);
|
||||
int stmtGetColFields2(TAOS_STMT2 *stmt, int *nums, TAOS_FIELD_E **fields);
|
||||
int stmtGetStbColFields2(TAOS_STMT2 *stmt, int *nums, TAOS_FIELD_ALL **fields);
|
||||
int stmtGetParamNum2(TAOS_STMT2 *stmt, int *nums);
|
||||
int stmtGetParamTbName(TAOS_STMT2 *stmt, int *nums);
|
||||
int stmtIsInsert2(TAOS_STMT2 *stmt, int *insert);
|
||||
TAOS_RES *stmtUseResult2(TAOS_STMT2 *stmt);
|
||||
const char *stmtErrstr2(TAOS_STMT2 *stmt);
|
||||
|
|
|
@ -24,13 +24,13 @@
|
|||
#include "query.h"
|
||||
#include "scheduler.h"
|
||||
#include "tcompare.h"
|
||||
#include "tconv.h"
|
||||
#include "tdatablock.h"
|
||||
#include "tglobal.h"
|
||||
#include "tmsg.h"
|
||||
#include "tref.h"
|
||||
#include "trpc.h"
|
||||
#include "version.h"
|
||||
#include "tconv.h"
|
||||
|
||||
#define TSC_VAR_NOT_RELEASE 1
|
||||
#define TSC_VAR_RELEASED 0
|
||||
|
@ -56,12 +56,12 @@ int taos_options(TSDB_OPTION option, const void *arg, ...) {
|
|||
}
|
||||
|
||||
#ifndef WINDOWS
|
||||
static void freeTz(void *p){
|
||||
static void freeTz(void *p) {
|
||||
timezone_t tz = *(timezone_t *)p;
|
||||
tzfree(tz);
|
||||
}
|
||||
|
||||
int32_t tzInit(){
|
||||
int32_t tzInit() {
|
||||
pTimezoneMap = taosHashInit(0, MurmurHash3_32, false, HASH_ENTRY_LOCK);
|
||||
if (pTimezoneMap == NULL) {
|
||||
return terrno;
|
||||
|
@ -75,15 +75,15 @@ int32_t tzInit(){
|
|||
return 0;
|
||||
}
|
||||
|
||||
void tzCleanup(){
|
||||
void tzCleanup() {
|
||||
taosHashCleanup(pTimezoneMap);
|
||||
taosHashCleanup(pTimezoneNameMap);
|
||||
}
|
||||
|
||||
static timezone_t setConnnectionTz(const char* val){
|
||||
timezone_t tz = NULL;
|
||||
static timezone_t setConnnectionTz(const char *val) {
|
||||
timezone_t tz = NULL;
|
||||
timezone_t *tmp = taosHashGet(pTimezoneMap, val, strlen(val));
|
||||
if (tmp != NULL && *tmp != NULL){
|
||||
if (tmp != NULL && *tmp != NULL) {
|
||||
tz = *tmp;
|
||||
goto END;
|
||||
}
|
||||
|
@ -100,20 +100,20 @@ static timezone_t setConnnectionTz(const char* val){
|
|||
}
|
||||
}
|
||||
int32_t code = taosHashPut(pTimezoneMap, val, strlen(val), &tz, sizeof(timezone_t));
|
||||
if (code != 0){
|
||||
if (code != 0) {
|
||||
tscError("%s put timezone to tz map error:%d", __func__, code);
|
||||
tzfree(tz);
|
||||
tz = NULL;
|
||||
goto END;
|
||||
}
|
||||
|
||||
time_t tx1 = taosGetTimestampSec();
|
||||
char output[TD_TIMEZONE_LEN] = {0};
|
||||
time_t tx1 = taosGetTimestampSec();
|
||||
char output[TD_TIMEZONE_LEN] = {0};
|
||||
code = taosFormatTimezoneStr(tx1, val, tz, output);
|
||||
if (code == 0){
|
||||
if (code == 0) {
|
||||
code = taosHashPut(pTimezoneNameMap, &tz, sizeof(timezone_t), output, strlen(output) + 1);
|
||||
}
|
||||
if (code != 0){
|
||||
if (code != 0) {
|
||||
tscError("failed to put timezone %s to map", val);
|
||||
}
|
||||
|
||||
|
@ -122,18 +122,18 @@ END:
|
|||
}
|
||||
#endif
|
||||
|
||||
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char* val){
|
||||
static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, const char *val) {
|
||||
if (taos == NULL) {
|
||||
return terrno = TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
#ifdef WINDOWS
|
||||
if (option == TSDB_OPTION_CONNECTION_TIMEZONE){
|
||||
if (option == TSDB_OPTION_CONNECTION_TIMEZONE) {
|
||||
return terrno = TSDB_CODE_NOT_SUPPORTTED_IN_WINDOWS;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION){
|
||||
if (option < TSDB_OPTION_CONNECTION_CLEAR || option >= TSDB_MAX_OPTIONS_CONNECTION) {
|
||||
return terrno = TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
|
||||
|
@ -149,7 +149,7 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
|
|||
return terrno;
|
||||
}
|
||||
|
||||
if (option == TSDB_OPTION_CONNECTION_CLEAR){
|
||||
if (option == TSDB_OPTION_CONNECTION_CLEAR) {
|
||||
val = NULL;
|
||||
}
|
||||
|
||||
|
@ -165,19 +165,19 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
|
|||
goto END;
|
||||
}
|
||||
pObj->optionInfo.charsetCxt = tmp;
|
||||
}else{
|
||||
} else {
|
||||
pObj->optionInfo.charsetCxt = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (option == TSDB_OPTION_CONNECTION_TIMEZONE || option == TSDB_OPTION_CONNECTION_CLEAR) {
|
||||
#ifndef WINDOWS
|
||||
if (val != NULL){
|
||||
if (val[0] == 0){
|
||||
if (val != NULL) {
|
||||
if (val[0] == 0) {
|
||||
val = "UTC";
|
||||
}
|
||||
timezone_t tz = setConnnectionTz(val);
|
||||
if (tz == NULL){
|
||||
if (tz == NULL) {
|
||||
code = terrno;
|
||||
goto END;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ static int32_t setConnectionOption(TAOS *taos, TSDB_OPTION_CONNECTION option, co
|
|||
if (option == TSDB_OPTION_CONNECTION_USER_IP || option == TSDB_OPTION_CONNECTION_CLEAR) {
|
||||
if (val != NULL) {
|
||||
pObj->optionInfo.userIp = taosInetAddr(val);
|
||||
if (pObj->optionInfo.userIp == INADDR_NONE){
|
||||
if (pObj->optionInfo.userIp == INADDR_NONE) {
|
||||
code = TSDB_CODE_INVALID_PARA;
|
||||
goto END;
|
||||
}
|
||||
|
@ -213,7 +213,7 @@ END:
|
|||
return terrno = code;
|
||||
}
|
||||
|
||||
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...){
|
||||
int taos_options_connection(TAOS *taos, TSDB_OPTION_CONNECTION option, const void *arg, ...) {
|
||||
return setConnectionOption(taos, option, (const char *)arg);
|
||||
}
|
||||
|
||||
|
@ -2129,6 +2129,11 @@ int taos_stmt_close(TAOS_STMT *stmt) {
|
|||
}
|
||||
|
||||
TAOS_STMT2 *taos_stmt2_init(TAOS *taos, TAOS_STMT2_OPTION *option) {
|
||||
if (NULL == taos) {
|
||||
tscError("NULL parameter for %s", __FUNCTION__);
|
||||
terrno = TSDB_CODE_INVALID_PARA;
|
||||
return NULL;
|
||||
}
|
||||
STscObj *pObj = acquireTscObj(*(int64_t *)taos);
|
||||
if (NULL == pObj) {
|
||||
tscError("invalid parameter for %s", __FUNCTION__);
|
||||
|
@ -2257,16 +2262,7 @@ int taos_stmt2_close(TAOS_STMT2 *stmt) {
|
|||
|
||||
return stmtClose2(stmt);
|
||||
}
|
||||
/*
|
||||
int taos_stmt2_param_count(TAOS_STMT2 *stmt, int *nums) {
|
||||
if (stmt == NULL || nums == NULL) {
|
||||
tscError("NULL parameter for %s", __FUNCTION__);
|
||||
terrno = TSDB_CODE_INVALID_PARA;
|
||||
return terrno;
|
||||
}
|
||||
return stmtGetParamNum2(stmt, nums);
|
||||
}
|
||||
*/
|
||||
|
||||
int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
|
||||
if (stmt == NULL || insert == NULL) {
|
||||
tscError("NULL parameter for %s", __FUNCTION__);
|
||||
|
@ -2277,28 +2273,6 @@ int taos_stmt2_is_insert(TAOS_STMT2 *stmt, int *insert) {
|
|||
return stmtIsInsert2(stmt, insert);
|
||||
}
|
||||
|
||||
// int taos_stmt2_get_fields(TAOS_STMT2 *stmt, TAOS_FIELD_T field_type, int *count, TAOS_FIELD_E **fields) {
|
||||
// if (stmt == NULL || count == NULL) {
|
||||
// tscError("NULL parameter for %s", __FUNCTION__);
|
||||
// terrno = TSDB_CODE_INVALID_PARA;
|
||||
// return terrno;
|
||||
// }
|
||||
|
||||
// if (field_type == TAOS_FIELD_COL) {
|
||||
// return stmtGetColFields2(stmt, count, fields);
|
||||
// } else if (field_type == TAOS_FIELD_TAG) {
|
||||
// return stmtGetTagFields2(stmt, count, fields);
|
||||
// } else if (field_type == TAOS_FIELD_QUERY) {
|
||||
// return stmtGetParamNum2(stmt, count);
|
||||
// } else if (field_type == TAOS_FIELD_TBNAME) {
|
||||
// return stmtGetParamTbName(stmt, count);
|
||||
// } else {
|
||||
// tscError("invalid parameter for %s", __FUNCTION__);
|
||||
// terrno = TSDB_CODE_INVALID_PARA;
|
||||
// return terrno;
|
||||
// }
|
||||
// }
|
||||
|
||||
int taos_stmt2_get_fields(TAOS_STMT2 *stmt, int *count, TAOS_FIELD_ALL **fields) {
|
||||
if (stmt == NULL || count == NULL) {
|
||||
tscError("NULL parameter for %s", __FUNCTION__);
|
||||
|
|
|
@ -848,6 +848,7 @@ static int stmtSetDbName2(TAOS_STMT2* stmt, const char* dbName) {
|
|||
STMT_DLOG("start to set dbName: %s", dbName);
|
||||
|
||||
pStmt->db = taosStrdup(dbName);
|
||||
(void)strdequote(pStmt->db);
|
||||
STMT_ERR_RET(stmtCreateRequest(pStmt));
|
||||
|
||||
// The SQL statement specifies a database name, overriding the previously specified database
|
||||
|
@ -1036,28 +1037,6 @@ int stmtSetTbTags2(TAOS_STMT2* stmt, TAOS_STMT2_BIND* tags) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int stmtFetchTagFields2(STscStmt2* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) {
|
||||
if (pStmt->errCode != TSDB_CODE_SUCCESS) {
|
||||
return pStmt->errCode;
|
||||
}
|
||||
|
||||
if (STMT_TYPE_QUERY == pStmt->sql.type) {
|
||||
tscError("invalid operation to get query tag fileds");
|
||||
STMT_ERR_RET(TSDB_CODE_TSC_STMT_API_ERROR);
|
||||
}
|
||||
|
||||
STableDataCxt** pDataBlock =
|
||||
(STableDataCxt**)taosHashGet(pStmt->exec.pBlockHash, pStmt->bInfo.tbFName, strlen(pStmt->bInfo.tbFName));
|
||||
if (NULL == pDataBlock) {
|
||||
tscError("table %s not found in exec blockHash", pStmt->bInfo.tbFName);
|
||||
STMT_ERR_RET(TSDB_CODE_APP_ERROR);
|
||||
}
|
||||
|
||||
STMT_ERR_RET(qBuildStmtTagFields(*pDataBlock, pStmt->bInfo.boundTags, fieldNum, fields));
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int stmtFetchColFields2(STscStmt2* pStmt, int32_t* fieldNum, TAOS_FIELD_E** fields) {
|
||||
if (pStmt->errCode != TSDB_CODE_SUCCESS) {
|
||||
return pStmt->errCode;
|
||||
|
@ -1819,47 +1798,6 @@ int stmtAffectedRows(TAOS_STMT* stmt) { return ((STscStmt2*)stmt)->affectedRows;
|
|||
|
||||
int stmtAffectedRowsOnce(TAOS_STMT* stmt) { return ((STscStmt2*)stmt)->exec.affectedRows; }
|
||||
*/
|
||||
int stmtGetTagFields2(TAOS_STMT2* stmt, int* nums, TAOS_FIELD_E** fields) {
|
||||
int32_t code = 0;
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
int32_t preCode = pStmt->errCode;
|
||||
|
||||
STMT_DLOG_E("start to get tag fields");
|
||||
|
||||
if (pStmt->errCode != TSDB_CODE_SUCCESS) {
|
||||
return pStmt->errCode;
|
||||
}
|
||||
|
||||
if (STMT_TYPE_QUERY == pStmt->sql.type) {
|
||||
STMT_ERRI_JRET(TSDB_CODE_TSC_STMT_API_ERROR);
|
||||
}
|
||||
|
||||
STMT_ERRI_JRET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
|
||||
|
||||
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
|
||||
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
||||
pStmt->bInfo.needParse = false;
|
||||
}
|
||||
|
||||
if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
|
||||
taos_free_result(pStmt->exec.pRequest);
|
||||
pStmt->exec.pRequest = NULL;
|
||||
}
|
||||
|
||||
STMT_ERRI_JRET(stmtCreateRequest(pStmt));
|
||||
|
||||
if (pStmt->bInfo.needParse) {
|
||||
STMT_ERRI_JRET(stmtParseSql(pStmt));
|
||||
}
|
||||
|
||||
STMT_ERRI_JRET(stmtFetchTagFields2(stmt, nums, fields));
|
||||
|
||||
_return:
|
||||
|
||||
pStmt->errCode = preCode;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
int stmtParseColFields2(TAOS_STMT2* stmt) {
|
||||
int32_t code = 0;
|
||||
|
@ -1902,15 +1840,6 @@ _return:
|
|||
return code;
|
||||
}
|
||||
|
||||
int stmtGetColFields2(TAOS_STMT2* stmt, int* nums, TAOS_FIELD_E** fields) {
|
||||
int32_t code = stmtParseColFields2(stmt);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
return stmtFetchColFields2(stmt, nums, fields);
|
||||
}
|
||||
|
||||
int stmtGetStbColFields2(TAOS_STMT2* stmt, int* nums, TAOS_FIELD_ALL** fields) {
|
||||
int32_t code = stmtParseColFields2(stmt);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1956,95 +1885,6 @@ int stmtGetParamNum2(TAOS_STMT2* stmt, int* nums) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int stmtGetParamTbName(TAOS_STMT2* stmt, int* nums) {
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
int32_t code = 0;
|
||||
int32_t preCode = pStmt->errCode;
|
||||
|
||||
STMT_DLOG_E("start to get param num");
|
||||
|
||||
if (pStmt->errCode != TSDB_CODE_SUCCESS) {
|
||||
return pStmt->errCode;
|
||||
}
|
||||
|
||||
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
|
||||
|
||||
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
|
||||
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
||||
pStmt->bInfo.needParse = false;
|
||||
}
|
||||
|
||||
if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
|
||||
taos_free_result(pStmt->exec.pRequest);
|
||||
pStmt->exec.pRequest = NULL;
|
||||
}
|
||||
|
||||
STMT_ERR_RET(stmtCreateRequest(pStmt));
|
||||
|
||||
if (pStmt->bInfo.needParse) {
|
||||
STMT_ERRI_JRET(stmtParseSql(pStmt));
|
||||
}
|
||||
|
||||
*nums = STMT_TYPE_MULTI_INSERT == pStmt->sql.type ? 1 : 0;
|
||||
|
||||
_return:
|
||||
if (TSDB_CODE_TSC_STMT_TBNAME_ERROR == code) {
|
||||
*nums = 1;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
pStmt->errCode = preCode;
|
||||
return code;
|
||||
}
|
||||
/*
|
||||
int stmtGetParam(TAOS_STMT* stmt, int idx, int* type, int* bytes) {
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
|
||||
STMT_DLOG_E("start to get param");
|
||||
|
||||
if (pStmt->errCode != TSDB_CODE_SUCCESS) {
|
||||
return pStmt->errCode;
|
||||
}
|
||||
|
||||
if (STMT_TYPE_QUERY == pStmt->sql.type) {
|
||||
STMT_RET(TSDB_CODE_TSC_STMT_API_ERROR);
|
||||
}
|
||||
|
||||
STMT_ERR_RET(stmtSwitchStatus(pStmt, STMT_FETCH_FIELDS));
|
||||
|
||||
if (pStmt->bInfo.needParse && pStmt->sql.runTimes && pStmt->sql.type > 0 &&
|
||||
STMT_TYPE_MULTI_INSERT != pStmt->sql.type) {
|
||||
pStmt->bInfo.needParse = false;
|
||||
}
|
||||
|
||||
if (pStmt->exec.pRequest && STMT_TYPE_QUERY == pStmt->sql.type && pStmt->sql.runTimes) {
|
||||
taos_free_result(pStmt->exec.pRequest);
|
||||
pStmt->exec.pRequest = NULL;
|
||||
}
|
||||
|
||||
STMT_ERR_RET(stmtCreateRequest(pStmt));
|
||||
|
||||
if (pStmt->bInfo.needParse) {
|
||||
STMT_ERR_RET(stmtParseSql(pStmt));
|
||||
}
|
||||
|
||||
int32_t nums = 0;
|
||||
TAOS_FIELD_E* pField = NULL;
|
||||
STMT_ERR_RET(stmtFetchColFields(stmt, &nums, &pField));
|
||||
if (idx >= nums) {
|
||||
tscError("idx %d is too big", idx);
|
||||
taosMemoryFree(pField);
|
||||
STMT_ERR_RET(TSDB_CODE_INVALID_PARA);
|
||||
}
|
||||
|
||||
*type = pField[idx].type;
|
||||
*bytes = pField[idx].bytes;
|
||||
|
||||
taosMemoryFree(pField);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
*/
|
||||
TAOS_RES* stmtUseResult2(TAOS_STMT2* stmt) {
|
||||
STscStmt2* pStmt = (STscStmt2*)stmt;
|
||||
|
||||
|
|
|
@ -41,6 +41,12 @@ TARGET_LINK_LIBRARIES(
|
|||
PUBLIC ${TAOS_LIB}
|
||||
)
|
||||
|
||||
ADD_EXECUTABLE(stmt2Test stmt2Test.cpp)
|
||||
TARGET_LINK_LIBRARIES(
|
||||
stmt2Test
|
||||
os util common transport parser catalog scheduler gtest ${TAOS_LIB_STATIC} qcom executor function
|
||||
)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
clientTest
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/client/"
|
||||
|
@ -62,6 +68,10 @@ IF(${TD_LINUX})
|
|||
NAME connectOptionsTest
|
||||
COMMAND connectOptionsTest
|
||||
)
|
||||
add_test(
|
||||
NAME stmt2Test
|
||||
COMMAND stmt2Test
|
||||
)
|
||||
ENDIF ()
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
|
@ -82,6 +92,12 @@ TARGET_INCLUDE_DIRECTORIES(
|
|||
# PRIVATE "${TD_SOURCE_DIR}/source/client/inc"
|
||||
#)
|
||||
|
||||
TARGET_INCLUDE_DIRECTORIES(
|
||||
stmt2Test
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/client/"
|
||||
PRIVATE "${TD_SOURCE_DIR}/source/client/inc"
|
||||
)
|
||||
|
||||
add_test(
|
||||
NAME smlTest
|
||||
COMMAND smlTest
|
||||
|
@ -96,4 +112,3 @@ add_test(
|
|||
NAME userOperTest
|
||||
COMMAND userOperTest
|
||||
)
|
||||
|
||||
|
|
|
@ -126,6 +126,10 @@ void fetchCallback(void* param, void* res, int32_t numOfRow) {
|
|||
void queryCallback(void* param, void* res, int32_t code) {
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
(void)printf("failed to execute, reason:%s\n", taos_errstr(res));
|
||||
taos_free_result(res);
|
||||
tsem_t *sem = (tsem_t *)param;
|
||||
tsem_post(sem);
|
||||
return;
|
||||
}
|
||||
(void)printf("start to fetch data\n");
|
||||
taos_fetch_raw_block_a(res, fetchCallback, param);
|
||||
|
|
|
@ -276,6 +276,7 @@ TEST(testCase, smlParseCols_Test) {
|
|||
info->dataFormat = false;
|
||||
SSmlLineInfo elements = {0};
|
||||
info->msgBuf = msgBuf;
|
||||
ASSERT_EQ(smlInitHandle(NULL), TSDB_CODE_INVALID_PARA);
|
||||
|
||||
const char *data =
|
||||
"st,t=1 cb\\=in=\"pass\\,it "
|
||||
|
|
|
@ -0,0 +1,827 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <string.h>
|
||||
#include "clientInt.h"
|
||||
#include "osSemaphore.h"
|
||||
#include "taoserror.h"
|
||||
#include "tglobal.h"
|
||||
#include "thash.h"
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
#include "../inc/clientStmt.h"
|
||||
#include "../inc/clientStmt2.h"
|
||||
#include "executor.h"
|
||||
#include "taos.h"
|
||||
|
||||
namespace {
|
||||
|
||||
void checkRows(TAOS* pConn, const char* sql, int32_t expectedRows) {
|
||||
TAOS_RES* pRes = taos_query(pConn, sql);
|
||||
ASSERT_EQ(taos_errno(pRes), TSDB_CODE_SUCCESS);
|
||||
TAOS_ROW pRow = NULL;
|
||||
int rows = 0;
|
||||
while ((pRow = taos_fetch_row(pRes)) != NULL) {
|
||||
rows++;
|
||||
}
|
||||
ASSERT_EQ(rows, expectedRows);
|
||||
taos_free_result(pRes);
|
||||
}
|
||||
|
||||
void stmtAsyncQueryCb(void* param, TAOS_RES* pRes, int code) {
|
||||
int affected_rows = taos_affected_rows(pRes);
|
||||
return;
|
||||
}
|
||||
|
||||
void getFieldsSuccess(TAOS* taos, const char* sql, TAOS_FIELD_ALL* expectedFields, int expectedFieldNum) {
|
||||
TAOS_STMT2_OPTION option = {0};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
int fieldNum = 0;
|
||||
TAOS_FIELD_ALL* pFields = NULL;
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, &pFields);
|
||||
ASSERT_EQ(code, 0);
|
||||
ASSERT_EQ(fieldNum, expectedFieldNum);
|
||||
|
||||
for (int i = 0; i < fieldNum; i++) {
|
||||
ASSERT_STREQ(pFields[i].name, expectedFields[i].name);
|
||||
ASSERT_EQ(pFields[i].type, expectedFields[i].type);
|
||||
ASSERT_EQ(pFields[i].field_type, expectedFields[i].field_type);
|
||||
ASSERT_EQ(pFields[i].precision, expectedFields[i].precision);
|
||||
ASSERT_EQ(pFields[i].bytes, expectedFields[i].bytes);
|
||||
ASSERT_EQ(pFields[i].scale, expectedFields[i].scale);
|
||||
}
|
||||
taos_stmt2_free_fields(stmt, pFields);
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
void getFieldsError(TAOS* taos, const char* sql, int errorCode) {
|
||||
TAOS_STMT2_OPTION option = {0};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
int fieldNum = 0;
|
||||
TAOS_FIELD_ALL* pFields = NULL;
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, &pFields);
|
||||
ASSERT_EQ(code, errorCode);
|
||||
taos_stmt2_free_fields(stmt, pFields);
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
void getQueryFields(TAOS* taos, const char* sql, int expectedFieldNum) {
|
||||
TAOS_STMT2_OPTION option = {0};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
int fieldNum = 0;
|
||||
TAOS_FIELD_ALL* pFields = NULL;
|
||||
code = taos_stmt2_get_fields(stmt, &fieldNum, NULL);
|
||||
ASSERT_EQ(code, 0);
|
||||
ASSERT_EQ(fieldNum, expectedFieldNum);
|
||||
taos_stmt2_free_fields(stmt, NULL);
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
void do_query(TAOS* taos, const char* sql) {
|
||||
TAOS_RES* result = taos_query(taos, sql);
|
||||
int code = taos_errno(result);
|
||||
ASSERT_EQ(code, 0);
|
||||
|
||||
taos_free_result(result);
|
||||
}
|
||||
|
||||
void do_stmt(TAOS* taos, const char* sql, int CTB_NUMS, int ROW_NUMS, int CYC_NUMS, bool createTable) {
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db");
|
||||
do_query(taos, "create table db.stb (ts timestamp, b binary(10)) tags(t1 int, t2 binary(10))");
|
||||
do_query(taos, "use db");
|
||||
|
||||
TAOS_STMT2_OPTION option = {0, true, true, NULL, NULL};
|
||||
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
int code = taos_stmt2_prepare(stmt, sql, 0);
|
||||
ASSERT_EQ(code, 0);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
|
||||
// tbname
|
||||
char** tbs = (char**)taosMemoryMalloc(CTB_NUMS * sizeof(char*));
|
||||
for (int i = 0; i < CTB_NUMS; i++) {
|
||||
tbs[i] = (char*)taosMemoryMalloc(sizeof(char) * 20);
|
||||
sprintf(tbs[i], "ctb_%d", i);
|
||||
if (createTable) {
|
||||
char* tmp = (char*)taosMemoryMalloc(sizeof(char) * 100);
|
||||
sprintf(tmp, "create table db.%s using db.stb tags(0, 'after')", tbs[i]);
|
||||
do_query(taos, tmp);
|
||||
}
|
||||
}
|
||||
for (int r = 0; r < CYC_NUMS; r++) {
|
||||
// col params
|
||||
int64_t** ts = (int64_t**)taosMemoryMalloc(CTB_NUMS * sizeof(int64_t*));
|
||||
char** b = (char**)taosMemoryMalloc(CTB_NUMS * sizeof(char*));
|
||||
int* ts_len = (int*)taosMemoryMalloc(ROW_NUMS * sizeof(int));
|
||||
int* b_len = (int*)taosMemoryMalloc(ROW_NUMS * sizeof(int));
|
||||
for (int i = 0; i < ROW_NUMS; i++) {
|
||||
ts_len[i] = sizeof(int64_t);
|
||||
b_len[i] = 1;
|
||||
}
|
||||
for (int i = 0; i < CTB_NUMS; i++) {
|
||||
ts[i] = (int64_t*)taosMemoryMalloc(ROW_NUMS * sizeof(int64_t));
|
||||
b[i] = (char*)taosMemoryMalloc(ROW_NUMS * sizeof(char));
|
||||
for (int j = 0; j < ROW_NUMS; j++) {
|
||||
ts[i][j] = 1591060628000 + r * 100000 + j;
|
||||
b[i][j] = 'a' + j;
|
||||
}
|
||||
}
|
||||
// tag params
|
||||
int t1 = 0;
|
||||
int t1len = sizeof(int);
|
||||
int t2len = 3;
|
||||
// TAOS_STMT2_BIND* tagv[2] = {&tags[0][0], &tags[1][0]};
|
||||
|
||||
// bind params
|
||||
TAOS_STMT2_BIND** paramv = (TAOS_STMT2_BIND**)taosMemoryMalloc(CTB_NUMS * sizeof(TAOS_STMT2_BIND*));
|
||||
TAOS_STMT2_BIND** tags = (TAOS_STMT2_BIND**)taosMemoryMalloc(CTB_NUMS * sizeof(TAOS_STMT2_BIND*));
|
||||
for (int i = 0; i < CTB_NUMS; i++) {
|
||||
// create tags
|
||||
tags[i] = (TAOS_STMT2_BIND*)taosMemoryMalloc(2 * sizeof(TAOS_STMT2_BIND));
|
||||
tags[i][0] = {TSDB_DATA_TYPE_INT, &t1, &t1len, NULL, 0};
|
||||
tags[i][1] = {TSDB_DATA_TYPE_BINARY, (void*)"after", &t2len, NULL, 0};
|
||||
|
||||
// create col params
|
||||
paramv[i] = (TAOS_STMT2_BIND*)taosMemoryMalloc(2 * sizeof(TAOS_STMT2_BIND));
|
||||
paramv[i][0] = {TSDB_DATA_TYPE_TIMESTAMP, &ts[i][0], &ts_len[0], NULL, ROW_NUMS};
|
||||
paramv[i][1] = {TSDB_DATA_TYPE_BINARY, &b[i][0], &b_len[0], NULL, ROW_NUMS};
|
||||
}
|
||||
// bind
|
||||
TAOS_STMT2_BINDV bindv = {CTB_NUMS, tbs, tags, paramv};
|
||||
code = taos_stmt2_bind_param(stmt, &bindv, -1);
|
||||
ASSERT_EQ(code, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
|
||||
// exec
|
||||
code = taos_stmt2_exec(stmt, NULL);
|
||||
ASSERT_EQ(code, 0);
|
||||
ASSERT_EQ(errno, 0);
|
||||
|
||||
for (int i = 0; i < CTB_NUMS; i++) {
|
||||
taosMemoryFree(tags[i]);
|
||||
taosMemoryFree(paramv[i]);
|
||||
taosMemoryFree(ts[i]);
|
||||
taosMemoryFree(b[i]);
|
||||
}
|
||||
taosMemoryFree(ts);
|
||||
taosMemoryFree(b);
|
||||
taosMemoryFree(ts_len);
|
||||
taosMemoryFree(b_len);
|
||||
taosMemoryFree(paramv);
|
||||
taosMemoryFree(tags);
|
||||
}
|
||||
|
||||
checkRows(taos, "select * from db.stb", CYC_NUMS * ROW_NUMS * CTB_NUMS);
|
||||
for (int i = 0; i < CTB_NUMS; i++) {
|
||||
taosMemoryFree(tbs[i]);
|
||||
}
|
||||
taosMemoryFree(tbs);
|
||||
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
TEST(clientCase, driverInit_Test) {
|
||||
// taosInitGlobalCfg();
|
||||
// taos_init();
|
||||
}
|
||||
|
||||
TEST(stmt2Case, insert_stb_get_fields_Test) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db PRECISION 'ns'");
|
||||
do_query(taos,
|
||||
"create table db.stb (ts timestamp, b binary(10)) tags(t1 "
|
||||
"int, t2 binary(10))");
|
||||
do_query(
|
||||
taos,
|
||||
"create table if not exists db.all_stb(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 "
|
||||
"tinyint unsigned, v7 smallint unsigned, v8 int unsigned, v9 bigint unsigned, v10 float, v11 double, v12 "
|
||||
"binary(20), v13 varbinary(20), v14 geometry(100), v15 nchar(20))tags(tts timestamp, tv1 bool, tv2 tinyint, tv3 "
|
||||
"smallint, tv4 int, tv5 bigint, tv6 tinyint unsigned, tv7 smallint unsigned, tv8 int unsigned, tv9 bigint "
|
||||
"unsigned, tv10 float, tv11 double, tv12 binary(20), tv13 varbinary(20), tv14 geometry(100), tv15 nchar(20));");
|
||||
printf("support case \n");
|
||||
|
||||
// case 1 : test super table
|
||||
{
|
||||
const char* sql = "insert into db.stb(t1,t2,ts,b,tbname) values(?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME}};
|
||||
printf("case 1 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
{
|
||||
// case 2 : no tag
|
||||
const char* sql = "insert into db.stb(ts,b,tbname) values(?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[3] = {{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME}};
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 3);
|
||||
}
|
||||
|
||||
// case 3 : random order
|
||||
{
|
||||
const char* sql = "insert into db.stb(tbname,ts,t2,b,t1) values(?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG}};
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 4 : random order 2
|
||||
{
|
||||
const char* sql = "insert into db.stb(ts,tbname,b,t2,t1) values(?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG}};
|
||||
printf("case 4 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 5 : 'db'.'stb'
|
||||
{
|
||||
const char* sql = "insert into 'db'.'stb'(t1,t2,ts,b,tbname) values(?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME}};
|
||||
printf("case 5 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 6 : use db
|
||||
{
|
||||
do_query(taos, "use db");
|
||||
const char* sql = "insert into stb(t1,t2,ts,b,tbname) values(?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME}};
|
||||
printf("case 6 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 7 : less param
|
||||
{
|
||||
const char* sql = "insert into db.stb(ts,tbname) values(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[2] = {{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME}};
|
||||
printf("case 7 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 2);
|
||||
}
|
||||
|
||||
// case 8 : test all types
|
||||
{
|
||||
const char* sql =
|
||||
"insert into "
|
||||
"all_stb(tbname,tts,tv1,tv2,tv3,tv4,tv5,tv6,tv7,tv8,tv9,tv10,tv11,tv12,tv13,tv14,tv15,ts,v1,v2,v3,v4,v5,v6,v7,"
|
||||
"v8,v9,v10,"
|
||||
"v11,v12,v13,v14,v15) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[33] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"tts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv1", TSDB_DATA_TYPE_BOOL, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv2", TSDB_DATA_TYPE_TINYINT, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv3", TSDB_DATA_TYPE_SMALLINT, 0, 0, 2, TAOS_FIELD_TAG},
|
||||
{"tv4", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv5", TSDB_DATA_TYPE_BIGINT, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv6", TSDB_DATA_TYPE_UTINYINT, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv7", TSDB_DATA_TYPE_USMALLINT, 0, 0, 2, TAOS_FIELD_TAG},
|
||||
{"tv8", TSDB_DATA_TYPE_UINT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv9", TSDB_DATA_TYPE_UBIGINT, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv10", TSDB_DATA_TYPE_FLOAT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv11", TSDB_DATA_TYPE_DOUBLE, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv12", TSDB_DATA_TYPE_VARCHAR, 0, 0, 22, TAOS_FIELD_TAG},
|
||||
{"tv13", TSDB_DATA_TYPE_VARBINARY, 0, 0, 22, TAOS_FIELD_TAG},
|
||||
{"tv14", TSDB_DATA_TYPE_GEOMETRY, 0, 0, 102, TAOS_FIELD_TAG},
|
||||
{"tv15", TSDB_DATA_TYPE_NCHAR, 0, 0, 82, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"v1", TSDB_DATA_TYPE_BOOL, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v2", TSDB_DATA_TYPE_TINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v3", TSDB_DATA_TYPE_SMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v4", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v5", TSDB_DATA_TYPE_BIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v6", TSDB_DATA_TYPE_UTINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v7", TSDB_DATA_TYPE_USMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v8", TSDB_DATA_TYPE_UINT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v9", TSDB_DATA_TYPE_UBIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v10", TSDB_DATA_TYPE_FLOAT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v11", TSDB_DATA_TYPE_DOUBLE, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v12", TSDB_DATA_TYPE_VARCHAR, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v13", TSDB_DATA_TYPE_VARBINARY, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v14", TSDB_DATA_TYPE_GEOMETRY, 0, 0, 102, TAOS_FIELD_COL},
|
||||
{"v15", TSDB_DATA_TYPE_NCHAR, 0, 0, 82, TAOS_FIELD_COL}};
|
||||
printf("case 8 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 33);
|
||||
}
|
||||
|
||||
// not support case
|
||||
printf("not support case \n");
|
||||
|
||||
// case 5 : add in main TD-33353
|
||||
{
|
||||
const char* sql = "insert into db.stb(t1,t2,ts,b,tbname) values(1,?,?,'abc',?)";
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 2 : no pk
|
||||
{
|
||||
const char* sql = "insert into db.stb(b,tbname) values(?,?)";
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 3 : no tbname and tag(not support bind)
|
||||
{
|
||||
const char* sql = "insert into db.stb(ts,b) values(?,?)";
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 4 : no col and tag(not support bind)
|
||||
{
|
||||
const char* sql = "insert into db.stb(tbname) values(?)";
|
||||
printf("case 4 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 5 : no field name
|
||||
{
|
||||
const char* sql = "insert into db.stb(?,?,?,?,?)";
|
||||
printf("case 5 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 6 : test super table not exist
|
||||
{
|
||||
const char* sql = "insert into db.nstb(?,?,?,?,?)";
|
||||
printf("case 6 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 7 : no col
|
||||
{
|
||||
const char* sql = "insert into db.stb(t1,t2,tbname) values(?,?,?)";
|
||||
printf("case 7 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 8 : wrong para nums
|
||||
{
|
||||
const char* sql = "insert into db.stb(ts,b,tbname) values(?,?,?,?,?)";
|
||||
printf("case 8 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
|
||||
}
|
||||
|
||||
// case 9 : wrong simbol
|
||||
{
|
||||
const char* sql = "insert into db.stb(t1,t2,ts,b,tbname) values(*,*,*,*,*)";
|
||||
printf("case 9 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
taos_close(taos);
|
||||
}
|
||||
|
||||
TEST(stmt2Case, insert_ctb_using_get_fields_Test) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db PRECISION 'ns'");
|
||||
do_query(taos,
|
||||
"create table db.stb (ts timestamp, b binary(10)) tags(t1 "
|
||||
"int, t2 binary(10))");
|
||||
do_query(
|
||||
taos,
|
||||
"create table if not exists db.all_stb(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 "
|
||||
"tinyint unsigned, v7 smallint unsigned, v8 int unsigned, v9 bigint unsigned, v10 float, v11 double, v12 "
|
||||
"binary(20), v13 varbinary(20), v14 geometry(100), v15 nchar(20))tags(tts timestamp, tv1 bool, tv2 tinyint, tv3 "
|
||||
"smallint, tv4 int, tv5 bigint, tv6 tinyint unsigned, tv7 smallint unsigned, tv8 int unsigned, tv9 bigint "
|
||||
"unsigned, tv10 float, tv11 double, tv12 binary(20), tv13 varbinary(20), tv14 geometry(100), tv15 nchar(20));");
|
||||
do_query(taos, "CREATE TABLE db.t0 USING db.stb (t1,t2) TAGS (7,'Cali');");
|
||||
|
||||
printf("support case \n");
|
||||
// case 1 : test child table already exist
|
||||
{
|
||||
const char* sql = "INSERT INTO db.t0(ts,b)using db.stb (t1,t2) TAGS(?,?) VALUES (?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[4] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 1 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 4);
|
||||
}
|
||||
|
||||
// case 2 : insert clause
|
||||
{
|
||||
const char* sql = "INSERT INTO db.? using db.stb (t1,t2) TAGS(?,?) (ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 3 : insert child table not exist
|
||||
{
|
||||
const char* sql = "INSERT INTO db.d1 using db.stb (t1,t2)TAGS(?,?) (ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[4] = {{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 4);
|
||||
}
|
||||
|
||||
// case 4 : random order
|
||||
{
|
||||
const char* sql = "INSERT INTO db.? using db.stb (t2,t1)TAGS(?,?) (b,ts)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL}};
|
||||
printf("case 4 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 5 : less para
|
||||
{
|
||||
const char* sql = "insert into db.? using db.stb (t2)tags(?) (ts)values(?)";
|
||||
TAOS_FIELD_ALL expectedFields[3] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL}};
|
||||
printf("case 5 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 3);
|
||||
}
|
||||
|
||||
// case 6 : insert into db.? using db.stb tags(?, ?) values(?,?)
|
||||
// no field name
|
||||
{
|
||||
const char* sql = "insert into db.? using db.stb tags(?, ?) values(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 6 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 7 : insert into db.d0 (ts)values(?)
|
||||
// less para
|
||||
{
|
||||
const char* sql = "insert into db.t0 (ts)values(?)";
|
||||
TAOS_FIELD_ALL expectedFields[1] = {{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL}};
|
||||
printf("case 7 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 1);
|
||||
}
|
||||
|
||||
// case 8 : 'db' 'stb'
|
||||
{
|
||||
const char* sql = "INSERT INTO 'db'.? using 'db'.'stb' (t1,t2) TAGS(?,?) (ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 8 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 9 : use db
|
||||
{
|
||||
do_query(taos, "use db");
|
||||
const char* sql = "INSERT INTO ? using stb (t1,t2) TAGS(?,?) (ts,b)VALUES(?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[5] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"t1", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"t2", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"b", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL}};
|
||||
printf("case 9 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 5);
|
||||
}
|
||||
|
||||
// case 10 : test all types
|
||||
{
|
||||
const char* sql =
|
||||
"insert into ? using all_stb tags(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?) values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[33] = {{"tbname", TSDB_DATA_TYPE_BINARY, 0, 0, 271, TAOS_FIELD_TBNAME},
|
||||
{"tts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv1", TSDB_DATA_TYPE_BOOL, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv2", TSDB_DATA_TYPE_TINYINT, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv3", TSDB_DATA_TYPE_SMALLINT, 0, 0, 2, TAOS_FIELD_TAG},
|
||||
{"tv4", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv5", TSDB_DATA_TYPE_BIGINT, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv6", TSDB_DATA_TYPE_UTINYINT, 0, 0, 1, TAOS_FIELD_TAG},
|
||||
{"tv7", TSDB_DATA_TYPE_USMALLINT, 0, 0, 2, TAOS_FIELD_TAG},
|
||||
{"tv8", TSDB_DATA_TYPE_UINT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv9", TSDB_DATA_TYPE_UBIGINT, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv10", TSDB_DATA_TYPE_FLOAT, 0, 0, 4, TAOS_FIELD_TAG},
|
||||
{"tv11", TSDB_DATA_TYPE_DOUBLE, 0, 0, 8, TAOS_FIELD_TAG},
|
||||
{"tv12", TSDB_DATA_TYPE_VARCHAR, 0, 0, 22, TAOS_FIELD_TAG},
|
||||
{"tv13", TSDB_DATA_TYPE_VARBINARY, 0, 0, 22, TAOS_FIELD_TAG},
|
||||
{"tv14", TSDB_DATA_TYPE_GEOMETRY, 0, 0, 102, TAOS_FIELD_TAG},
|
||||
{"tv15", TSDB_DATA_TYPE_NCHAR, 0, 0, 82, TAOS_FIELD_TAG},
|
||||
{"ts", TSDB_DATA_TYPE_TIMESTAMP, 2, 0, 8, TAOS_FIELD_COL},
|
||||
{"v1", TSDB_DATA_TYPE_BOOL, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v2", TSDB_DATA_TYPE_TINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v3", TSDB_DATA_TYPE_SMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v4", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v5", TSDB_DATA_TYPE_BIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v6", TSDB_DATA_TYPE_UTINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v7", TSDB_DATA_TYPE_USMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v8", TSDB_DATA_TYPE_UINT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v9", TSDB_DATA_TYPE_UBIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v10", TSDB_DATA_TYPE_FLOAT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v11", TSDB_DATA_TYPE_DOUBLE, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v12", TSDB_DATA_TYPE_VARCHAR, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v13", TSDB_DATA_TYPE_VARBINARY, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v14", TSDB_DATA_TYPE_GEOMETRY, 0, 0, 102, TAOS_FIELD_COL},
|
||||
{"v15", TSDB_DATA_TYPE_NCHAR, 0, 0, 82, TAOS_FIELD_COL}};
|
||||
printf("case 10 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 33);
|
||||
}
|
||||
printf("not support case \n");
|
||||
|
||||
// case 1 : test super table not exist
|
||||
{
|
||||
const char* sql = "INSERT INTO db.?(ts,b)using db.nstb (t1,t2) TAGS(?,?) VALUES (?,?)";
|
||||
printf("case 1 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 2 : no pk
|
||||
{
|
||||
const char* sql = "INSERT INTO db.?(ts,b)using db.nstb (t1,t2) TAGS(?,?) (n)VALUES (?)";
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 3 : less param and no filed name
|
||||
{
|
||||
const char* sql = "INSERT INTO db.?(ts,b)using db.stb TAGS(?)VALUES (?,?)";
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 4 : none para for ctbname
|
||||
{
|
||||
const char* sql = "INSERT INTO db.d0 using db.stb values(?,?)";
|
||||
printf("case 4 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_SQL_SYNTAX_ERROR);
|
||||
}
|
||||
|
||||
// case 5 : none para for ctbname
|
||||
{
|
||||
const char* sql = "insert into ! using db.stb tags(?, ?) values(?,?)";
|
||||
printf("case 5 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_SQL_SYNTAX_ERROR);
|
||||
}
|
||||
taos_close(taos);
|
||||
}
|
||||
|
||||
TEST(stmt2Case, insert_ntb_get_fields_Test) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db PRECISION 'ms'");
|
||||
do_query(taos, "CREATE TABLE db.ntb(nts timestamp, nb binary(10),nvc varchar(16),ni int);");
|
||||
do_query(
|
||||
taos,
|
||||
"create table if not exists db.all_ntb(ts timestamp, v1 bool, v2 tinyint, v3 smallint, v4 int, v5 bigint, v6 "
|
||||
"tinyint unsigned, v7 smallint unsigned, v8 int unsigned, v9 bigint unsigned, v10 float, v11 double, v12 "
|
||||
"binary(20), v13 varbinary(20), v14 geometry(100), v15 nchar(20));");
|
||||
|
||||
printf("support case \n");
|
||||
|
||||
// case 1 : test normal table no field name
|
||||
{
|
||||
const char* sql = "INSERT INTO db.ntb VALUES(?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[4] = {{"nts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"nb", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"nvc", TSDB_DATA_TYPE_BINARY, 0, 0, 18, TAOS_FIELD_COL},
|
||||
{"ni", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_COL}};
|
||||
printf("case 1 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 4);
|
||||
}
|
||||
|
||||
// case 2 : test random order
|
||||
{
|
||||
const char* sql = "INSERT INTO db.ntb (ni,nb,nvc,nts)VALUES(?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[4] = {{"ni", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"nb", TSDB_DATA_TYPE_BINARY, 0, 0, 12, TAOS_FIELD_COL},
|
||||
{"nvc", TSDB_DATA_TYPE_BINARY, 0, 0, 18, TAOS_FIELD_COL},
|
||||
{"nts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0, 8, TAOS_FIELD_COL}};
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 4);
|
||||
}
|
||||
|
||||
// case 3 : less param
|
||||
{
|
||||
const char* sql = "INSERT INTO db.ntb (nts)VALUES(?)";
|
||||
TAOS_FIELD_ALL expectedFields[1] = {{"nts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0, 8, TAOS_FIELD_COL}};
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 1);
|
||||
}
|
||||
|
||||
// case 4 : test all types
|
||||
{
|
||||
const char* sql = "insert into db.all_ntb values(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)";
|
||||
TAOS_FIELD_ALL expectedFields[16] = {{"ts", TSDB_DATA_TYPE_TIMESTAMP, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v1", TSDB_DATA_TYPE_BOOL, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v2", TSDB_DATA_TYPE_TINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v3", TSDB_DATA_TYPE_SMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v4", TSDB_DATA_TYPE_INT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v5", TSDB_DATA_TYPE_BIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v6", TSDB_DATA_TYPE_UTINYINT, 0, 0, 1, TAOS_FIELD_COL},
|
||||
{"v7", TSDB_DATA_TYPE_USMALLINT, 0, 0, 2, TAOS_FIELD_COL},
|
||||
{"v8", TSDB_DATA_TYPE_UINT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v9", TSDB_DATA_TYPE_UBIGINT, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v10", TSDB_DATA_TYPE_FLOAT, 0, 0, 4, TAOS_FIELD_COL},
|
||||
{"v11", TSDB_DATA_TYPE_DOUBLE, 0, 0, 8, TAOS_FIELD_COL},
|
||||
{"v12", TSDB_DATA_TYPE_VARCHAR, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v13", TSDB_DATA_TYPE_VARBINARY, 0, 0, 22, TAOS_FIELD_COL},
|
||||
{"v14", TSDB_DATA_TYPE_GEOMETRY, 0, 0, 102, TAOS_FIELD_COL},
|
||||
{"v15", TSDB_DATA_TYPE_NCHAR, 0, 0, 82, TAOS_FIELD_COL}};
|
||||
printf("case 4 : %s\n", sql);
|
||||
getFieldsSuccess(taos, sql, expectedFields, 16);
|
||||
}
|
||||
|
||||
printf("not support case \n");
|
||||
|
||||
// case 1 : wrong db
|
||||
{
|
||||
const char* sql = "insert into ntb values(?,?,?,?)";
|
||||
printf("case 1 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_TSC_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
// case 2 : normal table must have tbnam
|
||||
{
|
||||
const char* sql = "insert into db.? values(?,?)";
|
||||
printf("case 2 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_TABLE_NOT_EXIST);
|
||||
}
|
||||
|
||||
// case 3 : wrong para nums
|
||||
{
|
||||
const char* sql = "insert into db.ntb(nts,ni) values(?,?,?,?,?)";
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_INVALID_COLUMNS_NUM);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(stmt2Case, select_get_fields_Test) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
do_query(taos, "drop database if exists db");
|
||||
do_query(taos, "create database db PRECISION 'ns'");
|
||||
do_query(taos, "use db");
|
||||
do_query(taos, "CREATE TABLE db.ntb(nts timestamp, nb binary(10),nvc varchar(16),ni int);");
|
||||
{
|
||||
// case 1 :
|
||||
const char* sql = "select * from ntb where ts = ?";
|
||||
printf("case 1 : %s\n", sql);
|
||||
getQueryFields(taos, sql, 1);
|
||||
}
|
||||
|
||||
{
|
||||
// case 2 :
|
||||
const char* sql = "select * from ntb where ts = ? and b = ?";
|
||||
printf("case 2 : %s\n", sql);
|
||||
getQueryFields(taos, sql, 2);
|
||||
}
|
||||
|
||||
{
|
||||
// case 3 :
|
||||
const char* sql = "select * from ? where ts = ?";
|
||||
printf("case 3 : %s\n", sql);
|
||||
getFieldsError(taos, sql, TSDB_CODE_PAR_SYNTAX_ERROR);
|
||||
}
|
||||
taos_close(taos);
|
||||
}
|
||||
|
||||
TEST(stmt2Case, get_fields_error_Test) {
|
||||
// case 1 :
|
||||
{
|
||||
printf("case 1 : NULL param \n");
|
||||
int code = taos_stmt2_get_fields(NULL, NULL, NULL);
|
||||
ASSERT_EQ(code, TSDB_CODE_INVALID_PARA);
|
||||
}
|
||||
}
|
||||
|
||||
TEST(stmt2Case, stmt2_init_prepare_Test) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
{
|
||||
(void)taos_stmt2_init(NULL, NULL);
|
||||
ASSERT_EQ(terrno, TSDB_CODE_INVALID_PARA);
|
||||
terrno = 0;
|
||||
}
|
||||
|
||||
{
|
||||
(void)taos_stmt2_prepare(NULL, NULL, 0);
|
||||
ASSERT_EQ(terrno, TSDB_CODE_INVALID_PARA);
|
||||
terrno = 0;
|
||||
}
|
||||
|
||||
{
|
||||
TAOS_STMT2_OPTION option = {0, true, true, NULL, NULL};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
int code = taos_stmt2_prepare(stmt, "wrong sql", 0);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
ASSERT_EQ(((STscStmt2*)stmt)->db, nullptr);
|
||||
|
||||
code = taos_stmt2_prepare(stmt, "insert into 'db'.stb(t1,t2,ts,b,tbname) values(?,?,?,?,?)", 0);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
ASSERT_STREQ(((STscStmt2*)stmt)->db, "db"); // add in main TD-33332
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
{
|
||||
TAOS_STMT2_OPTION option = {0, true, false, NULL, NULL};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
|
||||
{
|
||||
TAOS_STMT2_OPTION option = {0, true, true, stmtAsyncQueryCb, NULL};
|
||||
TAOS_STMT2* stmt = taos_stmt2_init(taos, &option);
|
||||
ASSERT_EQ(terrno, 0);
|
||||
ASSERT_NE(stmt, nullptr);
|
||||
taos_stmt2_close(stmt);
|
||||
}
|
||||
taos_close(taos);
|
||||
}
|
||||
|
||||
TEST(stmt2Case, stmt2_all) {
|
||||
TAOS* taos = taos_connect("localhost", "root", "taosdata", "", 0);
|
||||
ASSERT_NE(taos, nullptr);
|
||||
|
||||
{ do_stmt(taos, "insert into db.stb (tbname,ts,b,t1,t2) values(?,?,?,?,?)", 3, 3, 3, true); }
|
||||
taos_close(taos);
|
||||
}
|
||||
|
||||
TEST(stmt2Case, stmt2_status_Test) {}
|
||||
|
||||
#pragma GCC diagnostic pop
|
|
@ -66,9 +66,9 @@ int32_t s3Begin() {
|
|||
void s3End() { S3_deinitialize(); }
|
||||
|
||||
int32_t s3Init() { TAOS_RETURN(TSDB_CODE_SUCCESS); /*s3Begin();*/ }
|
||||
|
||||
#if 0
|
||||
static int32_t s3ListBucket(char const *bucketname);
|
||||
|
||||
#endif
|
||||
static void s3DumpCfgByEp(int8_t epIndex) {
|
||||
// clang-format off
|
||||
(void)fprintf(stdout,
|
||||
|
@ -291,7 +291,7 @@ static int32_t s3ListBucketByEp(char const *bucketname, int8_t epIndex) {
|
|||
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int32_t s3ListBucket(char const *bucketname) {
|
||||
int32_t code = 0;
|
||||
|
||||
|
@ -312,7 +312,7 @@ static int32_t s3ListBucket(char const *bucketname) {
|
|||
|
||||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
#endif
|
||||
typedef struct growbuffer {
|
||||
// The total number of bytes, and the start byte
|
||||
int size;
|
||||
|
|
|
@ -11141,6 +11141,7 @@ void tOffsetCopy(STqOffsetVal *pLeft, const STqOffsetVal *pRight) {
|
|||
}
|
||||
|
||||
void tOffsetDestroy(void *param) {
|
||||
if (param == NULL) return;
|
||||
STqOffsetVal *pVal = (STqOffsetVal *)param;
|
||||
if (IS_VAR_DATA_TYPE(pVal->primaryKey.type)) {
|
||||
taosMemoryFreeClear(pVal->primaryKey.pData);
|
||||
|
@ -11148,6 +11149,7 @@ void tOffsetDestroy(void *param) {
|
|||
}
|
||||
|
||||
void tDeleteSTqOffset(void *param) {
|
||||
if (param == NULL) return;
|
||||
STqOffset *pVal = (STqOffset *)param;
|
||||
tOffsetDestroy(&pVal->val);
|
||||
}
|
||||
|
|
|
@ -123,6 +123,9 @@ static const SSysDbTableSchema userDBSchema[] = {
|
|||
{.name = "s3_compact", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT, .sysInfo = true},
|
||||
{.name = "with_arbitrator", .bytes = 1, .type = TSDB_DATA_TYPE_TINYINT, .sysInfo = true},
|
||||
{.name = "encrypt_algorithm", .bytes = TSDB_ENCRYPT_ALGO_STR_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "compact_interval", .bytes = 12 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "compact_time_range", .bytes = 24 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
{.name = "compact_time_offset", .bytes = 4 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema userFuncSchema[] = {
|
||||
|
@ -314,6 +317,8 @@ static const SSysDbTableSchema transSchema[] = {
|
|||
{.name = "oper", .bytes = TSDB_TRANS_OPER_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "db", .bytes = SYSTABLE_SCH_DB_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "stable", .bytes = SYSTABLE_SCH_TABLE_NAME_LEN, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "killable", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
//{.name = "kill_mnode", .bytes = 10 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "failed_times", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "last_exec_time", .bytes = 8, .type = TSDB_DATA_TYPE_TIMESTAMP, .sysInfo = false},
|
||||
{.name = "last_action_info", .bytes = (TSDB_TRANS_ERROR_LEN - 1) + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR},
|
||||
|
@ -403,6 +408,15 @@ static const SSysDbTableSchema userCompactsDetailSchema[] = {
|
|||
{.name = "remain_time(s)", .bytes = 8, .type = TSDB_DATA_TYPE_BIGINT, .sysInfo = false},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema userTransactionDetailSchema[] = {
|
||||
{.name = "transaction_id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "action", .bytes = 30 + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "obj_type", .bytes = TSDB_TRANS_OBJTYPE_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "result", .bytes = TSDB_TRANS_RESULT_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "target", .bytes = TSDB_TRANS_TARGET_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
{.name = "detail", .bytes = TSDB_TRANS_DETAIL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = false},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema anodesSchema[] = {
|
||||
{.name = "id", .bytes = 4, .type = TSDB_DATA_TYPE_INT, .sysInfo = false},
|
||||
{.name = "url", .bytes = TSDB_ANALYTIC_ANODE_URL_LEN + VARSTR_HEADER_SIZE, .type = TSDB_DATA_TYPE_VARCHAR, .sysInfo = true},
|
||||
|
@ -521,6 +535,7 @@ static const SSysTableMeta infosMeta[] = {
|
|||
{TSDB_INS_TABLE_ANODES_FULL, anodesFullSchema, tListLen(anodesFullSchema), true},
|
||||
{TSDB_INS_DISK_USAGE, diskUsageSchema, tListLen(diskUsageSchema), false},
|
||||
{TSDB_INS_TABLE_FILESETS, filesetsFullSchema, tListLen(filesetsFullSchema), false},
|
||||
{TSDB_INS_TABLE_TRANSACTION_DETAILS, userTransactionDetailSchema, tListLen(userTransactionDetailSchema), false},
|
||||
};
|
||||
|
||||
static const SSysDbTableSchema connectionsSchema[] = {
|
||||
|
|
|
@ -2671,8 +2671,13 @@ static void (*tColDataGetValueImpl[])(SColData *pColData, int32_t iVal, SColVal
|
|||
tColDataGetValue6, // HAS_VALUE | HAS_NULL
|
||||
tColDataGetValue7 // HAS_VALUE | HAS_NULL | HAS_NONE
|
||||
};
|
||||
void tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) {
|
||||
int32_t tColDataGetValue(SColData *pColData, int32_t iVal, SColVal *pColVal) {
|
||||
if (iVal < 0 || iVal >= pColData->nVal ||
|
||||
(pColData->flag <= 0 || pColData->flag >= sizeof(tColDataGetValueImpl)/POINTER_BYTES)){
|
||||
return TSDB_CODE_INVALID_PARA;
|
||||
}
|
||||
tColDataGetValueImpl[pColData->flag](pColData, iVal, pColVal);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal) {
|
||||
|
@ -3436,7 +3441,10 @@ static int32_t tColDataCopyRowAppend(SColData *aFromColData, int32_t iFromRow, S
|
|||
|
||||
for (int32_t i = 0; i < nColData; i++) {
|
||||
SColVal cv = {0};
|
||||
tColDataGetValue(&aFromColData[i], iFromRow, &cv);
|
||||
code = tColDataGetValue(&aFromColData[i], iFromRow, &cv);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
code = tColDataAppendValue(&aToColData[i], &cv);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
|
@ -3575,7 +3583,10 @@ static int32_t tColDataMerge(SArray **colArr) {
|
|||
SColData *dstCol = taosArrayGet(dst, j);
|
||||
|
||||
SColVal cv;
|
||||
tColDataGetValue(srcCol, i, &cv);
|
||||
code = tColDataGetValue(srcCol, i, &cv);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
code = tColDataAppendValue(dstCol, &cv);
|
||||
if (code) {
|
||||
goto _exit;
|
||||
|
@ -3588,7 +3599,10 @@ static int32_t tColDataMerge(SArray **colArr) {
|
|||
SColData *dstCol = taosArrayGet(dst, j);
|
||||
|
||||
SColVal cv;
|
||||
tColDataGetValue(srcCol, i, &cv);
|
||||
code = tColDataGetValue(srcCol, i, &cv);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
goto _exit;
|
||||
}
|
||||
code = tColDataUpdateValue(dstCol, &cv, true);
|
||||
if (code) {
|
||||
goto _exit;
|
||||
|
|
|
@ -102,9 +102,8 @@ int32_t tsMaxStreamBackendCache = 128; // M
|
|||
int32_t tsPQSortMemThreshold = 16; // M
|
||||
int32_t tsRetentionSpeedLimitMB = 0; // unlimited
|
||||
|
||||
const char *tsAlterCompactTaskKeywords = "max_compact_tasks";
|
||||
int32_t tsNumOfCompactThreads = 2;
|
||||
int32_t tsNumOfRetentionThreads = 1;
|
||||
int32_t tsNumOfCompactThreads = 2;
|
||||
int32_t tsNumOfRetentionThreads = 1;
|
||||
|
||||
// sync raft
|
||||
int32_t tsElectInterval = 25 * 1000;
|
||||
|
@ -327,7 +326,6 @@ char tsUdfdLdLibPath[512] = "";
|
|||
bool tsDisableStream = false;
|
||||
int64_t tsStreamBufferSize = 128 * 1024 * 1024;
|
||||
bool tsFilterScalarMode = false;
|
||||
int tsResolveFQDNRetryTime = 100; // seconds
|
||||
int tsStreamAggCnt = 100000;
|
||||
bool tsStreamCoverage = false;
|
||||
|
||||
|
@ -746,7 +744,8 @@ static int32_t taosAddClientCfg(SConfig *pCfg) {
|
|||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "tsmaDataDeleteMark", tsmaDataDeleteMark, 60 * 60 * 1000, INT64_MAX,
|
||||
CFG_SCOPE_CLIENT, CFG_DYN_CLIENT, CFG_CATEGORY_LOCAL));
|
||||
|
||||
TAOS_CHECK_RETURN(cfgAddBool(pCfg, "streamCoverage", tsStreamCoverage, CFG_DYN_CLIENT, CFG_DYN_CLIENT, CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(
|
||||
cfgAddBool(pCfg, "streamCoverage", tsStreamCoverage, CFG_DYN_CLIENT, CFG_DYN_CLIENT, CFG_CATEGORY_LOCAL));
|
||||
|
||||
TAOS_RETURN(TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
@ -795,9 +794,6 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
tsNumOfCommitThreads = tsNumOfCores / 2;
|
||||
tsNumOfCommitThreads = TRANGE(tsNumOfCommitThreads, 2, 4);
|
||||
|
||||
tsNumOfCompactThreads = tsNumOfCommitThreads;
|
||||
tsNumOfCompactThreads = TRANGE(tsNumOfCompactThreads, 2, 4);
|
||||
|
||||
tsNumOfSupportVnodes = tsNumOfCores * 2 + 5;
|
||||
tsNumOfSupportVnodes = TMAX(tsNumOfSupportVnodes, 2);
|
||||
|
||||
|
@ -842,7 +838,7 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "queryBufferSize", tsQueryBufferSize, -1, 500000000000, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY, CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "queryRspPolicy", tsQueryRspPolicy, 0, 1, CFG_SCOPE_SERVER, CFG_DYN_SERVER,CFG_CATEGORY_GLOBAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "numOfCommitThreads", tsNumOfCommitThreads, 1, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "maxCompactConcurrency", tsNumOfCompactThreads, 1, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER_LAZY,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "numOfCompactThreads", tsNumOfCompactThreads, 1, 16, CFG_SCOPE_SERVER, CFG_DYN_SERVER,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "retentionSpeedLimitMB", tsRetentionSpeedLimitMB, 0, 1024, CFG_SCOPE_SERVER, CFG_DYN_SERVER,CFG_CATEGORY_GLOBAL));
|
||||
TAOS_CHECK_RETURN(cfgAddBool(pCfg, "queryUseMemoryPool", tsQueryUseMemoryPool, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0);
|
||||
TAOS_CHECK_RETURN(cfgAddBool(pCfg, "memPoolFullFunc", tsMemPoolFullFunc, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL) != 0);
|
||||
|
@ -956,7 +952,6 @@ static int32_t taosAddServerCfg(SConfig *pCfg) {
|
|||
TAOS_CHECK_RETURN(cfgAddBool(pCfg, "filterScalarMode", tsFilterScalarMode, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "maxStreamBackendCache", tsMaxStreamBackendCache, 16, 1024, CFG_SCOPE_SERVER, CFG_DYN_ENT_SERVER_LAZY,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "pqSortMemThreshold", tsPQSortMemThreshold, 1, 10240, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_LOCAL));
|
||||
TAOS_CHECK_RETURN(cfgAddInt32(pCfg, "resolveFQDNRetryTime", tsResolveFQDNRetryTime, 1, 10240, CFG_SCOPE_SERVER, CFG_DYN_NONE,CFG_CATEGORY_GLOBAL));
|
||||
|
||||
TAOS_CHECK_RETURN(cfgAddString(pCfg, "s3Accesskey", tsS3AccessKey[0], CFG_SCOPE_SERVER, CFG_DYN_ENT_SERVER_LAZY,CFG_CATEGORY_GLOBAL));
|
||||
TAOS_CHECK_RETURN(cfgAddString(pCfg, "s3Endpoint", tsS3Endpoint[0], CFG_SCOPE_SERVER, CFG_DYN_ENT_SERVER_LAZY,CFG_CATEGORY_GLOBAL));
|
||||
|
@ -1040,10 +1035,8 @@ static int32_t taosUpdateServerCfg(SConfig *pCfg) {
|
|||
pItem->stype = stype;
|
||||
}
|
||||
|
||||
pItem = cfgGetItem(pCfg, "maxCompactConcurrency");
|
||||
pItem = cfgGetItem(pCfg, "numOfCompactThreads");
|
||||
if (pItem != NULL && pItem->stype == CFG_STYPE_DEFAULT) {
|
||||
tsNumOfCompactThreads = numOfCores / 2;
|
||||
tsNumOfCompactThreads = TRANGE(tsNumOfCompactThreads, 2, 4);
|
||||
pItem->i32 = tsNumOfCompactThreads;
|
||||
pItem->stype = stype;
|
||||
}
|
||||
|
@ -1548,7 +1541,7 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
|||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "numOfCommitThreads");
|
||||
tsNumOfCommitThreads = pItem->i32;
|
||||
|
||||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "maxCompactConcurrency");
|
||||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "numOfCompactThreads");
|
||||
tsNumOfCompactThreads = pItem->i32;
|
||||
|
||||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "retentionSpeedLimitMB");
|
||||
|
@ -1822,9 +1815,6 @@ static int32_t taosSetServerCfg(SConfig *pCfg) {
|
|||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "pqSortMemThreshold");
|
||||
tsPQSortMemThreshold = pItem->i32;
|
||||
|
||||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "resolveFQDNRetryTime");
|
||||
tsResolveFQDNRetryTime = pItem->i32;
|
||||
|
||||
TAOS_CHECK_GET_CFG_ITEM(pCfg, pItem, "minDiskFreeSize");
|
||||
tsMinDiskFreeSize = pItem->i64;
|
||||
|
||||
|
@ -2354,6 +2344,8 @@ static int32_t taosCfgSetOption(OptionNameAndVar *pOptions, int32_t optionSize,
|
|||
TAOS_RETURN(code);
|
||||
}
|
||||
|
||||
extern void tsdbAlterNumCompactThreads();
|
||||
|
||||
static int32_t taosCfgDynamicOptionsForServer(SConfig *pCfg, const char *name) {
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
int32_t lino = -1;
|
||||
|
@ -2404,6 +2396,17 @@ static int32_t taosCfgDynamicOptionsForServer(SConfig *pCfg, const char *name) {
|
|||
goto _exit;
|
||||
}
|
||||
|
||||
if (strcasecmp(name, "numOfCompactThreads") == 0) {
|
||||
#ifdef TD_ENTERPRISE
|
||||
tsNumOfCompactThreads = pItem->i32;
|
||||
code = TSDB_CODE_SUCCESS;
|
||||
// tsdbAlterNumCompactThreads();
|
||||
#else
|
||||
code = TSDB_CODE_INVALID_CFG;
|
||||
#endif
|
||||
goto _exit;
|
||||
}
|
||||
|
||||
{ // 'bool/int32_t/int64_t/float/double' variables with general modification function
|
||||
static OptionNameAndVar debugOptions[] = {
|
||||
{"dDebugFlag", &dDebugFlag}, {"vDebugFlag", &vDebugFlag},
|
||||
|
@ -2453,7 +2456,6 @@ static int32_t taosCfgDynamicOptionsForServer(SConfig *pCfg, const char *name) {
|
|||
{"randErrorDivisor", &tsRandErrDivisor},
|
||||
{"randErrorScope", &tsRandErrScope},
|
||||
{"syncLogBufferMemoryAllowed", &tsLogBufferMemoryAllowed},
|
||||
{"resolveFQDNRetryTime", &tsResolveFQDNRetryTime},
|
||||
{"syncHeartbeatInterval", &tsHeartbeatInterval},
|
||||
{"syncHeartbeatTimeout", &tsHeartbeatTimeout},
|
||||
{"syncSnapReplMaxWaitN", &tsSnapReplMaxWaitN},
|
||||
|
|
|
@ -40,6 +40,46 @@ add_test(
|
|||
COMMAND dataformatTest
|
||||
)
|
||||
|
||||
# cosCpTest.cpp
|
||||
add_executable(cosCpTest "")
|
||||
target_sources(
|
||||
cosCpTest
|
||||
PRIVATE
|
||||
"cosCpTest.cpp"
|
||||
)
|
||||
target_link_libraries(cosCpTest gtest gtest_main util common)
|
||||
target_include_directories(
|
||||
cosCpTest
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/common"
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/util"
|
||||
)
|
||||
add_test(
|
||||
NAME cosCpTest
|
||||
COMMAND cosCpTest
|
||||
)
|
||||
|
||||
if(TD_LINUX)
|
||||
|
||||
# cosTest.cpp
|
||||
add_executable(cosTest "")
|
||||
target_sources(
|
||||
cosTest
|
||||
PRIVATE
|
||||
"cosTest.cpp"
|
||||
)
|
||||
target_link_libraries(cosTest gtest gtest_main util common)
|
||||
target_include_directories(
|
||||
cosTest
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/common"
|
||||
PUBLIC "${TD_SOURCE_DIR}/include/util"
|
||||
)
|
||||
add_test(
|
||||
NAME cosTest
|
||||
COMMAND cosTest
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
if (${TD_LINUX})
|
||||
# tmsg test
|
||||
add_executable(tmsgTest "")
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cos_cp.h>
|
||||
#include <taoserror.h>
|
||||
#include <tglobal.h>
|
||||
#include <iostream>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
TEST(testCase, cpOpenCloseRemove) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int64_t contentLength = 1024;
|
||||
const int64_t MULTIPART_CHUNK_SIZE = 64 << 20; // multipart is 768M
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
}
|
||||
SCheckpoint cp;
|
||||
char const *file = "./afile";
|
||||
char file_cp_path[TSDB_FILENAME_LEN];
|
||||
|
||||
(void)snprintf(file_cp_path, TSDB_FILENAME_LEN, "%s.cp", file);
|
||||
|
||||
cp.parts = (SCheckpointPart *)taosMemoryCalloc(max_part_num, sizeof(SCheckpointPart));
|
||||
if (!cp.parts) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_open(file_cp_path, &cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
if (cp.thefile) {
|
||||
EXPECT_EQ(cos_cp_close(cp.thefile), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
if (cp.parts) {
|
||||
taosMemoryFree(cp.parts);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_remove(file_cp_path), TSDB_CODE_SUCCESS);
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
||||
|
||||
TEST(testCase, cpBuild) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int64_t contentLength = 1024;
|
||||
const int64_t MULTIPART_CHUNK_SIZE = 64 << 20; // multipart is 768M
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
}
|
||||
SCheckpoint cp;
|
||||
char const *file = "./afile";
|
||||
char file_cp_path[TSDB_FILENAME_LEN];
|
||||
int64_t lmtime = 20241220141705;
|
||||
char const *upload_id = "upload-id-xxx";
|
||||
|
||||
(void)snprintf(file_cp_path, TSDB_FILENAME_LEN, "%s.cp", file);
|
||||
(void)memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.parts = (SCheckpointPart *)taosMemoryCalloc(max_part_num, sizeof(SCheckpointPart));
|
||||
if (!cp.parts) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_open(file_cp_path, &cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
cos_cp_build_upload(&cp, file, contentLength, lmtime, upload_id, chunk_size);
|
||||
|
||||
EXPECT_EQ(cos_cp_dump(&cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
if (cp.thefile) {
|
||||
EXPECT_EQ(cos_cp_close(cp.thefile), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
if (cp.parts) {
|
||||
taosMemoryFree(cp.parts);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
||||
|
||||
TEST(testCase, cpLoad) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int64_t contentLength = 1024;
|
||||
const int64_t MULTIPART_CHUNK_SIZE = 64 << 20; // multipart is 768M
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
}
|
||||
SCheckpoint cp;
|
||||
char const *file = "./afile";
|
||||
char file_cp_path[TSDB_FILENAME_LEN];
|
||||
int64_t lmtime = 20241220141705;
|
||||
char const *upload_id = "upload-id-xxx";
|
||||
|
||||
(void)snprintf(file_cp_path, TSDB_FILENAME_LEN, "%s.cp", file);
|
||||
(void)memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.parts = (SCheckpointPart *)taosMemoryCalloc(max_part_num, sizeof(SCheckpointPart));
|
||||
if (!cp.parts) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
if (taosCheckExistFile(file_cp_path)) {
|
||||
EXPECT_EQ(cos_cp_load(file_cp_path, &cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
EXPECT_EQ(cos_cp_is_valid_upload(&cp, contentLength, lmtime), true);
|
||||
|
||||
EXPECT_EQ(cp.cp_type, COS_CP_TYPE_UPLOAD);
|
||||
EXPECT_EQ(cp.md5, std::string(""));
|
||||
EXPECT_EQ(cp.thefile, nullptr);
|
||||
EXPECT_EQ(std::string(cp.file_path), "./afile");
|
||||
EXPECT_EQ(cp.file_size, 1024);
|
||||
EXPECT_EQ(cp.file_last_modified, 20241220141705);
|
||||
EXPECT_EQ(cp.file_md5, std::string(""));
|
||||
EXPECT_EQ(cp.object_name, std::string(""));
|
||||
EXPECT_EQ(cp.object_size, 0);
|
||||
EXPECT_EQ(cp.object_last_modified, std::string(""));
|
||||
EXPECT_EQ(cp.object_etag, std::string(""));
|
||||
EXPECT_EQ(cp.upload_id, std::string("upload-id-xxx"));
|
||||
|
||||
EXPECT_EQ(cp.part_num, 1);
|
||||
EXPECT_EQ(cp.part_size, 8388608);
|
||||
EXPECT_EQ(cp.parts[0].index, 0);
|
||||
EXPECT_EQ(cp.parts[0].offset, 0);
|
||||
EXPECT_EQ(cp.parts[0].size, 1024);
|
||||
EXPECT_EQ(cp.parts[0].completed, 0);
|
||||
EXPECT_EQ(cp.parts[0].etag, std::string(""));
|
||||
EXPECT_EQ(cp.parts[0].crc64, 0);
|
||||
}
|
||||
|
||||
if (cp.thefile) {
|
||||
EXPECT_EQ(cos_cp_close(cp.thefile), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
if (cp.parts) {
|
||||
taosMemoryFree(cp.parts);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_remove(file_cp_path), TSDB_CODE_SUCCESS);
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
||||
|
||||
TEST(testCase, cpBuildUpdate) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int64_t contentLength = 1024;
|
||||
const int64_t MULTIPART_CHUNK_SIZE = 64 << 20; // multipart is 768M
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
}
|
||||
SCheckpoint cp;
|
||||
char const *file = "./afile";
|
||||
char file_cp_path[TSDB_FILENAME_LEN];
|
||||
int64_t lmtime = 20241220141705;
|
||||
char const *upload_id = "upload-id-xxx";
|
||||
int seq = 1;
|
||||
char *etags[1] = {"etags-1-xxx"};
|
||||
|
||||
(void)snprintf(file_cp_path, TSDB_FILENAME_LEN, "%s.cp", file);
|
||||
(void)memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.parts = (SCheckpointPart *)taosMemoryCalloc(max_part_num, sizeof(SCheckpointPart));
|
||||
if (!cp.parts) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_open(file_cp_path, &cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
cos_cp_build_upload(&cp, file, contentLength, lmtime, upload_id, chunk_size);
|
||||
|
||||
cos_cp_update(&cp, cp.parts[seq - 1].index, etags[seq - 1], 0);
|
||||
|
||||
EXPECT_EQ(cos_cp_dump(&cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
if (cp.thefile) {
|
||||
EXPECT_EQ(cos_cp_close(cp.thefile), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
if (cp.parts) {
|
||||
taosMemoryFree(cp.parts);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
||||
|
||||
TEST(testCase, cpLoadUpdate) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int64_t contentLength = 1024;
|
||||
const int64_t MULTIPART_CHUNK_SIZE = 64 << 20; // multipart is 768M
|
||||
uint64_t chunk_size = MULTIPART_CHUNK_SIZE >> 3;
|
||||
int totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
const int max_part_num = 10000;
|
||||
if (totalSeq > max_part_num) {
|
||||
chunk_size = (contentLength + max_part_num - contentLength % max_part_num) / max_part_num;
|
||||
totalSeq = (contentLength + chunk_size - 1) / chunk_size;
|
||||
}
|
||||
SCheckpoint cp;
|
||||
char const *file = "./afile";
|
||||
char file_cp_path[TSDB_FILENAME_LEN];
|
||||
int64_t lmtime = 20241220141705;
|
||||
char const *upload_id = "upload-id-xxx";
|
||||
|
||||
(void)snprintf(file_cp_path, TSDB_FILENAME_LEN, "%s.cp", file);
|
||||
(void)memset(&cp, 0, sizeof(cp));
|
||||
|
||||
cp.parts = (SCheckpointPart *)taosMemoryCalloc(max_part_num, sizeof(SCheckpointPart));
|
||||
if (!cp.parts) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
if (taosCheckExistFile(file_cp_path)) {
|
||||
EXPECT_EQ(cos_cp_load(file_cp_path, &cp), TSDB_CODE_SUCCESS);
|
||||
|
||||
EXPECT_EQ(cos_cp_is_valid_upload(&cp, contentLength, lmtime), true);
|
||||
|
||||
EXPECT_EQ(cp.cp_type, COS_CP_TYPE_UPLOAD);
|
||||
EXPECT_EQ(cp.md5, std::string(""));
|
||||
EXPECT_EQ(cp.thefile, nullptr);
|
||||
EXPECT_EQ(std::string(cp.file_path), "./afile");
|
||||
EXPECT_EQ(cp.file_size, 1024);
|
||||
EXPECT_EQ(cp.file_last_modified, 20241220141705);
|
||||
EXPECT_EQ(cp.file_md5, std::string(""));
|
||||
EXPECT_EQ(cp.object_name, std::string(""));
|
||||
EXPECT_EQ(cp.object_size, 0);
|
||||
EXPECT_EQ(cp.object_last_modified, std::string(""));
|
||||
EXPECT_EQ(cp.object_etag, std::string(""));
|
||||
EXPECT_EQ(cp.upload_id, std::string("upload-id-xxx"));
|
||||
|
||||
EXPECT_EQ(cp.part_num, 1);
|
||||
EXPECT_EQ(cp.part_size, 8388608);
|
||||
EXPECT_EQ(cp.parts[0].index, 0);
|
||||
EXPECT_EQ(cp.parts[0].offset, 0);
|
||||
EXPECT_EQ(cp.parts[0].size, 1024);
|
||||
EXPECT_EQ(cp.parts[0].completed, 1);
|
||||
EXPECT_EQ(cp.parts[0].etag, std::string("etags-1-xxx"));
|
||||
EXPECT_EQ(cp.parts[0].crc64, 0);
|
||||
}
|
||||
|
||||
if (cp.thefile) {
|
||||
EXPECT_EQ(cos_cp_close(cp.thefile), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
if (cp.parts) {
|
||||
taosMemoryFree(cp.parts);
|
||||
}
|
||||
|
||||
EXPECT_EQ(cos_cp_remove(file_cp_path), TSDB_CODE_SUCCESS);
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (c) 2019 TAOS Data, Inc. <jhtao@taosdata.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <cos.h>
|
||||
#include <taoserror.h>
|
||||
#include <tglobal.h>
|
||||
#include <iostream>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wwrite-strings"
|
||||
#pragma GCC diagnostic ignored "-Wunused-function"
|
||||
#pragma GCC diagnostic ignored "-Wunused-variable"
|
||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
|
||||
int32_t cosInitEnv() {
|
||||
int32_t code = 0;
|
||||
bool isBlob = false;
|
||||
|
||||
extern int8_t tsS3Ablob;
|
||||
extern char tsS3Hostname[][TSDB_FQDN_LEN];
|
||||
extern char tsS3AccessKeyId[][TSDB_FQDN_LEN];
|
||||
extern char tsS3AccessKeySecret[][TSDB_FQDN_LEN];
|
||||
extern char tsS3BucketName[TSDB_FQDN_LEN];
|
||||
|
||||
tsS3Ablob = isBlob;
|
||||
/*
|
||||
const char *hostname = "endpoint/<account-name>.blob.core.windows.net";
|
||||
const char *accessKeyId = "<access-key-id/account-name>";
|
||||
const char *accessKeySecret = "<access-key-secret/account-key>";
|
||||
const char *bucketName = "<bucket/container-name>";
|
||||
*/
|
||||
|
||||
// const char *hostname = "http://192.168.1.52:9000";
|
||||
// const char *accessKeyId = "zOgllR6bSnw2Ah3mCNel";
|
||||
// const char *accessKeySecret = "cdO7oXAu3Cqdb1rUdevFgJMi0LtRwCXdWKQx4bhX";
|
||||
// const char *bucketName = "test-bucket";
|
||||
const char *hostname = "192.168.1.52:9000";
|
||||
const char *accessKeyId = "zOgllR6bSnw2Ah3mCNel";
|
||||
const char *accessKeySecret = "cdO7oXAu3Cqdb1rUdevFgJMi0LtRwCXdWKQx4bhX";
|
||||
const char *bucketName = "ci-bucket19";
|
||||
|
||||
tstrncpy(&tsS3Hostname[0][0], hostname, TSDB_FQDN_LEN);
|
||||
tstrncpy(&tsS3AccessKeyId[0][0], accessKeyId, TSDB_FQDN_LEN);
|
||||
tstrncpy(&tsS3AccessKeySecret[0][0], accessKeySecret, TSDB_FQDN_LEN);
|
||||
tstrncpy(tsS3BucketName, bucketName, TSDB_FQDN_LEN);
|
||||
|
||||
// setup s3 env
|
||||
extern int8_t tsS3EpNum;
|
||||
extern int8_t tsS3Https[TSDB_MAX_EP_NUM];
|
||||
|
||||
tsS3EpNum = 1;
|
||||
tsS3Https[0] = false;
|
||||
|
||||
tstrncpy(tsTempDir, "/tmp/", PATH_MAX);
|
||||
|
||||
tsS3Enabled = true;
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
TEST(testCase, cosCpPutError) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
char const *objectName = "testObject";
|
||||
|
||||
EXPECT_EQ(cosInitEnv(), TSDB_CODE_SUCCESS);
|
||||
EXPECT_EQ(s3Begin(), TSDB_CODE_SUCCESS);
|
||||
|
||||
#if defined(USE_S3)
|
||||
EXPECT_EQ(s3Size(objectName), -1);
|
||||
#else
|
||||
EXPECT_EQ(s3Size(objectName), 0);
|
||||
#endif
|
||||
|
||||
s3EvictCache("", 0);
|
||||
|
||||
s3End();
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
||||
|
||||
TEST(testCase, cosCpPut) {
|
||||
int32_t code = 0, lino = 0;
|
||||
|
||||
int8_t with_cp = 0;
|
||||
char *data = nullptr;
|
||||
|
||||
const long objectSize = 65 * 1024 * 1024;
|
||||
char const *objectName = "cosut.bin";
|
||||
const char object_name[] = "cosut.bin";
|
||||
|
||||
EXPECT_EQ(std::string(object_name), objectName);
|
||||
|
||||
EXPECT_EQ(cosInitEnv(), TSDB_CODE_SUCCESS);
|
||||
EXPECT_EQ(s3Begin(), TSDB_CODE_SUCCESS);
|
||||
|
||||
{
|
||||
data = (char *)taosMemoryCalloc(1, objectSize);
|
||||
if (!data) {
|
||||
TAOS_CHECK_EXIT(terrno);
|
||||
}
|
||||
|
||||
for (int i = 0; i < objectSize / 2; ++i) {
|
||||
data[i * 2 + 1] = 1;
|
||||
}
|
||||
|
||||
char path[PATH_MAX] = {0};
|
||||
char path_download[PATH_MAX] = {0};
|
||||
int ds_len = strlen(TD_DIRSEP);
|
||||
int tmp_len = strlen(tsTempDir);
|
||||
|
||||
(void)snprintf(path, PATH_MAX, "%s", tsTempDir);
|
||||
if (strncmp(tsTempDir + tmp_len - ds_len, TD_DIRSEP, ds_len) != 0) {
|
||||
(void)snprintf(path + tmp_len, PATH_MAX - tmp_len, "%s", TD_DIRSEP);
|
||||
(void)snprintf(path + tmp_len + ds_len, PATH_MAX - tmp_len - ds_len, "%s", object_name);
|
||||
} else {
|
||||
(void)snprintf(path + tmp_len, PATH_MAX - tmp_len, "%s", object_name);
|
||||
}
|
||||
|
||||
tstrncpy(path_download, path, strlen(path) + 1);
|
||||
tstrncpy(path_download + strlen(path), ".download", strlen(".download") + 1);
|
||||
|
||||
TdFilePtr fp = taosOpenFile(path, TD_FILE_WRITE | TD_FILE_CREATE | TD_FILE_WRITE_THROUGH);
|
||||
GTEST_ASSERT_NE(fp, nullptr);
|
||||
|
||||
int n = taosWriteFile(fp, data, objectSize);
|
||||
GTEST_ASSERT_EQ(n, objectSize);
|
||||
|
||||
code = taosCloseFile(&fp);
|
||||
GTEST_ASSERT_EQ(code, 0);
|
||||
|
||||
code = s3PutObjectFromFile2(path, objectName, with_cp);
|
||||
GTEST_ASSERT_EQ(code, 0);
|
||||
|
||||
with_cp = 1;
|
||||
code = s3PutObjectFromFile2(path, objectName, with_cp);
|
||||
GTEST_ASSERT_EQ(code, 0);
|
||||
|
||||
#if defined(USE_S3)
|
||||
EXPECT_EQ(s3Size(objectName), objectSize);
|
||||
#else
|
||||
EXPECT_EQ(s3Size(objectName), 0);
|
||||
#endif
|
||||
|
||||
s3End();
|
||||
s3EvictCache("", 0);
|
||||
|
||||
taosMemoryFree(data);
|
||||
|
||||
EXPECT_EQ(taosRemoveFile(path), TSDB_CODE_SUCCESS);
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
_exit:
|
||||
if (data) {
|
||||
taosMemoryFree(data);
|
||||
s3End();
|
||||
}
|
||||
|
||||
std::cout << "code: " << code << std::endl;
|
||||
}
|
|
@ -449,6 +449,20 @@ static void checkTSRow(const char **data, STSRow *row, STSchema *pTSchema) {
|
|||
checkSColVal(data[i], &colVal, pCol->type);
|
||||
}
|
||||
}
|
||||
#ifndef WINDOWS
|
||||
TEST(testCase, tColDataGetValue) {
|
||||
SColData pColData = {0};
|
||||
SColVal pColVal = {0};
|
||||
ASSERT_NE(tColDataGetValue(&pColData, 0, &pColVal),0);
|
||||
|
||||
pColData = {.flag = 8};
|
||||
pColVal = {0};
|
||||
ASSERT_NE(tColDataGetValue(&pColData, 0, &pColVal),0);
|
||||
|
||||
pColData = {.nVal = 1, .flag = 8};
|
||||
ASSERT_NE(tColDataGetValue(&pColData, 0, &pColVal),0);
|
||||
}
|
||||
#endif
|
||||
|
||||
TEST(testCase, AllNormTest) {
|
||||
int16_t nCols = 14;
|
||||
|
|