Merge branch 'develop' into feature/update
This commit is contained in:
commit
951a0df6b9
|
@ -4,3 +4,6 @@
|
|||
[submodule "src/connector/grafanaplugin"]
|
||||
path = src/connector/grafanaplugin
|
||||
url = https://github.com/taosdata/grafanaplugin
|
||||
[submodule "src/connector/hivemq-tdengine-extension"]
|
||||
path = src/connector/hivemq-tdengine-extension
|
||||
url = https://github.com/huskar-t/hivemq-tdengine-extension.git
|
||||
|
|
|
@ -0,0 +1,402 @@
|
|||
##########################################################################################
|
||||
# Customize file classifications. #
|
||||
# Results from files under any classifier will be excluded from LGTM #
|
||||
# statistics. #
|
||||
##########################################################################################
|
||||
|
||||
##########################################################################################
|
||||
# Use the `path_classifiers` block to define changes to the default classification of #
|
||||
# files. #
|
||||
##########################################################################################
|
||||
|
||||
path_classifiers:
|
||||
# docs:
|
||||
# Identify the top-level file called `generate_javadoc.py` as documentation-related.
|
||||
test:
|
||||
# Override LGTM's default classification of test files by excluding all files.
|
||||
- exclude: /
|
||||
# Classify all files in the top-level directories tests/ and testsuites/ as test code.
|
||||
- tests
|
||||
# - testsuites
|
||||
# Classify all files with suffix `.test` as test code.
|
||||
# Note: use only forward slash / as a path separator.
|
||||
# Use ** to indicate an arbitrary parent path.
|
||||
# Use * to indicate any sequence of characters excluding /.
|
||||
# Always enclose the expression in double quotes if it includes *.
|
||||
# - "**/*.test"
|
||||
# Refine the classifications above by excluding files in test/util/.
|
||||
# - exclude: test/util
|
||||
# The default behavior is to tag all files created during the
|
||||
# build as `generated`. Results are hidden for generated code. You can tag
|
||||
# further files as being generated by adding them to the `generated` section.
|
||||
generated:
|
||||
# Exclude all `*.c` files under the `ui/` directory from classification as
|
||||
# generated code.
|
||||
# - exclude: ui/**/*.c
|
||||
# By default, all files not checked into the repository are considered to be
|
||||
# 'generated'.
|
||||
# The default behavior is to tag library code as `library`. Results are hidden
|
||||
# for library code. You can tag further files as being library code by adding them
|
||||
# to the `library` section.
|
||||
library:
|
||||
- exclude: deps/
|
||||
# The default behavior is to tag template files as `template`. Results are hidden
|
||||
# for template files. You can tag further files as being template files by adding
|
||||
# them to the `template` section.
|
||||
template:
|
||||
#- exclude: path/to/template/code/**/*.c
|
||||
# Define your own category, for example: 'some_custom_category'.
|
||||
some_custom_category:
|
||||
# Classify all files in the top-level directory tools/ (or the top-level file
|
||||
# called tools).
|
||||
# - tools
|
||||
|
||||
#########################################################################################
|
||||
# Use the `queries` block to change the default display of query results. #
|
||||
#########################################################################################
|
||||
|
||||
# queries:
|
||||
# Start by hiding the results of all queries.
|
||||
# - exclude: "*"
|
||||
# Then include all queries tagged 'security' and 'correctness', and with a severity of
|
||||
# 'error'.
|
||||
# - include:
|
||||
# tags:
|
||||
# - "security"
|
||||
# - "correctness"
|
||||
# severity: "error"
|
||||
# Specifically hide the results of two queries.
|
||||
# - exclude: cpp/use-of-goto
|
||||
# - exclude: java/equals-on-unrelated-types
|
||||
# Refine by including the `java/command-line-injection` query.
|
||||
# - include: java/command-line-injection
|
||||
|
||||
#########################################################################################
|
||||
# Define changes to the default code extraction process. #
|
||||
# Each block configures the extraction of a single language, and modifies actions in a #
|
||||
# named step. Every named step includes automatic default actions, #
|
||||
# except for the 'prepare' step. The steps are performed in the following sequence: #
|
||||
# prepare #
|
||||
# after_prepare #
|
||||
# configure (C/C++ only) #
|
||||
# python_setup (Python only) #
|
||||
# before_index #
|
||||
# index #
|
||||
##########################################################################################
|
||||
|
||||
#########################################################################################
|
||||
# Environment variables available to the steps: #
|
||||
#########################################################################################
|
||||
|
||||
# LGTM_SRC
|
||||
# The root of the source tree.
|
||||
# LGTM_WORKSPACE
|
||||
# An existing (initially empty) folder outside the source tree.
|
||||
# Used for temporary download and setup commands.
|
||||
|
||||
#########################################################################################
|
||||
# Use the extraction block to define changes to the default code extraction process #
|
||||
# for one or more languages. The settings for each language are defined in a child #
|
||||
# block, with one or more steps. #
|
||||
#########################################################################################
|
||||
|
||||
extraction:
|
||||
# Define settings for C/C++ analysis
|
||||
#####################################
|
||||
cpp:
|
||||
# The `prepare` step exists for customization on LGTM.com only.
|
||||
prepare:
|
||||
# # The `packages` section is valid for LGTM.com only. It names Ubuntu packages to
|
||||
# # be installed.
|
||||
packages:
|
||||
- cmake
|
||||
# Add an `after-prepare` step if you need to run commands after the prepare step.
|
||||
# Each command should be listed on a separate line.
|
||||
# This step is useful for C/C++ analysis where you want to prepare the environment
|
||||
# for the `configure` step without changing the default behavior for that step.
|
||||
# after_prepare:
|
||||
#- export GNU_MAKE=make
|
||||
#- export GIT=true
|
||||
# The `configure` step generates build configuration files which the `index` step
|
||||
# then uses to build the codebase.
|
||||
configure:
|
||||
command:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- cmake ..
|
||||
# - ./prepare_deps
|
||||
# Optional step. You should add a `before_index` step if you need to run commands
|
||||
# before the `index` step.
|
||||
# before_index:
|
||||
# - export BOOST_DIR=$LGTM_SRC/boost
|
||||
# - export GTEST_DIR=$LGTM_SRC/googletest
|
||||
# - export HUNSPELL_DIR=$LGTM_SRC/hunspell
|
||||
# - export CRYPTOPP_DIR=$LGTM_SRC/cryptopp
|
||||
# The `index` step builds the code and extracts information during the build
|
||||
# process.
|
||||
index:
|
||||
# Override the autobuild process by specifying a list of custom build commands
|
||||
# to use instead.
|
||||
build_command:
|
||||
- cd build
|
||||
- make
|
||||
# - $GNU_MAKE -j2 -s
|
||||
# Specify that all project or solution files should be used for extraction.
|
||||
# Default: false.
|
||||
# all_solutions: true
|
||||
# Specify a list of one or more project or solution files for extraction.
|
||||
# Default: LGTM chooses the file closest to the root of the repository (this may
|
||||
# fail if there are multiple candidates).
|
||||
# solution:
|
||||
# - myProject.sln
|
||||
# Specify MSBuild settings
|
||||
# msbuild:
|
||||
# Specify a list of additional arguments to MSBuild. Default: empty.
|
||||
# arguments: /p:Platform=x64 /p:Configuration=Release
|
||||
# Specify the MSBuild configuration to use, for example, debug or release.
|
||||
# Default: read from the solution file or files.
|
||||
# configuration:
|
||||
# Specify the platform to target, for example: x86, x64, or Any CPU.
|
||||
# Default: read from the solution file or files.
|
||||
# platform:
|
||||
# Specify the MSBuild target. Default: rebuild.
|
||||
# target:
|
||||
# Specify whether or not to perform a NuGet restore for extraction. Default: true.
|
||||
# nuget_restore: false
|
||||
# Specify a version of Microsoft Visual Studio to use for MSBuild or any custom
|
||||
# build commands (build_command). For example:
|
||||
# 10 for Visual Studio 2010
|
||||
# 12 for Visual Studio 2012
|
||||
# 14 for Visual Studio 2015
|
||||
# 15 for Visual Studio 2017
|
||||
# Default: read from project files.
|
||||
# vstools_version: 10
|
||||
|
||||
# Define settings for C# analysis
|
||||
##################################
|
||||
# csharp:
|
||||
# The `prepare` step exists for customization on LGTM.com only.
|
||||
# prepare:
|
||||
# packages:
|
||||
# - example_package
|
||||
# Add an `after-prepare` step if you need to run commands after the `prepare` step.
|
||||
# Each command should be listed on a separate line.
|
||||
# after_prepare:
|
||||
# - export PATH=$LGTM_WORKSPACE/tools:$PATH
|
||||
# The `index` step builds the code and extracts information during the build
|
||||
# process.
|
||||
#index:
|
||||
# Specify that all project or solution files should be used for extraction.
|
||||
# Default: false.
|
||||
# all_solutions: true
|
||||
# Specify a list of one or more project or solution files for extraction.
|
||||
# Default: LGTM chooses the file closest to the root of the repository (this may
|
||||
# fail if there are multiple candidates).
|
||||
# solution:
|
||||
# - myProject.sln
|
||||
# Override the autobuild process by specifying a list of custom build commands
|
||||
# to use instead.
|
||||
# build_command:
|
||||
# - ./example-compile-all.sh
|
||||
# By default, LGTM analyzes the code by building it. You can override this,
|
||||
# and tell LGTM not to build the code. Beware that this can lead
|
||||
# to less accurate results.
|
||||
# buildless: true
|
||||
# Specify .NET Core settings.
|
||||
# dotnet:
|
||||
# Specify additional arguments to `dotnet build`.
|
||||
# Default: empty.
|
||||
# arguments: "example_arg"
|
||||
# Specify the version of .NET Core SDK to use.
|
||||
# Default: The version installed on the build machine.
|
||||
# version: 2.1
|
||||
# Specify MSBuild settings.
|
||||
# msbuild:
|
||||
# Specify a list of additional arguments to MSBuild. Default: empty.
|
||||
# arguments: /P:WarningLevel=2
|
||||
# Specify the MSBuild configuration to use, for example, debug or release.
|
||||
# Default: read from the solution file or files.
|
||||
# configuration: release
|
||||
# Specify the platform to target, for example: x86, x64, or Any CPU.
|
||||
# Default: read from the solution file or files.
|
||||
# platform: x86
|
||||
# Specify the MSBuild target. Default: rebuild.
|
||||
# target: notest
|
||||
# Specify whether or not to perform a NuGet restore for extraction. Default: true.
|
||||
# nuget_restore: false
|
||||
# Specify a version of Microsoft Visual Studio to use for MSBuild or any custom
|
||||
# build commands (build_command). For example:
|
||||
# 10 for Visual Studio 2010
|
||||
# 12 for Visual Studio 2012
|
||||
# 14 for Visual Studio 2015
|
||||
# 15 for Visual Studio 2017
|
||||
# Default: read from project files
|
||||
# vstools_version: 10
|
||||
# Specify additional options for the extractor,
|
||||
# for example --fast to perform a faster extraction that produces a smaller
|
||||
# database.
|
||||
# extractor: "--fast"
|
||||
|
||||
# Define settings for Go analysis
|
||||
##################################
|
||||
# go:
|
||||
# The `prepare` step exists for customization on LGTM.com only.
|
||||
# prepare:
|
||||
# packages:
|
||||
# - example_package
|
||||
# Add an `after-prepare` step if you need to run commands after the `prepare` step.
|
||||
# Each command should be listed on a separate line.
|
||||
# after_prepare:
|
||||
# - export PATH=$LGTM_WORKSPACE/tools:$PATH
|
||||
# The `index` step builds the code and extracts information during the build
|
||||
# process.
|
||||
# index:
|
||||
# Override the autobuild process by specifying a list of custom build commands
|
||||
# to use instead.
|
||||
# build_command:
|
||||
# - ./compile-all.sh
|
||||
|
||||
# Define settings for Java analysis
|
||||
####################################
|
||||
# java:
|
||||
# The `prepare` step exists for customization on LGTM.com only.
|
||||
# prepare:
|
||||
# packages:
|
||||
# - example_package
|
||||
# Add an `after-prepare` step if you need to run commands after the prepare step.
|
||||
# Each command should be listed on a separate line.
|
||||
# after_prepare:
|
||||
# - export PATH=$LGTM_WORKSPACE/tools:$PATH
|
||||
# The `index` step extracts information from the files in the codebase.
|
||||
# index:
|
||||
# Specify Gradle settings.
|
||||
# gradle:
|
||||
# Specify the required Gradle version.
|
||||
# Default: determined automatically.
|
||||
# version: 4.4
|
||||
# Override the autobuild process by specifying a list of custom build commands
|
||||
# to use instead.
|
||||
# build_command: ./compile-all.sh
|
||||
# Specify the Java version required to build the project.
|
||||
# java_version: 11
|
||||
# Specify whether to extract Java .properties files
|
||||
# Default: false
|
||||
# properties_files: true
|
||||
# Specify Maven settings.
|
||||
# maven:
|
||||
# Specify the path (absolute or relative) of a Maven settings file to use.
|
||||
# Default: Maven uses a settings file in the default location, if it exists.
|
||||
# settings_file: /opt/share/settings.xml
|
||||
# Specify the path of a Maven toolchains file.
|
||||
# Default: Maven uses a toolchains file in the default location, if it exists.
|
||||
# toolchains_file: /opt/share/toolchains.xml
|
||||
# Specify the required Maven version.
|
||||
# Default: the Maven version is determined automatically, where feasible.
|
||||
# version: 3.5.2
|
||||
# Specify how XML files should be extracted:
|
||||
# all = extract all XML files.
|
||||
# default = only extract XML files named `AndroidManifest.xml`, `pom.xml`, and `web.xml`.
|
||||
# disabled = do not extract any XML files.
|
||||
# xml_mode: all
|
||||
|
||||
# Define settings for JavaScript analysis
|
||||
##########################################
|
||||
# javascript:
|
||||
# The `prepare` step exists for customization on LGTM.com only.
|
||||
# prepare:
|
||||
# packages:
|
||||
# - example_package
|
||||
# Add an `after-prepare` step if you need to run commands after the prepare step.
|
||||
# Each command should be listed on a separate line.
|
||||
# after_prepare:
|
||||
# - export PATH=$LGTM_WORKSPACE/tools:$PATH
|
||||
# The `index` step extracts information from the files in the codebase.
|
||||
# index:
|
||||
# Specify a list of files and folders to extract.
|
||||
# Default: The project root directory.
|
||||
# include:
|
||||
# - src/js
|
||||
# Specify a list of files and folders to exclude from extraction.
|
||||
# exclude:
|
||||
# - thirdparty/lib
|
||||
# You can add additional file types for LGTM to extract, by mapping file
|
||||
# extensions (including the leading dot) to file types. The usual
|
||||
# include/exclude patterns apply, so, for example, `.jsm` files under
|
||||
# `thirdparty/lib` will not be extracted.
|
||||
# filetypes:
|
||||
# ".jsm": "js"
|
||||
# ".tmpl": "html"
|
||||
# Specify a list of glob patterns to include/exclude files from extraction; this
|
||||
# is applied on top of the include/exclude paths from above; patterns are
|
||||
# processed in the same way as for path classifiers above.
|
||||
# Default: include all files with known extensions (such as .js, .ts and .html),
|
||||
# but exclude files ending in `-min.js` or `.min.js` and folders named `node_modules`
|
||||
# or `bower_components`
|
||||
# filters:
|
||||
# exclude any *.ts files anywhere.
|
||||
# - exclude: "**/*.ts"
|
||||
# but include *.ts files under src/js/typescript.
|
||||
# - include: "src/js/typescript/**/*.ts"
|
||||
# Specify how TypeScript files should be extracted:
|
||||
# none = exclude all TypeScript files.
|
||||
# basic = extract syntactic information from TypeScript files.
|
||||
# full = extract syntactic and type information from TypeScript files.
|
||||
# Default: full.
|
||||
# typescript: basic
|
||||
# By default, LGTM doesn't extract any XML files. You can override this by
|
||||
# using the `xml_mode` property and setting it to `all`.
|
||||
# xml_mode: all
|
||||
|
||||
# Define settings for Python analysis
|
||||
######################################
|
||||
# python:
|
||||
# # The `prepare` step exists for customization on LGTM.com only.
|
||||
# # prepare:
|
||||
# # # The `packages` section is valid for LGTM.com only. It names packages to
|
||||
# # # be installed.
|
||||
# # packages: libpng-dev
|
||||
# # This step is useful for Python analysis where you want to prepare the
|
||||
# # environment for the `python_setup` step without changing the default behavior
|
||||
# # for that step.
|
||||
# after_prepare:
|
||||
# - export PATH=$LGTM_WORKSPACE/tools:$PATH
|
||||
# # This sets up the Python interpreter and virtual environment, ready for the
|
||||
# # `index` step to extract the codebase.
|
||||
# python_setup:
|
||||
# # Specify packages that should NOT be installed despite being mentioned in the
|
||||
# # requirements.txt file.
|
||||
# # Default: no package marked for exclusion.
|
||||
# exclude_requirements:
|
||||
# - pywin32
|
||||
# # Specify a list of pip packages to install.
|
||||
# # If any of these packages cannot be installed, the extraction will fail.
|
||||
# requirements:
|
||||
# - Pillow
|
||||
# # Specify a list of requirements text files to use to set up the environment,
|
||||
# # or false for none. Default: any requirements.txt, test-requirements.txt,
|
||||
# # and similarly named files identified in the codebase are used.
|
||||
# requirements_files:
|
||||
# - required-packages.txt
|
||||
# # Specify a setup.py file to use to set up the environment, or false for none.
|
||||
# # Default: any setup.py files identified in the codebase are used in preference
|
||||
# # to any requirements text files.
|
||||
# setup_py: new-setup.py
|
||||
# # Override the version of the Python interpreter used for setup and extraction
|
||||
# # Default: Python 3.
|
||||
# version: 2
|
||||
# # Optional step. You should add a `before_index` step if you need to run commands
|
||||
# # before the `index` step.
|
||||
# before_index:
|
||||
# - antlr4 -Dlanguage=Python3 Grammar.g4
|
||||
# # The `index` step extracts information from the files in the codebase.
|
||||
# index:
|
||||
# # Specify a list of files and folders to exclude from extraction.
|
||||
# # Default: Git submodules and Subversion externals.
|
||||
# exclude:
|
||||
# - legacy-implementation
|
||||
# - thirdparty/libs
|
||||
# filters:
|
||||
# - exclude: "**/documentation/examples/snippets/*.py"
|
||||
# - include: "**/documentation/examples/test_application/*"
|
||||
# include:
|
||||
# - example/to/include
|
|
@ -32,6 +32,8 @@ matrix:
|
|||
- python3-setuptools
|
||||
- valgrind
|
||||
- psmisc
|
||||
- unixodbc
|
||||
- unixodbc-dev
|
||||
|
||||
before_script:
|
||||
- export TZ=Asia/Harbin
|
||||
|
@ -54,6 +56,7 @@ matrix:
|
|||
|
||||
py3ver=`python3 --version|awk '{print $2}'|cut -d "." -f 1,2` && apt install python$py3ver-dev
|
||||
pip3 install psutil
|
||||
pip3 install guppy3
|
||||
pip3 install --user ${TRAVIS_BUILD_DIR}/src/connector/python/linux/python3/
|
||||
|
||||
cd ${TRAVIS_BUILD_DIR}/tests
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
pipeline {
|
||||
agent none
|
||||
environment{
|
||||
WK = '/var/lib/jenkins/workspace/TDinternal'
|
||||
WKC= '/var/lib/jenkins/workspace/TDinternal/community'
|
||||
}
|
||||
|
||||
stages {
|
||||
stage('Parallel test stage') {
|
||||
parallel {
|
||||
stage('pytest') {
|
||||
agent{label '184'}
|
||||
steps {
|
||||
sh '''
|
||||
date
|
||||
cd ${WKC}
|
||||
git checkout develop
|
||||
git pull
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git checkout develop
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake .. > /dev/null
|
||||
make > /dev/null
|
||||
cd ${WKC}/tests
|
||||
#./test-all.sh smoke
|
||||
./test-all.sh pytest
|
||||
date'''
|
||||
}
|
||||
}
|
||||
stage('test_b1') {
|
||||
agent{label 'master'}
|
||||
steps {
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git checkout develop
|
||||
git pull
|
||||
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git checkout develop
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake .. > /dev/null
|
||||
make > /dev/null
|
||||
cd ${WKC}/tests
|
||||
#./test-all.sh smoke
|
||||
./test-all.sh b1
|
||||
date'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('test_crash_gen') {
|
||||
agent{label "185"}
|
||||
steps {
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git checkout develop
|
||||
git pull
|
||||
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git checkout develop
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake .. > /dev/null
|
||||
make > /dev/null
|
||||
cd ${WKC}/tests/pytest
|
||||
'''
|
||||
catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
|
||||
sh '''
|
||||
cd ${WKC}/tests/pytest
|
||||
./crash_gen.sh -a -p -t 4 -s 2000
|
||||
'''
|
||||
}
|
||||
sh '''
|
||||
date
|
||||
cd ${WKC}/tests
|
||||
./test-all.sh b2
|
||||
date
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('test_valgrind') {
|
||||
agent{label "186"}
|
||||
|
||||
steps {
|
||||
sh '''
|
||||
cd ${WKC}
|
||||
git checkout develop
|
||||
git pull
|
||||
|
||||
git submodule update
|
||||
cd ${WK}
|
||||
git checkout develop
|
||||
git pull
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WK}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake .. > /dev/null
|
||||
make > /dev/null
|
||||
cd ${WKC}/tests/pytest
|
||||
./valgrind-test.sh 2>&1 > mem-error-out.log
|
||||
./handle_val_log.sh
|
||||
|
||||
date
|
||||
cd ${WKC}/tests
|
||||
./test-all.sh b3
|
||||
date'''
|
||||
}
|
||||
}
|
||||
stage('connector'){
|
||||
agent{label "release"}
|
||||
steps{
|
||||
sh'''
|
||||
cd ${WORKSPACE}
|
||||
git checkout develop
|
||||
cd tests/gotest
|
||||
bash batchtest.sh
|
||||
cd ${WORKSPACE}/tests/examples/JDBC/JDBCDemo/
|
||||
mvn clean package assembly:single >/dev/null
|
||||
java -jar target/jdbcChecker-SNAPSHOT-jar-with-dependencies.jar -host 127.0.0.1
|
||||
cd ${WORKSPACE}/tests/examples/python/PYTHONConnectorChecker
|
||||
python3 PythonChecker.py
|
||||
'''
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -83,12 +83,18 @@ sudo dnf install -y maven
|
|||
|
||||
## Get the source codes
|
||||
|
||||
- github:
|
||||
First of all, you may clone the source codes from github:
|
||||
```bash
|
||||
git clone https://github.com/taosdata/TDengine.git
|
||||
cd TDengine
|
||||
```
|
||||
|
||||
The connectors for go & grafana have been moved to separated repositories,
|
||||
so you should run this command in the TDengine directory to install them:
|
||||
```bash
|
||||
git submodule update --init --recursive
|
||||
```
|
||||
|
||||
## Build TDengine
|
||||
|
||||
### On Linux platform
|
||||
|
|
|
@ -61,7 +61,7 @@ The use of each configuration item is:
|
|||
|
||||
* **port**: This is the `http` service port which enables other application to manage rules by `restful API`.
|
||||
* **database**: rules are stored in a `sqlite` database, this is the path of the database file (if the file does not exist, the alert application creates it automatically).
|
||||
* **tdengine**: connection string of `TDEngine` server, note in most cases the database information should be put in a rule, thus it should NOT be included here.
|
||||
* **tdengine**: connection string of `TDEngine` server, note the database name should be put in the `sql` field of a rule in most cases, thus it should NOT be included in the string.
|
||||
* **log > level**: log level, could be `production` or `debug`.
|
||||
* **log > path**: log output file path.
|
||||
* **receivers > alertManager**: the alert application pushes alerts to `AlertManager` at this URL.
|
||||
|
|
|
@ -58,7 +58,7 @@ $ go build
|
|||
|
||||
* **port**:报警监测程序支持使用 `restful API` 对规则进行管理,这个参数用于配置 `http` 服务的侦听端口。
|
||||
* **database**:报警监测程序将规则保存到了一个 `sqlite` 数据库中,这个参数用于指定数据库文件的路径(不需要提前创建这个文件,如果它不存在,程序会自动创建它)。
|
||||
* **tdengine**:`TDEngine` 的连接信息,一般来说,数据库信息应该在报警规则中指定,所以这里 **不** 应包含这一部分信息。
|
||||
* **tdengine**:`TDEngine` 的连接字符串,一般来说,数据库名应该在报警规则的 `sql` 语句中指定,所以这个字符串中 **不** 应包含数据库名。
|
||||
* **log > level**:日志的记录级别,可选 `production` 或 `debug`。
|
||||
* **log > path**:日志文件的路径。
|
||||
* **receivers > alertManager**:报警监测程序会将报警推送到 `AlertManager`,在这里指定 `AlertManager` 的接收地址。
|
||||
|
|
|
@ -48,6 +48,7 @@ ENDIF ()
|
|||
IF (TD_LINUX_64)
|
||||
ADD_DEFINITIONS(-D_M_X64)
|
||||
ADD_DEFINITIONS(-D_TD_LINUX_64)
|
||||
MESSAGE(STATUS "linux64 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
ENDIF ()
|
||||
|
@ -55,30 +56,38 @@ ENDIF ()
|
|||
IF (TD_LINUX_32)
|
||||
ADD_DEFINITIONS(-D_TD_LINUX_32)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -munaligned-access -fpack-struct=8 -latomic -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
MESSAGE(STATUS "linux32 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -munaligned-access -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM_64)
|
||||
ADD_DEFINITIONS(-D_M_X64)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_64_)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_64)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "arm64 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM_32)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_32_)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_32)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "arm32 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE -Wno-pointer-to-int-cast -Wno-int-to-pointer-cast -Wno-incompatible-pointer-types ")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS_64)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_64_)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "mips64 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS_32)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_32_)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "mips32 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
|
@ -86,6 +95,7 @@ IF (TD_APLHINE)
|
|||
SET(COMMON_FLAGS "${COMMON_FLAGS} -largp")
|
||||
link_libraries(/usr/lib/libargp.a)
|
||||
ADD_DEFINITIONS(-D_ALPINE)
|
||||
MESSAGE(STATUS "aplhine is defined")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_LINUX)
|
||||
|
@ -95,7 +105,7 @@ IF (TD_LINUX)
|
|||
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
|
||||
|
||||
IF (TD_NINGSI_60)
|
||||
ADD_DEFINITIONS(-D_TD_NINGSI_60_)
|
||||
ADD_DEFINITIONS(-D_TD_NINGSI_60)
|
||||
MESSAGE(STATUS "set ningsi macro to true")
|
||||
ENDIF ()
|
||||
|
||||
|
@ -118,6 +128,7 @@ IF (TD_DARWIN_64)
|
|||
ADD_DEFINITIONS(-DDARWIN)
|
||||
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "darwin64 is defined")
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -g -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
SET(DEBUG_FLAGS "-O0 -DDEBUG")
|
||||
SET(RELEASE_FLAGS "-O0")
|
||||
|
@ -147,11 +158,13 @@ IF (TD_WINDOWS_64)
|
|||
ADD_DEFINITIONS(-D_M_X64)
|
||||
ADD_DEFINITIONS(-D_TD_WINDOWS_64)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "windows64 is defined")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_WINDOWS_32)
|
||||
ADD_DEFINITIONS(-D_TD_WINDOWS_32)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
MESSAGE(STATUS "windows32 is defined")
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc)
|
||||
|
|
|
@ -45,7 +45,7 @@ IF (${CMAKE_BUILD_TYPE} MATCHES "Debug")
|
|||
ELSEIF (${CMAKE_BUILD_TYPE} MATCHES "Release")
|
||||
MESSAGE(STATUS "Build Release Version")
|
||||
ELSE ()
|
||||
IF (TD_WINDOWS_64)
|
||||
IF (TD_WINDOWS)
|
||||
SET(CMAKE_BUILD_TYPE "Release")
|
||||
MESSAGE(STATUS "Build Release Version in Windows as default")
|
||||
ELSE ()
|
||||
|
|
|
@ -10,31 +10,28 @@ ELSEIF (TD_WINDOWS)
|
|||
SET(CMAKE_INSTALL_PREFIX C:/TDengine)
|
||||
ENDIF ()
|
||||
|
||||
IF (NOT TD_GODLL)
|
||||
#INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector)
|
||||
#INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/grafana DESTINATION connector)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/tests/examples DESTINATION .)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/packaging/cfg DESTINATION .)
|
||||
INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taos.h DESTINATION include)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/go DESTINATION connector)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/nodejs DESTINATION connector)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/src/connector/python DESTINATION connector)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/tests/examples DESTINATION .)
|
||||
INSTALL(DIRECTORY ${TD_COMMUNITY_DIR}/packaging/cfg DESTINATION .)
|
||||
INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taos.h DESTINATION include)
|
||||
INSTALL(FILES ${TD_COMMUNITY_DIR}/src/inc/taoserror.h DESTINATION include)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.lib DESTINATION driver)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.exp DESTINATION driver)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos.dll DESTINATION driver)
|
||||
|
||||
IF (TD_POWER)
|
||||
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .)
|
||||
ELSE ()
|
||||
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .)
|
||||
ENDIF ()
|
||||
IF (TD_POWER)
|
||||
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/power.exe DESTINATION .)
|
||||
ELSE ()
|
||||
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taos.exe DESTINATION .)
|
||||
INSTALL(FILES ${EXECUTABLE_OUTPUT_PATH}/taosdemo.exe DESTINATION .)
|
||||
ENDIF ()
|
||||
|
||||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.0-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSE ()
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/libtaos.dll DESTINATION driver)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/libtaos.dll.a DESTINATION driver)
|
||||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.8-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
|
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "2.0.4.0")
|
||||
SET(TD_VER_NUMBER "2.0.6.0")
|
||||
ENDIF ()
|
||||
|
||||
IF (DEFINED VERCOMPATIBLE)
|
||||
|
@ -42,6 +42,12 @@ IF (DEFINED CPUTYPE)
|
|||
ELSE ()
|
||||
IF (TD_WINDOWS_32)
|
||||
SET(TD_VER_CPUTYPE "x86")
|
||||
ELSEIF (TD_LINUX_32)
|
||||
SET(TD_VER_CPUTYPE "x86")
|
||||
ELSEIF (TD_ARM_32)
|
||||
SET(TD_VER_CPUTYPE "x86")
|
||||
ELSEIF (TD_MIPS_32)
|
||||
SET(TD_VER_CPUTYPE "x86")
|
||||
ELSE ()
|
||||
SET(TD_VER_CPUTYPE "x64")
|
||||
ENDIF ()
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_LINUX)
|
||||
INCLUDE_DIRECTORIES(inc)
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
ADD_LIBRARY(z ${SRC})
|
||||
ENDIF ()
|
||||
IF (TD_WINDOWS)
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX-")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX-")
|
||||
ENDIF()
|
||||
|
||||
INCLUDE_DIRECTORIES(inc)
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
ADD_LIBRARY(z ${SRC})
|
||||
|
|
|
@ -472,7 +472,7 @@ typedef uint64_t z_crc_t;
|
|||
#endif
|
||||
#ifndef Z_SOLO
|
||||
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
#if (_WIN64)
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
|
|
|
@ -472,7 +472,7 @@ typedef uLong FAR uLongf;
|
|||
#endif
|
||||
#ifndef Z_SOLO
|
||||
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
|
||||
#if (_WIN64)
|
||||
#if defined(_WIN64) || defined(_WIN32)
|
||||
#include <io.h>
|
||||
#include <process.h>
|
||||
#else
|
||||
|
|
|
@ -51,8 +51,8 @@ INTERVAL(1M)</code></pre>
|
|||
<li><p>mseconds:查询数据库更新的时间间隔,单位为毫秒。一般设置为1000毫秒。返回值为指向TDengine_SUB 结构的指针,如果返回为空,表示失败。</p></li>
|
||||
</ul><li><p><code>TAOS_ROW taos_consume(TAOS_SUB *tsub)</code>
|
||||
</p><p>该函数用来获取订阅的结果,用户应用程序将其置于一个无限循环语句。如果数据库有新记录到达,该API将返回该最新的记录。如果没有新的记录,该API将阻塞。如果返回值为空,说明系统出错。参数说明:</p></li><ul><li><p>tsub:taos_subscribe的结构体指针。</p></li></ul><li><p><code>void taos_unsubscribe(TAOS_SUB *tsub)</code></p><p>取消订阅。应用程序退出时,务必调用该函数以避免资源泄露。</p></li>
|
||||
<li><p><code>int taos_num_subfields(TAOS_SUB *tsub)</code></p><p>获取返回的一行记录中数据包含多少列。</p></li>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_subfields(TAOS_SUB *tsub)</code></p><p>获取每列数据的属性(数据类型、名字、长度),与taos_num_subfileds配合使用,可解析返回的每行数据。</p></li></ul>
|
||||
<li><p><code>int taos_num_fields(TAOS_SUB *tsub)</code></p><p>获取返回的一行记录中数据包含多少列。</p></li>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_fields(TAOS_SUB *tsub)</code></p><p>获取每列数据的属性(数据类型、名字、长度),与taos_num_subfileds配合使用,可解析返回的每行数据。</p></li></ul>
|
||||
<p>示例代码:请看安装包中的的示范程序</p>
|
||||
<a class='anchor' id='缓存-(Cache)'></a><h2>缓存 (Cache)</h2>
|
||||
<p>TDengine采用时间驱动缓存管理策略(First-In-First-Out,FIFO),又称为写驱动的缓存管理机制。这种策略有别于读驱动的数据缓存模式(Least-Recent-Use,LRU),直接将最近写入的数据保存在系统的缓存中。当缓存达到临界值的时候,将最早的数据批量写入磁盘。一般意义上来说,对于物联网数据的使用,用户最为关心最近产生的数据,即当前状态。TDengine充分利用了这一特性,将最近到达的(当前状态)数据保存在缓存中。</p>
|
||||
|
|
|
@ -64,9 +64,9 @@
|
|||
<p>该API用来获取最新消息,应用程序一般会将其置于一个无限循环语句中。其中参数tsub是taos_subscribe的返回值。如果数据库有新的记录,该API将返回,返回参数是一行记录。如果没有新的记录,该API将阻塞。如果返回值为空,说明系统出错,需要检查系统是否还在正常运行。</p></li>
|
||||
<li><p><code>void taos_unsubscribe(TAOS_SUB *tsub)</code></p>
|
||||
<p>该API用于取消订阅,参数tsub是taos_subscribe的返回值。应用程序退出时,需要调用该API,否则有资源泄露。</p></li>
|
||||
<li><p><code>int taos_num_subfields(TAOS_SUB *tsub)</code></p>
|
||||
<li><p><code>int taos_num_fields(TAOS_SUB *tsub)</code></p>
|
||||
<p>该API用来获取返回的一排数据中数据的列数</p></li>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_subfields(TAOS_RES *res)</code></p>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_fields(TAOS_RES *res)</code></p>
|
||||
<p>该API用来获取每列数据的属性(数据类型、名字、字节数),与taos_num_subfileds配合使用,可用来解析返回的一排数据。</p></li>
|
||||
</ul>
|
||||
<a class='anchor' id='Java-Connector'></a><h2>Java Connector</h2>
|
||||
|
@ -259,4 +259,4 @@ conn.close()
|
|||
_ "taosSql"
|
||||
)</code></pre>
|
||||
<p>taosSql驱动包内采用cgo模式,调用了TDengine的C/C++同步接口,与TDengine进行交互,因此,在数据库操作执行完成之前,客户端应用将处于阻塞状态。单个数据库连接,在同一时刻只能有一个线程调用API。客户应用可以建立多个连接,进行多线程的数据写入或查询处理。</p>
|
||||
<p>更多使用的细节,请参考下载目录中的示例源码。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
|
||||
<p>更多使用的细节,请参考下载目录中的示例源码。</p><a href='../index.html'>回去</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
|
||||
|
|
|
@ -72,9 +72,9 @@ The API is used to start a subscription session by given a handle. The parameter
|
|||
The API used to get the new data from a TDengine server. It should be put in an infinite loop. The parameter <em>tsub</em> is the handle returned by <em>taos_subscribe</em>. If new data are updated, the API will return a row of the result. Otherwise, the API is blocked until new data arrives. If <em>NULL</em> pointer is returned, it means an error occurs.</p></li>
|
||||
<li><p><code>void taos_unsubscribe(TAOS_SUB *tsub)</code>
|
||||
Stop a subscription session by the handle returned by <em>taos_subscribe</em>.</p></li>
|
||||
<li><p><code>int taos_num_subfields(TAOS_SUB *tsub)</code>
|
||||
<li><p><code>int taos_num_fields(TAOS_SUB *tsub)</code>
|
||||
The API used to get the number of fields in a row.</p></li>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_subfields(TAOS_RES *res)</code>
|
||||
<li><p><code>TAOS_FIELD *taos_fetch_fields(TAOS_RES *res)</code>
|
||||
The API used to get the description of each column.</p></li>
|
||||
</ul>
|
||||
<a class='anchor' id='Java-Connector'></a><h2>Java Connector</h2>
|
||||
|
@ -351,4 +351,4 @@ promise2.then(function(result) {
|
|||
})</code></pre>
|
||||
<h3>Example</h3>
|
||||
<p>An example of using the NodeJS connector to create a table with weather data and create and execute queries can be found <a href="https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example.js">here</a> (The preferred method for using the connector)</p>
|
||||
<p>An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found <a href="https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js">here</a></p><a href='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
|
||||
<p>An example of using the NodeJS connector to achieve the same things but without all the object wrappers that wrap around the data returned to achieve higher functionality can be found <a href="https://github.com/taosdata/TDengine/tree/master/tests/examples/nodejs/node-example-raw.js">here</a></p><a href='../index.html'>Back</a></section></main></div><?php include($s.'/footer.php'); ?><script>$('pre').addClass('prettyprint linenums');PR.prettyPrint()</script><script src='lib/docs/liner.js'></script></body></html>
|
||||
|
|
|
@ -11,7 +11,7 @@ TDengine的模块之一是时序数据库。但除此之外,为减少研发的
|
|||
* __全栈时序数据处理引擎__:将数据库、消息队列、缓存、流式计算等功能融为一体,应用无需再集成Kafka/Redis/HBase/Spark/HDFS等软件,大幅降低应用开发和维护的复杂度成本。
|
||||
* __强大的分析功能__:无论是十年前还是一秒钟前的数据,指定时间范围即可查询。数据可在时间轴上或多个设备上进行聚合。即席查询可通过Shell, Python, R, Matlab随时进行。
|
||||
* __与第三方工具无缝连接__:不用一行代码,即可与Telegraf, Grafana, EMQ, Prometheus, Matlab, R等集成。后续将支持OPC, Hadoop, Spark等, BI工具也将无缝连接。
|
||||
* __零运维成本、零学习成本__:安装、集群一秒搞定,无需分库分表,实时备份。标准SQL,支持JDBC, RESTful, 支持Python/Java/C/C++/Go, 与MySQL相似,零学习成本。
|
||||
* __零运维成本、零学习成本__:安装集群简单快捷,无需分库分表,实时备份。类似标准SQL,支持RESTful, 支持Python/Java/C/C++/C#/Go/Node.js, 与MySQL相似,零学习成本。
|
||||
|
||||
采用TDengine,可将典型的物联网、车联网、工业互联网大数据平台的总拥有成本大幅降低。但需要指出的是,因充分利用了物联网时序数据的特点,它无法用来处理网络爬虫、微博、微信、电商、ERP、CRM等通用型数据。
|
||||
|
||||
|
|
|
@ -30,13 +30,13 @@ TDengine软件分为服务器、客户端和报警模块三部分,目前2.0版
|
|||
|
||||
- TDengine-alert-2.0.0-Linux-x64.tar.gz (8.1M)
|
||||
|
||||
目前,TDengine只支持在使用[`systemd`](https://en.wikipedia.org/wiki/Systemd)做进程服务管理的linux系统上安装。其他linux系统的支持正在开发中。用`which`命令来检测系统中是否存在`systemd`:
|
||||
目前,TDengine只支持在使用[`systemd`](https://en.wikipedia.org/wiki/Systemd)做进程服务管理的linux系统上安装。其他linux系统的支持正在开发中。用`which systemctl`命令来检测系统中是否存在`systemd`包:
|
||||
|
||||
```cmd
|
||||
which systemd
|
||||
which systemctl
|
||||
```
|
||||
|
||||
如果系统中不存在`systemd`命令,请考虑[通过源码安装](#通过源码安装)TDengine。
|
||||
如果系统中不存在`systemd`包,请考虑[通过源码安装](#通过源码安装)TDengine。
|
||||
|
||||
具体的安装过程,请参见<a href="https://www.taosdata.com/blog/2019/08/09/566.html">TDengine多种安装包的安装和卸载</a>。
|
||||
|
||||
|
@ -68,7 +68,7 @@ systemctl status taosd
|
|||
taos
|
||||
```
|
||||
|
||||
如果TDengine终端链接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印错误消息出来(请参考[FAQ](https://www.taosdata.com/cn/faq/)来解决终端链接服务端失败的问题)。TDengine终端的提示符号如下:
|
||||
如果TDengine终端连接服务成功,将会打印出欢迎消息和版本信息。如果失败,则会打印错误消息出来(请参考[FAQ](https://www.taosdata.com/cn/faq/)来解决终端连接服务端失败的问题)。TDengine终端的提示符号如下:
|
||||
|
||||
```cmd
|
||||
taos>
|
||||
|
@ -99,8 +99,8 @@ Query OK, 2 row(s) in set (0.001700s)
|
|||
- -c, --config-dir: 指定配置文件目录,默认为_/etc/taos_
|
||||
- -h, --host: 指定服务的IP地址,默认为本地服务
|
||||
- -s, --commands: 在不进入终端的情况下运行TDengine命令
|
||||
- -u, -- user: 链接TDengine服务器的用户名,缺省为root
|
||||
- -p, --password: 链接TDengine服务器的密码,缺省为taosdata
|
||||
- -u, -- user: 连接TDengine服务器的用户名,缺省为root
|
||||
- -p, --password: 连接TDengine服务器的密码,缺省为taosdata
|
||||
- -?, --help: 打印出所有命令行参数
|
||||
|
||||
示例:
|
||||
|
|
|
@ -16,13 +16,13 @@ Three different packages are provided, please pick up the one you like.
|
|||
<li><a id='tdengine-deb' style='color:var(--b2)'>TDengine DEB package (1.7M)</a></li>
|
||||
<li><a id='tdengine-tar' style='color:var(--b2)'>TDengine Tarball (3.0M)</a></li>
|
||||
</ul>
|
||||
For the time being, TDengine only supports installation on Linux systems using [`systemd`](https://en.wikipedia.org/wiki/Systemd) as the service manager. To check if your system has *systemd*, use the _which_ command.
|
||||
For the time being, TDengine only supports installation on Linux systems using [`systemd`](https://en.wikipedia.org/wiki/Systemd) as the service manager. To check if your system has *systemd* package, use the _which systemctl_ command.
|
||||
|
||||
```cmd
|
||||
which systemd
|
||||
which systemctl
|
||||
```
|
||||
|
||||
If the `systemd` command is not found, please [install from source code](#Install-from-Source).
|
||||
If the `systemd` package is not found, please [install from source code](#Install-from-Source).
|
||||
|
||||
### Running TDengine
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@ CREATE DATABASE power KEEP 365 DAYS 10 BLOCKS 4;
|
|||
USE power;
|
||||
```
|
||||
|
||||
就当前链接里操作的库换为power,否则对具体表操作前,需要使用“库名.表名”来指定库的名字。
|
||||
就当前连接里操作的库换为power,否则对具体表操作前,需要使用“库名.表名”来指定库的名字。
|
||||
|
||||
**注意:**
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ TDengine是基于硬件、软件系统不可靠、一定会有故障的假设进
|
|||
|
||||
**对外服务地址**:TDengine集群可以容纳单台、多台甚至几千台物理节点。应用只需要向集群中任何一个物理节点的publicIp发起连接即可。启动CLI应用taos时,选项-h需要提供的就是publicIp。
|
||||
|
||||
**master/secondIp**:每一个dnode都需要配置一个masterIp。dnode启动后,将对配置的masterIp发起加入集群的连接请求。masterIp是已经创建的集群中的任何一个节点的privateIp,对于集群中的第一个节点,就是它自己的privateIp。为保证连接成功,每个dnode还可配置secondIp, 该IP地址也是已创建的集群中的任何一个节点的privateIp。如果一个节点连接masterIp失败,它将试图链接secondIp。
|
||||
**master/secondIp**:每一个dnode都需要配置一个masterIp。dnode启动后,将对配置的masterIp发起加入集群的连接请求。masterIp是已经创建的集群中的任何一个节点的privateIp,对于集群中的第一个节点,就是它自己的privateIp。为保证连接成功,每个dnode还可配置secondIp, 该IP地址也是已创建的集群中的任何一个节点的privateIp。如果一个节点连接masterIp失败,它将试图连接secondIp。
|
||||
|
||||
dnode启动后,会获知集群的mnode IP列表,并且定时向mnode发送状态信息。
|
||||
|
||||
|
@ -245,4 +245,4 @@ vnode(虚拟数据节点)保存采集的时序数据,而且查询、计算都
|
|||
|
||||
|
||||
|
||||
**Note:**目前集群功能仅仅限于企业版
|
||||
**Note:**目前集群功能仅仅限于企业版
|
||||
|
|
|
@ -29,23 +29,9 @@ Query OK, 2 row(s) in set (0.001100s)
|
|||
具体的查询语法请看<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>。
|
||||
|
||||
## 多表聚合查询
|
||||
物联网场景中,往往同一个类型的数据采集点有多个。TDengine采用超级表(STable)的概念来描述某一个类型的数据采集点,一张普通的表来描述一个具体的数据采集点。同时TDengine使用标签来描述数据采集点的静态属性,一个具体的数据采集点有具体的标签值。通过指定标签的过滤条件,TDengine提供了一高效的方法将超级表(某一类型的数据采集点)所属的子表进行聚合查询。对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样。
|
||||
|
||||
TDengine对每个数据采集点单独建表,但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是包含多张表的表集合,集合里每张表的模式(schema)完全一致,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。
|
||||
|
||||
应用可通过指定标签的过滤条件,对一个STable下的全部或部分表进行聚合或统计操作,这样大大简化应用的开发。其具体流程如下图所示:
|
||||
|
||||
<center> <img src="../assets/stable.png"> </center>
|
||||
|
||||
<center> 多表聚合查询原理图 </center>
|
||||
|
||||
1:应用将一个查询条件发往系统;2: taosc将超级表的名字发往 Meta Node(管理节点);3:管理节点将超级表所拥有的 vnode 列表发回 taosc;4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
|
||||
|
||||
由于TDengine在vnode内将标签数据与时序数据分离存储,通过先在内存里过滤标签数据,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。
|
||||
|
||||
对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看 TAOS SQL。
|
||||
|
||||
比如:在TAOS Shell,查找所有智能电表采集的电压平均值,并按照location分组
|
||||
|
||||
**示例1**:在TAOS Shell,查找北京所有智能电表采集的电压平均值,并按照location分组
|
||||
```mysql
|
||||
taos> SELECT AVG(voltage) FROM meters GROUP BY location;
|
||||
avg(voltage) | location |
|
||||
|
@ -55,6 +41,18 @@ taos> SELECT AVG(voltage) FROM meters GROUP BY location;
|
|||
Query OK, 2 row(s) in set (0.002136s)
|
||||
```
|
||||
|
||||
**示例2**:在TAOS shell, 查找groupId为2的所有智能电表过去24小时的记录条数,电流的最大值
|
||||
|
||||
```mysql
|
||||
taos> SELECT count(*), max(current) FROM meters where groupId = 2 and ts > now - 24h;
|
||||
cunt(*) | max(current) |
|
||||
==================================
|
||||
5 | 13.4 |
|
||||
Query OK, 1 row(s) in set (0.002136s)
|
||||
```
|
||||
|
||||
TDengine仅容许对属于同一个超级表的表之间进行聚合查询,不同超级表之间的聚合查询不支持。在<a href="https://www.taosdata.com/cn/documentation20/taos-sql/">TAOS SQL </a>一章,查询类操作都会注明是否支持超级表。
|
||||
|
||||
## 降采样查询、插值
|
||||
|
||||
物联网场景里,经常需要通过降采样(down sampling)将采集的数据按时间段进行聚合。TDengine 提供了一个简便的关键词 interval 让按照时间窗口的查询操作变得极为简单。比如,将智能电表 d1001 采集的电流值每10秒钟求和
|
||||
|
@ -66,9 +64,9 @@ taos> SELECT sum(current) FROM d1001 INTERVAL(10s);
|
|||
2018-10-03 14:38:10.000 | 24.900000572 |
|
||||
Query OK, 2 row(s) in set (0.000883s)
|
||||
```
|
||||
降采样操作也适用于超级表,比如:将所有智能电表采集的电流值每秒钟求和
|
||||
降采样操作也适用于超级表,比如:将北京所有智能电表采集的电流值每秒钟求和
|
||||
```mysql
|
||||
taos> SELECT SUM(current) FROM meters INTERVAL(1s);
|
||||
taos> SELECT SUM(current) FROM meters where location like "Beijing%" INTERVAL(1s);
|
||||
ts | sum(current) |
|
||||
======================================================
|
||||
2018-10-03 14:38:04.000 | 10.199999809 |
|
||||
|
|
|
@ -98,12 +98,12 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
|
|||
KEEP参数是指修改数据文件保存的天数,缺省值为3650,取值范围[days, 365000],必须大于或等于days参数值。
|
||||
|
||||
```mysql
|
||||
ALTER DATABASE db_name QUORUM 365;
|
||||
ALTER DATABASE db_name QUORUM 2;
|
||||
```
|
||||
QUORUM参数是指数据写入成功所需要的确认数。取值范围[1, 3]。对于异步复制,quorum设为1,具有master角色的虚拟节点自己确认即可。对于同步复制,需要至少大于等于2。原则上,Quorum >=1 并且 Quorum <= replica(副本数),这个参数在启动一个同步模块实例时需要提供。
|
||||
|
||||
```mysql
|
||||
ALTER DATABASE db_name BLOCKS 365;
|
||||
ALTER DATABASE db_name BLOCKS 100;
|
||||
```
|
||||
BLOCKS参数是每个VNODE (TSDB) 中有多少cache大小的内存块,因此一个VNODE的用的内存大小粗略为(cache * blocks)。取值范围[3, 1000]。
|
||||
|
||||
|
@ -124,7 +124,8 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
|
|||
说明:
|
||||
1) 表的第一个字段必须是TIMESTAMP,并且系统自动将其设为主键;
|
||||
2) 表名最大长度为193;
|
||||
3) 表的每行长度不能超过16k个字符;
|
||||
3) 表的每行长度不能超过16k个字符;
|
||||
4) 子表名只能由字母、数字和下划线组成,且不能以数字开头
|
||||
5) 使用数据类型binary或nchar,需指定其最长的字节数,如binary(20),表示20字节;
|
||||
|
||||
- **删除数据表**
|
||||
|
|
|
@ -82,8 +82,7 @@ TDengine系统后台服务由taosd提供,可以在配置文件taos.cfg里修
|
|||
|
||||
下面仅仅列出一些重要的配置参数,更多的参数请看配置文件里的说明。各个参数的详细介绍及作用请看前述章节,而且这些参数的缺省配置都是工作的,一般无需设置。**注意:配置修改后,需要重启*taosd*服务才能生效。**
|
||||
|
||||
- firstEp: taosd启动时,主动连接的集群中第一个dnode的end point, 默认值为localhost:6030。
|
||||
- secondEp: taosd启动时,如果first连接不上,尝试连接集群中第二个dnode的end point, 默认值为空。
|
||||
- firstEp: taosd启动时,主动连接的集群中首个dnode的end point, 默认值为localhost:6030。
|
||||
- fqdn:数据节点的FQDN,缺省为操作系统配置的第一个hostname。如果习惯IP地址访问,可设置为该节点的IP地址。
|
||||
- serverPort:taosd启动后,对外服务的端口号,默认值为6030。
|
||||
- httpPort: RESTful服务使用的端口号,所有的HTTP请求(TCP)都需要向该接口发起查询/写入请求, 默认值为6041。
|
||||
|
@ -130,9 +129,25 @@ TDengine集群中加入一个新的dnode时,涉及集群相关的一些参数
|
|||
- statusInterval: dnode向mnode报告状态时长。单位为秒,默认值:1。
|
||||
- maxTablesPerVnode: 每个vnode中能够创建的最大表个数。默认值:1000000。
|
||||
- maxVgroupsPerDb: 每个数据库中能够使用的最大vnode个数。
|
||||
- arbitrator: 系统中裁决器的end point,缺省为空
|
||||
- arbitrator: 系统中裁决器的end point,缺省为空。
|
||||
- timezone、locale、charset 的配置见客户端配置。
|
||||
|
||||
为方便调试,可通过SQL语句临时调整每个dnode的日志配置,系统重启后会失效:
|
||||
|
||||
```mysql
|
||||
ALTER DNODE <dnode_id> <config>
|
||||
```
|
||||
|
||||
- dnode_id: 可以通过SQL语句"SHOW DNODES"命令获取
|
||||
- config: 要调整的日志参数,在如下列表中取值
|
||||
> resetlog 截断旧日志文件,创建一个新日志文件
|
||||
> debugFlag < 131 | 135 | 143 > 设置debugFlag为131、135或者143
|
||||
|
||||
例如:
|
||||
```
|
||||
alter dnode 1 debugFlag 135;
|
||||
```
|
||||
|
||||
## 客户端配置
|
||||
|
||||
TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同一个配置文件taos.cfg。运行taos时,使用参数-c指定配置文件目录,如taos -c /home/cfg,表示使用/home/cfg/目录下的taos.cfg配置文件中的参数,缺省目录是/etc/taos。本节主要说明 taos 客户端应用在配置文件 taos.cfg 文件中使用到的参数。
|
||||
|
@ -140,76 +155,80 @@ TDengine系统的前台交互客户端应用程序为taos,它与taosd共享同
|
|||
客户端配置参数
|
||||
|
||||
- firstEp: taos启动时,主动连接的集群中第一个taosd实例的end point, 缺省值为 localhost:6030。
|
||||
- secondEp: taos启动时,如果first连接不上,尝试连接集群中第二个taosd实例的end point, 缺省值为空。
|
||||
- locale
|
||||
|
||||
> 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置
|
||||
默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置
|
||||
|
||||
TDengine为存储中文、日文、韩文等非ASCII编码的宽字符,提供一种专门的字段类型nchar。写入nchar字段的数据将统一采用UCS4-LE格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用nchar字段来存储诸如中文、日文、韩文等非ASCII字符,需要正确设置客户端的编码格式。
|
||||
TDengine为存储中文、日文、韩文等非ASCII编码的宽字符,提供一种专门的字段类型nchar。写入nchar字段的数据将统一采用UCS4-LE格式进行编码并发送到服务器。需要注意的是,编码正确性是客户端来保证。因此,如果用户想要正常使用nchar字段来存储诸如中文、日文、韩文等非ASCII字符,需要正确设置客户端的编码格式。
|
||||
|
||||
客户端的输入的字符均采用操作系统当前默认的编码格式,在Linux系统上多为UTF-8,部分中文系统编码则可能是GB18030或GBK等。在docker环境中默认的编码是POSIX。在中文版Windows系统中,编码则是CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证nchar中的数据正确转换为UCS4-LE编码格式。
|
||||
客户端的输入的字符均采用操作系统当前默认的编码格式,在Linux系统上多为UTF-8,部分中文系统编码则可能是GB18030或GBK等。在docker环境中默认的编码是POSIX。在中文版Windows系统中,编码则是CP936。客户端需要确保正确设置自己所使用的字符集,即客户端运行的操作系统当前编码字符集,才能保证nchar中的数据正确转换为UCS4-LE编码格式。
|
||||
|
||||
在 Linux 中 locale 的命名规则为: <语言>_<地区>.<字符集编码> 如:zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux系统与 Mac OSX 系统可以通过设置locale来确定系统的字符编码,由于Windows使用的locale中不是POSIX标准的locale格式,因此在Windows下需要采用另一个配置参数charset来指定字符编码。在Linux 系统中也可以使用charset来指定字符编码。
|
||||
在 Linux 中 locale 的命名规则为: <语言>_<地区>.<字符集编码> 如:zh_CN.UTF-8,zh代表中文,CN代表大陆地区,UTF-8表示字符集。字符集编码为客户端正确解析本地字符串提供编码转换的说明。Linux系统与 Mac OSX 系统可以通过设置locale来确定系统的字符编码,由于Windows使用的locale中不是POSIX标准的locale格式,因此在Windows下需要采用另一个配置参数charset来指定字符编码。在Linux 系统中也可以使用charset来指定字符编码。
|
||||
|
||||
- charset
|
||||
|
||||
> 默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置
|
||||
默认值:系统中动态获取,如果自动获取失败,需要用户在配置文件设置或通过API设置
|
||||
|
||||
如果配置文件中不设置charset,在Linux系统中,taos在启动时候,自动读取系统当前的locale信息,并从locale信息中解析提取charset编码格式。如果自动读取locale信息失败,则尝试读取charset配置,如果读取charset配置也失败,则中断启动过程。
|
||||
如果配置文件中不设置charset,在Linux系统中,taos在启动时候,自动读取系统当前的locale信息,并从locale信息中解析提取charset编码格式。如果自动读取locale信息失败,则尝试读取charset配置,如果读取charset配置也失败,则中断启动过程。
|
||||
|
||||
在Linux系统中,locale信息包含了字符编码信息,因此正确设置了Linux系统locale以后可以不用再单独设置charset。例如:
|
||||
```
|
||||
在Linux系统中,locale信息包含了字符编码信息,因此正确设置了Linux系统locale以后可以不用再单独设置charset。例如:
|
||||
```
|
||||
locale zh_CN.UTF-8
|
||||
```
|
||||
在Windows系统中,无法从locale获取系统当前编码。如果无法从配置文件中读取字符串编码信息,taos默认设置为字符编码为CP936。其等效在配置文件中添加如下配置:
|
||||
```
|
||||
```
|
||||
在Windows系统中,无法从locale获取系统当前编码。如果无法从配置文件中读取字符串编码信息,taos默认设置为字符编码为CP936。其等效在配置文件中添加如下配置:
|
||||
```
|
||||
charset CP936
|
||||
```
|
||||
如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。
|
||||
```
|
||||
如果需要调整字符编码,请查阅当前操作系统使用的编码,并在配置文件中正确设置。
|
||||
|
||||
在Linux系统中,如果用户同时设置了locale和字符集编码charset,并且locale和charset的不一致,后设置的值将覆盖前面设置的值。
|
||||
```
|
||||
在Linux系统中,如果用户同时设置了locale和字符集编码charset,并且locale和charset的不一致,后设置的值将覆盖前面设置的值。
|
||||
```
|
||||
locale zh_CN.UTF-8
|
||||
charset GBK
|
||||
```
|
||||
则charset的有效值是GBK。
|
||||
```
|
||||
```
|
||||
则charset的有效值是GBK。
|
||||
```
|
||||
charset GBK
|
||||
locale zh_CN.UTF-8
|
||||
```
|
||||
charset的有效值是UTF-8。
|
||||
```
|
||||
charset的有效值是UTF-8。
|
||||
|
||||
日志的配置参数,与server 的配置参数完全一样。
|
||||
日志的配置参数,与server 的配置参数完全一样。
|
||||
|
||||
- timezone
|
||||
|
||||
默认值:从系统中动态获取当前的时区设置
|
||||
|
||||
客户端运行系统所在的时区。为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。
|
||||
客户端运行系统所在的时区。为应对多时区的数据写入和查询问题,TDengine 采用 Unix 时间戳(Unix Timestamp)来记录和存储时间戳。Unix 时间戳的特点决定了任一时刻不论在任何时区,产生的时间戳均一致。需要注意的是,Unix时间戳是在客户端完成转换和记录。为了确保客户端其他形式的时间转换为正确的 Unix 时间戳,需要设置正确的时区。
|
||||
|
||||
在Linux系统中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如:
|
||||
```
|
||||
在Linux系统中,客户端会自动读取系统设置的时区信息。用户也可以采用多种方式在配置文件设置时区。例如:
|
||||
```
|
||||
timezone UTC-8
|
||||
timezone GMT-8
|
||||
timezone Asia/Shanghai
|
||||
```
|
||||
均是合法的设置东八区时区的格式。
|
||||
```
|
||||
均是合法的设置东八区时区的格式。
|
||||
|
||||
时区的设置对于查询和写入SQL语句中非Unix时间戳的内容(时间戳字符串、关键词now的解析)产生影响。例如:
|
||||
```
|
||||
时区的设置对于查询和写入SQL语句中非Unix时间戳的内容(时间戳字符串、关键词now的解析)产生影响。例如:
|
||||
```
|
||||
SELECT count(*) FROM table_name WHERE TS<'2019-04-11 12:01:08';
|
||||
```
|
||||
在东八区,SQL语句等效于
|
||||
```
|
||||
```
|
||||
在东八区,SQL语句等效于
|
||||
```
|
||||
SELECT count(*) FROM table_name WHERE TS<1554955268000;
|
||||
```
|
||||
在UTC时区,SQL语句等效于
|
||||
```
|
||||
```
|
||||
在UTC时区,SQL语句等效于
|
||||
```
|
||||
SELECT count(*) FROM table_name WHERE TS<1554984068000;
|
||||
```
|
||||
为了避免使用字符串时间格式带来的不确定性,也可以直接使用Unix时间戳。此外,还可以在SQL语句中使用带有时区的时间戳字符串,例如:RFC3339格式的时间戳字符串,2013-04-12T15:52:01.123+08:00或者ISO-8601格式时间戳字符串2013-04-12T15:52:01.123+0800。上述两个字符串转化为Unix时间戳不受系统所在时区的影响。
|
||||
```
|
||||
为了避免使用字符串时间格式带来的不确定性,也可以直接使用Unix时间戳。此外,还可以在SQL语句中使用带有时区的时间戳字符串,例如:RFC3339格式的时间戳字符串,2013-04-12T15:52:01.123+08:00或者ISO-8601格式时间戳字符串2013-04-12T15:52:01.123+0800。上述两个字符串转化为Unix时间戳不受系统所在时区的影响。
|
||||
|
||||
启动taos时,也可以从命令行指定一个taosd实例的end point,否则就从taos.cfg读取。
|
||||
启动taos时,也可以从命令行指定一个taosd实例的end point,否则就从taos.cfg读取。
|
||||
|
||||
- maxBinaryDisplayWidth
|
||||
|
||||
Shell中binary 和 nchar字段的显示宽度上限,超过此限制的部分将被隐藏。默认值:30。可在 shell 中通过命令 set max_binary_display_width nn 动态修改此选项。
|
||||
|
||||
|
||||
## 用户管理
|
||||
|
||||
|
@ -233,6 +252,12 @@ ALTER USER <user_name> PASS <'password'>;
|
|||
|
||||
修改用户密码, 为避免被转换为小写,密码需要用单引号引用,单引号为英文半角
|
||||
|
||||
```
|
||||
ALTER USER <user_name> PRIVILEDGE <super|write|read>;
|
||||
```
|
||||
|
||||
修改用户权限为:super/write/read,不需要添加单引号
|
||||
|
||||
```
|
||||
SHOW USERS;
|
||||
```
|
||||
|
@ -356,7 +381,7 @@ KILL STREAM <stream-id>;
|
|||
|
||||
## 系统监控
|
||||
|
||||
TDengine启动后,会自动创建一个监测数据库SYS,并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作(比如登录、创建、删除数据库等)日志以及各种错误报警信息记录下来存放在SYS库里。系统管理员可以从CLI直接查看这个数据库,也可以在WEB通过图形化界面查看这些监测信息。
|
||||
TDengine启动后,会自动创建一个监测数据库log,并自动将服务器的CPU、内存、硬盘空间、带宽、请求数、磁盘读写速度、慢查询等信息定时写入该数据库。TDengine还将重要的系统操作(比如登录、创建、删除数据库等)日志以及各种错误报警信息记录下来存放在log库里。系统管理员可以从CLI直接查看这个数据库,也可以在WEB通过图形化界面查看这些监测信息。
|
||||
|
||||
这些监测信息的采集缺省是打开的,但可以修改配置文件里的选项enableMonitor将其关闭或打开。
|
||||
|
||||
|
@ -387,4 +412,3 @@ TDengine的所有可执行文件默认存放在 _/usr/local/taos/bin_ 目录下
|
|||
您可以通过修改系统配置文件taos.cfg来配置不同的数据目录和日志目录。
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ create table D1002 using meters tags ("Beijing.Haidian", 2);
|
|||
我们已经知道,可以通过下面这条SQL语句以一分钟为时间窗口、30秒为前向增量统计这些电表的平均电压。
|
||||
|
||||
```sql
|
||||
select avg(voltage) from meters interval(1m) sliding(30s);
|
||||
select avg(voltage) from meters interval(1m) sliding(30s);
|
||||
```
|
||||
|
||||
每次执行这条语句,都会重新计算所有数据。
|
||||
|
@ -47,14 +47,14 @@ select avg(voltage) from meters interval(1m) sliding(30s);
|
|||
可以把上面的语句改进成下面的样子,每次使用不同的 `startTime` 并定期执行:
|
||||
|
||||
```sql
|
||||
select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s);
|
||||
select avg(voltage) from meters where ts > {startTime} interval(1m) sliding(30s);
|
||||
```
|
||||
|
||||
这样做没有问题,但TDengine提供了更简单的方法,
|
||||
只要在最初的查询语句前面加上 `create table {tableName} as ` 就可以了, 例如:
|
||||
|
||||
```sql
|
||||
create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s);
|
||||
create table avg_vol as select avg(voltage) from meters interval(1m) sliding(30s);
|
||||
```
|
||||
|
||||
会自动创建一个名为 `avg_vol` 的新表,然后每隔30秒,TDengine会增量执行 `as` 后面的 SQL 语句,
|
||||
|
@ -80,7 +80,7 @@ taos> select * from avg_vol;
|
|||
比如使用下面的SQL创建的连续查询将运行一小时,之后会自动停止。
|
||||
|
||||
```sql
|
||||
create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s);
|
||||
create table avg_vol as select avg(voltage) from meters where ts > now and ts <= now + 1h interval(1m) sliding(30s);
|
||||
```
|
||||
|
||||
需要说明的是,上面例子中的 `now` 是指创建连续查询的时间,而不是查询执行的时间,否则,查询就无法自动停止了。
|
||||
|
@ -396,7 +396,7 @@ ts: 1597465200000 current: 11.2 voltage: 220 phase: 1 location: Beijing.Haidian
|
|||
|
||||
```sql
|
||||
# taos
|
||||
taos> use power;
|
||||
taos> use power;
|
||||
taos> insert into d1001 values("2020-08-15 12:40:00.000", 12.4, 220, 1);
|
||||
```
|
||||
|
||||
|
|
|
@ -65,36 +65,36 @@ TDengine 的设计是基于单个硬件、软件系统不可靠,基于任何
|
|||
TDengine 分布式架构的逻辑结构图如下:
|
||||
<center> <img src="../assets/structure.png"> </center>
|
||||
<center> 图 1 TDengine架构示意图 </center>
|
||||
一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine客户端(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过taosc的API与TDengine集群进行互动。下面对每个逻辑单元进行简要介绍。
|
||||
一个完整的 TDengine 系统是运行在一到多个物理节点上的,逻辑上,它包含数据节点(dnode)、TDengine应用驱动(taosc)以及应用(app)。系统中存在一到多个数据节点,这些数据节点组成一个集群(cluster)。应用通过taosc的API与TDengine集群进行互动。下面对每个逻辑单元进行简要介绍。
|
||||
|
||||
**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》。
|
||||
**物理节点(pnode):** pnode是一独立运行、拥有自己的计算、存储和网络能力的计算机,可以是安装有OS的物理机、虚拟机或Docker容器。物理节点由其配置的 FQDN(Fully Qualified Domain Name)来标识。TDengine完全依赖FQDN来进行网络通讯,如果不了解FQDN,请看博文《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》。
|
||||
|
||||
**数据节点(dnode):** dnode 是 TDengine 服务器侧执行代码 taosd 在物理节点上的一个运行实例,一个工作的系统必须有至少一个数据节点。dnode包含零到多个逻辑的虚拟节点(VNODE),零或者至多一个逻辑的管理节点(mnode)。dnode在系统中的唯一标识由实例的End Point (EP )决定。EP是dnode所在物理节点的FQDN (Fully Qualified Domain Name)和系统所配置的网络端口号(Port)的组合。通过配置不同的端口,一个物理节点(一台物理机、虚拟机或容器)可以运行多个实例,或有多个数据节点。
|
||||
|
||||
**虚拟节点(vnode)**: 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode,图中V2, V3, V4等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个DB,但一个DB可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的SCHEMA、标签值等。一个虚拟节点由所属的数据节点的EP,以及所属的VGroup ID在系统内唯一标识,由管理节点创建并管理。
|
||||
**虚拟节点(vnode)**: 为更好的支持数据分片、负载均衡,防止数据过热或倾斜,数据节点被虚拟化成多个虚拟节点(vnode,图中V2, V3, V4等)。每个 vnode 都是一个相对独立的工作单元,是时序数据存储的基本单元,具有独立的运行线程、内存空间与持久化存储的路径。一个 vnode 包含一定数量的表(数据采集点)。当创建一张新表时,系统会检查是否需要创建新的 vnode。一个数据节点上能创建的 vnode 的数量取决于该数据节点所在物理节点的硬件资源。一个 vnode 只属于一个DB,但一个DB可以有多个 vnode。一个 vnode 除存储的时序数据外,也保存有所包含的表的schema、标签值等。一个虚拟节点由所属的数据节点的EP,以及所属的VGroup ID在系统内唯一标识,由管理节点创建并管理。
|
||||
|
||||
**管理节点(mnode):** 一个虚拟的逻辑单元,负责所有数据节点运行状态的监控和维护,以及节点之间的负载均衡(图中M)。同时,管理节点也负责元数据(包括用户、数据库、表、静态标签等)的存储和管理,因此也称为 Meta Node。TDengine 集群中可配置多个(最多不超过5个) mnode,它们自动构建成为一个虚拟管理节点组(图中M0, M1, M2)。mnode 间采用 master/slave 的机制进行管理,而且采取强一致方式进行数据同步, 任何数据更新操作只能在 Master 上进行。mnode 集群的创建由系统自动完成,无需人工干预。每个dnode上至多有一个mnode,由所属的数据节点的EP来唯一标识。每个dnode通过内部消息交互自动获取整个集群中所有 mnode 所在的 dnode 的EP。
|
||||
|
||||
**虚拟节点组(VGroup):** 不同数据节点上的 vnode 可以组成一个虚拟节点组(vnode group)来保证系统的高可靠。虚拟节点组内采取master/slave的方式进行管理。写操作只能在 master vnode 上进行,系统采用异步复制的方式将数据同步到 slave vnode,这样确保了一份数据在多个物理节点上有拷贝。一个 vgroup 里虚拟节点个数就是数据的副本数。如果一个DB的副本数为N,系统必须有至少N个数据节点。副本数在创建DB时通过参数 replica 可以指定,缺省为1。使用 TDengine 的多副本特性,可以不再需要昂贵的磁盘阵列等存储设备,就可以获得同样的数据高可靠性。虚拟节点组由管理节点创建、管理,并且由管理节点分配一个系统唯一的ID,VGroup ID。如果两个虚拟节点的vnode group ID相同,说明他们属于同一个组,数据互为备份。虚拟节点组里虚拟节点的个数是可以动态改变的,容许只有一个,也就是没有数据复制。VGroup ID是永远不变的,即使一个虚拟节点组被删除,它的ID也不会被收回重复利用。
|
||||
|
||||
**TAOSC:** taosc是TDengine给应用提供的驱动程序(driver),负责处理应用与集群的接口交互,内嵌于JDBC、ODBC driver中,或者C、Python、Go语言连接库里。应用都是通过taosc而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于JDBC, ODBC, C/C++接口而言,这个模块是在应用所处的物理节点上运行,但消耗的资源很小。同时,为支持全分布式的RESTful接口,taosc在TDengine集群的每个dnode上都有一运行实例。
|
||||
**TAOSC:** taosc是TDengine给应用提供的驱动程序(driver),负责处理应用与集群的接口交互,提供C/C++语言原生接口,内嵌于JDBC、C#、Python、Go、Node.js语言连接库里。应用都是通过taosc而不是直接连接集群中的数据节点与整个集群进行交互的。这个模块负责获取并缓存元数据;将插入、查询等请求转发到正确的数据节点;在把结果返回给应用时,还需要负责最后一级的聚合、排序、过滤等操作。对于JDBC, C/C++/C#/Python/Go/Node.js接口而言,这个模块是在应用所处的物理节点上运行。同时,为支持全分布式的RESTful接口,taosc在TDengine集群的每个dnode上都有一运行实例。
|
||||
|
||||
### 节点之间的通讯
|
||||
**通讯方式:**TDengine系统的各个节点之间的通讯是通过TCP/UDP进行的。因为考虑到物联网场景,数据写入的包一般不大,因此TDengine 除采用TCP做传输之外,还采用UDP方式,因为UDP 更加高效,而且不受连接数的限制。TDengine实现了自己的超时、重传、确认等机制,以确保UDP的可靠传输。对于数据量不到15K的数据包,采取UDP的方式进行传输,超过15K的,或者是查询类的操作,自动采取TCP的方式进行传输。同时,TDengine根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制,只采用TCP方式进行数据传输。
|
||||
**通讯方式:**TDengine系统的各个数据节点之间,以及应用驱动与各数据节点之间的通讯是通过TCP/UDP进行的。因为考虑到物联网场景,数据写入的包一般不大,因此TDengine 除采用TCP做传输之外,还采用UDP方式,因为UDP 更加高效,而且不受连接数的限制。TDengine实现了自己的超时、重传、确认等机制,以确保UDP的可靠传输。对于数据量不到15K的数据包,采取UDP的方式进行传输,超过15K的,或者是查询类的操作,自动采取TCP的方式进行传输。同时,TDengine根据配置和数据包,会自动对数据进行压缩/解压缩,数字签名/认证等处理。对于数据节点之间的数据复制,只采用TCP方式进行数据传输。
|
||||
|
||||
**FQDN配置**:一个数据节点有一个或多个FQDN,可以在系统配置文件taos.cfg通过参数“fqdn"进行指定,如果没有指定,系统将自动获取FQDN。如果节点没有配置FQDN,可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP,因为IP地址可变,一旦变化,将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN,需要保证DNS服务正常工作,或者在节点以及应用所在的节点配置好hosts文件。
|
||||
**FQDN配置**:一个数据节点有一个或多个FQDN,可以在系统配置文件taos.cfg通过参数“fqdn"进行指定,如果没有指定,系统将自动获取计算机的hostname作为其FQDN。如果节点没有配置FQDN,可以直接将该节点的配置参数fqdn设置为它的IP地址。但不建议使用IP,因为IP地址可变,一旦变化,将让集群无法正常工作。一个数据节点的EP(End Point)由FQDN + Port组成。采用FQDN,需要保证DNS服务正常工作,或者在节点以及应用所在的节点配置好hosts文件。
|
||||
|
||||
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定,对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口,是serverPort+10. 为支持多线程高效的处理UDP数据,每个对内和对外的UDP链接,都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10,总共11个TCP/UDP端口。使用时,需要确保防火墙将这些端口打开。每个数据节点可以配置不同的serverPort。
|
||||
**端口配置:**一个数据节点对外的端口由TDengine的系统配置参数serverPort决定,对集群内部通讯的端口是serverPort+5。集群内数据节点之间的数据复制操作还占有一个TCP端口,是serverPort+10. 为支持多线程高效的处理UDP数据,每个对内和对外的UDP连接,都需要占用5个连续的端口。因此一个数据节点总的端口范围为serverPort到serverPort + 10,总共11个TCP/UDP端口。使用时,需要确保防火墙将这些端口打开。每个数据节点可以配置不同的serverPort。
|
||||
|
||||
**集群对外链接:** TDengine集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可,链接需要提供的网络参数是一数据节点的End Point(FQDN加配置的端口号)。通过命令行CLI启动应用taos时,可以通过选项-h来指定数据节点的FQDN, -P来指定其配置的端口号,如果端口不配置,将采用TDengine的系统配置参数serverPort。
|
||||
**集群对外连接:** TDengine集群可以容纳单个、多个甚至几千个数据节点。应用只需要向集群中任何一个数据节点发起连接即可,连接需要提供的网络参数是一数据节点的End Point(FQDN加配置的端口号)。通过命令行CLI启动应用taos时,可以通过选项-h来指定数据节点的FQDN, -P来指定其配置的端口号,如果端口不配置,将采用TDengine的系统配置参数serverPort。
|
||||
|
||||
**集群内部通讯**: 各个数据节点之间通过TCP/UDP进行链接。一个数据节点启动时,将获取mnode所在的dnode的EP信息,然后与系统中的mnode建立起链接,交换信息。获取mnode的EP信息有三步,1:检查mnodeEpList文件是否存在,如果不存在或不能正常打开获得mnode EP信息,进入第二步;2:检查系统配置文件taos.cfg, 获取mnode EP配置参数first, second,如果不存在或者taos.cfg里没有这两个配置参数,或无效,进入第三步;3:将自己的EP设为mnode EP, 并独立运行起来。获取mnode EP列表后,数据节点发起链接,如果链接成功,则成功加入进工作的集群,如果不成功,则尝试mnode EP列表中的下一个。如果都尝试了,但链接都仍然失败,则休眠几秒后,再进行尝试。
|
||||
**集群内部通讯**: 各个数据节点之间通过TCP/UDP进行连接。一个数据节点启动时,将获取mnode所在的dnode的EP信息,然后与系统中的mnode建立起连接,交换信息。获取mnode的EP信息有三步,1:检查mnodeEpList文件是否存在,如果不存在或不能正常打开获得mnode EP信息,进入第二步;2:检查系统配置文件taos.cfg, 获取mnode EP配置参数first, second,如果不存在或者taos.cfg里没有这两个配置参数,或无效,进入第三步;3:将自己的EP设为mnode EP, 并独立运行起来。获取mnode EP列表后,数据节点发起连接,如果连接成功,则成功加入进工作的集群,如果不成功,则尝试mnode EP列表中的下一个。如果都尝试了,但连接都仍然失败,则休眠几秒后,再进行尝试。
|
||||
|
||||
**MNODE的选择:** TDengine逻辑上有管理节点,但没有单独的执行代码,服务器侧只有一套执行代码taosd。那么哪个数据节点会是管理节点呢?这是系统自动决定的,无需任何人工干预。原则如下:一个数据节点启动时,会检查自己的End Point, 并与获取的mnode EP List进行比对,如果在其中,该数据节点认为自己应该启动mnode模块,成为mnode。如果自己的EP不在mnode EP List里,则不启动mnode模块。在系统的运行过程中,由于负载均衡、宕机等原因,mnode有可能迁移至新的dnode,但一切都是透明的,无需人工干预,配置参数的修改,是mnode自己根据资源做出的决定。
|
||||
|
||||
**新数据节点的加入**:系统有了一个数据节点后,就已经成为一个工作的系统。添加新的节点进集群时,有两个步骤,第一步:使用TDengine CLI链接到现有工作的数据节点,然后用命令”create dnode"将新的数据节点的End Point添加进去; 第二步:在新的数据节点的系统配置参数文件taos.cfg里,将first, second参数设置为现有集群中任意两个数据节点的EP即可。具体添加的详细步骤请见详细的用户手册。这样就把集群一步一步的建立起来。
|
||||
**新数据节点的加入**:系统有了一个数据节点后,就已经成为一个工作的系统。添加新的节点进集群时,有两个步骤,第一步:使用TDengine CLI连接到现有工作的数据节点,然后用命令”create dnode"将新的数据节点的End Point添加进去; 第二步:在新的数据节点的系统配置参数文件taos.cfg里,将first, second参数设置为现有集群中任意两个数据节点的EP即可。具体添加的详细步骤请见详细的用户手册。这样就把集群一步一步的建立起来。
|
||||
|
||||
**重定向**:无论是dnode还是taosc,最先都是要发起与mnode的链接,但mnode是系统自动创建并维护的,因此对于用户来说,并不知道哪个dnode在运行mnode。TDengine只要求向系统中任何一个工作的dnode发起链接即可。因为任何一个正在运行的dnode,都维护有目前运行的mnode EP List。当收到一个来自新启动的dnode或taosc的链接请求,如果自己不是mnode,则将mnode EP List回复给对方,taosc或新启动的dnode收到这个list, 就重新尝试建立链接。当mnode EP List发生改变,通过节点之间的消息交互,各个数据节点就很快获取最新列表,并通知taosc。
|
||||
**重定向**:无论是dnode还是taosc,最先都是要发起与mnode的连接,但mnode是系统自动创建并维护的,因此对于用户来说,并不知道哪个dnode在运行mnode。TDengine只要求向系统中任何一个工作的dnode发起连接即可。因为任何一个正在运行的dnode,都维护有目前运行的mnode EP List。当收到一个来自新启动的dnode或taosc的连接请求,如果自己不是mnode,则将mnode EP List回复给对方,taosc或新启动的dnode收到这个list, 就重新尝试建立连接。当mnode EP List发生改变,通过节点之间的消息交互,各个数据节点就很快获取最新列表,并通知taosc。
|
||||
|
||||
### 一个典型的消息流程
|
||||
为解释vnode, mnode, taosc和应用之间的关系以及各自扮演的角色,下面对写入数据这个典型操作的流程进行剖析。
|
||||
|
@ -153,6 +153,7 @@ TDengine除vnode分片之外,还对时序数据按照时间段进行分区。
|
|||
当新的数据节点被添加进集群,因为新的计算和存储被添加进来,系统也将自动启动负载均衡流程。
|
||||
|
||||
负载均衡过程无需任何人工干预,应用也无需重启,将自动连接新的节点,完全透明。
|
||||
**提示:负载均衡由参数balance控制,决定开启/关闭自动负载均衡。**
|
||||
|
||||
## 数据写入与复制流程
|
||||
如果一个数据库有N个副本,那一个虚拟节点组就有N个虚拟节点,但是只有一个是Master,其他都是slave。当应用将新的记录写入系统时,只有Master vnode能接受写的请求。如果slave vnode收到写的请求,系统将通知taosc需要重新定向。
|
||||
|
@ -192,12 +193,13 @@ Master Vnode遵循下面的写入流程:
|
|||
|
||||
理论上,只要是异步复制,就无法保证100%不丢失。但是这个窗口极小,mater与slave要同时发生故障,而且发生在刚给应用确认写入成功之后。
|
||||
|
||||
注:异地容灾、IDC无中断迁移,仅仅企业版支持
|
||||
注:异地容灾、IDC无中断迁移,仅仅企业版支持。
|
||||
**提示:该功能暂未提供**
|
||||
|
||||
### 主从选择
|
||||
Vnode会保持一个数据版本号(Version),对内存数据进行持久化存储时,对该版本号也进行持久化存储。每个数据更新操作,无论是采集的时序数据还是元数据,这个版本号将增一。
|
||||
|
||||
一个vnode启动时,角色(master、slave) 是不定的,数据是处于未同步状态,它需要与虚拟节点组内其他节点建立TCP链接,并互相交换status,其中包括version和自己的角色。通过status的交换,系统进入选主流程,规则如下:
|
||||
一个vnode启动时,角色(master、slave) 是不定的,数据是处于未同步状态,它需要与虚拟节点组内其他节点建立TCP连接,并互相交换status,其中包括version和自己的角色。通过status的交换,系统进入选主流程,规则如下:
|
||||
|
||||
1. 如果只有一个副本,该副本永远就是master
|
||||
2. 所有副本都在线时,版本最高的被选为master
|
||||
|
@ -226,7 +228,7 @@ TDengine采用数据驱动的方式让缓存中的数据写入硬盘进行持久
|
|||
|
||||
为充分利用时序数据特点,TDengine将一个vnode保存在持久化存储的数据切分成多个文件,每个文件只保存固定天数的数据,这个天数由系统配置参数days决定。切分成多个文件后,给定查询的起止日期,无需任何索引,就可以立即定位需要打开哪些数据文件,大大加快读取速度。
|
||||
|
||||
对于采集的数据,一般有保留时长,这个时长由系统配置参数keep决定。超过这个设置天数的数据文件,将被系统将自动删除,释放存储空间。
|
||||
对于采集的数据,一般有保留时长,这个时长由系统配置参数keep决定。超过这个设置天数的数据文件,将被系统自动删除,释放存储空间。
|
||||
|
||||
给定days与keep两个参数,一个vnode总的数据文件数为:keep/days。总的数据文件个数不宜过大,也不宜过小。10到100以内合适。基于这个原则,可以设置合理的days。 目前的版本,参数keep可以修改,但对于参数days,一但设置后,不可修改。
|
||||
|
||||
|
@ -259,6 +261,7 @@ dataDir /mnt/disk6/taos 2
|
|||
挂载的盘也可以是非本地的网络盘,只要系统能访问即可。
|
||||
|
||||
注:多级存储功能仅企业版支持
|
||||
**提示:该功能暂未提供**
|
||||
|
||||
## 数据查询
|
||||
TDengine提供了多种多样针对表和超级表的查询处理功能,除了常规的聚合查询之外,还提供针对时序数据的窗口查询、统计聚合等功能。TDengine的查询处理需要客户端、vnode, mnode节点协同完成。
|
||||
|
@ -276,24 +279,31 @@ SQL语句的解析和校验工作在客户端完成。解析SQL语句并生成
|
|||
|
||||
在TDengine中引入关键词interval来进行时间轴上固定长度时间窗口的切分,并按照时间窗口对数据进行聚合,对窗口范围内的数据按需进行聚合。例如:
|
||||
```mysql
|
||||
select count(*) from d1001 interval(1h);
|
||||
select count(*) from d1001 interval(1h);
|
||||
```
|
||||
|
||||
针对d1001设备采集的数据,按照1小时的时间窗口返回每小时存储的记录数量。
|
||||
|
||||
在需要连续获得查询结果的应用场景下,如果给定的时间区间存在数据缺失,会导致该区间数据结果也丢失。TDengine提供策略针对时间轴聚合计算的结果进行插值,通过使用关键词Fill就能够对时间轴聚合结果进行插值。例如:
|
||||
```mysql
|
||||
select count(*) from d1001 interval(1h) fill(prev);
|
||||
select count(*) from d1001 interval(1h) fill(prev);
|
||||
```
|
||||
|
||||
针对d1001设备采集数据统计每小时记录数,如果某一个小时不存在数据,这返回之前一个小时的统计数据。TDengine提供前向插值(prev)、线性插值(linear)、NULL值填充(NULL)、特定值填充(value)。
|
||||
|
||||
### 多表聚合查询
|
||||
多表聚合查询与单表查询的整体流程相同,但是存在如下的差异:
|
||||
TDengine对每个数据采集点单独建表,但在实际应用中经常需要对不同的采集点数据进行聚合。为高效的进行聚合操作,TDengine引入超级表(STable)的概念。超级表用来代表一特定类型的数据采集点,它是包含多张表的表集合,集合里每张表的模式(schema)完全一致,但每张表都带有自己的静态标签,标签可以多个,可以随时增加、删除和修改。 应用可通过指定标签的过滤条件,对一个STable下的全部或部分表进行聚合或统计操作,这样大大简化应用的开发。其具体流程如下图所示:
|
||||
<center> <img src="../assets/multi_tables.png"> </center>
|
||||
|
||||
- 由于多表可能分布在不同的节点(dnode),因此多表的聚合查询需要首先获得表所在的全部数据节点的信息,并且同时向相关的dnode发出查询请求。
|
||||
- 每个vnode的计算获得的中间结果(partial results)需要进行第二阶段的聚合才能形成最终结果,第二阶段的聚合过程在客户端完成。
|
||||
- 由于表标签信息存储在vnode中,因此针对标签信息的查询也需要vnode完成。客户端将标签的过滤表达式封装在查询请求结构体中发送给vnode,由vnode的查询执行线程从中抽取出标签查询条件,然后执行查询。标签查询与过滤是在针对表的查询之前完成。标签查询完成以后,将符合条件的表纳入到接下来的查询处理流程中。
|
||||
<center> 图 5 多表聚合查询原理图 </center>
|
||||
1:应用将一个查询条件发往系统;
|
||||
2: taosc将超级表的名字发往 Meta Node(管理节点);
|
||||
3:管理节点将超级表所拥有的 vnode 列表发回 taosc;
|
||||
4:taosc将计算的请求连同标签过滤条件发往这些vnode对应的多个数据节点;
|
||||
5:每个vnode先在内存里查找出自己节点里符合标签过滤条件的表的集合,然后扫描存储的时序数据,完成相应的聚合计算,将结果返回给taosc;
|
||||
6:taosc将多个数据节点返回的结果做最后的聚合,将其返回给应用。
|
||||
|
||||
由于TDengine在vnode内将标签数据与时序数据分离存储,通过在内存里过滤标签数据,先找到需要参与聚合操作的表的集合,将需要扫描的数据集大幅减少,大幅提升聚合计算速度。同时,由于数据分布在多个vnode/dnode,聚合计算操作在多个vnode里并发进行,又进一步提升了聚合的速度。 对普通表的聚合函数以及绝大部分操作都适用于超级表,语法完全一样,细节请看 TAOS SQL。
|
||||
|
||||
### 预计算
|
||||
为有效提升查询处理的性能,针对物联网数据的不可更改的特点,在数据块头部记录该数据块中存储数据的统计信息:包括最大值、最小值、和。我们称之为预计算单元。如果查询处理涉及整个数据块的全部数据,直接使用预计算结果,完全不需要读取数据块的内容。由于预计算数据量远小于磁盘上存储的数据块数据的大小,对于磁盘IO为瓶颈的查询处理,使用预计算结果可以极大地减小读取IO压力,加速查询处理的流程。预计算机制与Postgre SQL的索引BRIN(block range index)有异曲同工之妙。
|
||||
|
|
|
@ -8,7 +8,7 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预
|
|||
|
||||
## 准备工作
|
||||
|
||||
**第零步**:如果没有部署DNS服务,请规划集群所有物理节点的FQDN,然后按照《[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)》里的步骤,将所有集群物理节点的IP与FQDN的对应关系添加好。
|
||||
**第零步**:规划集群所有物理节点的FQDN,将规划好的FQDN分别添加到每个物理节点的/etc/hostname;修改每个物理节点的/etc/hosts,将所有集群物理节点的IP与FQDN的对应添加好。【如部署了DNS,请联系网络管理员在DNS上做好相关配置】
|
||||
|
||||
**第一步**:如果搭建集群的物理节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html )
|
||||
**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/);
|
||||
|
@ -16,9 +16,9 @@ TDengine的集群管理极其简单,除添加和删除节点需要人工干预
|
|||
|
||||
**第二步**:建议关闭所有物理节点的防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口;
|
||||
|
||||
**第三步**:在所有节点安装TDengine,且版本必须是一致的,**但不要启动taosd**。安装时,提示输入是否要加入一个已经存在的TDengine集群时,第一个物理节点直接回车创建新集群,后续物理节点则输入该集群任何一个在线的物理节点的FQDN:端口号(默认6030);
|
||||
**第三步**:在所有物理节点安装TDengine,且版本必须是一致的,**但不要启动taosd**。安装时,提示输入是否要加入一个已经存在的TDengine集群时,第一个物理节点直接回车创建新集群,后续物理节点则输入该集群任何一个在线的物理节点的FQDN:端口号(默认6030);
|
||||
|
||||
**第四步**:检查所有数据节点,以及应用所在物理节点的网络设置:
|
||||
**第四步**:检查所有数据节点,以及应用程序所在物理节点的网络设置:
|
||||
|
||||
1. 每个物理节点上执行命令`hostname -f`,查看和确认所有节点的hostname是不相同的(应用驱动所在节点无需做此项检查);
|
||||
2. 每个物理节点上执行`ping host`, 其中host是其他物理节点的hostname, 看能否ping通其它物理节点; 如果不能ping通,需要检查网络设置, 或/etc/hosts文件(Windows系统默认路径为C:\Windows\system32\drivers\etc\hosts),或DNS的配置。如果无法ping通,是无法组成集群的;
|
||||
|
@ -89,7 +89,7 @@ taos>
|
|||
2. 在第一个数据节点,使用CLI程序taos, 登录进TDengine系统, 执行命令:
|
||||
|
||||
```
|
||||
CREATE DNODE "h2.taos.com:6030";
|
||||
CREATE DNODE "h2.taos.com:6030";
|
||||
```
|
||||
|
||||
将新数据节点的End Point (准备工作中第四步获知的) 添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为这个新数据节点的End Point。
|
||||
|
@ -97,7 +97,7 @@ taos>
|
|||
3. 然后执行命令
|
||||
|
||||
```
|
||||
SHOW DNODES;
|
||||
SHOW DNODES;
|
||||
```
|
||||
|
||||
查看新节点是否被成功加入。如果该被加入的数据节点处于离线状态,请做两个检查
|
||||
|
@ -122,7 +122,7 @@ taos>
|
|||
执行CLI程序taos, 使用root账号登录进系统, 执行:
|
||||
|
||||
```
|
||||
CREATE DNODE "fqdn:port";
|
||||
CREATE DNODE "fqdn:port";
|
||||
```
|
||||
|
||||
将新数据节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个数据节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。【强烈不建议用自动获取方式来配置FQDN,可能导致生成的数据节点的End Point不是所期望的】
|
||||
|
@ -213,6 +213,6 @@ SHOW MNODES;
|
|||
|
||||
## Arbitrator的使用
|
||||
|
||||
如果副本数为偶数,当一个vnode group里一半或超过一半的vnode不工作时,是无法从中选出master的。同理,一半或超过一半的mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
|
||||
如果副本数为偶数,当一个vnode group里一半vnode不工作时,是无法从中选出master的。同理,一半mnode不工作时,是无法选出mnode的master的,因为存在“split brain”问题。为解决这个问题,TDengine引入了arbitrator的概念。Arbitrator模拟一个vnode或mnode在工作,但只简单的负责网络连接,不处理任何数据插入或访问。只要包含arbitrator在内,超过半数的vnode或mnode工作,那么该vnode group或mnode组就可以正常的提供数据插入或查询服务。比如对于副本数为2的情形,如果一个节点A离线,但另外一个节点B正常,而且能连接到arbitrator, 那么节点B就能正常工作。
|
||||
|
||||
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号,缺省是6042。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的arbitrator。
|
||||
TDengine提供一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。请点击[安装包下载](https://www.taosdata.com/cn/all-downloads/),在TDengine Arbitrator Linux一节中,选择适合的版本下载并安装。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号,缺省是6042。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的arbitrator。如果副本数为奇数,即使配置了arbitrator, 系统也不会去建立连接。
|
||||
|
|
|
@ -46,7 +46,7 @@ taos>
|
|||
5. 在第一个节点,使用CLI程序taos, 登录进TDengine系统, 使用命令:
|
||||
|
||||
```
|
||||
CREATE DNODE "h2.taos.com:6030";
|
||||
CREATE DNODE "h2.taos.com:6030";
|
||||
```
|
||||
|
||||
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为你自己第一个节点的End Point
|
||||
|
@ -54,7 +54,7 @@ taos>
|
|||
6. 使用命令
|
||||
|
||||
```
|
||||
SHOW DNODES;
|
||||
SHOW DNODES;
|
||||
```
|
||||
|
||||
查看新节点是否被成功加入。
|
||||
|
@ -71,7 +71,7 @@ taos>
|
|||
###添加节点
|
||||
执行CLI程序taos, 使用root账号登录进系统, 执行:
|
||||
```
|
||||
CREATE DNODE "fqdn:port";
|
||||
CREATE DNODE "fqdn:port";
|
||||
```
|
||||
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。
|
||||
|
||||
|
|
|
@ -142,7 +142,7 @@ C/C++的API类似于MySQL的C API。应用程序使用时,需要包含TDengine
|
|||
获取最近一次API调用失败的原因,返回值为错误代码。
|
||||
|
||||
|
||||
**注意**:对于单个数据库连接,在同一时刻只能有一个线程使用该链接调用API,否则会有未定义的行为出现并可能导致客户端crash。客户端应用可以通过建立多个连接进行多线程的数据写入或查询处理。
|
||||
**注意**:对于单个数据库连接,在同一时刻只能有一个线程使用该连接调用API,否则会有未定义的行为出现并可能导致客户端crash。客户端应用可以通过建立多个连接进行多线程的数据写入或查询处理。
|
||||
|
||||
|
||||
### 异步查询API
|
||||
|
|
|
@ -72,38 +72,34 @@ maven 项目中使用如下 pom.xml 配置即可:
|
|||
|
||||
### 获取连接
|
||||
|
||||
如下所示配置即可获取 TDengine Connection:
|
||||
#### 通过JdbcUrl获取连接
|
||||
|
||||
通过指定的jdbcUrl获取连接,如下所示:
|
||||
```java
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
String jdbcUrl = "jdbc:TAOS://127.0.0.1:6030/log?user=root&password=taosdata";
|
||||
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
|
||||
Connection conn = DriverManager.getConnection(jdbcUrl);
|
||||
```
|
||||
> 端口 6030 为默认连接端口,JDBC URL 中的 log 为系统本身的监控数据库。
|
||||
以上示例,建立了到hostname为taosdemo.com,端口为6030(TDengine的默认端口),数据库名为test的连接。这个url中指定用户名(user)为root,密码(password)为taosdata。
|
||||
|
||||
TDengine 的 JDBC URL 规范格式为:
|
||||
`jdbc:TAOS://{host_ip}:{port}/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
|
||||
|
||||
其中,`{}` 中的内容必须,`[]` 中为可选。配置参数说明如下:
|
||||
|
||||
`jdbc:TAOS://[host_name]:[port]/[database_name]?[user={user}|&password={password}|&charset={charset}|&cfgdir={config_dir}|&locale={locale}|&timezone={timezone}]`
|
||||
url中的配置参数如下:
|
||||
* user:登录 TDengine 用户名,默认值 root。
|
||||
* password:用户登录密码,默认值 taosdata。
|
||||
* charset:客户端使用的字符集,默认值为系统字符集。
|
||||
* cfgdir:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。
|
||||
* charset:客户端使用的字符集,默认值为系统字符集。
|
||||
* locale:客户端语言环境,默认值系统当前 locale。
|
||||
* timezone:客户端使用的时区,默认值为系统当前时区。
|
||||
|
||||
以上参数可以在 3 处配置,`优先级由高到低`分别如下:
|
||||
1. JDBC URL 参数
|
||||
如上所述,可以在 JDBC URL 的参数中指定。
|
||||
2. java.sql.DriverManager.getConnection(String jdbcUrl, Properties connProps)
|
||||
#### 使用JdbcUrl和Properties获取连接
|
||||
|
||||
除了通过指定的jdbcUrl获取连接,还可以使用Properties指定建立连接时的参数,如下所示:
|
||||
```java
|
||||
public Connection getConn() throws Exception{
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
String jdbcUrl = "jdbc:TAOS://127.0.0.1:0/log?user=root&password=taosdata";
|
||||
String jdbcUrl = "jdbc:TAOS://taosdemo.com:6030/test?user=root&password=taosdata";
|
||||
Properties connProps = new Properties();
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR, "/etc/taos");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
|
@ -111,16 +107,39 @@ public Connection getConn() throws Exception{
|
|||
return conn;
|
||||
}
|
||||
```
|
||||
以上示例,建立一个到hostname为taosdemo.com,端口为6030,数据库名为test的连接。这个连接在url中指定了用户名(user)为root,密码(password)为taosdata,并在connProps中指定了使用的字符集、语言环境、时区等信息。
|
||||
|
||||
3. 客户端配置文件 taos.cfg
|
||||
properties中的配置参数如下:
|
||||
* TSDBDriver.PROPERTY_KEY_USER:登录 TDengine 用户名,默认值 root。
|
||||
* TSDBDriver.PROPERTY_KEY_PASSWORD:用户登录密码,默认值 taosdata。
|
||||
* TSDBDriver.PROPERTY_KEY_CONFIG_DIR:客户端配置文件目录路径,Linux OS 上默认值 /etc/taos ,Windows OS 上默认值 C:/TDengine/cfg。
|
||||
* TSDBDriver.PROPERTY_KEY_CHARSET:客户端使用的字符集,默认值为系统字符集。
|
||||
* TSDBDriver.PROPERTY_KEY_LOCALE:客户端语言环境,默认值系统当前 locale。
|
||||
* TSDBDriver.PROPERTY_KEY_TIME_ZONE:客户端使用的时区,默认值为系统当前时区。
|
||||
|
||||
linux 系统默认配置文件为 /var/lib/taos/taos.cfg,windows 系统默认配置文件路径为 C:\TDengine\cfg\taos.cfg。
|
||||
```properties
|
||||
# client default username
|
||||
# defaultUser root
|
||||
#### 使用客户端配置文件建立连接
|
||||
当使用JDBC连接TDengine集群时,可以使用客户端配置文件,在客户端配置文件中指定集群的firstEp、secondEp参数。
|
||||
如下所示:
|
||||
1. 在java中不指定hostname和port
|
||||
```java
|
||||
public Connection getConn() throws Exception{
|
||||
Class.forName("com.taosdata.jdbc.TSDBDriver");
|
||||
String jdbcUrl = "jdbc:TAOS://:/test?user=root&password=taosdata";
|
||||
Properties connProps = new Properties();
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||
connProps.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||
Connection conn = DriverManager.getConnection(jdbcUrl, connProps);
|
||||
return conn;
|
||||
}
|
||||
```
|
||||
2. 在配置文件中指定firstEp和secondEp
|
||||
```
|
||||
# first fully qualified domain name (FQDN) for TDengine system
|
||||
firstEp cluster_node1:6030
|
||||
|
||||
# client default password
|
||||
# defaultPass taosdata
|
||||
# second fully qualified domain name (FQDN) for TDengine system, for cluster only
|
||||
secondEp cluster_node2:6030
|
||||
|
||||
# default system charset
|
||||
# charset UTF-8
|
||||
|
@ -128,6 +147,19 @@ public Connection getConn() throws Exception{
|
|||
# system locale
|
||||
# locale en_US.UTF-8
|
||||
```
|
||||
|
||||
以上示例,jdbc会使用客户端的配置文件,建立到hostname为cluster_node1,端口为6030,数据库名为test的连接。当集群中firstEp节点失效时,JDBC会尝试使用secondEp连接集群。
|
||||
TDengine中,只要保证firstEp和secondEp中一个节点有效,就可以正常建立到集群的连接。
|
||||
|
||||
> 注意:这里的配置文件指的是调用JDBC Connector的应用程序所在机器上的配置文件,Linux OS 上默认值 /etc/taos/taos.cfg ,Windows OS 上默认值 C://TDengine/cfg/taos.cfg。
|
||||
|
||||
#### 配置参数的优先级
|
||||
通过以上3种方式获取连接,如果配置参数在url、Properties、客户端配置文件中有重复,则参数的`优先级由高到低`分别如下:
|
||||
1. JDBC URL 参数,如上所述,可以在 JDBC URL 的参数中指定。
|
||||
2. Properties connProps
|
||||
3. 客户端配置文件 taos.cfg
|
||||
例如:在url中指定了password为taosdata,在Properties中指定了password为taosdemo,那么,JDBC会使用url中的password建立连接。
|
||||
|
||||
> 更多详细配置请参考[客户端配置][13]
|
||||
|
||||
### 创建数据库和表
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
## 5. 遇到错误"Unable to establish connection", 我怎么办?
|
||||
|
||||
客户端遇到链接故障,请按照下面的步骤进行检查:
|
||||
客户端遇到连接故障,请按照下面的步骤进行检查:
|
||||
|
||||
1. 检查网络环境
|
||||
* 云服务器:检查云服务器的安全组是否打开TCP/UDP 端口6030-6042的访问权限
|
||||
|
@ -45,7 +45,7 @@
|
|||
9. 如果仍不能排除连接故障,请使用命令行工具nc来分别判断指定端口的TCP和UDP连接是否通畅
|
||||
检查UDP端口连接是否工作:`nc -vuz {hostIP} {port} `
|
||||
检查服务器侧TCP端口连接是否工作:`nc -l {port}`
|
||||
检查客户端侧TCP端口链接是否工作:`nc {hostIP} {port}`
|
||||
检查客户端侧TCP端口连接是否工作:`nc {hostIP} {port}`
|
||||
|
||||
10. 也可以使用taos程序内嵌的网络连通检测功能,来验证服务器和客户端之间指定的端口连接是否通畅(包括TCP和UDP):[TDengine 内嵌网络检测工具使用指南](https://www.taosdata.com/blog/2020/09/08/1816.html)。
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
|||
1. 请检查连接的服务器的FQDN是否正确,FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。
|
||||
2. 如果网络配置有DNS server, 请检查是否正常工作
|
||||
3. 如果网络没有配置DNS server, 请检查客户端所在机器的hosts文件,查看该FQDN是否配置,并是否有正确的IP地址。
|
||||
4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法链接服务器的
|
||||
4. 如果网络配置OK,从客户端所在机器,你需要能Ping该连接的FQDN,否则客户端是无法连接服务器的
|
||||
|
||||
|
||||
## 7. 虽然语法正确,为什么我还是得到 "Invalid SQL" 错误
|
||||
|
@ -108,4 +108,8 @@ Connection = DriverManager.getConnection(url, properties);
|
|||
|
||||
附上必要的问题描述,以及发生该问题的执行操作,出现问题的表征及大概的时间,在<a href='https://github.com/taosdata/TDengine'> GitHub</a>提交Issue。
|
||||
|
||||
为了保证有足够的debug信息,如果问题能够重复,请修改/etc/taos/taos.cfg文件,最后面添加一行“debugFlag 135"(不带引号本身),然后重启taosd, 重复问题,然后再递交。但系统正常运行时,请一定将debugFlag设置为131,否则会产生大量的日志信息,降低系统效率。
|
||||
为了保证有足够的debug信息,如果问题能够重复,请修改/etc/taos/taos.cfg文件,最后面添加一行“debugFlag 135"(不带引号本身),然后重启taosd, 重复问题,然后再递交。也可以通过如下SQL语句,临时设置taosd的日志级别。
|
||||
```
|
||||
alter dnode <dnode_id> debugFlag 135;
|
||||
```
|
||||
但系统正常运行时,请一定将debugFlag设置为131,否则会产生大量的日志信息,降低系统效率。
|
||||
|
|
|
@ -22,7 +22,7 @@ INSERT INTO d1001 VALUES (1538548685000, 10.3, 219, 0.31) (1538548695000, 12.6,
|
|||
|
||||
**Tips:**
|
||||
|
||||
- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置,最大可配置为8M)。
|
||||
- 要提高写入效率,需要批量写入。一批写入的记录条数越多,插入效率就越高。但一条记录不能超过16K,一条SQL语句总长度不能超过64K(可通过参数maxSQLLength配置,最大可配置为1M)。
|
||||
- TDengine支持多线程同时写入,要进一步提高写入速度,一个客户端需要打开20个以上的线程同时写。但线程数达到一定数量后,无法再提高,甚至还会下降,因为线程切频繁切换,带来额外开销。
|
||||
- 对同一张表,如果新插入记录的时间戳已经存在,新记录将被直接抛弃,也就是说,在一张表里,时间戳必须是唯一的。如果应用自动生成记录,很有可能生成的时间戳是一样的,这样,成功插入的记录条数会小于应用插入的记录条数。
|
||||
- 写入的数据的时间戳必须大于当前时间减去配置参数keep的时间。如果keep配置为3650天,那么无法写入比3650天还老的数据。写入数据的时间戳也不能大于当前时间加配置参数days。如果days配置为2,那么无法写入比当前时间还晚2天的数据。
|
||||
|
|
|
@ -66,21 +66,21 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
|
||||
数据实时复制有三个主要流程:选主、数据转发、数据恢复。后续做详细讨论。
|
||||
|
||||
## 虚拟节点之间的网络链接
|
||||
## 虚拟节点之间的网络连接
|
||||
|
||||
虚拟节点之间通过TCP进行链接,节点之间的状态交换、数据包的转发都是通过这个TCP链接(peerFd)进行。为避免竞争,两个虚拟节点之间的TCP链接,总是由IP地址(UINT32)小的节点作为TCP客户端发起。一旦TCP链接被中断,虚拟节点能通过TCP socket自动检测到,将对方标为offline。如果监测到任何错误(比如数据恢复流程),虚拟节点将主动重置该链接。
|
||||
虚拟节点之间通过TCP进行连接,节点之间的状态交换、数据包的转发都是通过这个TCP连接(peerFd)进行。为避免竞争,两个虚拟节点之间的TCP连接,总是由IP地址(UINT32)小的节点作为TCP客户端发起。一旦TCP连接被中断,虚拟节点能通过TCP socket自动检测到,将对方标为offline。如果监测到任何错误(比如数据恢复流程),虚拟节点将主动重置该连接。
|
||||
|
||||
一旦作为客户端的节点链接不成或中断,它将周期性的每隔一秒钟去试图去链接一次。因为TCP本身有心跳机制,虚拟节点之间不再另行提供心跳。
|
||||
一旦作为客户端的节点连接不成或中断,它将周期性的每隔一秒钟去试图去连接一次。因为TCP本身有心跳机制,虚拟节点之间不再另行提供心跳。
|
||||
|
||||
如果一个unsynced节点要发起数据恢复流程,它与Master将建立起专有的TCP链接(syncFd)。数据恢复完成后,该链接会被关闭。而且为限制资源的使用,系统只容许一定数量(配置参数tsMaxSyncNum)的数据恢复的socket存在。如果超过这个数字,系统会将新的数据恢复请求延后处理。
|
||||
如果一个unsynced节点要发起数据恢复流程,它与Master将建立起专有的TCP连接(syncFd)。数据恢复完成后,该连接会被关闭。而且为限制资源的使用,系统只容许一定数量(配置参数tsMaxSyncNum)的数据恢复的socket存在。如果超过这个数字,系统会将新的数据恢复请求延后处理。
|
||||
|
||||
任意一个节点,无论有多少虚拟节点,都会启动而且只会启动一个TCP server, 来接受来自其他虚拟节点的上述两类TCP的链接请求。当TCP socket建立起来,客户端侧发送的消息体里会带有vgId(全局唯一的vgroup ID), TCP 服务器侧会检查该vgId是否已经在该节点启动运行。如果已经启动运行,就接受其请求。如果不存在,就直接将链接请求关闭。在TDengine代码里,mnode group的vgId设置为1。
|
||||
任意一个节点,无论有多少虚拟节点,都会启动而且只会启动一个TCP server, 来接受来自其他虚拟节点的上述两类TCP的连接请求。当TCP socket建立起来,客户端侧发送的消息体里会带有vgId(全局唯一的vgroup ID), TCP 服务器侧会检查该vgId是否已经在该节点启动运行。如果已经启动运行,就接受其请求。如果不存在,就直接将连接请求关闭。在TDengine代码里,mnode group的vgId设置为1。
|
||||
|
||||
## 选主流程
|
||||
|
||||
当同一组的两个虚拟节点之间(vnode A, vnode B)建立连接后,他们互换status消息。status消息里包含本地存储的同一虚拟节点组内所有虚拟节点的role和version。
|
||||
|
||||
如果一个虚拟节点(vnode A)检测到与同一虚拟节点组内另外一虚拟节点(vnode B)的链接中断,vnode A将立即把vnode B的role设置为offline。无论是接收到另外一虚拟节点发来的status消息,还是检测与另外一虚拟节点的链接中断,该虚拟节点都将进入状态处理流程。状态处理流程的规则如下:
|
||||
如果一个虚拟节点(vnode A)检测到与同一虚拟节点组内另外一虚拟节点(vnode B)的连接中断,vnode A将立即把vnode B的role设置为offline。无论是接收到另外一虚拟节点发来的status消息,还是检测与另外一虚拟节点的连接中断,该虚拟节点都将进入状态处理流程。状态处理流程的规则如下:
|
||||
|
||||
1. 如果检测到在线的节点数没有超过一半,则将自己的状态设置为unsynced.
|
||||
2. 如果在线的虚拟节点数超过一半,会检查master节点是否存在,如果存在,则会决定是否将自己状态改为slave或启动数据恢复流程
|
||||
|
@ -118,7 +118,7 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
9. 如果quorum为1,上述6,7,8步不会发生。
|
||||
10. 如果要等待slave的确认,master会启动2秒的定时器(可配置),如果超时,则认为失败。
|
||||
|
||||
对于回复确认,sync模块提供的是异步回调函数,因此APP在调用syncForwardToPeer之后,无需等待,可以处理下一个操作。在Master与Slave的TCP链接管道里,可能有多个Forward消息,这些消息是严格按照应用提供的顺序排好的。对于Forward Response也是一样,TCP管道里存在多个,但都是排序好的。这个顺序,SYNC模块并没有做特别的事情,是由APP单线程顺序写来保证的(TDengine里每个vnode的写数据,都是单线程)。
|
||||
对于回复确认,sync模块提供的是异步回调函数,因此APP在调用syncForwardToPeer之后,无需等待,可以处理下一个操作。在Master与Slave的TCP连接管道里,可能有多个Forward消息,这些消息是严格按照应用提供的顺序排好的。对于Forward Response也是一样,TCP管道里存在多个,但都是排序好的。这个顺序,SYNC模块并没有做特别的事情,是由APP单线程顺序写来保证的(TDengine里每个vnode的写数据,都是单线程)。
|
||||
|
||||
## 数据恢复流程
|
||||
|
||||
|
@ -142,9 +142,9 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
|
||||
<center> <img src="../assets/replica-restore.png"> </center>
|
||||
|
||||
1. 通过已经建立的TCP链接,发送sync req给master节点
|
||||
2. master收到sync req后,以client的身份,向vnode B主动建立一新的专用于同步的TCP链接(syncFd)
|
||||
3. 新的TCP链接建立成功后,master将开始retrieve流程,对应的,vnode B将同步启动restore流程
|
||||
1. 通过已经建立的TCP连接,发送sync req给master节点
|
||||
2. master收到sync req后,以client的身份,向vnode B主动建立一新的专用于同步的TCP连接(syncFd)
|
||||
3. 新的TCP连接建立成功后,master将开始retrieve流程,对应的,vnode B将同步启动restore流程
|
||||
4. Retrieve/Restore流程里,先处理所有archived data (vnode里的data, head, last文件),后处理WAL data。
|
||||
5. 对于archived data,master将通过回调函数getFileInfo获取数据文件的基本信息,包括文件名、magic以及文件大小。
|
||||
6. master 将获得的文件名、magic以及文件大小发给vnode B
|
||||
|
@ -157,7 +157,7 @@ TDengine采取的是Master-Slave模式进行同步,与流行的RAFT一致性
|
|||
1. master节点调用回调函数getWalInfo,获取WAL的文件名。
|
||||
2. 如果getWalInfo返回值大于0,表示该文件还不是最后一个WAL,因此master调用sendfile一下把该文件发送给vnode B
|
||||
3. 如果getWalInfo返回时为0,表示该文件是最后一个WAL,因为文件可能还处于写的状态中,sync模块要根据WAL Head的定义逐条读出记录,然后发往vnode B。
|
||||
4. vnode A读取TCP链接传来的数据,按照WAL Head,逐条读取,如果版本号比现有的大,调用回调函数writeToCache,交给应用处理。如果小,直接扔掉。
|
||||
4. vnode A读取TCP连接传来的数据,按照WAL Head,逐条读取,如果版本号比现有的大,调用回调函数writeToCache,交给应用处理。如果小,直接扔掉。
|
||||
5. 上述流程循环,直到所有WAL文件都被处理完。处理完后,master就会将新来的数据包通过Forward消息转发给slave。
|
||||
|
||||
从同步文件启动起,sync模块会通过inotify监控所有处理过的file以及wal。一旦发现被处理过的文件有更新变化,同步流程将中止,会重新启动。因为有可能落盘操作正在进行(比如历史数据导入,内存数据落盘),把已经处理过的文件进行了修改,需要重新同步才行。
|
||||
|
@ -194,15 +194,15 @@ sync模块通过inotify监控LastWal文件的更新和关闭操作。而且在
|
|||
|
||||
因为写入失败,客户端会重新写入数据。但对于TDengine而言,是OK的。因为时序数据都是有时间戳的,时间戳相同的数据更新操作,第一次会执行,但第二次会自动扔掉。对于Meta Data(增加、删除库、表等等)的操作,也是OK的。一张表、库已经被创建或删除,再创建或删除,不会被执行的。
|
||||
|
||||
在TDengine的设计里,虚拟节点与虚拟节点之间,是一个TCP链接,是一个pipeline,数据块一个接一个按顺序在这个pipeline里等待处理。一旦某个数据块的处理失败,这个链接会被重置,后续的数据块的处理都会失败。因此不会存在Pipeline里一个数据块更新失败,但下一个数据块成功的可能。
|
||||
在TDengine的设计里,虚拟节点与虚拟节点之间,是一个TCP连接,是一个pipeline,数据块一个接一个按顺序在这个pipeline里等待处理。一旦某个数据块的处理失败,这个连接会被重置,后续的数据块的处理都会失败。因此不会存在Pipeline里一个数据块更新失败,但下一个数据块成功的可能。
|
||||
|
||||
## Split Brain的问题
|
||||
|
||||
选举流程中,有个强制要求,那就是一定有超过半数的虚拟节点在线。但是如果replication正好是偶数,这个时候,完全可能存在splt brain问题。
|
||||
|
||||
为解决这个问题,TDengine提供Arbitrator的解决方法。Arbitrator是一个节点,它的任务就是接受任何虚拟节点的链接请求,并保持它。
|
||||
为解决这个问题,TDengine提供Arbitrator的解决方法。Arbitrator是一个节点,它的任务就是接受任何虚拟节点的连接请求,并保持它。
|
||||
|
||||
在启动复制模块实例时,在配置参数中,应用可以提供Arbitrator的IP地址。如果是奇数个副本,复制模块不会与这个arbitrator去建立链接,但如果是偶数个副本,就会主动去建立链接。
|
||||
在启动复制模块实例时,在配置参数中,应用可以提供Arbitrator的IP地址。如果是奇数个副本,复制模块不会与这个arbitrator去建立连接,但如果是偶数个副本,就会主动去建立连接。
|
||||
|
||||
Arbitrator的程序tarbitrator.c在复制模块的同一目录, 编译整个系统时,会在bin目录生成。命令行参数“-?”查看可以配置的参数,比如绑定的IP地址,监听的端口号。
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ taosd的启动入口是dnode模块,dnode然后启动其他模块,包括可
|
|||
|
||||
该模块负责taosd与taosc, 以及其他数据节点之间的通讯。TDengine没有采取标准的HTTP或gRPC等第三方工具,而是实现了自己的通讯模块RPC。
|
||||
|
||||
考虑到物联网场景下,数据写入的包一般不大,因此除支持TCP链接之外,RPC还支持UDP链接。当数据包小于15K时,RPC将采用UDP方式进行链接,否则将采用TCP链接。对于查询类的消息,RPC不管包的大小,总是采取TCP链接。对于UDP链接,RPC实现了自己的超时、重传、顺序检查等机制,以保证数据可靠传输。
|
||||
考虑到物联网场景下,数据写入的包一般不大,因此除支持TCP连接之外,RPC还支持UDP连接。当数据包小于15K时,RPC将采用UDP方式进行连接,否则将采用TCP连接。对于查询类的消息,RPC不管包的大小,总是采取TCP连接。对于UDP连接,RPC实现了自己的超时、重传、顺序检查等机制,以保证数据可靠传输。
|
||||
|
||||
RPC模块还提供数据压缩功能,如果数据包的字节数超过系统配置参数compressMsgSize, RPC在传输中将自动压缩数据,以节省带宽。
|
||||
|
||||
|
@ -25,7 +25,7 @@ RPC模块还提供数据压缩功能,如果数据包的字节数超过系统
|
|||
|
||||
- 系统的初始化,包括
|
||||
- 从文件taos.cfg读取系统配置参数,从文件dnodeCfg.json读取数据节点的配置参数;
|
||||
- 启动RPC模块,并建立起与taosc通讯的server链接,与其他数据节点通讯的server链接;
|
||||
- 启动RPC模块,并建立起与taosc通讯的server连接,与其他数据节点通讯的server连接;
|
||||
- 启动并初始化dnode的内部管理, 该模块将扫描该数据节点已有的vnode,并打开它们;
|
||||
- 初始化可配置的模块,如mnode, http, monitor等。
|
||||
- 数据节点的管理,包括
|
||||
|
@ -61,7 +61,7 @@ vnode与其子模块是通过API直接调用,而不是通过消息队列传递
|
|||
|
||||
mnode是整个系统的大脑,负责整个系统的资源调度,负责meta data的管理与存储。
|
||||
|
||||
一个运行的系统里,只有一个mnode,但它有多个副本(由系统配置参数numOfMpeers控制)。这些副本分布在不同的dnode里,目的是保证系统的高可靠运行。副本之间的数据复制是采用同步而非异步的方式,以确保数据的一致性,确保数据不会丢失。这些副本会自动选举一个Master,其他副本是slave。所有数据更新类的操作,都只能在master上进行,而查询类的可以在slave节点上进行。代码实现上,同步模块与vnode共享,但mnode被分配一个特殊的vgroup ID: 1,而且quorum大于1。整个集群系统是由多个dnode组成的,运行的mnode的副本数不可能超过dnode的个数,但不会超过配置的副本数。如果某个mnode副本宕机一段时间,只要超过半数的mnode副本仍在运行,运行的mnode会自动根据整个系统的资源情况,在其他dnode里再启动一个mnode, 以保证运行的副本数。
|
||||
一个运行的系统里,只有一个mnode,但它有多个副本(由系统配置参数numOfMnodes控制)。这些副本分布在不同的dnode里,目的是保证系统的高可靠运行。副本之间的数据复制是采用同步而非异步的方式,以确保数据的一致性,确保数据不会丢失。这些副本会自动选举一个Master,其他副本是slave。所有数据更新类的操作,都只能在master上进行,而查询类的可以在slave节点上进行。代码实现上,同步模块与vnode共享,但mnode被分配一个特殊的vgroup ID: 1,而且quorum大于1。整个集群系统是由多个dnode组成的,运行的mnode的副本数不可能超过dnode的个数,但不会超过配置的副本数。如果某个mnode副本宕机一段时间,只要超过半数的mnode副本仍在运行,运行的mnode会自动根据整个系统的资源情况,在其他dnode里再启动一个mnode, 以保证运行的副本数。
|
||||
|
||||
各个dnode通过信息交换,保存有mnode各个副本的End Point列表,并向其中的master节点定时(间隔由系统配置参数statusInterval控制)发送status消息,消息体里包含该dnode的CPU、内存、剩余存储空间、vnode个数,以及各个vnode的状态(存储空间、原始数据大小、记录条数、角色等)。这样mnode就了解整个系统的资源情况,如果用户创建新的表,就可以决定需要在哪个dnode创建;如果增加或删除dnode, 或者监测到某dnode数据过热、或离线太长,就可以决定需要挪动那些vnode,以实现负载均衡。
|
||||
|
||||
|
|
|
@ -6,73 +6,76 @@
|
|||
########################################################
|
||||
|
||||
# first fully qualified domain name (FQDN) for TDengine system
|
||||
# firstEp hostname1:6030
|
||||
|
||||
# second fully qualified domain name (FQDN) for TDengine system, for cluster only
|
||||
# secondEp cluster_hostname2:6030
|
||||
# firstEp hostname:6030
|
||||
|
||||
# local fully qualified domain name (FQDN)
|
||||
# fqdn hostname
|
||||
# fqdn hostname
|
||||
|
||||
# first port number for the connection (12 continuous UDP/TCP port number are used)
|
||||
# serverPort 6030
|
||||
# serverPort 6030
|
||||
|
||||
# log file's directory
|
||||
# logDir /var/log/taos
|
||||
# logDir /var/log/taos
|
||||
|
||||
# data file's directory
|
||||
# dataDir /var/lib/taos
|
||||
# dataDir /var/lib/taos
|
||||
|
||||
# the arbitrator's fully qualified domain name (FQDN) for TDengine system, for cluster only
|
||||
# arbitrator arbitrator_hostname:6042
|
||||
# arbitrator arbitrator_hostname:6042
|
||||
|
||||
# number of threads per CPU core
|
||||
# numOfThreadsPerCore 1.0
|
||||
# numOfThreadsPerCore 1.0
|
||||
|
||||
# the proportion of total threads responsible for query
|
||||
# ratioOfQueryThreads 0.5
|
||||
|
||||
# number of management nodes in the system
|
||||
# numOfMnodes 3
|
||||
# numOfMnodes 3
|
||||
|
||||
# enable/disable backuping vnode directory when removing dnode
|
||||
# vnodeBak 1
|
||||
# vnodeBak 1
|
||||
|
||||
# if report installation / use information
|
||||
# telemetryReporting 1
|
||||
|
||||
# enable/disable load balancing
|
||||
# balance 1
|
||||
# balance 1
|
||||
|
||||
# role for dnode. 0 - any, 1 - mnode, 2 - dnode
|
||||
# role 0
|
||||
# role 0
|
||||
|
||||
# max timer control blocks
|
||||
# maxTmrCtrl 512
|
||||
# maxTmrCtrl 512
|
||||
|
||||
# time interval of system monitor, seconds
|
||||
# monitorInterval 30
|
||||
# monitorInterval 30
|
||||
|
||||
# number of seconds allowed for a dnode to be offline, for cluster only
|
||||
# offlineThreshold 8640000
|
||||
# offlineThreshold 8640000
|
||||
|
||||
# RPC re-try timer, millisecond
|
||||
# rpcTimer 300
|
||||
# rpcTimer 300
|
||||
|
||||
# RPC maximum time for ack, seconds.
|
||||
# rpcMaxTime 600
|
||||
# rpcMaxTime 600
|
||||
|
||||
# time interval of dnode status reporting to mnode, seconds, for cluster only
|
||||
# statusInterval 1
|
||||
# statusInterval 1
|
||||
|
||||
# time interval of heart beat from shell to dnode, seconds
|
||||
# shellActivityTimer 3
|
||||
# shellActivityTimer 3
|
||||
|
||||
# time of keeping table meta data in cache, seconds
|
||||
# tableMetaKeepTimer 7200
|
||||
# tableMetaKeepTimer 7200
|
||||
|
||||
# minimum sliding window time, milli-second
|
||||
# minSlidingTime 10
|
||||
# minSlidingTime 10
|
||||
|
||||
# minimum time window, milli-second
|
||||
# minIntervalTime 10
|
||||
# minIntervalTime 10
|
||||
|
||||
# maximum delay before launching a stream compution, milli-second
|
||||
# maxStreamCompDelay 20000
|
||||
# maxStreamCompDelay 20000
|
||||
|
||||
# maximum delay before launching a stream computation for the first time, milli-second
|
||||
# maxFirstStreamCompDelay 10000
|
||||
|
@ -89,9 +92,6 @@
|
|||
# max number of tables per vnode
|
||||
# maxTablesPerVnode 1000000
|
||||
|
||||
# step size of increasing table number in a vnode
|
||||
# tableIncStepPerVnode 1000
|
||||
|
||||
# cache block size (Mbyte)
|
||||
# cache 16
|
||||
|
||||
|
@ -110,6 +110,9 @@
|
|||
# maximum rows of records in file block
|
||||
# maxRows 4096
|
||||
|
||||
# the number of acknowledgments required for successful data writing
|
||||
# quorum 1
|
||||
|
||||
# enable/disable compression
|
||||
# comp 2
|
||||
|
||||
|
@ -122,15 +125,6 @@
|
|||
# number of replications, for cluster only
|
||||
# replica 1
|
||||
|
||||
# mqtt hostname
|
||||
# mqttHostName test.mosquitto.org
|
||||
|
||||
# mqtt port
|
||||
# mqttPort 1883
|
||||
|
||||
# mqtt topic
|
||||
# mqttTopic /test
|
||||
|
||||
# the compressed rpc message, option:
|
||||
# -1 (no compression)
|
||||
# 0 (all message compressed),
|
||||
|
@ -167,12 +161,12 @@
|
|||
# stop writing data when the disk size of the log folder is less than this value
|
||||
# minimalDataDirGB 0.1
|
||||
|
||||
# One mnode is equal to the number of vnode consumed
|
||||
# mnodeEqualVnodeNum 4
|
||||
|
||||
# enbale/disable http service
|
||||
# http 1
|
||||
|
||||
# enable/disable muqq service
|
||||
# mqtt 0
|
||||
|
||||
# enable/disable system monitor
|
||||
# monitor 1
|
||||
|
||||
|
@ -189,11 +183,12 @@
|
|||
# max number of rows per log filters
|
||||
# numOfLogLines 10000000
|
||||
|
||||
# enable/disable async log
|
||||
# asyncLog 1
|
||||
|
||||
# time of keeping log files, days
|
||||
# logKeepDays 0
|
||||
|
||||
# enable/disable async log
|
||||
# asyncLog 1
|
||||
|
||||
# The following parameters are used for debug purpose only.
|
||||
# debugFlag 8 bits mask: FILE-SCREEN-UNUSED-HeartBeat-DUMP-TRACE_WARN-ERROR
|
||||
|
@ -231,18 +226,12 @@
|
|||
# debug flag for JNI
|
||||
# jniDebugflag 131
|
||||
|
||||
# debug flag for ODBC
|
||||
# odbcDebugflag 131
|
||||
|
||||
# debug flag for storage
|
||||
# uDebugflag 131
|
||||
|
||||
# debug flag for http server
|
||||
# httpDebugFlag 131
|
||||
|
||||
# debug flag for mqtt
|
||||
# mqttDebugFlag 131
|
||||
|
||||
# debug flag for monitor
|
||||
# monitorDebugFlag 131
|
||||
|
||||
|
@ -255,6 +244,9 @@
|
|||
# debug flag for http server
|
||||
# tsdbDebugFlag 131
|
||||
|
||||
# debug flag for continue query
|
||||
# cqDebugFlag 131
|
||||
|
||||
# enable/disable recording the SQL in taos client
|
||||
# tscEnableRecordSql 0
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ cp -r ${top_dir}/tests/examples/* ${pkg_dir}${install_home_pat
|
|||
cp -r ${top_dir}/src/connector/grafanaplugin ${pkg_dir}${install_home_path}/connector
|
||||
cp -r ${top_dir}/src/connector/python ${pkg_dir}${install_home_path}/connector
|
||||
cp -r ${top_dir}/src/connector/go ${pkg_dir}${install_home_path}/connector
|
||||
cp ${compile_dir}/build/lib/taos-jdbcdriver*dist.* ${pkg_dir}${install_home_path}/connector
|
||||
cp -r ${top_dir}/src/connector/nodejs ${pkg_dir}${install_home_path}/connector
|
||||
cp ${compile_dir}/build/lib/taos-jdbcdriver*dist.* ${pkg_dir}${install_home_path}/connector ||:
|
||||
|
||||
cp -r ${compile_dir}/../packaging/deb/DEBIAN ${pkg_dir}/
|
||||
chmod 755 ${pkg_dir}/DEBIAN/*
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
FROM centos:7
|
||||
FROM ubuntu:20.04
|
||||
|
||||
WORKDIR /root
|
||||
|
||||
ARG version
|
||||
RUN echo $version
|
||||
COPY tdengine.tar.gz /root/
|
||||
RUN tar -zxf tdengine.tar.gz
|
||||
WORKDIR /root/TDengine-server/
|
||||
RUN sh install.sh -e no
|
||||
WORKDIR /root/TDengine-server-$version/
|
||||
RUN /bin/bash install.sh -e no
|
||||
|
||||
|
||||
ENV LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/lib"
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -x
|
||||
docker build --rm -f "Dockerfile" -t tdengine/tdengine-aarch64:$1 "." --build-arg version=$1
|
||||
docker login -u tdengine -p $2 #replace the docker registry username and password
|
||||
docker push tdengine/tdengine-aarch64:$1
|
|
@ -1,5 +1,5 @@
|
|||
#!/bin/bash
|
||||
set -x
|
||||
docker build --rm -f "Dockerfile" -t tdengine/tdengine:$1 "."
|
||||
docker build --rm -f "Dockerfile" -t tdengine/tdengine:$1 "." --build-arg version=$1
|
||||
docker login -u tdengine -p $2 #replace the docker registry username and password
|
||||
docker push tdengine/tdengine:$1
|
||||
|
|
|
@ -156,9 +156,15 @@ build_time=$(date +"%F %R")
|
|||
|
||||
# get commint id from git
|
||||
gitinfo=$(git rev-parse --verify HEAD)
|
||||
enterprise_dir="${top_dir}/../enterprise"
|
||||
cd ${enterprise_dir}
|
||||
gitinfoOfInternal=$(git rev-parse --verify HEAD)
|
||||
|
||||
if [[ "$verMode" == "cluster" ]]; then
|
||||
enterprise_dir="${top_dir}/../enterprise"
|
||||
cd ${enterprise_dir}
|
||||
gitinfoOfInternal=$(git rev-parse --verify HEAD)
|
||||
else
|
||||
gitinfoOfInternal=NULL
|
||||
fi
|
||||
|
||||
cd ${curr_dir}
|
||||
|
||||
# 2. cmake executable file
|
||||
|
@ -193,23 +199,35 @@ cd ${curr_dir}
|
|||
# 3. Call the corresponding script for packaging
|
||||
if [ "$osType" != "Darwin" ]; then
|
||||
if [[ "$verMode" != "cluster" ]] && [[ "$cpuType" == "x64" ]] && [[ "$dbName" == "taos" ]]; then
|
||||
echo "====do deb package for the ubuntu system===="
|
||||
output_dir="${top_dir}/debs"
|
||||
if [ -d ${output_dir} ]; then
|
||||
${csudo} rm -rf ${output_dir}
|
||||
ret='0'
|
||||
command -v dpkg >/dev/null 2>&1 || { ret='1'; }
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
echo "====do deb package for the ubuntu system===="
|
||||
output_dir="${top_dir}/debs"
|
||||
if [ -d ${output_dir} ]; then
|
||||
${csudo} rm -rf ${output_dir}
|
||||
fi
|
||||
${csudo} mkdir -p ${output_dir}
|
||||
cd ${script_dir}/deb
|
||||
${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
|
||||
else
|
||||
echo "==========dpkg command not exist, so not release deb package!!!"
|
||||
fi
|
||||
${csudo} mkdir -p ${output_dir}
|
||||
cd ${script_dir}/deb
|
||||
${csudo} ./makedeb.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
|
||||
|
||||
echo "====do rpm package for the centos system===="
|
||||
output_dir="${top_dir}/rpms"
|
||||
if [ -d ${output_dir} ]; then
|
||||
${csudo} rm -rf ${output_dir}
|
||||
ret='0'
|
||||
command -v rpmbuild >/dev/null 2>&1 || { ret='1'; }
|
||||
if [ "$ret" -eq 0 ]; then
|
||||
echo "====do rpm package for the centos system===="
|
||||
output_dir="${top_dir}/rpms"
|
||||
if [ -d ${output_dir} ]; then
|
||||
${csudo} rm -rf ${output_dir}
|
||||
fi
|
||||
${csudo} mkdir -p ${output_dir}
|
||||
cd ${script_dir}/rpm
|
||||
${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
|
||||
else
|
||||
echo "==========rpmbuild command not exist, so not release rpm package!!!"
|
||||
fi
|
||||
${csudo} mkdir -p ${output_dir}
|
||||
cd ${script_dir}/rpm
|
||||
${csudo} ./makerpm.sh ${compile_dir} ${output_dir} ${verNumber} ${cpuType} ${osType} ${verMode} ${verType}
|
||||
fi
|
||||
|
||||
echo "====do tar.gz package for all systems===="
|
||||
|
|
|
@ -64,7 +64,8 @@ cp %{_compiledir}/../src/inc/taoserror.h %{buildroot}%{homepath}/incl
|
|||
cp -r %{_compiledir}/../src/connector/grafanaplugin %{buildroot}%{homepath}/connector
|
||||
cp -r %{_compiledir}/../src/connector/python %{buildroot}%{homepath}/connector
|
||||
cp -r %{_compiledir}/../src/connector/go %{buildroot}%{homepath}/connector
|
||||
cp %{_compiledir}/build/lib/taos-jdbcdriver*dist.* %{buildroot}%{homepath}/connector
|
||||
cp -r %{_compiledir}/../src/connector/nodejs %{buildroot}%{homepath}/connector
|
||||
cp %{_compiledir}/build/lib/taos-jdbcdriver*dist.* %{buildroot}%{homepath}/connector ||:
|
||||
cp -r %{_compiledir}/../tests/examples/* %{buildroot}%{homepath}/examples
|
||||
|
||||
#Scripts executed before installation
|
||||
|
|
|
@ -272,6 +272,29 @@ function install_config() {
|
|||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# user email
|
||||
#EMAIL_PATTERN='^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$'
|
||||
#EMAIL_PATTERN='^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$'
|
||||
#EMAIL_PATTERN="^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
|
||||
echo
|
||||
echo -e -n "${GREEN}Enter your email address for priority support or enter empty to skip${NC}: "
|
||||
read emailAddr
|
||||
while true; do
|
||||
if [ ! -z "$emailAddr" ]; then
|
||||
# check the format of the emailAddr
|
||||
#if [[ "$emailAddr" =~ $EMAIL_PATTERN ]]; then
|
||||
# Write the email address to temp file
|
||||
email_file="${install_main_dir}/email"
|
||||
${csudo} bash -c "echo $emailAddr > ${email_file}"
|
||||
break
|
||||
#else
|
||||
# read -p "Please enter the correct email address: " emailAddr
|
||||
#fi
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -278,11 +278,11 @@ function install_service_on_sysvinit() {
|
|||
|
||||
# Install taosd service
|
||||
if ((${os_type}==1)); then
|
||||
${csudo} cp -f ${script_dir}/../deb/init.d/taosd ${install_main_dir}/init.d
|
||||
${csudo} cp ${script_dir}/../deb/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
|
||||
${csudo} cp -f ${script_dir}/../deb/taosd ${install_main_dir}/init.d
|
||||
${csudo} cp ${script_dir}/../deb/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
|
||||
elif ((${os_type}==2)); then
|
||||
${csudo} cp -f ${script_dir}/../rpm/init.d/taosd ${install_main_dir}/init.d
|
||||
${csudo} cp ${script_dir}/../rpm/init.d/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
|
||||
${csudo} cp -f ${script_dir}/../rpm/taosd ${install_main_dir}/init.d
|
||||
${csudo} cp ${script_dir}/../rpm/taosd ${service_config_dir} && ${csudo} chmod a+x ${service_config_dir}/taosd
|
||||
fi
|
||||
|
||||
#restart_config_str="taos:2345:respawn:${service_config_dir}/taosd start"
|
||||
|
|
|
@ -25,9 +25,9 @@ release_dir="${top_dir}/release"
|
|||
|
||||
#package_name='linux'
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/TDengine-enterprise-arbitrator"
|
||||
install_dir="${release_dir}/TDengine-enterprise-arbitrator-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/TDengine-arbitrator"
|
||||
install_dir="${release_dir}/TDengine-arbitrator-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -48,9 +48,9 @@ mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_rpm} ${install_dir}
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -25,9 +25,9 @@ release_dir="${top_dir}/release"
|
|||
|
||||
#package_name='linux'
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/PowerDB-enterprise-arbitrator"
|
||||
install_dir="${release_dir}/PowerDB-enterprise-arbitrator-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/PowerDB-arbitrator"
|
||||
install_dir="${release_dir}/PowerDB-arbitrator-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -48,9 +48,9 @@ mkdir -p ${install_dir}/init.d && cp ${init_file_tarbitrator_rpm} ${install_dir}
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -32,9 +32,9 @@ release_dir="${top_dir}/release"
|
|||
#package_name='linux'
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/TDengine-enterprise-client"
|
||||
install_dir="${release_dir}/TDengine-enterprise-client-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/TDengine-client"
|
||||
install_dir="${release_dir}/TDengine-client-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -97,6 +97,8 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
cp -r ${examples_dir}/python ${install_dir}/examples
|
||||
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||
cp -r ${examples_dir}/nodejs ${install_dir}/examples
|
||||
cp -r ${examples_dir}/C# ${install_dir}/examples
|
||||
fi
|
||||
# Copy driver
|
||||
mkdir -p ${install_dir}/driver
|
||||
|
@ -108,11 +110,12 @@ mkdir -p ${install_dir}/connector
|
|||
|
||||
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||
if [ "$osType" != "Darwin" ]; then
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
|
||||
fi
|
||||
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/go ${install_dir}/connector
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/go ${install_dir}/connector
|
||||
cp -r ${connector_dir}/nodejs ${install_dir}/connector
|
||||
fi
|
||||
# Copy release note
|
||||
# cp ${script_dir}/release_note ${install_dir}
|
||||
|
@ -122,9 +125,9 @@ fi
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -32,9 +32,9 @@ release_dir="${top_dir}/release"
|
|||
#package_name='linux'
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/PowerDB-enterprise-client"
|
||||
install_dir="${release_dir}/PowerDB-enterprise-client-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/PowerDB-client"
|
||||
install_dir="${release_dir}/PowerDB-client-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -123,7 +123,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/src/taosapp/taosapp.go
|
||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/taosdemo.go
|
||||
fi
|
||||
# Copy driver
|
||||
mkdir -p ${install_dir}/driver
|
||||
|
@ -135,7 +135,7 @@ mkdir -p ${install_dir}/connector
|
|||
|
||||
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||
if [ "$osType" != "Darwin" ]; then
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
|
||||
fi
|
||||
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
|
@ -164,9 +164,9 @@ fi
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -25,9 +25,9 @@ release_dir="${top_dir}/release"
|
|||
|
||||
#package_name='linux'
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/TDengine-enterprise-server"
|
||||
install_dir="${release_dir}/TDengine-enterprise-server-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/TDengine-server"
|
||||
install_dir="${release_dir}/TDengine-server-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -113,6 +113,8 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
cp -r ${examples_dir}/python ${install_dir}/examples
|
||||
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||
cp -r ${examples_dir}/nodejs ${install_dir}/examples
|
||||
cp -r ${examples_dir}/C# ${install_dir}/examples
|
||||
fi
|
||||
# Copy driver
|
||||
mkdir -p ${install_dir}/driver
|
||||
|
@ -122,10 +124,11 @@ cp ${lib_files} ${install_dir}/driver
|
|||
connector_dir="${code_dir}/connector"
|
||||
mkdir -p ${install_dir}/connector
|
||||
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
|
||||
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/go ${install_dir}/connector
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/go ${install_dir}/connector
|
||||
cp -r ${connector_dir}/nodejs ${install_dir}/connector
|
||||
fi
|
||||
# Copy release note
|
||||
# cp ${script_dir}/release_note ${install_dir}
|
||||
|
@ -135,9 +138,9 @@ fi
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -25,9 +25,9 @@ release_dir="${top_dir}/release"
|
|||
|
||||
#package_name='linux'
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
install_dir="${release_dir}/PowerDB-enterprise-server"
|
||||
install_dir="${release_dir}/PowerDB-enterprise-server-${version}"
|
||||
else
|
||||
install_dir="${release_dir}/PowerDB-server"
|
||||
install_dir="${release_dir}/PowerDB-server-${version}"
|
||||
fi
|
||||
|
||||
# Directories and files.
|
||||
|
@ -146,7 +146,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
cp -r ${examples_dir}/R ${install_dir}/examples
|
||||
sed -i '/password/ {s/taosdata/powerdb/g}' ${install_dir}/examples/R/command.txt
|
||||
cp -r ${examples_dir}/go ${install_dir}/examples
|
||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/src/taosapp/taosapp.go
|
||||
sed -i '/root/ {s/taosdata/powerdb/g}' ${install_dir}/examples/go/taosdemo.go
|
||||
fi
|
||||
# Copy driver
|
||||
mkdir -p ${install_dir}/driver
|
||||
|
@ -156,7 +156,7 @@ cp ${lib_files} ${install_dir}/driver
|
|||
connector_dir="${code_dir}/connector"
|
||||
mkdir -p ${install_dir}/connector
|
||||
if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector
|
||||
cp ${build_dir}/lib/*.jar ${install_dir}/connector ||:
|
||||
cp -r ${connector_dir}/grafanaplugin ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/python ${install_dir}/connector/
|
||||
cp -r ${connector_dir}/go ${install_dir}/connector
|
||||
|
@ -184,9 +184,9 @@ fi
|
|||
cd ${release_dir}
|
||||
|
||||
if [ "$verMode" == "cluster" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
elif [ "$verMode" == "edge" ]; then
|
||||
pkg_name=${install_dir}-${version}-${osType}-${cpuType}
|
||||
pkg_name=${install_dir}-${osType}-${cpuType}
|
||||
else
|
||||
echo "unknow verMode, nor cluster or edge"
|
||||
exit 1
|
||||
|
|
|
@ -10,6 +10,7 @@ data_dir="/var/lib/taos"
|
|||
log_dir="/var/log/taos"
|
||||
data_link_dir="/usr/local/taos/data"
|
||||
log_link_dir="/usr/local/taos/log"
|
||||
install_main_dir="/usr/local/taos"
|
||||
|
||||
# static directory
|
||||
cfg_dir="/usr/local/taos/cfg"
|
||||
|
@ -134,6 +135,29 @@ function install_config() {
|
|||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
# user email
|
||||
#EMAIL_PATTERN='^[A-Za-z0-9\u4e00-\u9fa5]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$'
|
||||
#EMAIL_PATTERN='^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$'
|
||||
#EMAIL_PATTERN="^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$"
|
||||
echo
|
||||
echo -e -n "${GREEN}Enter your email address for priority support or enter empty to skip${NC}: "
|
||||
read emailAddr
|
||||
while true; do
|
||||
if [ ! -z "$emailAddr" ]; then
|
||||
# check the format of the emailAddr
|
||||
#if [[ "$emailAddr" =~ $EMAIL_PATTERN ]]; then
|
||||
# Write the email address to temp file
|
||||
email_file="${install_main_dir}/email"
|
||||
${csudo} bash -c "echo $emailAddr > ${email_file}"
|
||||
break
|
||||
#else
|
||||
# read -p "Please enter the correct email address: " emailAddr
|
||||
#fi
|
||||
else
|
||||
break
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: tdengine
|
||||
base: core18
|
||||
version: 'RELEASE_VERSION'
|
||||
version: '2.0.6.0'
|
||||
icon: snap/gui/t-dengine.svg
|
||||
summary: an open-source big data platform designed and optimized for IoT.
|
||||
description: |
|
||||
|
@ -72,7 +72,7 @@ parts:
|
|||
- usr/bin/taosd
|
||||
- usr/bin/taos
|
||||
- usr/bin/taosdemo
|
||||
- usr/lib/libtaos.so.RELEASE_VERSION
|
||||
- usr/lib/libtaos.so.2.0.6.0
|
||||
- usr/lib/libtaos.so.1
|
||||
- usr/lib/libtaos.so
|
||||
|
||||
|
|
|
@ -20,4 +20,6 @@ ADD_SUBDIRECTORY(tsdb)
|
|||
ADD_SUBDIRECTORY(wal)
|
||||
ADD_SUBDIRECTORY(cq)
|
||||
ADD_SUBDIRECTORY(dnode)
|
||||
ADD_SUBDIRECTORY(connector/odbc)
|
||||
ADD_SUBDIRECTORY(connector/jdbc)
|
||||
|
||||
|
|
|
@ -126,6 +126,8 @@ int32_t balanceAllocVnodes(SVgObj *pVgroup) {
|
|||
|
||||
balanceAccquireDnodeList();
|
||||
|
||||
mDebug("db:%s, try alloc %d vnodes to vgroup, dnodes total:%d, avail:%d", pVgroup->dbName, pVgroup->numOfVnodes,
|
||||
mnodeGetDnodesNum(), tsBalanceDnodeListSize);
|
||||
for (int32_t i = 0; i < pVgroup->numOfVnodes; ++i) {
|
||||
for (; dnode < tsBalanceDnodeListSize; ++dnode) {
|
||||
SDnodeObj *pDnode = tsBalanceDnodeList[dnode];
|
||||
|
@ -135,17 +137,33 @@ int32_t balanceAllocVnodes(SVgObj *pVgroup) {
|
|||
pVnodeGid->pDnode = pDnode;
|
||||
dnode++;
|
||||
vnodes++;
|
||||
mDebug("dnode:%d, is selected, vnodeIndex:%d", pDnode->dnodeId, i);
|
||||
break;
|
||||
} else {
|
||||
mDebug("dnode:%d, is not selected, status:%s vnodes:%d disk:%fGB role:%d", pDnode->dnodeId,
|
||||
mnodeGetDnodeStatusStr(pDnode->status), pDnode->openVnodes, pDnode->diskAvailable,
|
||||
pDnode->alternativeRole);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (vnodes != pVgroup->numOfVnodes) {
|
||||
mDebug("vgId:%d, db:%s need vnodes:%d, but alloc:%d, free them", pVgroup->vgId, pVgroup->dbName,
|
||||
pVgroup->numOfVnodes, vnodes);
|
||||
balanceReleaseDnodeList();
|
||||
balanceUnLock();
|
||||
|
||||
mDebug("db:%s, need vnodes:%d, but alloc:%d", pVgroup->dbName, pVgroup->numOfVnodes, vnodes);
|
||||
|
||||
void * pIter = NULL;
|
||||
SDnodeObj *pDnode = NULL;
|
||||
while (1) {
|
||||
pIter = mnodeGetNextDnode(pIter, &pDnode);
|
||||
if (pDnode == NULL) break;
|
||||
mDebug("dnode:%d, status:%s vnodes:%d disk:%fGB role:%d", pDnode->dnodeId, mnodeGetDnodeStatusStr(pDnode->status),
|
||||
pDnode->openVnodes, pDnode->diskAvailable, pDnode->alternativeRole);
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
}
|
||||
sdbFreeIter(pIter);
|
||||
|
||||
if (mnodeGetOnlineDnodesNum() == 0) {
|
||||
return TSDB_CODE_MND_NOT_READY;
|
||||
} else {
|
||||
|
@ -198,8 +216,8 @@ static bool balanceCheckVgroupReady(SVgObj *pVgroup, SVnodeGid *pRmVnode) {
|
|||
SVnodeGid *pVnode = pVgroup->vnodeGid + i;
|
||||
if (pVnode == pRmVnode) continue;
|
||||
|
||||
mTrace("vgId:%d, change vgroup status, dnode:%d status:%d", pVgroup->vgId, pVnode->pDnode->dnodeId,
|
||||
pVnode->pDnode->status);
|
||||
mTrace("vgId:%d, check vgroup status, dnode:%d status:%d, vnode role:%s", pVgroup->vgId, pVnode->pDnode->dnodeId,
|
||||
pVnode->pDnode->status, syncRole[pVnode->role]);
|
||||
if (pVnode->pDnode->status == TAOS_DN_STATUS_DROPPING) continue;
|
||||
if (pVnode->pDnode->status == TAOS_DN_STATUS_OFFLINE) continue;
|
||||
|
||||
|
@ -389,6 +407,7 @@ void balanceReset() {
|
|||
pDnode->lastAccess = 0;
|
||||
if (pDnode->status != TAOS_DN_STATUS_DROPPING) {
|
||||
pDnode->status = TAOS_DN_STATUS_OFFLINE;
|
||||
pDnode->offlineReason = TAOS_DN_OFF_STATUS_NOT_RECEIVED;
|
||||
}
|
||||
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
|
@ -551,7 +570,9 @@ static void balanceCheckDnodeAccess() {
|
|||
if (tsAccessSquence - pDnode->lastAccess > 3) {
|
||||
if (pDnode->status != TAOS_DN_STATUS_DROPPING && pDnode->status != TAOS_DN_STATUS_OFFLINE) {
|
||||
pDnode->status = TAOS_DN_STATUS_OFFLINE;
|
||||
mInfo("dnode:%d, set to offline state", pDnode->dnodeId);
|
||||
pDnode->offlineReason = TAOS_DN_OFF_STATUS_MSG_TIMEOUT;
|
||||
mInfo("dnode:%d, set to offline state, access seq:%d, last seq:%d", pDnode->dnodeId, tsAccessSquence,
|
||||
pDnode->lastAccess);
|
||||
balanceSetVgroupOffline(pDnode);
|
||||
}
|
||||
}
|
||||
|
@ -935,6 +956,7 @@ static int32_t balanceRetrieveScores(SShowObj *pShow, char *data, int32_t rows,
|
|||
mnodeDecDnodeRef(pDnode);
|
||||
}
|
||||
|
||||
mnodeVacuumResult(data, pShow->numOfColumns, numOfRows, rows, pShow);
|
||||
pShow->numOfReads += numOfRows;
|
||||
return numOfRows;
|
||||
}
|
||||
|
@ -955,11 +977,16 @@ static void balanceMonitorDnodeModule() {
|
|||
continue;
|
||||
}
|
||||
|
||||
mLInfo("dnode:%d, numOfMnodes:%d expect:%d, add mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes);
|
||||
mnodeAddMnode(pDnode->dnodeId);
|
||||
|
||||
mLInfo("dnode:%d, numOfMnodes:%d expect:%d, create mnode in this dnode", pDnode->dnodeId, numOfMnodes, tsNumOfMnodes);
|
||||
mnodeCreateMnode(pDnode->dnodeId, pDnode->dnodeEp, true);
|
||||
|
||||
#if 0
|
||||
// Only create one mnode each time
|
||||
return;
|
||||
#else
|
||||
numOfMnodes = mnodeGetMnodesNum();
|
||||
if (numOfMnodes >= tsNumOfMnodes) return;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -72,17 +72,10 @@ typedef struct SLocalReducer {
|
|||
bool orderPrjOnSTable; // projection query on stable
|
||||
} SLocalReducer;
|
||||
|
||||
typedef struct SSubqueryState {
|
||||
int32_t numOfRemain; // the number of remain unfinished subquery
|
||||
int32_t numOfTotal; // the number of total sub-queries
|
||||
uint64_t numOfRetrievedRows; // total number of points in this query
|
||||
} SSubqueryState;
|
||||
|
||||
typedef struct SRetrieveSupport {
|
||||
tExtMemBuffer ** pExtMemBuffer; // for build loser tree
|
||||
tOrderDescriptor *pOrderDescriptor;
|
||||
SColumnModel * pFinalColModel; // colModel for final result
|
||||
SSubqueryState * pState;
|
||||
int32_t subqueryIndex; // index of current vnode in vnode list
|
||||
SSqlObj * pParentSql;
|
||||
tFilePage * localBuffer; // temp buffer, there is a buffer for each vnode to
|
||||
|
|
|
@ -28,7 +28,7 @@ void tscFetchDatablockFromSubquery(SSqlObj* pSql);
|
|||
void tscSetupOutputColumnIndex(SSqlObj* pSql);
|
||||
void tscJoinQueryCallback(void* param, TAOS_RES* tres, int code);
|
||||
|
||||
SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState, int32_t index);
|
||||
SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, int32_t index);
|
||||
|
||||
void tscHandleMasterJoinQuery(SSqlObj* pSql);
|
||||
|
||||
|
@ -39,7 +39,7 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql);
|
|||
int32_t tscHandleInsertRetry(SSqlObj* pSql);
|
||||
|
||||
void tscBuildResFromSubqueries(SSqlObj *pSql);
|
||||
void **doSetResultRowData(SSqlObj *pSql, bool finalResult);
|
||||
TAOS_ROW doSetResultRowData(SSqlObj *pSql, bool finalResult);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -66,7 +66,6 @@ typedef struct STidTags {
|
|||
#pragma pack(pop)
|
||||
|
||||
typedef struct SJoinSupporter {
|
||||
SSubqueryState* pState;
|
||||
SSqlObj* pObj; // parent SqlObj
|
||||
int32_t subqueryIndex; // index of sub query
|
||||
SInterval interval;
|
||||
|
@ -83,6 +82,7 @@ typedef struct SJoinSupporter {
|
|||
char* pIdTagList; // result of first stage tags
|
||||
int32_t totalLen;
|
||||
int32_t num;
|
||||
SArray* pVgroupTables;
|
||||
} SJoinSupporter;
|
||||
|
||||
typedef struct SVgroupTableInfo {
|
||||
|
@ -110,7 +110,6 @@ SParamInfo* tscAddParamToDataBlock(STableDataBlocks* pDataBlock, char type, uint
|
|||
|
||||
void* tscDestroyBlockArrayList(SArray* pDataBlockList);
|
||||
int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock);
|
||||
void tscFreeUnusedDataBlocks(SArray* pDataBlockList);
|
||||
int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pDataList);
|
||||
int32_t tscGetDataBlockFromList(void* pHashList, SArray* pDataBlockList, int64_t id, int32_t size,
|
||||
int32_t startOffset, int32_t rowSize, const char* tableId, STableMeta* pTableMeta,
|
||||
|
@ -151,14 +150,13 @@ int tscAllocPayload(SSqlCmd* pCmd, int size);
|
|||
|
||||
TAOS_FIELD tscCreateField(int8_t type, const char* name, int16_t bytes);
|
||||
|
||||
SFieldSupInfo* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField);
|
||||
SFieldSupInfo* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* field);
|
||||
SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField);
|
||||
SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* field);
|
||||
|
||||
SFieldSupInfo* tscFieldInfoGetSupp(SFieldInfo* pFieldInfo, int32_t index);
|
||||
SInternalField* tscFieldInfoGetInternalField(SFieldInfo* pFieldInfo, int32_t index);
|
||||
TAOS_FIELD* tscFieldInfoGetField(SFieldInfo* pFieldInfo, int32_t index);
|
||||
|
||||
void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo);
|
||||
void tscFieldInfoCopy(SFieldInfo* dst, const SFieldInfo* src);
|
||||
void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo);
|
||||
|
||||
int16_t tscFieldInfoGetOffset(SQueryInfo* pQueryInfo, int32_t index);
|
||||
|
@ -191,6 +189,7 @@ SColumn* tscColumnListInsert(SArray* pColList, SColumnIndex* colIndex);
|
|||
SArray* tscColumnListClone(const SArray* src, int16_t tableIndex);
|
||||
void tscColumnListDestroy(SArray* pColList);
|
||||
|
||||
void tscDequoteAndTrimToken(SStrToken* pToken);
|
||||
int32_t tscValidateName(SStrToken* pToken);
|
||||
|
||||
void tscIncStreamExecutionCount(void* pStream);
|
||||
|
@ -206,8 +205,6 @@ void tscTagCondRelease(STagCond* pCond);
|
|||
|
||||
void tscGetSrcColumnInfo(SSrcColumnInfo* pColInfo, SQueryInfo* pQueryInfo);
|
||||
|
||||
void tscSetFreeHeatBeat(STscObj* pObj);
|
||||
bool tscShouldFreeHeartBeat(SSqlObj* pHb);
|
||||
bool tscShouldBeFreed(SSqlObj* pSql);
|
||||
|
||||
STableMetaInfo* tscGetTableMetaInfoFromCmd(SSqlCmd *pCmd, int32_t subClauseIndex, int32_t tableIndex);
|
||||
|
@ -219,7 +216,7 @@ SQueryInfo *tscGetQueryInfoDetailSafely(SSqlCmd *pCmd, int32_t subClauseIndex);
|
|||
void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache);
|
||||
|
||||
STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, STableMeta* pTableMeta,
|
||||
SVgroupsInfo* vgroupList, SArray* pTagCols);
|
||||
SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables);
|
||||
|
||||
STableMetaInfo* tscAddEmptyMetaInfo(SQueryInfo *pQueryInfo);
|
||||
int32_t tscAddSubqueryInfo(SSqlCmd *pCmd);
|
||||
|
@ -228,16 +225,19 @@ void tscInitQueryInfo(SQueryInfo* pQueryInfo);
|
|||
|
||||
void tscClearSubqueryInfo(SSqlCmd* pCmd);
|
||||
void tscFreeVgroupTableInfo(SArray* pVgroupTables);
|
||||
SArray* tscCloneVgroupTableInfo(SArray* pVgroupTables);
|
||||
void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index);
|
||||
|
||||
int tscGetSTableVgroupInfo(SSqlObj* pSql, int32_t clauseIndex);
|
||||
int tscGetTableMeta(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo);
|
||||
int tscGetMeterMetaEx(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, bool createIfNotExists);
|
||||
|
||||
void tscResetForNextRetrieve(SSqlRes* pRes);
|
||||
|
||||
void tscAddTimestampColumn(SQueryInfo* pQueryInfo, int16_t functionId, int16_t tableIndex);
|
||||
void tscDoQuery(SSqlObj* pSql);
|
||||
|
||||
SVgroupsInfo* tscVgroupInfoClone(SVgroupsInfo *pInfo);
|
||||
void* tscVgroupInfoClear(SVgroupsInfo *pInfo);
|
||||
void tscSCMVgroupInfoCopy(SCMVgroupInfo* dst, const SCMVgroupInfo* src);
|
||||
/**
|
||||
* The create object function must be successful expect for the out of memory issue.
|
||||
*
|
||||
|
@ -257,6 +257,8 @@ void tscDoQuery(SSqlObj* pSql);
|
|||
*/
|
||||
SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cmd);
|
||||
|
||||
void registerSqlObj(SSqlObj* pSql);
|
||||
|
||||
SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void* param, int32_t cmd, SSqlObj* pPrevSql);
|
||||
void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClauseIndex, int32_t tableIndex);
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ extern "C" {
|
|||
#include "tsqlfunction.h"
|
||||
#include "tutil.h"
|
||||
#include "tcache.h"
|
||||
#include "tref.h"
|
||||
|
||||
#include "qExecutor.h"
|
||||
#include "qSqlparser.h"
|
||||
|
@ -80,6 +81,8 @@ enum {
|
|||
DATA_FROM_DATA_FILE = 2,
|
||||
};
|
||||
|
||||
typedef void (*__async_cb_func_t)(void *param, TAOS_RES *tres, int32_t numOfRows);
|
||||
|
||||
typedef struct STableComInfo {
|
||||
uint8_t numOfTags;
|
||||
uint8_t precision;
|
||||
|
@ -88,10 +91,10 @@ typedef struct STableComInfo {
|
|||
} STableComInfo;
|
||||
|
||||
typedef struct SCMCorVgroupInfo {
|
||||
int32_t version;
|
||||
int8_t inUse;
|
||||
int8_t numOfEps;
|
||||
SEpAddr epAddr[TSDB_MAX_REPLICA];
|
||||
int32_t version;
|
||||
int8_t inUse;
|
||||
int8_t numOfEps;
|
||||
SEpAddr1 epAddr[TSDB_MAX_REPLICA];
|
||||
} SCMCorVgroupInfo;
|
||||
|
||||
typedef struct STableMeta {
|
||||
|
@ -99,6 +102,7 @@ typedef struct STableMeta {
|
|||
uint8_t tableType;
|
||||
int16_t sversion;
|
||||
int16_t tversion;
|
||||
char sTableId[TSDB_TABLE_FNAME_LEN];
|
||||
SCMVgroupInfo vgroupInfo;
|
||||
SCMCorVgroupInfo corVgroupInfo;
|
||||
STableId id;
|
||||
|
@ -106,7 +110,7 @@ typedef struct STableMeta {
|
|||
} STableMeta;
|
||||
|
||||
typedef struct STableMetaInfo {
|
||||
STableMeta * pTableMeta; // table meta, cached in client side and acquired by name
|
||||
STableMeta *pTableMeta; // table meta, cached in client side and acquired by name
|
||||
SVgroupsInfo *vgroupList;
|
||||
SArray *pVgroupTables; // SArray<SVgroupTableInfo>
|
||||
|
||||
|
@ -139,16 +143,17 @@ typedef struct SColumnIndex {
|
|||
int16_t columnIndex;
|
||||
} SColumnIndex;
|
||||
|
||||
typedef struct SFieldSupInfo {
|
||||
typedef struct SInternalField {
|
||||
TAOS_FIELD field;
|
||||
bool visible;
|
||||
SExprInfo *pArithExprInfo;
|
||||
SSqlExpr *pSqlExpr;
|
||||
} SFieldSupInfo;
|
||||
} SInternalField;
|
||||
|
||||
typedef struct SFieldInfo {
|
||||
int16_t numOfOutput; // number of column in result
|
||||
SArray *pFields; // SArray<TAOS_FIELD>
|
||||
SArray *pSupportInfo; // SArray<SFieldSupInfo>
|
||||
int16_t numOfOutput; // number of column in result
|
||||
TAOS_FIELD* final;
|
||||
SArray *internalField; // SArray<SInternalField>
|
||||
} SFieldInfo;
|
||||
|
||||
typedef struct SColumn {
|
||||
|
@ -225,10 +230,9 @@ typedef struct STableDataBlocks {
|
|||
typedef struct SQueryInfo {
|
||||
int16_t command; // the command may be different for each subclause, so keep it seperately.
|
||||
uint32_t type; // query/insert type
|
||||
// TODO refactor
|
||||
|
||||
STimeWindow window; // query time window
|
||||
SInterval interval;
|
||||
int32_t tz; // query client timezone
|
||||
|
||||
SSqlGroupbyExpr groupbyExpr; // group by tags info
|
||||
SArray * colList; // SArray<SColumn*>
|
||||
|
@ -260,7 +264,7 @@ typedef struct {
|
|||
};
|
||||
|
||||
int32_t insertType;
|
||||
int32_t clauseIndex; // index of multiple subclause query
|
||||
int32_t clauseIndex; // index of multiple subclause query
|
||||
|
||||
char * curSql; // current sql, resume position of sql after parsing paused
|
||||
int8_t parseFinished;
|
||||
|
@ -275,7 +279,8 @@ typedef struct {
|
|||
int32_t numOfParams;
|
||||
|
||||
int8_t dataSourceType; // load data from file or not
|
||||
int8_t submitSchema; // submit block is built with table schema
|
||||
int8_t submitSchema; // submit block is built with table schema
|
||||
STagData tagData;
|
||||
SHashObj *pTableList; // referred table involved in sql
|
||||
SArray *pDataBlocks; // SArray<STableDataBlocks*> submit data blocks after parsing sql
|
||||
} SSqlCmd;
|
||||
|
@ -305,7 +310,7 @@ typedef struct {
|
|||
int32_t numOfGroups;
|
||||
SResRec * pGroupRec;
|
||||
char * data;
|
||||
void ** tsrow;
|
||||
TAOS_ROW tsrow;
|
||||
int32_t* length; // length for each field for current row
|
||||
char ** buffer; // Buffer used to put multibytes encoded using unicode (wchar_t)
|
||||
SColumnIndex * pColumnIndex;
|
||||
|
@ -333,6 +338,12 @@ typedef struct STscObj {
|
|||
T_REF_DECLARE()
|
||||
} STscObj;
|
||||
|
||||
typedef struct SSubqueryState {
|
||||
int32_t numOfRemain; // the number of remain unfinished subquery
|
||||
int32_t numOfSub; // the number of total sub-queries
|
||||
uint64_t numOfRetrievedRows; // total number of points in this query
|
||||
} SSubqueryState;
|
||||
|
||||
typedef struct SSqlObj {
|
||||
void *signature;
|
||||
pthread_t owner; // owner of sql object, by which it is executed
|
||||
|
@ -354,10 +365,11 @@ typedef struct SSqlObj {
|
|||
tsem_t rspSem;
|
||||
SSqlCmd cmd;
|
||||
SSqlRes res;
|
||||
uint16_t numOfSubs;
|
||||
struct SSqlObj **pSubs;
|
||||
struct SSqlObj * prev, *next;
|
||||
|
||||
SSubqueryState subState;
|
||||
struct SSqlObj **pSubs;
|
||||
|
||||
struct SSqlObj *prev, *next;
|
||||
struct SSqlObj **self;
|
||||
} SSqlObj;
|
||||
|
||||
|
@ -432,19 +444,20 @@ void tscPartiallyFreeSqlObj(SSqlObj *pSql);
|
|||
* @param pObj
|
||||
*/
|
||||
void tscFreeSqlObj(SSqlObj *pSql);
|
||||
void tscFreeRegisteredSqlObj(void *pSql);
|
||||
void tscFreeTableMetaHelper(void *pTableMeta);
|
||||
|
||||
void tscFreeSqlObjInCache(void *pSql);
|
||||
|
||||
void tscCloseTscObj(STscObj *pObj);
|
||||
void tscCloseTscObj(void *pObj);
|
||||
|
||||
// todo move to taos? or create a new file: taos_internal.h
|
||||
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
|
||||
void *param, void **taos);
|
||||
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) ;
|
||||
void *param, TAOS **taos);
|
||||
TAOS_RES* taos_query_h(TAOS* taos, const char *sqlstr, TAOS_RES** res);
|
||||
void waitForQueryRsp(void *param, TAOS_RES *tres, int code);
|
||||
|
||||
void doAsyncQuery(STscObj *pObj, SSqlObj *pSql, void (*fp)(), void *param, const char *sqlstr, size_t sqlLen);
|
||||
void doAsyncQuery(STscObj *pObj, SSqlObj *pSql, __async_cb_func_t fp, void *param, const char *sqlstr, size_t sqlLen);
|
||||
|
||||
void tscProcessMultiVnodesImportFromFile(SSqlObj *pSql);
|
||||
void tscKillSTableQuery(SSqlObj *pSql);
|
||||
void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen);
|
||||
bool tscIsUpdateQuery(SSqlObj* pSql);
|
||||
bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes);
|
||||
|
@ -457,7 +470,7 @@ int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* s
|
|||
int32_t tscToSQLCmd(SSqlObj *pSql, struct SSqlInfo *pInfo);
|
||||
|
||||
static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pFieldInfo, int32_t columnIndex) {
|
||||
SFieldSupInfo* pInfo = (SFieldSupInfo*) TARRAY_GET_ELEM(pFieldInfo->pSupportInfo, columnIndex);
|
||||
SInternalField* pInfo = (SInternalField*) TARRAY_GET_ELEM(pFieldInfo->internalField, columnIndex);
|
||||
assert(pInfo->pSqlExpr != NULL);
|
||||
|
||||
int32_t type = pInfo->pSqlExpr->resType;
|
||||
|
@ -470,11 +483,11 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField
|
|||
if (type == TSDB_DATA_TYPE_NCHAR || type == TSDB_DATA_TYPE_BINARY) {
|
||||
pData = pInfo->pSqlExpr->param[1].pz;
|
||||
pRes->length[columnIndex] = pInfo->pSqlExpr->param[1].nLen;
|
||||
pRes->tsrow[columnIndex] = (pInfo->pSqlExpr->param[1].nType == TSDB_DATA_TYPE_NULL) ? NULL : pData;
|
||||
pRes->tsrow[columnIndex] = (pInfo->pSqlExpr->param[1].nType == TSDB_DATA_TYPE_NULL) ? NULL : (unsigned char*)pData;
|
||||
} else {
|
||||
assert(bytes == tDataTypeDesc[type].nSize);
|
||||
|
||||
pRes->tsrow[columnIndex] = isNull(pData, type) ? NULL : &pInfo->pSqlExpr->param[1].i64Key;
|
||||
pRes->tsrow[columnIndex] = isNull(pData, type) ? NULL : (unsigned char*)&pInfo->pSqlExpr->param[1].i64Key;
|
||||
pRes->length[columnIndex] = bytes;
|
||||
}
|
||||
} else {
|
||||
|
@ -482,7 +495,7 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField
|
|||
int32_t realLen = varDataLen(pData);
|
||||
assert(realLen <= bytes - VARSTR_HEADER_SIZE);
|
||||
|
||||
pRes->tsrow[columnIndex] = (isNull(pData, type)) ? NULL : ((tstr *)pData)->data;
|
||||
pRes->tsrow[columnIndex] = (isNull(pData, type)) ? NULL : (unsigned char*)((tstr *)pData)->data;
|
||||
if (realLen < pInfo->pSqlExpr->resBytes - VARSTR_HEADER_SIZE) { // todo refactor
|
||||
*(pData + realLen + VARSTR_HEADER_SIZE) = 0;
|
||||
}
|
||||
|
@ -491,7 +504,7 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField
|
|||
} else {
|
||||
assert(bytes == tDataTypeDesc[type].nSize);
|
||||
|
||||
pRes->tsrow[columnIndex] = isNull(pData, type) ? NULL : pData;
|
||||
pRes->tsrow[columnIndex] = isNull(pData, type) ? NULL : (unsigned char*)pData;
|
||||
pRes->length[columnIndex] = bytes;
|
||||
}
|
||||
}
|
||||
|
@ -504,13 +517,12 @@ extern void * tscQhandle;
|
|||
extern int tscKeepConn[];
|
||||
extern int tsInsertHeadSize;
|
||||
extern int tscNumOfThreads;
|
||||
extern int tscRefId;
|
||||
|
||||
extern SRpcCorEpSet tscMgmtEpSet;
|
||||
|
||||
extern int (*tscBuildMsg[TSDB_SQL_MAX])(SSqlObj *pSql, SSqlInfo *pInfo);
|
||||
|
||||
typedef void (*__async_cb_func_t)(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
int32_t tscCompareTidTags(const void* p1, const void* p2);
|
||||
void tscBuildVgroupTableInfo(SSqlObj* pSql, STableMetaInfo* pTableMetaInfo, SArray* tables);
|
||||
|
||||
|
|
|
@ -149,7 +149,7 @@ JNIEXPORT void JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_initImp(JNIEnv *e
|
|||
JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv *env, jobject jobj, jint optionIndex,
|
||||
jstring optionValue) {
|
||||
if (optionValue == NULL) {
|
||||
jniDebug("option index:%d value is null", optionIndex);
|
||||
jniDebug("option index:%d value is null", (int32_t)optionIndex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -183,7 +183,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_setOptions(JNIEnv
|
|||
}
|
||||
(*env)->ReleaseStringUTFChars(env, optionValue, tz1);
|
||||
} else {
|
||||
jniError("option index:%d is not found", optionIndex);
|
||||
jniError("option index:%d is not found", (int32_t)optionIndex);
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -227,10 +227,10 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn
|
|||
ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport);
|
||||
if (ret == 0) {
|
||||
jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
|
||||
(char *)host, (char *)user, (char *)dbname, jport);
|
||||
(char *)host, (char *)user, (char *)dbname, (int32_t)jport);
|
||||
} else {
|
||||
jniDebug("jobj:%p, conn:%p, connect to database succeed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret,
|
||||
(char *)host, (char *)user, (char *)dbname, jport);
|
||||
(char *)host, (char *)user, (char *)dbname, (int32_t)jport);
|
||||
}
|
||||
|
||||
if (host != NULL) (*env)->ReleaseStringUTFChars(env, jhost, host);
|
||||
|
@ -385,7 +385,7 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_getAffectedRowsIm
|
|||
}
|
||||
|
||||
jint ret = taos_affected_rows((SSqlObj *)res);
|
||||
jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (void *)con, (void *)res, ret);
|
||||
jniDebug("jobj:%p, conn:%p, sql:%p, res: %p, affect rows:%d", jobj, tscon, (void *)con, (void *)res, (int32_t)ret);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -490,13 +490,13 @@ JNIEXPORT jint JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_fetchRowImp(JNIEn
|
|||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetBooleanFp, i, (jboolean)(*((char *)row[i]) == 1));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteFp, i, (jbyte) * ((char *)row[i]));
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetByteFp, i, (jbyte) * ((int8_t *)row[i]));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetShortFp, i, (jshort) * ((short *)row[i]));
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetShortFp, i, (jshort) * ((int16_t *)row[i]));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetIntFp, i, (jint) * (int *)row[i]);
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetIntFp, i, (jint) * (int32_t *)row[i]);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
(*env)->CallVoidMethod(env, rowobj, g_rowdataSetLongFp, i, (jlong) * ((int64_t *)row[i]));
|
||||
|
|
|
@ -40,7 +40,7 @@ static void tscProcessAsyncRetrieveImpl(void *param, TAOS_RES *tres, int numOfRo
|
|||
static void tscAsyncFetchRowsProxy(void *param, TAOS_RES *tres, int numOfRows);
|
||||
static void tscAsyncFetchSingleRowProxy(void *param, TAOS_RES *tres, int numOfRows);
|
||||
|
||||
void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const char* sqlstr, size_t sqlLen) {
|
||||
void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, __async_cb_func_t fp, void* param, const char* sqlstr, size_t sqlLen) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
pSql->signature = pSql;
|
||||
|
@ -51,10 +51,7 @@ void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const
|
|||
pSql->fp = fp;
|
||||
pSql->fetchFp = fp;
|
||||
|
||||
uint64_t handle = (uint64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &handle, sizeof(uint64_t), &pSql, sizeof(uint64_t), 2*3600*1000);
|
||||
|
||||
T_REF_INC(pSql->pTscObj);
|
||||
registerSqlObj(pSql);
|
||||
|
||||
pSql->sqlstr = calloc(1, sqlLen + 1);
|
||||
if (pSql->sqlstr == NULL) {
|
||||
|
@ -330,7 +327,7 @@ void tscAsyncFetchSingleRowProxy(void *param, TAOS_RES *tres, int numOfRows) {
|
|||
}
|
||||
|
||||
for (int i = 0; i < pCmd->numOfCols; ++i){
|
||||
SFieldSupInfo* pSup = taosArrayGet(pQueryInfo->fieldsInfo.pSupportInfo, i);
|
||||
SInternalField* pSup = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
|
||||
if (pSup->pSqlExpr != NULL) {
|
||||
// pRes->tsrow[i] = TSC_GET_RESPTR_BASE(pRes, pQueryInfo, i) + pSup->pSqlExpr->resBytes * pRes->row;
|
||||
} else {
|
||||
|
@ -351,7 +348,7 @@ void tscProcessFetchRow(SSchedMsg *pMsg) {
|
|||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
for (int i = 0; i < pCmd->numOfCols; ++i) {
|
||||
SFieldSupInfo* pSup = taosArrayGet(pQueryInfo->fieldsInfo.pSupportInfo, i);
|
||||
SInternalField* pSup = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
|
||||
|
||||
if (pSup->pSqlExpr != NULL) {
|
||||
tscGetResultColumnChr(pRes, &pQueryInfo->fieldsInfo, i);
|
||||
|
@ -364,15 +361,6 @@ void tscProcessFetchRow(SSchedMsg *pMsg) {
|
|||
(*pSql->fetchFp)(pSql->param, pSql, pRes->tsrow);
|
||||
}
|
||||
|
||||
void tscProcessAsyncRes(SSchedMsg *pMsg) {
|
||||
SSqlObj *pSql = (SSqlObj *)pMsg->ahandle;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
assert(pSql->fp != NULL && pSql->fetchFp != NULL);
|
||||
|
||||
pSql->fp = pSql->fetchFp;
|
||||
(*pSql->fp)(pSql->param, pSql, pRes->code);
|
||||
}
|
||||
|
||||
// this function will be executed by queue task threads, so the terrno is not valid
|
||||
static void tscProcessAsyncError(SSchedMsg *pMsg) {
|
||||
void (*fp)() = pMsg->ahandle;
|
||||
|
@ -396,22 +384,15 @@ void tscQueueAsyncRes(SSqlObj *pSql) {
|
|||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
tscDebug("%p SqlObj is freed, not add into queue async res", pSql);
|
||||
return;
|
||||
} else {
|
||||
tscError("%p add into queued async res, code:%s", pSql, tstrerror(pSql->res.code));
|
||||
}
|
||||
|
||||
SSchedMsg schedMsg = { 0 };
|
||||
schedMsg.fp = tscProcessAsyncRes;
|
||||
schedMsg.ahandle = pSql;
|
||||
schedMsg.thandle = (void *)1;
|
||||
schedMsg.msg = NULL;
|
||||
taosScheduleTask(tscQhandle, &schedMsg);
|
||||
}
|
||||
tscError("%p add into queued async res, code:%s", pSql, tstrerror(pSql->res.code));
|
||||
|
||||
void tscProcessAsyncFree(SSchedMsg *pMsg) {
|
||||
SSqlObj *pSql = (SSqlObj *)pMsg->ahandle;
|
||||
tscDebug("%p sql is freed", pSql);
|
||||
taos_free_result(pSql);
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
assert(pSql->fp != NULL && pSql->fetchFp != NULL);
|
||||
|
||||
pSql->fp = pSql->fetchFp;
|
||||
(*pSql->fp)(pSql->param, pSql, pRes->code);
|
||||
}
|
||||
|
||||
int tscSendMsgToServer(SSqlObj *pSql);
|
||||
|
@ -424,11 +405,11 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
|
|||
SSqlRes *pRes = &pSql->res;
|
||||
pRes->code = code;
|
||||
|
||||
const char* msg = (pCmd->command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"table-meta";
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("%p get tableMeta failed, code:%s", pSql, tstrerror(code));
|
||||
tscError("%p get %s failed, code:%s", pSql, msg, tstrerror(code));
|
||||
goto _error;
|
||||
} else {
|
||||
const char* msg = (pCmd->command == TSDB_SQL_STABLEVGROUP)? "vgroup-list":"table-meta";
|
||||
tscDebug("%p get %s successfully", pSql, msg);
|
||||
}
|
||||
|
||||
|
@ -512,7 +493,7 @@ void tscTableMetaCallBack(void *param, TAOS_RES *res, int code) {
|
|||
goto _error;
|
||||
}
|
||||
|
||||
if (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_STMT_INSERT)) {
|
||||
if (pCmd->insertType == TSDB_QUERY_TYPE_STMT_INSERT) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
|
|
|
@ -525,7 +525,7 @@ static void do_sum(SQLFunctionCtx *pCtx) {
|
|||
*retVal += pCtx->preAggVals.statis.sum;
|
||||
} else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) {
|
||||
double *retVal = (double*) pCtx->aOutputBuf;
|
||||
*retVal += GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.sum));
|
||||
*retVal += GET_DOUBLE_VAL((const char*)&(pCtx->preAggVals.statis.sum));
|
||||
}
|
||||
} else { // computing based on the true data block
|
||||
void *pData = GET_INPUT_CHAR(pCtx);
|
||||
|
@ -768,7 +768,7 @@ static void avg_function(SQLFunctionCtx *pCtx) {
|
|||
if (pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
*pVal += pCtx->preAggVals.statis.sum;
|
||||
} else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) {
|
||||
*pVal += GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.sum));
|
||||
*pVal += GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.sum));
|
||||
}
|
||||
} else {
|
||||
void *pData = GET_INPUT_CHAR(pCtx);
|
||||
|
@ -2445,8 +2445,8 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) {
|
|||
// in the first round, get the min-max value of all involved data
|
||||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
SPercentileInfo *pInfo = pResInfo->interResultBuf;
|
||||
pInfo->minval = DBL_MAX;
|
||||
pInfo->maxval = -DBL_MAX;
|
||||
SET_DOUBLE_VAL(&pInfo->minval, DBL_MAX);
|
||||
SET_DOUBLE_VAL(&pInfo->maxval, -DBL_MAX);
|
||||
pInfo->numOfElems = 0;
|
||||
|
||||
return true;
|
||||
|
@ -2461,12 +2461,22 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
|
|||
// the first stage, only acquire the min/max value
|
||||
if (pInfo->stage == 0) {
|
||||
if (pCtx->preAggVals.isSet) {
|
||||
if (pInfo->minval > pCtx->preAggVals.statis.min) {
|
||||
pInfo->minval = (double)pCtx->preAggVals.statis.min;
|
||||
double tmin = 0.0, tmax = 0.0;
|
||||
if (pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
tmin = (double)GET_INT64_VAL(&pCtx->preAggVals.statis.min);
|
||||
tmax = (double)GET_INT64_VAL(&pCtx->preAggVals.statis.max);
|
||||
} else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) {
|
||||
tmin = GET_DOUBLE_VAL(&pCtx->preAggVals.statis.min);
|
||||
tmax = GET_DOUBLE_VAL(&pCtx->preAggVals.statis.max);
|
||||
} else {
|
||||
assert(true);
|
||||
}
|
||||
if (GET_DOUBLE_VAL(&pInfo->minval) > tmin) {
|
||||
SET_DOUBLE_VAL(&pInfo->minval, tmin);
|
||||
}
|
||||
|
||||
if (pInfo->maxval < pCtx->preAggVals.statis.max) {
|
||||
pInfo->maxval = (double)pCtx->preAggVals.statis.max;
|
||||
if (GET_DOUBLE_VAL(&pInfo->maxval) < tmax) {
|
||||
SET_DOUBLE_VAL(&pInfo->maxval, tmax);
|
||||
}
|
||||
|
||||
pInfo->numOfElems += (pCtx->size - pCtx->preAggVals.statis.numOfNull);
|
||||
|
@ -2500,12 +2510,12 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (v < pInfo->minval) {
|
||||
pInfo->minval = v;
|
||||
if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
|
||||
SET_DOUBLE_VAL(&pInfo->minval, v);
|
||||
}
|
||||
|
||||
if (v > pInfo->maxval) {
|
||||
pInfo->maxval = v;
|
||||
if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
|
||||
SET_DOUBLE_VAL(&pInfo->maxval, v);
|
||||
}
|
||||
|
||||
pInfo->numOfElems += 1;
|
||||
|
@ -2564,12 +2574,12 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
break;
|
||||
}
|
||||
|
||||
if (v < pInfo->minval) {
|
||||
pInfo->minval = v;
|
||||
if (v < GET_DOUBLE_VAL(&pInfo->minval)) {
|
||||
SET_DOUBLE_VAL(&pInfo->minval, v);
|
||||
}
|
||||
|
||||
if (v > pInfo->maxval) {
|
||||
pInfo->maxval = v;
|
||||
if (v > GET_DOUBLE_VAL(&pInfo->maxval)) {
|
||||
SET_DOUBLE_VAL(&pInfo->maxval, v);
|
||||
}
|
||||
|
||||
pInfo->numOfElems += 1;
|
||||
|
@ -2609,7 +2619,7 @@ static void percentile_next_step(SQLFunctionCtx *pCtx) {
|
|||
}
|
||||
|
||||
pInfo->stage += 1;
|
||||
pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval);
|
||||
pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, GET_DOUBLE_VAL(&pInfo->minval), GET_DOUBLE_VAL(&pInfo->maxval));
|
||||
} else {
|
||||
pResInfo->complete = true;
|
||||
}
|
||||
|
@ -3516,12 +3526,12 @@ static void spread_function(SQLFunctionCtx *pCtx) {
|
|||
pInfo->max = (double)pCtx->preAggVals.statis.max;
|
||||
}
|
||||
} else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) {
|
||||
if (pInfo->min > GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.min))) {
|
||||
pInfo->min = GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.min));
|
||||
if (pInfo->min > GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.min))) {
|
||||
pInfo->min = GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.min));
|
||||
}
|
||||
|
||||
if (pInfo->max < GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.max))) {
|
||||
pInfo->max = GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.max));
|
||||
if (pInfo->max < GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.max))) {
|
||||
pInfo->max = GET_DOUBLE_VAL((const char *)&(pCtx->preAggVals.statis.max));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4025,11 +4035,11 @@ static void ts_comp_function(SQLFunctionCtx *pCtx) {
|
|||
|
||||
// primary ts must be existed, so no need to check its existance
|
||||
if (pCtx->order == TSDB_ORDER_ASC) {
|
||||
tsBufAppend(pTSbuf, 0, &pCtx->tag, input, pCtx->size * TSDB_KEYSIZE);
|
||||
tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, input, pCtx->size * TSDB_KEYSIZE);
|
||||
} else {
|
||||
for (int32_t i = pCtx->size - 1; i >= 0; --i) {
|
||||
char *d = GET_INPUT_CHAR_INDEX(pCtx, i);
|
||||
tsBufAppend(pTSbuf, 0, &pCtx->tag, d, TSDB_KEYSIZE);
|
||||
tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, d, (int32_t)TSDB_KEYSIZE);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4048,7 +4058,7 @@ static void ts_comp_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
|
||||
STSBuf *pTSbuf = pInfo->pTSBuf;
|
||||
|
||||
tsBufAppend(pTSbuf, 0, &pCtx->tag, pData, TSDB_KEYSIZE);
|
||||
tsBufAppend(pTSbuf, (int32_t)pCtx->param[0].i64Key, &pCtx->tag, pData, TSDB_KEYSIZE);
|
||||
SET_VAL(pCtx, pCtx->size, 1);
|
||||
|
||||
pResInfo->hasResult = DATA_SET_FLAG;
|
||||
|
|
|
@ -23,7 +23,30 @@
|
|||
#include "tscUtil.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
#include "taos.h"
|
||||
#include "tscSubquery.h"
|
||||
|
||||
#define STR_NOCASE_EQUAL(str1, len1, str2, len2) ((len1 == len2) && 0 == strncasecmp(str1, str2, len1))
|
||||
|
||||
typedef enum BuildType {
|
||||
SCREATE_BUILD_TABLE = 1,
|
||||
SCREATE_BUILD_DB = 2,
|
||||
} BuildType;
|
||||
|
||||
typedef enum Stage {
|
||||
SCREATE_CALLBACK_QUERY = 1,
|
||||
SCREATE_CALLBACK_RETRIEVE = 2,
|
||||
} Stage;
|
||||
|
||||
// support 'show create table'
|
||||
typedef struct SCreateBuilder {
|
||||
char sTableName[TSDB_TABLE_FNAME_LEN];
|
||||
char buf[TSDB_TABLE_FNAME_LEN];
|
||||
SSqlObj *pParentSql;
|
||||
SSqlObj *pInterSql;
|
||||
int32_t (*fp)(void *para, char* result);
|
||||
Stage callStage;
|
||||
} SCreateBuilder;
|
||||
static void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnName, int16_t type, size_t valueLength);
|
||||
|
||||
static int32_t getToStringLength(const char *pData, int32_t length, int32_t type) {
|
||||
|
@ -216,7 +239,7 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols,
|
|||
TAOS_FIELD f = {.type = TSDB_DATA_TYPE_BINARY, .bytes = (TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE};
|
||||
tstrncpy(f.name, "Field", sizeof(f.name));
|
||||
|
||||
SFieldSupInfo* pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
SInternalField* pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
|
||||
(TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE, (TSDB_COL_NAME_LEN - 1), false);
|
||||
|
||||
|
@ -272,14 +295,511 @@ static int32_t tscProcessDescribeTable(SSqlObj *pSql) {
|
|||
tscFieldInfoUpdateOffset(pQueryInfo);
|
||||
return tscSetValueToResObj(pSql, rowLen);
|
||||
}
|
||||
static int32_t tscGetNthFieldResult(TAOS_ROW row, TAOS_FIELD* fields, int *lengths, int idx, char *result) {
|
||||
const char *val = (const char*)row[idx];
|
||||
if (val == NULL) {
|
||||
sprintf(result, "%s", TSDB_DATA_NULL_STR);
|
||||
return -1;
|
||||
}
|
||||
uint8_t type = fields[idx].type;
|
||||
int32_t length = lengths[idx];
|
||||
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
sprintf(result, "%s", ((((int32_t)(*((char *)val))) == 1) ? "true" : "false"));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
sprintf(result, "%d", *((int8_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
sprintf(result, "%d", *((int16_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
sprintf(result, "%d", *((int32_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
sprintf(result, "%"PRId64, *((int64_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
sprintf(result, "%f", GET_FLOAT_VAL(val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
sprintf(result, "%f", GET_DOUBLE_VAL(val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
memcpy(result, val, length);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
///formatTimestamp(buf, *(int64_t*)val, TSDB_TIME_PRECISION_MICRO);
|
||||
//memcpy(result, val, strlen(buf));
|
||||
sprintf(result, "%"PRId64, *((int64_t *)val));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tscSCreateCallBack(void *param, TAOS_RES *tres, int code) {
|
||||
if (param == NULL || tres == NULL) {
|
||||
return;
|
||||
}
|
||||
SCreateBuilder *builder = (SCreateBuilder *)(param);
|
||||
SSqlObj *pParentSql = builder->pParentSql;
|
||||
SSqlObj *pSql = (SSqlObj *)tres;
|
||||
|
||||
SSqlRes *pRes = &pParentSql->res;
|
||||
pRes->code = taos_errno(pSql);
|
||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||
taos_free_result(pSql);
|
||||
free(builder);
|
||||
tscQueueAsyncRes(pParentSql);
|
||||
return;
|
||||
}
|
||||
|
||||
if (builder->callStage == SCREATE_CALLBACK_QUERY) {
|
||||
taos_fetch_rows_a(tres, tscSCreateCallBack, param);
|
||||
builder->callStage = SCREATE_CALLBACK_RETRIEVE;
|
||||
} else {
|
||||
char *result = calloc(1, TSDB_MAX_BINARY_LEN);
|
||||
pRes->code = builder->fp(builder, result);
|
||||
|
||||
taos_free_result(pSql);
|
||||
free(builder);
|
||||
free(result);
|
||||
|
||||
if (pRes->code == TSDB_CODE_SUCCESS) {
|
||||
(*pParentSql->fp)(pParentSql->param, pParentSql, code);
|
||||
} else {
|
||||
tscQueueAsyncRes(pParentSql);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TAOS_ROW tscFetchRow(void *param) {
|
||||
SCreateBuilder *builder = (SCreateBuilder *)param;
|
||||
if (builder == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
SSqlObj *pSql = builder->pInterSql;
|
||||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
if (pRes->qhandle == 0 ||
|
||||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
|
||||
pCmd->command == TSDB_SQL_INSERT) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// set the sql object owner
|
||||
tscSetSqlOwner(pSql);
|
||||
|
||||
// current data set are exhausted, fetch more data from node
|
||||
if (pRes->row >= pRes->numOfRows && (pRes->completed != true || hasMoreVnodesToTry(pSql) || hasMoreClauseToTry(pSql)) &&
|
||||
(pCmd->command == TSDB_SQL_RETRIEVE ||
|
||||
pCmd->command == TSDB_SQL_RETRIEVE_LOCALMERGE ||
|
||||
pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
|
||||
pCmd->command == TSDB_SQL_FETCH ||
|
||||
pCmd->command == TSDB_SQL_SHOW ||
|
||||
pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
|
||||
pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
|
||||
pCmd->command == TSDB_SQL_SELECT ||
|
||||
pCmd->command == TSDB_SQL_DESCRIBE_TABLE ||
|
||||
pCmd->command == TSDB_SQL_SERV_STATUS ||
|
||||
pCmd->command == TSDB_SQL_CURRENT_DB ||
|
||||
pCmd->command == TSDB_SQL_SERV_VERSION ||
|
||||
pCmd->command == TSDB_SQL_CLI_VERSION ||
|
||||
pCmd->command == TSDB_SQL_CURRENT_USER )) {
|
||||
taos_fetch_rows_a(pSql, tscSCreateCallBack, param);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void* data = doSetResultRowData(pSql, true);
|
||||
|
||||
tscClearSqlOwner(pSql);
|
||||
return data;
|
||||
}
|
||||
static int32_t tscGetTableTagValue(SCreateBuilder *builder, char *result) {
|
||||
TAOS_ROW row = tscFetchRow(builder);
|
||||
SSqlObj* pSql = builder->pInterSql;
|
||||
|
||||
if (row == NULL) {
|
||||
return TSDB_CODE_TSC_INVALID_TABLE_NAME;
|
||||
}
|
||||
|
||||
int32_t* lengths = taos_fetch_lengths(pSql);
|
||||
int num_fields = taos_num_fields(pSql);
|
||||
TAOS_FIELD *fields = taos_fetch_fields(pSql);
|
||||
|
||||
char buf[TSDB_COL_NAME_LEN + 16];
|
||||
for (int i = 0; i < num_fields; i++) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
int32_t ret = tscGetNthFieldResult(row, fields, lengths, i, buf);
|
||||
|
||||
if (i == 0) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s", "(");
|
||||
}
|
||||
if ((fields[i].type == TSDB_DATA_TYPE_NCHAR
|
||||
|| fields[i].type == TSDB_DATA_TYPE_BINARY
|
||||
|| fields[i].type == TSDB_DATA_TYPE_TIMESTAMP) && 0 == ret) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "\"%s\",", buf);
|
||||
} else {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s,", buf);
|
||||
}
|
||||
if (i == num_fields - 1) {
|
||||
sprintf(result + strlen(result) - 1, "%s", ")");
|
||||
}
|
||||
}
|
||||
|
||||
if (0 == strlen(result)) {
|
||||
return TSDB_CODE_TSC_INVALID_TABLE_NAME;
|
||||
}
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
// build 'show create table/database' result fields
|
||||
static int32_t tscSCreateBuildResultFields(SSqlObj *pSql, BuildType type, const char *ddl) {
|
||||
int32_t rowLen = 0;
|
||||
int16_t ddlLen = (int16_t)strlen(ddl);
|
||||
SColumnIndex index = {0};
|
||||
pSql->cmd.numOfCols = 2;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
|
||||
TAOS_FIELD f;
|
||||
if (type == SCREATE_BUILD_TABLE) {
|
||||
f.type = TSDB_DATA_TYPE_BINARY;
|
||||
f.bytes = (TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE;
|
||||
tstrncpy(f.name, "Table", sizeof(f.name));
|
||||
} else {
|
||||
f.type = TSDB_DATA_TYPE_BINARY;
|
||||
f.bytes = (TSDB_DB_NAME_LEN - 1) + VARSTR_HEADER_SIZE;
|
||||
tstrncpy(f.name, "Database", sizeof(f.name));
|
||||
}
|
||||
|
||||
SInternalField* pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
|
||||
f.bytes, f.bytes - VARSTR_HEADER_SIZE, false);
|
||||
|
||||
rowLen += f.bytes;
|
||||
|
||||
f.bytes = (int16_t)(ddlLen + VARSTR_HEADER_SIZE);
|
||||
f.type = TSDB_DATA_TYPE_BINARY;
|
||||
if (type == SCREATE_BUILD_TABLE) {
|
||||
tstrncpy(f.name, "Create Table", sizeof(f.name));
|
||||
} else {
|
||||
tstrncpy(f.name, "Create Database", sizeof(f.name));
|
||||
}
|
||||
|
||||
pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY,
|
||||
(int16_t)(ddlLen + VARSTR_HEADER_SIZE), ddlLen, false);
|
||||
|
||||
rowLen += ddlLen + VARSTR_HEADER_SIZE;
|
||||
|
||||
return rowLen;
|
||||
}
|
||||
static int32_t tscSCreateSetValueToResObj(SSqlObj *pSql, int32_t rowLen, const char *tableName, const char *ddl) {
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
int32_t numOfRows = 1;
|
||||
if (strlen(ddl) == 0) {
|
||||
|
||||
}
|
||||
tscInitResObjForLocalQuery(pSql, numOfRows, rowLen);
|
||||
|
||||
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0);
|
||||
char* dst = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 0) * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(dst, tableName, pField->bytes);
|
||||
|
||||
pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 1);
|
||||
dst = pRes->data + tscFieldInfoGetOffset(pQueryInfo, 1) * numOfRows;
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(dst, ddl, pField->bytes);
|
||||
return 0;
|
||||
}
|
||||
static int32_t tscSCreateBuildResult(SSqlObj *pSql, BuildType type, const char *str, const char *result) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
int32_t rowLen = tscSCreateBuildResultFields(pSql, type, result);
|
||||
|
||||
tscFieldInfoUpdateOffset(pQueryInfo);
|
||||
return tscSCreateSetValueToResObj(pSql, rowLen, str, result);
|
||||
}
|
||||
int32_t tscRebuildCreateTableStatement(void *param,char *result) {
|
||||
SCreateBuilder *builder = (SCreateBuilder *)param;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
char *buf = calloc(1,TSDB_MAX_BINARY_LEN);
|
||||
if (buf == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
code = tscGetTableTagValue(builder, buf);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "CREATE TABLE %s USING %s TAGS %s", builder->buf, builder->sTableName, buf);
|
||||
code = tscSCreateBuildResult(builder->pParentSql, SCREATE_BUILD_TABLE, builder->buf, result);
|
||||
}
|
||||
free(buf);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tscGetDBInfo(SCreateBuilder *builder, char *result) {
|
||||
TAOS_ROW row = tscFetchRow(builder);
|
||||
if (row == NULL) {
|
||||
return TSDB_CODE_TSC_DB_NOT_SELECTED;
|
||||
}
|
||||
const char *showColumns[] = {"REPLICA", "QUORUM", "DAYS", "KEEP", "BLOCKS", NULL};
|
||||
|
||||
SSqlObj *pSql = builder->pInterSql;
|
||||
TAOS_FIELD *fields = taos_fetch_fields(pSql);
|
||||
int num_fields = taos_num_fields(pSql);
|
||||
|
||||
char buf[TSDB_DB_NAME_LEN + 64] = {0};
|
||||
do {
|
||||
int32_t* lengths = taos_fetch_lengths(pSql);
|
||||
int32_t ret = tscGetNthFieldResult(row, fields, lengths, 0, buf);
|
||||
if (0 == ret && STR_NOCASE_EQUAL(buf, strlen(buf), builder->buf, strlen(builder->buf))) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "CREATE DATABASE %s", buf);
|
||||
for (int i = 1; i < num_fields; i++) {
|
||||
for (int j = 0; showColumns[j] != NULL; j++) {
|
||||
if (STR_NOCASE_EQUAL(fields[i].name, strlen(fields[i].name), showColumns[j], strlen(showColumns[j]))) {
|
||||
memset(buf, 0, sizeof(buf));
|
||||
ret = tscGetNthFieldResult(row, fields, lengths, i, buf);
|
||||
if (ret == 0) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), " %s %s", showColumns[j], buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
row = tscFetchRow(builder);
|
||||
} while (row != NULL);
|
||||
|
||||
if (0 == strlen(result)) {
|
||||
return TSDB_CODE_TSC_DB_NOT_SELECTED;
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
int32_t tscRebuildCreateDBStatement(void *param,char *result) {
|
||||
SCreateBuilder *builder = (SCreateBuilder *)param;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
char *buf = calloc(1, TSDB_MAX_BINARY_LEN);
|
||||
if (buf == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
code = tscGetDBInfo(param, buf);
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
code = tscSCreateBuildResult(builder->pParentSql, SCREATE_BUILD_DB, builder->buf, buf);
|
||||
}
|
||||
free(buf);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tscGetTableTagColumnName(SSqlObj *pSql, char **result) {
|
||||
char *buf = (char *)malloc(TSDB_MAX_BINARY_LEN);
|
||||
if (buf == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
buf[0] = 0;
|
||||
|
||||
STableMeta *pMeta = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0)->pTableMeta;
|
||||
if (pMeta->tableType == TSDB_SUPER_TABLE || pMeta->tableType == TSDB_NORMAL_TABLE ||
|
||||
pMeta->tableType == TSDB_STREAM_TABLE) {
|
||||
free(buf);
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
SSchema *pTagsSchema = tscGetTableTagSchema(pMeta);
|
||||
int32_t numOfTags = tscGetNumOfTags(pMeta);
|
||||
for (int32_t i = 0; i < numOfTags; i++) {
|
||||
if (i != numOfTags - 1) {
|
||||
snprintf(buf + strlen(buf), TSDB_MAX_BINARY_LEN - strlen(buf), "%s,", pTagsSchema[i].name);
|
||||
} else {
|
||||
snprintf(buf + strlen(buf), TSDB_MAX_BINARY_LEN - strlen(buf), "%s", pTagsSchema[i].name);
|
||||
}
|
||||
}
|
||||
|
||||
*result = buf;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
static int32_t tscRebuildDDLForSubTable(SSqlObj *pSql, const char *tableName, char *ddl) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableMeta * pMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
SSqlObj *pInterSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
|
||||
if (pInterSql == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
SCreateBuilder *param = (SCreateBuilder *)malloc(sizeof(SCreateBuilder));
|
||||
if (param == NULL) {
|
||||
free(pInterSql);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char fullName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
extractDBName(pTableMetaInfo->name, fullName);
|
||||
extractTableName(pMeta->sTableId, param->sTableName);
|
||||
snprintf(fullName + strlen(fullName), TSDB_TABLE_FNAME_LEN - strlen(fullName), ".%s", param->sTableName);
|
||||
extractTableName(pTableMetaInfo->name, param->buf);
|
||||
|
||||
param->pParentSql = pSql;
|
||||
param->pInterSql = pInterSql;
|
||||
param->fp = tscRebuildCreateTableStatement;
|
||||
param->callStage = SCREATE_CALLBACK_QUERY;
|
||||
|
||||
char *query = (char *)calloc(1, TSDB_MAX_BINARY_LEN);
|
||||
if (query == NULL) {
|
||||
free(param);
|
||||
free(pInterSql);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
char *columns = NULL;
|
||||
int32_t code = tscGetTableTagColumnName(pSql, &columns) ;
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
free(param);
|
||||
free(pInterSql);
|
||||
free(query);
|
||||
return code;
|
||||
}
|
||||
|
||||
snprintf(query + strlen(query), TSDB_MAX_BINARY_LEN - strlen(query), "SELECT %s FROM %s WHERE TBNAME IN(\'%s\')", columns, fullName, param->buf);
|
||||
doAsyncQuery(pSql->pTscObj, pInterSql, tscSCreateCallBack, param, query, strlen(query));
|
||||
free(query);
|
||||
free(columns);
|
||||
|
||||
return TSDB_CODE_TSC_ACTION_IN_PROGRESS;
|
||||
}
|
||||
static int32_t tscRebuildDDLForNormalTable(SSqlObj *pSql, const char *tableName, char *ddl) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableMeta * pMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
int32_t numOfRows = tscGetNumOfColumns(pMeta);
|
||||
SSchema *pSchema = tscGetTableSchema(pMeta);
|
||||
|
||||
char *result = ddl;
|
||||
sprintf(result, "create table %s (", tableName);
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
uint8_t type = pSchema[i].type;
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
|
||||
} else {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[pSchema[i].type].aName);
|
||||
}
|
||||
}
|
||||
sprintf(result + strlen(result) - 1, "%s", ")");
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
static int32_t tscRebuildDDLForSuperTable(SSqlObj *pSql, const char *tableName, char *ddl) {
|
||||
char *result = ddl;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableMeta * pMeta = pTableMetaInfo->pTableMeta;
|
||||
|
||||
int32_t numOfRows = tscGetNumOfColumns(pMeta);
|
||||
int32_t totalRows = numOfRows + tscGetNumOfTags(pMeta);
|
||||
SSchema *pSchema = tscGetTableSchema(pMeta);
|
||||
|
||||
sprintf(result, "create table %s (", tableName);
|
||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||
uint8_t type = pSchema[i].type;
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result),"%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
|
||||
} else {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[type].aName);
|
||||
}
|
||||
}
|
||||
snprintf(result + strlen(result) - 1, TSDB_MAX_BINARY_LEN - strlen(result), "%s %s", ")", "TAGS (");
|
||||
|
||||
for (int32_t i = numOfRows; i < totalRows; i++) {
|
||||
uint8_t type = pSchema[i].type;
|
||||
if (type == TSDB_DATA_TYPE_BINARY || type == TSDB_DATA_TYPE_NCHAR) {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s(%d),", pSchema[i].name,tDataTypeDesc[pSchema[i].type].aName,pSchema->bytes);
|
||||
} else {
|
||||
snprintf(result + strlen(result), TSDB_MAX_BINARY_LEN - strlen(result), "%s %s,", pSchema[i].name, tDataTypeDesc[type].aName);
|
||||
}
|
||||
}
|
||||
sprintf(result + strlen(result) - 1, "%s", ")");
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t tscProcessShowCreateTable(SSqlObj *pSql) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
assert(pTableMetaInfo->pTableMeta != NULL);
|
||||
|
||||
char tableName[TSDB_TABLE_NAME_LEN] = {0};
|
||||
extractTableName(pTableMetaInfo->name, tableName);
|
||||
|
||||
char *result = (char *)calloc(1, TSDB_MAX_BINARY_LEN);
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
code = tscRebuildDDLForSuperTable(pSql, tableName, result);
|
||||
} else if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
|
||||
code = tscRebuildDDLForNormalTable(pSql, tableName, result);
|
||||
} else if (UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo)) {
|
||||
code = tscRebuildDDLForSubTable(pSql, tableName, result);
|
||||
} else {
|
||||
code = TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
code = tscSCreateBuildResult(pSql, SCREATE_BUILD_TABLE, tableName, result);
|
||||
}
|
||||
free(result);
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t tscProcessShowCreateDatabase(SSqlObj *pSql) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
SSqlObj *pInterSql = (SSqlObj *)calloc(1, sizeof(SSqlObj));
|
||||
if (pInterSql == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
SCreateBuilder *param = (SCreateBuilder *)malloc(sizeof(SCreateBuilder));
|
||||
if (param == NULL) {
|
||||
free(pInterSql);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
extractTableName(pTableMetaInfo->name, param->buf);
|
||||
param->pParentSql = pSql;
|
||||
param->pInterSql = pInterSql;
|
||||
param->fp = tscRebuildCreateDBStatement;
|
||||
param->callStage = SCREATE_CALLBACK_QUERY;
|
||||
|
||||
const char *query = "show databases";
|
||||
doAsyncQuery(pSql->pTscObj, pInterSql, tscSCreateCallBack, param, query, strlen(query));
|
||||
return TSDB_CODE_TSC_ACTION_IN_PROGRESS;
|
||||
}
|
||||
static int32_t tscProcessCurrentUser(SSqlObj *pSql) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
pExpr->resBytes = TSDB_USER_LEN + TSDB_DATA_TYPE_BINARY;
|
||||
pExpr->resType = TSDB_DATA_TYPE_BINARY;
|
||||
|
||||
|
||||
char* vx = calloc(1, pExpr->resBytes);
|
||||
if (vx == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -287,7 +807,7 @@ static int32_t tscProcessCurrentUser(SSqlObj *pSql) {
|
|||
|
||||
size_t size = sizeof(pSql->pTscObj->user);
|
||||
STR_WITH_MAXSIZE_TO_VARSTR(vx, pSql->pTscObj->user, size);
|
||||
|
||||
|
||||
tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
|
||||
free(vx);
|
||||
|
||||
|
@ -297,15 +817,15 @@ static int32_t tscProcessCurrentUser(SSqlObj *pSql) {
|
|||
static int32_t tscProcessCurrentDB(SSqlObj *pSql) {
|
||||
char db[TSDB_DB_NAME_LEN] = {0};
|
||||
extractDBName(pSql->pTscObj->db, db);
|
||||
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
|
||||
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
pExpr->resType = TSDB_DATA_TYPE_BINARY;
|
||||
|
||||
|
||||
size_t t = strlen(db);
|
||||
pExpr->resBytes = TSDB_DB_NAME_LEN + VARSTR_HEADER_SIZE;
|
||||
|
||||
|
||||
char* vx = calloc(1, pExpr->resBytes);
|
||||
if (vx == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -316,7 +836,7 @@ static int32_t tscProcessCurrentDB(SSqlObj *pSql) {
|
|||
} else {
|
||||
STR_WITH_SIZE_TO_VARSTR(vx, db, (VarDataLenT)t);
|
||||
}
|
||||
|
||||
|
||||
tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
|
||||
free(vx);
|
||||
|
||||
|
@ -326,49 +846,53 @@ static int32_t tscProcessCurrentDB(SSqlObj *pSql) {
|
|||
static int32_t tscProcessServerVer(SSqlObj *pSql) {
|
||||
const char* v = pSql->pTscObj->sversion;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
|
||||
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
pExpr->resType = TSDB_DATA_TYPE_BINARY;
|
||||
|
||||
|
||||
size_t t = strlen(v);
|
||||
pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE);
|
||||
|
||||
|
||||
char* vx = calloc(1, pExpr->resBytes);
|
||||
if (vx == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
||||
}
|
||||
|
||||
STR_WITH_SIZE_TO_VARSTR(vx, v, (VarDataLenT)t);
|
||||
tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
|
||||
|
||||
|
||||
free(vx);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static int32_t tscProcessClientVer(SSqlObj *pSql) {
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
pExpr->resType = TSDB_DATA_TYPE_BINARY;
|
||||
|
||||
|
||||
size_t t = strlen(version);
|
||||
pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE);
|
||||
|
||||
|
||||
char* v = calloc(1, pExpr->resBytes);
|
||||
if (v == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
||||
}
|
||||
|
||||
STR_WITH_SIZE_TO_VARSTR(v, version, (VarDataLenT)t);
|
||||
tscSetLocalQueryResult(pSql, v, pExpr->aliasName, pExpr->resType, pExpr->resBytes);
|
||||
|
||||
|
||||
free(v);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static int32_t tscProcessServStatus(SSqlObj *pSql) {
|
||||
STscObj* pObj = pSql->pTscObj;
|
||||
|
||||
|
||||
if (pObj->pHb != NULL) {
|
||||
if (pObj->pHb->res.code == TSDB_CODE_RPC_NETWORK_UNAVAIL) {
|
||||
pSql->res.code = TSDB_CODE_RPC_NETWORK_UNAVAIL;
|
||||
|
@ -379,9 +903,9 @@ static int32_t tscProcessServStatus(SSqlObj *pSql) {
|
|||
return pSql->res.code;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
|
||||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
int32_t val = 1;
|
||||
tscSetLocalQueryResult(pSql, (char*) &val, pExpr->aliasName, TSDB_DATA_TYPE_INT, sizeof(int32_t));
|
||||
|
@ -393,24 +917,22 @@ void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnNa
|
|||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
pCmd->numOfCols = 1;
|
||||
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
|
||||
|
||||
tscFieldInfoClear(&pQueryInfo->fieldsInfo);
|
||||
pQueryInfo->fieldsInfo.pFields = taosArrayInit(1, sizeof(TAOS_FIELD));
|
||||
pQueryInfo->fieldsInfo.pSupportInfo = taosArrayInit(1, sizeof(SFieldSupInfo));
|
||||
|
||||
pQueryInfo->fieldsInfo.internalField = taosArrayInit(1, sizeof(SInternalField));
|
||||
|
||||
TAOS_FIELD f = tscCreateField((int8_t)type, columnName, (int16_t)valueLength);
|
||||
tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f);
|
||||
|
||||
|
||||
tscInitResObjForLocalQuery(pSql, 1, (int32_t)valueLength);
|
||||
|
||||
TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0);
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, 0);
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, 0);
|
||||
pInfo->pSqlExpr = taosArrayGetP(pQueryInfo->exprList, 0);
|
||||
|
||||
memcpy(pRes->data, val, pField->bytes);
|
||||
|
||||
memcpy(pRes->data, val, pInfo->field.bytes);
|
||||
}
|
||||
|
||||
int tscProcessLocalCmd(SSqlObj *pSql) {
|
||||
|
@ -428,6 +950,10 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
|
|||
*/
|
||||
pRes->qhandle = 0x1;
|
||||
pRes->numOfRows = 0;
|
||||
} else if (pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE) {
|
||||
pRes->code = tscProcessShowCreateTable(pSql);
|
||||
} else if (pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE) {
|
||||
pRes->code = tscProcessShowCreateDatabase(pSql);
|
||||
} else if (pCmd->command == TSDB_SQL_RESET_CACHE) {
|
||||
taosCacheEmpty(tscMetaCache);
|
||||
pRes->code = TSDB_CODE_SUCCESS;
|
||||
|
@ -447,12 +973,13 @@ int tscProcessLocalCmd(SSqlObj *pSql) {
|
|||
}
|
||||
|
||||
// keep the code in local variable in order to avoid invalid read in case of async query
|
||||
|
||||
int32_t code = pRes->code;
|
||||
if (code == TSDB_CODE_SUCCESS) {
|
||||
(*pSql->fp)(pSql->param, pSql, code);
|
||||
} else if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS){
|
||||
} else {
|
||||
tscQueueAsyncRes(pSql);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -510,7 +510,8 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
|
|||
taosTFree(pLocalReducer->pResultBuf);
|
||||
|
||||
if (pLocalReducer->pResInfo != NULL) {
|
||||
for (int32_t i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
|
||||
size_t num = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
for (int32_t i = 0; i < num; ++i) {
|
||||
taosTFree(pLocalReducer->pResInfo[i].interResultBuf);
|
||||
}
|
||||
|
||||
|
@ -554,27 +555,48 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
|
|||
numOfGroupByCols++;
|
||||
}
|
||||
|
||||
int32_t *orderIdx = (int32_t *)calloc(numOfGroupByCols, sizeof(int32_t));
|
||||
if (orderIdx == NULL) {
|
||||
int32_t *orderColIndexList = (int32_t *)calloc(numOfGroupByCols, sizeof(int32_t));
|
||||
if (orderColIndexList == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
if (numOfGroupByCols > 0) {
|
||||
int32_t startCols = pQueryInfo->fieldsInfo.numOfOutput - pQueryInfo->groupbyExpr.numOfGroupCols;
|
||||
|
||||
// tags value locate at the last columns
|
||||
for (int32_t i = 0; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
|
||||
orderIdx[i] = startCols++;
|
||||
}
|
||||
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0) {
|
||||
int32_t startCols = pQueryInfo->fieldsInfo.numOfOutput - pQueryInfo->groupbyExpr.numOfGroupCols;
|
||||
|
||||
if (pQueryInfo->interval.interval != 0) {
|
||||
// the first column is the timestamp, handles queries like "interval(10m) group by tags"
|
||||
orderIdx[numOfGroupByCols - 1] = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
// the last "pQueryInfo->groupbyExpr.numOfGroupCols" columns are order-by columns
|
||||
for (int32_t i = 0; i < pQueryInfo->groupbyExpr.numOfGroupCols; ++i) {
|
||||
orderColIndexList[i] = startCols++;
|
||||
}
|
||||
|
||||
if (pQueryInfo->interval.interval != 0) {
|
||||
// the first column is the timestamp, handles queries like "interval(10m) group by tags"
|
||||
orderColIndexList[numOfGroupByCols - 1] = PRIMARYKEY_TIMESTAMP_COL_INDEX; //TODO ???
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* 1. the orderby ts asc/desc projection query for the super table
|
||||
* 2. interval query without groupby clause
|
||||
*/
|
||||
if (pQueryInfo->interval.interval != 0) {
|
||||
orderColIndexList[0] = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
} else {
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr->functionId == TSDB_FUNC_PRJ && pExpr->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
orderColIndexList[0] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
assert(pQueryInfo->order.orderColId == PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
}
|
||||
}
|
||||
|
||||
*pOrderDesc = tOrderDesCreate(orderIdx, numOfGroupByCols, pModel, pQueryInfo->order.order);
|
||||
taosTFree(orderIdx);
|
||||
*pOrderDesc = tOrderDesCreate(orderColIndexList, numOfGroupByCols, pModel, pQueryInfo->order.order);
|
||||
taosTFree(orderColIndexList);
|
||||
|
||||
if (*pOrderDesc == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -588,7 +610,6 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
|
|||
|
||||
// disable merge procedure for column projection query
|
||||
int16_t functionId = pReducer->pCtx[0].functionId;
|
||||
assert(functionId != TSDB_FUNC_ARITHM);
|
||||
if (pReducer->orderPrjOnSTable) {
|
||||
return true;
|
||||
}
|
||||
|
@ -606,7 +627,7 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
|
|||
return true;
|
||||
}
|
||||
|
||||
if (orderInfo->pData[numOfCols - 1] == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
if (orderInfo->colIndex[numOfCols - 1] == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
/*
|
||||
* super table interval query
|
||||
* if the order columns is the primary timestamp, all result data belongs to one group
|
||||
|
@ -620,7 +641,7 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
|
|||
}
|
||||
|
||||
// only one row exists
|
||||
int32_t index = orderInfo->pData[0];
|
||||
int32_t index = orderInfo->colIndex[0];
|
||||
int32_t offset = (pOrderDesc->pColumnModel)->pFields[index].offset;
|
||||
|
||||
int32_t ret = memcmp(pPrev + offset, tmpBuffer->data + offset, pOrderDesc->pColumnModel->rowSize - offset);
|
||||
|
@ -639,7 +660,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
|||
SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
(*pMemBuffer) = (tExtMemBuffer **)malloc(POINTER_BYTES * pSql->numOfSubs);
|
||||
(*pMemBuffer) = (tExtMemBuffer **)malloc(POINTER_BYTES * pSql->subState.numOfSub);
|
||||
if (*pMemBuffer == NULL) {
|
||||
tscError("%p failed to allocate memory", pSql);
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -661,7 +682,6 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
|||
|
||||
pSchema[i].bytes = pExpr->resBytes;
|
||||
pSchema[i].type = (int8_t)pExpr->resType;
|
||||
|
||||
rlen += pExpr->resBytes;
|
||||
}
|
||||
|
||||
|
@ -678,7 +698,8 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
|||
pg *= 2;
|
||||
}
|
||||
|
||||
size_t numOfSubs = pTableMetaInfo->vgroupList->numOfVgroups;
|
||||
size_t numOfSubs = pSql->subState.numOfSub;
|
||||
assert(numOfSubs <= pTableMetaInfo->vgroupList->numOfVgroups);
|
||||
for (int32_t i = 0; i < numOfSubs; ++i) {
|
||||
(*pMemBuffer)[i] = createExtMemBuffer(nBufferSizes, rlen, pg, pModel);
|
||||
(*pMemBuffer)[i]->flushModel = MULTIPLE_APPEND_MODEL;
|
||||
|
@ -701,12 +722,8 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr
|
|||
int16_t type = -1;
|
||||
int16_t bytes = 0;
|
||||
|
||||
// if ((pExpr->functionId >= TSDB_FUNC_FIRST_DST && pExpr->functionId <= TSDB_FUNC_LAST_DST) ||
|
||||
// (pExpr->functionId >= TSDB_FUNC_SUM && pExpr->functionId <= TSDB_FUNC_MAX) ||
|
||||
// pExpr->functionId == TSDB_FUNC_LAST_ROW) {
|
||||
// the final result size and type in the same as query on single table.
|
||||
// so here, set the flag to be false;
|
||||
|
||||
int32_t functionId = pExpr->functionId;
|
||||
if (functionId >= TSDB_FUNC_TS && functionId <= TSDB_FUNC_DIFF) {
|
||||
type = pModel->pFields[i].field.type;
|
||||
|
@ -742,6 +759,7 @@ void tscLocalReducerEnvDestroy(tExtMemBuffer **pMemBuffer, tOrderDescriptor *pDe
|
|||
int32_t numOfVnodes) {
|
||||
destroyColumnModel(pFinalModel);
|
||||
tOrderDescDestroy(pDesc);
|
||||
|
||||
for (int32_t i = 0; i < numOfVnodes; ++i) {
|
||||
pMemBuffer[i] = destoryExtMemBuffer(pMemBuffer[i]);
|
||||
}
|
||||
|
|
|
@ -406,7 +406,7 @@ static int32_t tsCheckTimestamp(STableDataBlocks *pDataBlocks, const char *start
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[], SParsedDataColInfo *spd, char *error,
|
||||
int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[], SParsedDataColInfo *spd, SSqlCmd* pCmd,
|
||||
int16_t timePrec, int32_t *code, char *tmpTokenBuf) {
|
||||
int32_t index = 0;
|
||||
SStrToken sToken = {0};
|
||||
|
@ -426,12 +426,17 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[
|
|||
*str += index;
|
||||
|
||||
if (sToken.type == TK_QUESTION) {
|
||||
if (pCmd->insertType != TSDB_QUERY_TYPE_STMT_INSERT) {
|
||||
*code = tscSQLSyntaxErrMsg(pCmd->payload, "? only allowed in binding insertion", *str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint32_t offset = (uint32_t)(start - pDataBlocks->pData);
|
||||
if (tscAddParamToDataBlock(pDataBlocks, pSchema->type, (uint8_t)timePrec, pSchema->bytes, offset) != NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
strcpy(error, "client out of memory");
|
||||
strcpy(pCmd->payload, "client out of memory");
|
||||
*code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
return -1;
|
||||
}
|
||||
|
@ -439,8 +444,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[
|
|||
int16_t type = sToken.type;
|
||||
if ((type != TK_NOW && type != TK_INTEGER && type != TK_STRING && type != TK_FLOAT && type != TK_BOOL &&
|
||||
type != TK_NULL && type != TK_HEX && type != TK_OCT && type != TK_BIN) || (sToken.n == 0) || (type == TK_RP)) {
|
||||
tscSQLSyntaxErrMsg(error, "invalid data or symbol", sToken.z);
|
||||
*code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
*code = tscSQLSyntaxErrMsg(pCmd->payload, "invalid data or symbol", sToken.z);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -470,14 +474,14 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[
|
|||
}
|
||||
|
||||
bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
int32_t ret = tsParseOneColumnData(pSchema, &sToken, start, error, str, isPrimaryKey, timePrec);
|
||||
int32_t ret = tsParseOneColumnData(pSchema, &sToken, start, pCmd->payload, str, isPrimaryKey, timePrec);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
*code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
return -1; // NOTE: here 0 mean error!
|
||||
}
|
||||
|
||||
if (isPrimaryKey && tsCheckTimestamp(pDataBlocks, start) != TSDB_CODE_SUCCESS) {
|
||||
tscInvalidSQLErrMsg(error, "client time/server time can not be mixed up", sToken.z);
|
||||
tscInvalidSQLErrMsg(pCmd->payload, "client time/server time can not be mixed up", sToken.z);
|
||||
*code = TSDB_CODE_TSC_INVALID_TIME_STAMP;
|
||||
return -1;
|
||||
}
|
||||
|
@ -522,7 +526,7 @@ static int32_t rowDataCompar(const void *lhs, const void *rhs) {
|
|||
}
|
||||
|
||||
int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMeta, int maxRows,
|
||||
SParsedDataColInfo *spd, char *error, int32_t *code, char *tmpTokenBuf) {
|
||||
SParsedDataColInfo *spd, SSqlCmd* pCmd, int32_t *code, char *tmpTokenBuf) {
|
||||
int32_t index = 0;
|
||||
SStrToken sToken;
|
||||
|
||||
|
@ -534,8 +538,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMe
|
|||
int32_t precision = tinfo.precision;
|
||||
|
||||
if (spd->hasVal[0] == false) {
|
||||
strcpy(error, "primary timestamp column can not be null");
|
||||
*code = TSDB_CODE_TSC_INVALID_SQL;
|
||||
*code = tscInvalidSQLErrMsg(pCmd->payload, "primary timestamp column can not be null", *str);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -547,17 +550,17 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMe
|
|||
*str += index;
|
||||
if (numOfRows >= maxRows || pDataBlock->size + tinfo.rowSize >= pDataBlock->nAllocSize) {
|
||||
int32_t tSize;
|
||||
int32_t retcode = tscAllocateMemIfNeed(pDataBlock, tinfo.rowSize, &tSize);
|
||||
if (retcode != TSDB_CODE_SUCCESS) { //TODO pass the correct error code to client
|
||||
strcpy(error, "client out of memory");
|
||||
*code = retcode;
|
||||
*code = tscAllocateMemIfNeed(pDataBlock, tinfo.rowSize, &tSize);
|
||||
if (*code != TSDB_CODE_SUCCESS) { //TODO pass the correct error code to client
|
||||
strcpy(pCmd->payload, "client out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
ASSERT(tSize > maxRows);
|
||||
maxRows = tSize;
|
||||
}
|
||||
|
||||
int32_t len = tsParseOneRowData(str, pDataBlock, pSchema, spd, error, precision, code, tmpTokenBuf);
|
||||
int32_t len = tsParseOneRowData(str, pDataBlock, pSchema, spd, pCmd, precision, code, tmpTokenBuf);
|
||||
if (len <= 0) { // error message has been set in tsParseOneRowData
|
||||
return -1;
|
||||
}
|
||||
|
@ -568,7 +571,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMe
|
|||
sToken = tStrGetToken(*str, &index, false, 0, NULL);
|
||||
*str += index;
|
||||
if (sToken.n == 0 || sToken.type != TK_RP) {
|
||||
tscSQLSyntaxErrMsg(error, ") expected", *str);
|
||||
tscSQLSyntaxErrMsg(pCmd->payload, ") expected", *str);
|
||||
*code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
return -1;
|
||||
}
|
||||
|
@ -577,7 +580,7 @@ int tsParseValues(char **str, STableDataBlocks *pDataBlock, STableMeta *pTableMe
|
|||
}
|
||||
|
||||
if (numOfRows <= 0) {
|
||||
strcpy(error, "no any data points");
|
||||
strcpy(pCmd->payload, "no any data points");
|
||||
*code = TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -704,7 +707,7 @@ static int32_t doParseInsertStatement(SSqlObj *pSql, void *pTableList, char **st
|
|||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
int32_t numOfRows = tsParseValues(str, dataBuf, pTableMeta, maxNumOfRows, spd, pCmd->payload, &code, tmpTokenBuf);
|
||||
int32_t numOfRows = tsParseValues(str, dataBuf, pTableMeta, maxNumOfRows, spd, pCmd, &code, tmpTokenBuf);
|
||||
free(tmpTokenBuf);
|
||||
if (numOfRows <= 0) {
|
||||
return code;
|
||||
|
@ -724,10 +727,6 @@ static int32_t doParseInsertStatement(SSqlObj *pSql, void *pTableList, char **st
|
|||
dataBuf->vgId = pTableMeta->vgroupInfo.vgId;
|
||||
dataBuf->numOfTables = 1;
|
||||
|
||||
/*
|
||||
* the value of pRes->numOfRows does not affect the true result of AFFECTED ROWS,
|
||||
* which is actually returned from server.
|
||||
*/
|
||||
*totalNum += numOfRows;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -791,7 +790,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) {
|
|||
sql += index;
|
||||
|
||||
tscAllocPayload(pCmd, sizeof(STagData));
|
||||
STagData *pTag = (STagData *) pCmd->payload;
|
||||
STagData *pTag = &pCmd->tagData;
|
||||
|
||||
memset(pTag, 0, sizeof(STagData));
|
||||
|
||||
|
@ -946,7 +945,6 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) {
|
|||
return tscSQLSyntaxErrMsg(pCmd->payload, ") expected", sToken.z);
|
||||
}
|
||||
|
||||
pCmd->payloadLen = sizeof(pTag->name) + sizeof(pTag->dataLen) + pTag->dataLen;
|
||||
pTag->dataLen = htonl(pTag->dataLen);
|
||||
|
||||
if (tscValidateName(&tableToken) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1192,8 +1190,7 @@ int tsParseInsertSql(SSqlObj *pSql) {
|
|||
str += index;
|
||||
|
||||
if (TK_STRING == sToken.type) {
|
||||
strdequote(sToken.z);
|
||||
sToken.n = (uint32_t)strtrim(sToken.z);
|
||||
tscDequoteAndTrimToken(&sToken);
|
||||
}
|
||||
|
||||
if (sToken.type == TK_RP) {
|
||||
|
@ -1460,8 +1457,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) {
|
|||
char *lineptr = line;
|
||||
strtolower(line, line);
|
||||
|
||||
int32_t len =
|
||||
tsParseOneRowData(&lineptr, pTableDataBlock, pSchema, &spd, pCmd->payload, tinfo.precision, &code, tokenBuf);
|
||||
int32_t len = tsParseOneRowData(&lineptr, pTableDataBlock, pSchema, &spd, pCmd, tinfo.precision, &code, tokenBuf);
|
||||
if (len <= 0 || pTableDataBlock->numOfParams > 0) {
|
||||
pSql->res.code = code;
|
||||
break;
|
||||
|
|
|
@ -43,10 +43,6 @@ typedef struct SNormalStmt {
|
|||
tVariant* params;
|
||||
} SNormalStmt;
|
||||
|
||||
//typedef struct SInsertStmt {
|
||||
//
|
||||
//} SInsertStmt;
|
||||
|
||||
typedef struct STscStmt {
|
||||
bool isInsert;
|
||||
STscObj* taos;
|
||||
|
@ -54,7 +50,6 @@ typedef struct STscStmt {
|
|||
SNormalStmt normal;
|
||||
} STscStmt;
|
||||
|
||||
|
||||
static int normalStmtAddPart(SNormalStmt* stmt, bool isParam, char* str, uint32_t len) {
|
||||
uint16_t size = stmt->numParts + 1;
|
||||
if (size > stmt->sizeParts) {
|
||||
|
@ -144,7 +139,7 @@ static int normalStmtBindParam(STscStmt* stmt, TAOS_BIND* bind) {
|
|||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -218,7 +213,7 @@ static char* normalStmtBuildSql(STscStmt* stmt) {
|
|||
case TSDB_DATA_TYPE_NULL:
|
||||
taosStringBuilderAppendNull(&sb);
|
||||
break;
|
||||
|
||||
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
|
@ -271,6 +266,388 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (1) {
|
||||
// allow user bind param data with different type
|
||||
short size = 0;
|
||||
union {
|
||||
int8_t v1;
|
||||
int16_t v2;
|
||||
int32_t v4;
|
||||
int64_t v8;
|
||||
float f4;
|
||||
double f8;
|
||||
unsigned char buf[32*1024];
|
||||
} u;
|
||||
switch (param->type) {
|
||||
case TSDB_DATA_TYPE_BOOL: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL: {
|
||||
u.v1 = *(int8_t*)bind->buffer;
|
||||
if (u.v1==0 || u.v1==1) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
u.v1 = *(int8_t*)bind->buffer;
|
||||
if (u.v1==0 || u.v1==1) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
u.v1 = (int8_t)*(int16_t*)bind->buffer;
|
||||
if (u.v1==0 || u.v1==1) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
u.v1 = (int8_t)*(int32_t*)bind->buffer;
|
||||
if (u.v1==0 || u.v1==1) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
u.v1 = (int8_t)*(int64_t*)bind->buffer;
|
||||
if (u.v1==0 || u.v1==1) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
// "0", "1" convertible
|
||||
if (strncmp((const char*)bind->buffer, "0", *bind->length)==0) {
|
||||
u.v1 = 0;
|
||||
break;
|
||||
}
|
||||
if (strncmp((const char*)bind->buffer, "1", *bind->length)==0) {
|
||||
u.v1 = 1;
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.v1, sizeof(u.v1));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
int8_t v = *(int8_t*)bind->buffer;
|
||||
u.v1 = v;
|
||||
if (v >= SCHAR_MIN && v <= SCHAR_MAX) break;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
int16_t v = *(int16_t*)bind->buffer;
|
||||
u.v1 = (int8_t)v;
|
||||
if (v >= SCHAR_MIN && v <= SCHAR_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
int32_t v = *(int32_t*)bind->buffer;
|
||||
u.v1 = (int8_t)v;
|
||||
if (v >= SCHAR_MIN && v <= SCHAR_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
int64_t v = *(int64_t*)bind->buffer;
|
||||
u.v1 = (int8_t)v;
|
||||
if (v >= SCHAR_MIN && v <= SCHAR_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int64_t v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%" PRId64 "%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.v1 = (int8_t)v;
|
||||
if (v >= SCHAR_MIN && v <= SCHAR_MAX) break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.v1, sizeof(u.v1));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
int v = *(int16_t*)bind->buffer;
|
||||
u.v2 = (int16_t)v;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
int32_t v = *(int32_t*)bind->buffer;
|
||||
u.v2 = (int16_t)v;
|
||||
if (v >= SHRT_MIN && v <= SHRT_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
int64_t v = *(int64_t*)bind->buffer;
|
||||
u.v2 = (int16_t)v;
|
||||
if (v >= SHRT_MIN && v <= SHRT_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int64_t v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%" PRId64 "%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.v2 = (int16_t)v;
|
||||
if (v >= SHRT_MIN && v <= SHRT_MAX) break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.v2, sizeof(u.v2));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
u.v4 = *(int32_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
int64_t v = *(int64_t*)bind->buffer;
|
||||
u.v4 = (int32_t)v;
|
||||
if (v >= INT_MIN && v <= INT_MAX) break;
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int64_t v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%" PRId64 "%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.v4 = (int32_t)v;
|
||||
if (v >= INT_MIN && v <= INT_MAX) break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.v2, sizeof(u.v2));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
u.f4 = *(int8_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
u.f4 = *(int16_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
u.f4 = (float)*(int32_t*)bind->buffer;
|
||||
// shall we check equality?
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
u.f4 = (float)*(int64_t*)bind->buffer;
|
||||
// shall we check equality?
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
u.f4 = *(float*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
u.f4 = *(float*)bind->buffer;
|
||||
// shall we check equality?
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
float v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%f%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.f4 = v;
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.f4, sizeof(u.f4));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
u.v8 = *(int8_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
u.v8 = *(int16_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
u.v8 = *(int32_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
u.v8 = *(int64_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
int64_t v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%" PRId64 "%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.v8 = v;
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
memcpy(data + param->offset, &u.v8, sizeof(u.v8));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
u.f8 = *(int8_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
u.f8 = *(int16_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
u.f8 = *(int32_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
u.f8 = (double)*(int64_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
u.f8 = *(float*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
u.f8 = *(double*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
double v;
|
||||
int n,r;
|
||||
r = sscanf((const char*)bind->buffer, "%lf%n", &v, &n);
|
||||
if (r==1 && n==strlen((const char*)bind->buffer)) {
|
||||
u.f8 = v;
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
} break;
|
||||
memcpy(data + param->offset, &u.f8, sizeof(u.f8));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||
u.v8 = *(int64_t*)bind->buffer;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
// is this the correct way to call taosParseTime?
|
||||
int32_t len = (int32_t)*bind->length;
|
||||
if (taosParseTime(bind->buffer, &u.v8, len, 3, tsDaylight) == TSDB_CODE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
} break;
|
||||
memcpy(data + param->offset, &u.v8, sizeof(u.v8));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
if ((*bind->length) > (uintptr_t)param->bytes) {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
size = (short)*bind->length;
|
||||
STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
switch (bind->buffer_type) {
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
size_t output = 0;
|
||||
if (!taosMbsToUcs4(bind->buffer, *bind->length, varDataVal(data + param->offset), param->bytes - VARSTR_HEADER_SIZE, &output)) {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
varDataSetLen(data + param->offset, output);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} break;
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
} break;
|
||||
default: {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bind->buffer_type != param->type) {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
@ -304,12 +681,12 @@ static int doBindParam(char* data, SParamInfo* param, TAOS_BIND* bind) {
|
|||
size = (short)*bind->length;
|
||||
STR_WITH_SIZE_TO_VARSTR(data + param->offset, bind->buffer, size);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
size_t output = 0;
|
||||
if (!taosMbsToUcs4(bind->buffer, *bind->length, varDataVal(data + param->offset), param->bytes - VARSTR_HEADER_SIZE, &output)) {
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
}
|
||||
varDataSetLen(data + param->offset, output);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -363,7 +740,7 @@ static int insertStmtBindParam(STscStmt* stmt, TAOS_BIND* bind) {
|
|||
}
|
||||
|
||||
// actual work of all data blocks is done, update block size and numOfRows.
|
||||
// note we don't do this block by block during the binding process, because
|
||||
// note we don't do this block by block during the binding process, because
|
||||
// we cannot recover if something goes wrong.
|
||||
pCmd->batchSize = binded * 2 + 1;
|
||||
|
||||
|
@ -410,7 +787,7 @@ static int insertStmtReset(STscStmt* pStmt) {
|
|||
}
|
||||
}
|
||||
pCmd->batchSize = 0;
|
||||
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
|
||||
pTableMetaInfo->vgroupIndex = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -452,7 +829,7 @@ static int insertStmtExecute(STscStmt* stmt) {
|
|||
pRes->numOfRows = 0;
|
||||
pRes->numOfTotal = 0;
|
||||
pRes->numOfClauseTotal = 0;
|
||||
|
||||
|
||||
pRes->qhandle = 0;
|
||||
|
||||
pSql->cmd.insertType = 0;
|
||||
|
@ -513,42 +890,39 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
|||
|
||||
SSqlObj* pSql = pStmt->pSql;
|
||||
size_t sqlLen = strlen(sql);
|
||||
|
||||
//doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
|
||||
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
pSql->param = (void*) pSql;
|
||||
pSql->fp = waitForQueryRsp;
|
||||
pSql->cmd.insertType = TSDB_QUERY_TYPE_STMT_INSERT;
|
||||
|
||||
|
||||
if (TSDB_CODE_SUCCESS != tscAllocPayload(pCmd, TSDB_DEFAULT_PAYLOAD_SIZE)) {
|
||||
tscError("%p failed to malloc payload buffer", pSql);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
|
||||
|
||||
|
||||
if (pSql->sqlstr == NULL) {
|
||||
tscError("%p failed to malloc sql string buffer", pSql);
|
||||
free(pCmd->payload);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
|
||||
pRes->qhandle = 0;
|
||||
pRes->numOfRows = 1;
|
||||
|
||||
|
||||
strtolower(pSql->sqlstr, sql);
|
||||
tscDebugL("%p SQL: %s", pSql, pSql->sqlstr);
|
||||
|
||||
if (tscIsInsertData(pSql->sqlstr)) {
|
||||
if (tscIsInsertData(pSql->sqlstr)) {
|
||||
pStmt->isInsert = true;
|
||||
|
||||
|
||||
pSql->cmd.numOfParams = 0;
|
||||
pSql->cmd.batchSize = 0;
|
||||
|
||||
uint64_t handle = (uint64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &handle, sizeof(uint64_t), &pSql, sizeof(uint64_t), 2*3600*1000);
|
||||
T_REF_INC(pSql->pTscObj);
|
||||
|
||||
registerSqlObj(pSql);
|
||||
|
||||
int32_t code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
|
@ -556,7 +930,7 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
|||
tsem_wait(&pSql->rspSem);
|
||||
return pSql->res.code;
|
||||
}
|
||||
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -645,3 +1019,80 @@ TAOS_RES *taos_stmt_use_result(TAOS_STMT* stmt) {
|
|||
pStmt->pSql = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
int taos_stmt_is_insert(TAOS_STMT *stmt, int *insert) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
|
||||
if (stmt == NULL || pStmt->taos == NULL || pStmt->pSql == NULL) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
return TSDB_CODE_TSC_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (insert) *insert = pStmt->isInsert;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int taos_stmt_num_params(TAOS_STMT *stmt, int *nums) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
|
||||
if (stmt == NULL || pStmt->taos == NULL || pStmt->pSql == NULL) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
return TSDB_CODE_TSC_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (pStmt->isInsert) {
|
||||
SSqlObj* pSql = pStmt->pSql;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
*nums = pCmd->numOfParams;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
SNormalStmt* normal = &pStmt->normal;
|
||||
*nums = normal->numParams;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
int taos_stmt_get_param(TAOS_STMT *stmt, int idx, int *type, int *bytes) {
|
||||
STscStmt* pStmt = (STscStmt*)stmt;
|
||||
|
||||
if (stmt == NULL || pStmt->taos == NULL || pStmt->pSql == NULL) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
return TSDB_CODE_TSC_DISCONNECTED;
|
||||
}
|
||||
|
||||
if (pStmt->isInsert) {
|
||||
SSqlObj* pSql = pStmt->pSql;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
STableDataBlocks* pBlock = taosArrayGetP(pCmd->pDataBlocks, 0);
|
||||
|
||||
assert(pCmd->numOfParams == pBlock->numOfParams);
|
||||
if (idx < 0 || idx >= pBlock->numOfParams) return -1;
|
||||
|
||||
SParamInfo* param = pBlock->params + idx;
|
||||
if (type) *type = param->type;
|
||||
if (bytes) *bytes = param->bytes;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
} else {
|
||||
return TSDB_CODE_TSC_APP_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
const char *taos_data_type(int type) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_NULL: return "TSDB_DATA_TYPE_NULL";
|
||||
case TSDB_DATA_TYPE_BOOL: return "TSDB_DATA_TYPE_BOOL";
|
||||
case TSDB_DATA_TYPE_TINYINT: return "TSDB_DATA_TYPE_TINYINT";
|
||||
case TSDB_DATA_TYPE_SMALLINT: return "TSDB_DATA_TYPE_SMALLINT";
|
||||
case TSDB_DATA_TYPE_INT: return "TSDB_DATA_TYPE_INT";
|
||||
case TSDB_DATA_TYPE_BIGINT: return "TSDB_DATA_TYPE_BIGINT";
|
||||
case TSDB_DATA_TYPE_FLOAT: return "TSDB_DATA_TYPE_FLOAT";
|
||||
case TSDB_DATA_TYPE_DOUBLE: return "TSDB_DATA_TYPE_DOUBLE";
|
||||
case TSDB_DATA_TYPE_BINARY: return "TSDB_DATA_TYPE_BINARY";
|
||||
case TSDB_DATA_TYPE_TIMESTAMP: return "TSDB_DATA_TYPE_TIMESTAMP";
|
||||
case TSDB_DATA_TYPE_NCHAR: return "TSDB_DATA_TYPE_NCHAR";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,10 @@
|
|||
#include "tutil.h"
|
||||
#include "taosmsg.h"
|
||||
|
||||
#include "taos.h"
|
||||
|
||||
void tscSaveSlowQueryFp(void *handle, void *tmrId);
|
||||
void *tscSlowQueryConn = NULL;
|
||||
TAOS *tscSlowQueryConn = NULL;
|
||||
bool tscSlowQueryConnInitialized = false;
|
||||
|
||||
void tscInitConnCb(void *param, TAOS_RES *result, int code) {
|
||||
|
@ -151,10 +153,12 @@ void tscKillQuery(STscObj *pObj, uint32_t killId) {
|
|||
|
||||
pthread_mutex_unlock(&pObj->mutex);
|
||||
|
||||
if (pSql == NULL) return;
|
||||
|
||||
tscDebug("%p query is killed, queryId:%d", pSql, killId);
|
||||
taos_stop_query(pSql);
|
||||
if (pSql == NULL) {
|
||||
tscError("failed to kill query, id:%d, it may have completed/terminated", killId);
|
||||
} else {
|
||||
tscDebug("%p query is killed, queryId:%d", pSql, killId);
|
||||
taos_stop_query(pSql);
|
||||
}
|
||||
}
|
||||
|
||||
void tscAddIntoStreamList(SSqlStream *pStream) {
|
||||
|
@ -242,6 +246,7 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
|
|||
pQdesc->stime = htobe64(pSql->stime);
|
||||
pQdesc->queryId = htonl(pSql->queryId);
|
||||
pQdesc->useconds = htobe64(pSql->res.useconds);
|
||||
pQdesc->qHandle = htobe64(pSql->res.qhandle);
|
||||
|
||||
pHeartbeat->numOfQueries++;
|
||||
pQdesc++;
|
||||
|
|
|
@ -122,7 +122,7 @@ static int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSql
|
|||
static int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo);
|
||||
static int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo);
|
||||
static int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index);
|
||||
static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray* pExprInfo, SQueryInfo* pQueryInfo, SArray* pCols);
|
||||
static int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid);
|
||||
|
||||
/*
|
||||
* Used during parsing query sql. Since the query sql usually small in length, error position
|
||||
|
@ -190,7 +190,8 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
SSqlRes* pRes = &pSql->res;
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
if (!pInfo->valid) {
|
||||
if (!pInfo->valid || terrno == TSDB_CODE_TSC_SQL_SYNTAX_ERROR) {
|
||||
terrno = TSDB_CODE_SUCCESS; // clear the error number
|
||||
return tscSQLSyntaxErrMsg(tscGetErrorMsgPayload(pCmd), NULL, pInfo->pzErrMsg);
|
||||
}
|
||||
|
||||
|
@ -362,13 +363,46 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
}
|
||||
|
||||
// additional msg has been attached already
|
||||
if (tscSetTableFullName(pTableMetaInfo, pToken, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
code = tscSetTableFullName(pTableMetaInfo, pToken, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
return tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
}
|
||||
case TSDB_SQL_SHOW_CREATE_TABLE: {
|
||||
SStrToken* pToken = &pInfo->pDCLInfo->a[0];
|
||||
const char* msg1 = "invalid table name";
|
||||
const char* msg2 = "table name is too long";
|
||||
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (!tscValidateTableNameLength(pToken->n)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
code = tscSetTableFullName(pTableMetaInfo, pToken, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
return tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
}
|
||||
case TSDB_SQL_SHOW_CREATE_DATABASE: {
|
||||
const char* msg1 = "invalid database name";
|
||||
SStrToken* pToken = &pInfo->pDCLInfo->a[0];
|
||||
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
if (pToken->n > TSDB_DB_NAME_LEN) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
return tscSetTableFullName(pTableMetaInfo, pToken, pSql);
|
||||
}
|
||||
case TSDB_SQL_CFG_DNODE: {
|
||||
const char* msg2 = "invalid configure options or values, such as resetlog / debugFlag 135 / balance 'vnode:2-dnode:2' / monitor 1 ";
|
||||
const char* msg3 = "invalid dnode ep";
|
||||
|
@ -593,6 +627,11 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// orderby column not set yet, set it to be the primary timestamp column
|
||||
if (pQueryInfo->order.orderColId == INT32_MIN) {
|
||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
}
|
||||
|
||||
// interval is not null
|
||||
SStrToken* t = &pQuerySql->interval;
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, &pQueryInfo->interval.intervalUnit) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -772,55 +811,44 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
|
|||
|
||||
int32_t tscSetTableFullName(STableMetaInfo* pTableMetaInfo, SStrToken* pzTableName, SSqlObj* pSql) {
|
||||
const char* msg1 = "name too long";
|
||||
const char* msg2 = "current database or database name invalid";
|
||||
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
// backup the old name in pTableMetaInfo
|
||||
size_t size = strlen(pTableMetaInfo->name);
|
||||
char* oldName = NULL;
|
||||
if (size > 0) {
|
||||
oldName = strdup(pTableMetaInfo->name);
|
||||
}
|
||||
char oldName[TSDB_TABLE_FNAME_LEN] = {0};
|
||||
tstrncpy(oldName, pTableMetaInfo->name, tListLen(oldName));
|
||||
|
||||
if (hasSpecifyDB(pzTableName)) {
|
||||
// db has been specified in sql string so we ignore current db path
|
||||
if (hasSpecifyDB(pzTableName)) { // db has been specified in sql string so we ignore current db path
|
||||
code = setObjFullName(pTableMetaInfo->name, getAccountId(pSql), NULL, pzTableName, NULL);
|
||||
if (code != 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
} else { // get current DB name first, then set it into path
|
||||
} else { // get current DB name first, and then set it into path
|
||||
SStrToken t = {0};
|
||||
getCurrentDBName(pSql, &t);
|
||||
if (t.n == 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
code = setObjFullName(pTableMetaInfo->name, NULL, &t, pzTableName, NULL);
|
||||
if (code != 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
if (t.n == 0) { // current database not available or not specified
|
||||
code = TSDB_CODE_TSC_DB_NOT_SELECTED;
|
||||
} else {
|
||||
code = setObjFullName(pTableMetaInfo->name, NULL, &t, pzTableName, NULL);
|
||||
if (code != 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
taosTFree(oldName);
|
||||
return code;
|
||||
}
|
||||
|
||||
/*
|
||||
* the old name exists and is not equalled to the new name. Release the metermeta/metricmeta
|
||||
* the old name exists and is not equalled to the new name. Release the table meta
|
||||
* that are corresponding to the old name for the new table name.
|
||||
*/
|
||||
if (size > 0) {
|
||||
if (strncasecmp(oldName, pTableMetaInfo->name, tListLen(pTableMetaInfo->name)) != 0) {
|
||||
tscClearTableMetaInfo(pTableMetaInfo, false);
|
||||
}
|
||||
} else {
|
||||
assert(pTableMetaInfo->pTableMeta == NULL);
|
||||
if (strlen(oldName) > 0 && strncasecmp(oldName, pTableMetaInfo->name, tListLen(pTableMetaInfo->name)) != 0) {
|
||||
tscClearTableMetaInfo(pTableMetaInfo, false);
|
||||
}
|
||||
|
||||
taosTFree(oldName);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -849,22 +877,13 @@ static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd) {
|
|||
|
||||
int32_t nLen = 0;
|
||||
for (int32_t i = 0; i < pFieldList->nField; ++i) {
|
||||
if (pFieldList->p[i].bytes == 0) {
|
||||
TAOS_FIELD* pField = &pFieldList->p[i];
|
||||
|
||||
if (pField->bytes == 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
return false;
|
||||
}
|
||||
nLen += pFieldList->p[i].bytes;
|
||||
}
|
||||
|
||||
// max row length must be less than TSDB_MAX_BYTES_PER_ROW
|
||||
if (nLen > TSDB_MAX_BYTES_PER_ROW) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
return false;
|
||||
}
|
||||
|
||||
// field name must be unique
|
||||
for (int32_t i = 0; i < pFieldList->nField; ++i) {
|
||||
TAOS_FIELD* pField = &pFieldList->p[i];
|
||||
if (pField->type < TSDB_DATA_TYPE_BOOL || pField->type > TSDB_DATA_TYPE_NCHAR) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
return false;
|
||||
|
@ -881,10 +900,19 @@ static bool validateTableColumnInfo(tFieldList* pFieldList, SSqlCmd* pCmd) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// field name must be unique
|
||||
if (has(pFieldList, i + 1, pFieldList->p[i].name) == true) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
return false;
|
||||
}
|
||||
|
||||
nLen += pField->bytes;
|
||||
}
|
||||
|
||||
// max row length must be less than TSDB_MAX_BYTES_PER_ROW
|
||||
if (nLen > TSDB_MAX_BYTES_PER_ROW) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -1178,6 +1206,10 @@ int32_t setObjFullName(char* fullName, const char* account, SStrToken* pDB, SStr
|
|||
return (totalLen < TSDB_TABLE_FNAME_LEN) ? TSDB_CODE_SUCCESS : TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
static void tscInsertPrimaryTSSourceColumn(SQueryInfo* pQueryInfo, SColumnIndex* pIndex) {
|
||||
SColumnIndex tsCol = {.tableIndex = pIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tscColumnListInsert(pQueryInfo->colList, &tsCol);
|
||||
}
|
||||
static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t exprIndex, tSQLExprItem* pItem) {
|
||||
const char* msg1 = "invalid column name, or illegal column type";
|
||||
const char* msg2 = "invalid arithmetic expression in select clause";
|
||||
|
@ -1218,7 +1250,7 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
|
|||
tExprNode* pNode = NULL;
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
|
||||
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pNode, pItem->pNode, pQueryInfo->exprList, pQueryInfo, colList);
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pNode, pItem->pNode, pQueryInfo, colList, NULL);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
taosArrayDestroy(colList);
|
||||
tExprTreeDestroy(&pNode, NULL);
|
||||
|
@ -1253,6 +1285,8 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
|
|||
addExprParams(pExpr, c, TSDB_DATA_TYPE_BINARY, (int32_t)len, index.tableIndex);
|
||||
|
||||
insertResultField(pQueryInfo, exprIndex, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName, pExpr);
|
||||
// add ts column
|
||||
tscInsertPrimaryTSSourceColumn(pQueryInfo, &index);
|
||||
|
||||
tbufCloseWriter(&bw);
|
||||
taosArrayDestroy(colList);
|
||||
|
@ -1272,17 +1306,17 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
|
|||
insertResultField(pQueryInfo, exprIndex, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, aliasName, NULL);
|
||||
|
||||
int32_t slot = tscNumOfFields(pQueryInfo) - 1;
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, slot);
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, slot);
|
||||
|
||||
if (pInfo->pSqlExpr == NULL) {
|
||||
SExprInfo* pArithExprInfo = calloc(1, sizeof(SExprInfo));
|
||||
|
||||
// arithmetic expression always return result in the format of double float
|
||||
pArithExprInfo->bytes = sizeof(double);
|
||||
pArithExprInfo->bytes = sizeof(double);
|
||||
pArithExprInfo->interBytes = sizeof(double);
|
||||
pArithExprInfo->type = TSDB_DATA_TYPE_DOUBLE;
|
||||
pArithExprInfo->type = TSDB_DATA_TYPE_DOUBLE;
|
||||
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pArithExprInfo->pExpr, pItem->pNode, pQueryInfo->exprList, pQueryInfo, NULL);
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pArithExprInfo->pExpr, pItem->pNode, pQueryInfo, NULL, &pArithExprInfo->uid);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
tExprTreeDestroy(&pArithExprInfo->pExpr, NULL);
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), "invalid expression in select clause");
|
||||
|
@ -1295,10 +1329,6 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static void tscInsertPrimaryTSSourceColumn(SQueryInfo* pQueryInfo, SColumnIndex* pIndex) {
|
||||
SColumnIndex tsCol = {.tableIndex = pIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tscColumnListInsert(pQueryInfo->colList, &tsCol);
|
||||
}
|
||||
|
||||
static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumnIndex* pIndex, tSQLExprItem* pItem) {
|
||||
SSqlExpr* pExpr = doAddProjectCol(pQueryInfo, startPos, pIndex->columnIndex, pIndex->tableIndex);
|
||||
|
@ -1323,6 +1353,32 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn
|
|||
insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, (int8_t)pExpr->resType, pExpr->aliasName, pExpr);
|
||||
}
|
||||
|
||||
static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo) {
|
||||
// primary timestamp column has been added already
|
||||
size_t size = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr->functionId == TSDB_FUNC_PRJ && pExpr->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SColumnIndex index = {0};
|
||||
|
||||
// set the constant column value always attached to first table.
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
|
||||
// add the timestamp column into the output columns
|
||||
int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, numOfCols, TSDB_FUNC_PRJ, &index, pSchema, TSDB_COL_NORMAL);
|
||||
|
||||
SInternalField* pSupInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, numOfCols);
|
||||
pSupInfo->visible = false;
|
||||
|
||||
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
|
||||
}
|
||||
|
||||
int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSelection, bool isSTable, bool joinQuery) {
|
||||
assert(pSelection != NULL && pCmd != NULL);
|
||||
|
||||
|
@ -1376,20 +1432,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
// there is only one user-defined column in the final result field, add the timestamp column.
|
||||
size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
|
||||
if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) {
|
||||
SColumnIndex index = {0};
|
||||
|
||||
// set the constant column value always attached to first table.
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, clauseIndex, 0);
|
||||
SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
|
||||
// add the timestamp column into the output columns
|
||||
int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, numOfCols, TSDB_FUNC_PRJ, &index, pSchema, TSDB_COL_NORMAL);
|
||||
|
||||
SFieldSupInfo* pSupInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, numOfCols);
|
||||
pSupInfo->visible = false;
|
||||
|
||||
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
|
||||
addPrimaryTsColIntoResult(pQueryInfo);
|
||||
}
|
||||
|
||||
if (!functionCompatibleCheck(pQueryInfo, joinQuery)) {
|
||||
|
@ -1427,7 +1470,7 @@ int32_t insertResultField(SQueryInfo* pQueryInfo, int32_t outputIndex, SColumnLi
|
|||
}
|
||||
|
||||
TAOS_FIELD f = tscCreateField(type, fieldName, bytes);
|
||||
SFieldSupInfo* pInfo = tscFieldInfoInsert(&pQueryInfo->fieldsInfo, outputIndex, &f);
|
||||
SInternalField* pInfo = tscFieldInfoInsert(&pQueryInfo->fieldsInfo, outputIndex, &f);
|
||||
pInfo->pSqlExpr = pSqlExpr;
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -1581,8 +1624,8 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSchema* pSchema, SConvertFunc cvtFunc, char* aliasName,
|
||||
int32_t resColIdx, SColumnIndex* pColIndex) {
|
||||
static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSchema* pSchema, SConvertFunc cvtFunc,
|
||||
char* aliasName, int32_t resColIdx, SColumnIndex* pColIndex, bool finalResult) {
|
||||
const char* msg1 = "not support column types";
|
||||
|
||||
int16_t type = 0;
|
||||
|
@ -1628,8 +1671,13 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
|
|||
SColumnIndex index = {.tableIndex = pColIndex->tableIndex, .columnIndex = PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tscColumnListInsert(pQueryInfo->colList, &index);
|
||||
|
||||
// if it is not in the final result, do not add it
|
||||
SColumnList ids = getColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex);
|
||||
insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, columnName, pExpr);
|
||||
if (finalResult) {
|
||||
insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, columnName, pExpr);
|
||||
} else {
|
||||
tscColumnListInsert(pQueryInfo->colList, &(ids.ids[0]));
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
@ -1666,7 +1714,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
if (pItem->pNode->pParam != NULL) {
|
||||
tSQLExprItem* pParamElem = &pItem->pNode->pParam->a[0];
|
||||
SStrToken* pToken = &pParamElem->pNode->colInfo;
|
||||
short sqlOptr = pParamElem->pNode->nSQLOptr;
|
||||
int16_t sqlOptr = pParamElem->pNode->nSQLOptr;
|
||||
if ((pToken->z == NULL || pToken->n == 0)
|
||||
&& (TK_INTEGER != sqlOptr)) /*select count(1) from table*/ {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
|
@ -1904,7 +1952,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
|
||||
for (int32_t j = 0; j < tscGetNumOfColumns(pTableMetaInfo->pTableMeta); ++j) {
|
||||
index.columnIndex = j;
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex++, &index) != 0) {
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex++, &index, finalResult) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
|
@ -1921,7 +1969,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
if ((index.columnIndex >= tscGetNumOfColumns(pTableMetaInfo->pTableMeta)) || (index.columnIndex < 0)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex + i, &index) != 0) {
|
||||
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex + i, &index, finalResult) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -1958,7 +2007,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
|
||||
for (int32_t i = 0; i < tscGetNumOfColumns(pTableMetaInfo->pTableMeta); ++i) {
|
||||
SColumnIndex index = {.tableIndex = j, .columnIndex = i};
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex, &index) != 0) {
|
||||
if (setExprInfoForFunctions(pCmd, pQueryInfo, pSchema, cvtFunc, pItem->aliasName, colIndex, &index, finalResult) != 0) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -3336,10 +3385,26 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer
|
|||
|
||||
tSQLExprItem item = {.pNode = pExpr, .aliasName = NULL};
|
||||
|
||||
// sql function in selection clause, append sql function info in pSqlCmd structure sequentially
|
||||
// sql function list in selection clause.
|
||||
// Append the sqlExpr into exprList of pQueryInfo structure sequentially
|
||||
if (addExprAndResultField(pCmd, pQueryInfo, outputIndex, &item, false) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// It is invalid in case of more than one sqlExpr, such as first(ts, k) - last(ts, k)
|
||||
int32_t inc = (int32_t) tscSqlExprNumOfExprs(pQueryInfo) - outputIndex;
|
||||
if (inc > 1) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// Not supported data type in arithmetic expression
|
||||
for(int32_t i = 0; i < inc; ++i) {
|
||||
SSqlExpr* p1 = tscSqlExprGet(pQueryInfo, i + outputIndex);
|
||||
int16_t t = p1->resType;
|
||||
if (t == TSDB_DATA_TYPE_BINARY || t == TSDB_DATA_TYPE_NCHAR || t == TSDB_DATA_TYPE_BOOL || t == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -4014,7 +4079,7 @@ static int32_t getTagQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SCondE
|
|||
tExprNode* p = NULL;
|
||||
|
||||
SArray* colList = taosArrayInit(10, sizeof(SColIndex));
|
||||
ret = exprTreeFromSqlExpr(pCmd, &p, p1, NULL, pQueryInfo, colList);
|
||||
ret = exprTreeFromSqlExpr(pCmd, &p, p1, pQueryInfo, colList, NULL);
|
||||
SBufferWriter bw = tbufInitWriter(NULL, false);
|
||||
|
||||
TRY(0) {
|
||||
|
@ -4341,14 +4406,13 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery
|
|||
|
||||
static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
|
||||
/* set default timestamp order information for all queries */
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
if (isTopBottomQuery(pQueryInfo)) {
|
||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
} else {
|
||||
pQueryInfo->order.orderColId = -1;
|
||||
} else { // in case of select tbname from super_table, the defualt order column can not be the primary ts column
|
||||
pQueryInfo->order.orderColId = INT32_MIN;
|
||||
}
|
||||
|
||||
/* for super table query, set default ascending order for group output */
|
||||
|
@ -4452,6 +4516,11 @@ int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
|
|||
} else {
|
||||
pQueryInfo->order.order = pSortorder->a[0].sortOrder;
|
||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||
|
||||
// orderby ts query on super table
|
||||
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||
addPrimaryTsColIntoResult(pQueryInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4533,6 +4602,8 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
const char* msg18 = "primary timestamp column cannot be dropped";
|
||||
const char* msg19 = "invalid new tag name";
|
||||
|
||||
int32_t code = TSDB_CODE_SUCCESS;
|
||||
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
SAlterTableSQL* pAlterSQL = pInfo->pAlterInfo;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
|
@ -4543,13 +4614,14 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (tscSetTableFullName(pTableMetaInfo, &(pAlterSQL->name), pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
code = tscSetTableFullName(pTableMetaInfo, &(pAlterSQL->name), pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t ret = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
@ -4678,7 +4750,7 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
|
||||
// validate the length of binary
|
||||
if ((pTagsSchema->type == TSDB_DATA_TYPE_BINARY || pTagsSchema->type == TSDB_DATA_TYPE_NCHAR) &&
|
||||
(pVarList->a[1].pVar.nLen + VARSTR_HEADER_SIZE) > pTagsSchema->bytes) {
|
||||
varDataTLen(pAlterSQL->tagData.data) > pTagsSchema->bytes) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg14);
|
||||
}
|
||||
|
||||
|
@ -5205,26 +5277,6 @@ int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDBInfo* pCreateDbSql) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
//void tscAddTimestampColumn(SQueryInfo* pQueryInfo, int16_t functionId, int16_t tableIndex) {
|
||||
// // the first column not timestamp column, add it
|
||||
// SSqlExpr* pExpr = NULL;
|
||||
// if (tscSqlExprNumOfExprs(pQueryInfo) > 0) {
|
||||
// pExpr = tscSqlExprGet(pQueryInfo, 0);
|
||||
// }
|
||||
//
|
||||
// if (pExpr == NULL || pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX || pExpr->functionId != functionId) {
|
||||
// SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
//
|
||||
// pExpr = tscSqlExprInsert(pQueryInfo, 0, functionId, &index, TSDB_DATA_TYPE_TIMESTAMP, TSDB_KEYSIZE, TSDB_KEYSIZE, false);
|
||||
// pExpr->colInfo.flag = TSDB_COL_NORMAL;
|
||||
//
|
||||
// // NOTE: tag column does not add to source column list
|
||||
// SColumnList ids = getColumnList(1, tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||
//
|
||||
// insertResultField(pQueryInfo, 0, &ids, TSDB_KEYSIZE, TSDB_DATA_TYPE_TIMESTAMP, "ts", pExpr);
|
||||
// }
|
||||
//}
|
||||
|
||||
void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClauseIndex, int32_t tableIndex) {
|
||||
SQueryInfo* pParentQueryInfo = tscGetQueryInfoDetail(&pParentObj->cmd, subClauseIndex);
|
||||
|
||||
|
@ -5281,7 +5333,7 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) {
|
|||
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, (int32_t)size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL);
|
||||
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, (int32_t)size);
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, (int32_t)size);
|
||||
doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr);
|
||||
pInfo->visible = false;
|
||||
}
|
||||
|
@ -5723,7 +5775,7 @@ int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCMCreateDbMsg* pCreate) {
|
|||
char msg[512] = {0};
|
||||
|
||||
if (pCreate->walLevel != -1 && (pCreate->walLevel < TSDB_MIN_WAL_LEVEL || pCreate->walLevel > TSDB_MAX_WAL_LEVEL)) {
|
||||
snprintf(msg, tListLen(msg), "invalid db option walLevel: %d, only 0-2 allowed", pCreate->walLevel);
|
||||
snprintf(msg, tListLen(msg), "invalid db option walLevel: %d, only 1-2 allowed", pCreate->walLevel);
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
|
||||
|
@ -5848,8 +5900,9 @@ int32_t doCheckForCreateTable(SSqlObj* pSql, int32_t subClauseIndex, SSqlInfo* p
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (tscSetTableFullName(pTableMetaInfo, pzTableName, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
int32_t code = tscSetTableFullName(pTableMetaInfo, pzTableName, pSql);
|
||||
if(code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (!validateTableColumnInfo(pFieldList, pCmd) ||
|
||||
|
@ -5903,15 +5956,16 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (tscSetTableFullName(pStableMeterMetaInfo, pToken, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
int32_t code = tscSetTableFullName(pStableMeterMetaInfo, pToken, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
// get meter meta from mnode
|
||||
tstrncpy(pCreateTable->usingInfo.tagdata.name, pStableMeterMetaInfo->name, sizeof(pCreateTable->usingInfo.tagdata.name));
|
||||
tVariantList* pList = pInfo->pCreateTableInfo->usingInfo.pTagVals;
|
||||
|
||||
int32_t code = tscGetTableMeta(pSql, pStableMeterMetaInfo);
|
||||
code = tscGetTableMeta(pSql, pStableMeterMetaInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
@ -5988,7 +6042,6 @@ int32_t doCheckForCreateFromStable(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
|
||||
int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
|
||||
const char* msg1 = "invalid table name";
|
||||
const char* msg2 = "table name too long";
|
||||
const char* msg3 = "fill only available for interval query";
|
||||
const char* msg4 = "fill option not supported in stream computing";
|
||||
const char* msg5 = "sql too long"; // todo ADD support
|
||||
|
@ -6020,11 +6073,12 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (tscSetTableFullName(pTableMetaInfo, &srcToken, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
int32_t code = tscSetTableFullName(pTableMetaInfo, &srcToken, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
int32_t code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
code = tscGetTableMeta(pSql, pTableMetaInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
@ -6051,8 +6105,9 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
}
|
||||
|
||||
// set the created table[stream] name
|
||||
if (tscSetTableFullName(pTableMetaInfo, pzTableName, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
code = tscSetTableFullName(pTableMetaInfo, pzTableName, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
if (pQuerySql->selectToken.n > TSDB_MAX_SAVED_SQL_LEN) {
|
||||
|
@ -6096,7 +6151,6 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
assert(pQuerySql != NULL && (pQuerySql->from == NULL || pQuerySql->from->nExpr > 0));
|
||||
|
||||
const char* msg0 = "invalid table name";
|
||||
//const char* msg1 = "table name too long";
|
||||
const char* msg2 = "point interpolation query needs timestamp";
|
||||
const char* msg5 = "fill only available for interval query";
|
||||
const char* msg6 = "start(end) time of query range required or time range too large";
|
||||
|
@ -6168,11 +6222,16 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
STableMetaInfo* pTableMetaInfo1 = tscGetMetaInfo(pQueryInfo, i/2);
|
||||
|
||||
SStrToken t = {.type = TSDB_DATA_TYPE_BINARY, .n = pTableItem->nLen, .z = pTableItem->pz};
|
||||
if (tscSetTableFullName(pTableMetaInfo1, &t, pSql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
code = tscSetTableFullName(pTableMetaInfo1, &t, pSql);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
tVariant* pTableItem1 = &pQuerySql->from->a[i + 1].pVar;
|
||||
if (pTableItem1->nType != TSDB_DATA_TYPE_BINARY) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg11);
|
||||
}
|
||||
|
||||
SStrToken aliasName = {.z = pTableItem1->pz, .n = pTableItem1->nLen, .type = TK_STRING};
|
||||
if (tscValidateName(&aliasName) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg11);
|
||||
|
@ -6238,6 +6297,11 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// set order by info
|
||||
if (parseOrderbyClause(pCmd, pQueryInfo, pQuerySql, tscGetTableSchema(pTableMetaInfo->pTableMeta)) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// set interval value
|
||||
if (parseIntervalClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
|
@ -6248,11 +6312,6 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
}
|
||||
}
|
||||
|
||||
// set order by info
|
||||
if (parseOrderbyClause(pCmd, pQueryInfo, pQuerySql, tscGetTableSchema(pTableMetaInfo->pTableMeta)) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
// user does not specified the query time window, twa is not allowed in such case.
|
||||
if ((pQueryInfo->window.skey == INT64_MIN || pQueryInfo->window.ekey == INT64_MAX ||
|
||||
(pQueryInfo->window.ekey == INT64_MAX / 1000 && tinfo.precision == TSDB_TIME_PRECISION_MILLI)) && tscIsTWAQuery(pQueryInfo)) {
|
||||
|
@ -6319,19 +6378,19 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
return TSDB_CODE_SUCCESS; // Does not build query message here
|
||||
}
|
||||
|
||||
int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SArray* pExprInfo, SQueryInfo* pQueryInfo, SArray* pCols) {
|
||||
int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pSqlExpr, SQueryInfo* pQueryInfo, SArray* pCols, int64_t *uid) {
|
||||
tExprNode* pLeft = NULL;
|
||||
tExprNode* pRight= NULL;
|
||||
|
||||
if (pSqlExpr->pLeft != NULL) {
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pLeft, pSqlExpr->pLeft, pExprInfo, pQueryInfo, pCols);
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pLeft, pSqlExpr->pLeft, pQueryInfo, pCols, uid);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSqlExpr->pRight != NULL) {
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pRight, pSqlExpr->pRight, pExprInfo, pQueryInfo, pCols);
|
||||
int32_t ret = exprTreeFromSqlExpr(pCmd, &pRight, pSqlExpr->pRight, pQueryInfo, pCols, uid);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
}
|
||||
|
@ -6358,14 +6417,19 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
|||
strncpy((*pExpr)->pSchema->name, pSqlExpr->operand.z, pSqlExpr->operand.n);
|
||||
|
||||
// set the input column data byte and type.
|
||||
size_t size = taosArrayGetSize(pExprInfo);
|
||||
size_t size = taosArrayGetSize(pQueryInfo->exprList);
|
||||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* p1 = taosArrayGetP(pExprInfo, i);
|
||||
SSqlExpr* p1 = taosArrayGetP(pQueryInfo->exprList, i);
|
||||
|
||||
if (strcmp((*pExpr)->pSchema->name, p1->aliasName) == 0) {
|
||||
(*pExpr)->pSchema->type = (uint8_t)p1->resType;
|
||||
(*pExpr)->pSchema->type = (uint8_t)p1->resType;
|
||||
(*pExpr)->pSchema->bytes = p1->resBytes;
|
||||
|
||||
if (uid != NULL) {
|
||||
*uid = p1->uid;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -145,10 +145,11 @@ static void tscInitCorVgroupInfo(SCMCorVgroupInfo *corVgroupInfo, SCMVgroupInfo
|
|||
corVgroupInfo->inUse = 0;
|
||||
corVgroupInfo->numOfEps = vgroupInfo->numOfEps;
|
||||
for (int32_t i = 0; i < corVgroupInfo->numOfEps; i++) {
|
||||
strncpy(corVgroupInfo->epAddr[i].fqdn, vgroupInfo->epAddr[i].fqdn, TSDB_FQDN_LEN);
|
||||
corVgroupInfo->epAddr[i].fqdn = strdup(vgroupInfo->epAddr[i].fqdn);
|
||||
corVgroupInfo->epAddr[i].port = vgroupInfo->epAddr[i].port;
|
||||
}
|
||||
}
|
||||
|
||||
STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size) {
|
||||
assert(pTableMetaMsg != NULL);
|
||||
|
||||
|
@ -162,14 +163,25 @@ STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size
|
|||
.numOfColumns = pTableMetaMsg->numOfColumns,
|
||||
};
|
||||
|
||||
pTableMeta->id.tid = pTableMetaMsg->sid;
|
||||
pTableMeta->id.tid = pTableMetaMsg->tid;
|
||||
pTableMeta->id.uid = pTableMetaMsg->uid;
|
||||
pTableMeta->vgroupInfo = pTableMetaMsg->vgroup;
|
||||
|
||||
tscInitCorVgroupInfo(&pTableMeta->corVgroupInfo, &pTableMeta->vgroupInfo);
|
||||
SCMVgroupInfo* pVgroupInfo = &pTableMeta->vgroupInfo;
|
||||
pVgroupInfo->numOfEps = pTableMetaMsg->vgroup.numOfEps;
|
||||
pVgroupInfo->vgId = pTableMetaMsg->vgroup.vgId;
|
||||
|
||||
for(int32_t i = 0; i < pVgroupInfo->numOfEps; ++i) {
|
||||
SEpAddrMsg* pEpMsg = &pTableMetaMsg->vgroup.epAddr[i];
|
||||
|
||||
pVgroupInfo->epAddr[i].fqdn = strndup(pEpMsg->fqdn, tListLen(pEpMsg->fqdn));
|
||||
pVgroupInfo->epAddr[i].port = pEpMsg->port;
|
||||
}
|
||||
|
||||
tscInitCorVgroupInfo(&pTableMeta->corVgroupInfo, pVgroupInfo);
|
||||
|
||||
pTableMeta->sversion = pTableMetaMsg->sversion;
|
||||
pTableMeta->tversion = pTableMetaMsg->tversion;
|
||||
tstrncpy(pTableMeta->sTableId, pTableMetaMsg->sTableId, TSDB_TABLE_FNAME_LEN);
|
||||
|
||||
memcpy(pTableMeta->schema, pTableMetaMsg->schema, schemaSize);
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
#include "ttimer.h"
|
||||
#include "tutil.h"
|
||||
#include "tlockfree.h"
|
||||
|
||||
SRpcCorEpSet tscMgmtEpSet;
|
||||
|
@ -53,7 +52,10 @@ static void tscSetDnodeEpSet(SSqlObj* pSql, SCMVgroupInfo* pVgroupInfo) {
|
|||
assert(pSql != NULL && pVgroupInfo != NULL && pVgroupInfo->numOfEps > 0);
|
||||
|
||||
SRpcEpSet* pEpSet = &pSql->epSet;
|
||||
pEpSet->inUse = 0;
|
||||
|
||||
// Issue the query to one of the vnode among a vgroup randomly.
|
||||
// change the inUse property would not affect the isUse attribute of STableMeta
|
||||
pEpSet->inUse = rand() % pVgroupInfo->numOfEps;
|
||||
|
||||
// apply the FQDN string length check here
|
||||
bool hasFqdn = false;
|
||||
|
@ -122,12 +124,15 @@ static void tscUpdateVgroupInfo(SSqlObj *pObj, SRpcEpSet *pEpSet) {
|
|||
pVgroupInfo->inUse = pEpSet->inUse;
|
||||
pVgroupInfo->numOfEps = pEpSet->numOfEps;
|
||||
for (int32_t i = 0; i < pVgroupInfo->numOfEps; i++) {
|
||||
tstrncpy(pVgroupInfo->epAddr[i].fqdn, pEpSet->fqdn[i], TSDB_FQDN_LEN);
|
||||
taosTFree(pVgroupInfo->epAddr[i].fqdn);
|
||||
pVgroupInfo->epAddr[i].fqdn = strndup(pEpSet->fqdn[i], tListLen(pEpSet->fqdn[i]));
|
||||
pVgroupInfo->epAddr[i].port = pEpSet->port[i];
|
||||
}
|
||||
|
||||
tscDebug("after: EndPoint in use: %d", pVgroupInfo->inUse);
|
||||
taosCorEndWrite(&pVgroupInfo->version);
|
||||
}
|
||||
|
||||
void tscPrintMgmtEp() {
|
||||
SRpcEpSet dump;
|
||||
tscDumpMgmtEpSet(&dump);
|
||||
|
@ -143,12 +148,13 @@ void tscPrintMgmtEp() {
|
|||
void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
|
||||
STscObj *pObj = (STscObj *)param;
|
||||
if (pObj == NULL) return;
|
||||
|
||||
if (pObj != pObj->signature) {
|
||||
tscError("heart beat msg, pObj:%p, signature:%p invalid", pObj, pObj->signature);
|
||||
return;
|
||||
}
|
||||
|
||||
SSqlObj *pSql = pObj->pHb;
|
||||
SSqlObj *pSql = tres;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
if (code == 0) {
|
||||
|
@ -169,33 +175,47 @@ void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int code) {
|
|||
if (pRsp->streamId) tscKillStream(pObj, htonl(pRsp->streamId));
|
||||
}
|
||||
} else {
|
||||
tscDebug("heart beat failed, code:%s", tstrerror(code));
|
||||
tscDebug("heartbeat failed, code:%s", tstrerror(code));
|
||||
}
|
||||
|
||||
taosTmrReset(tscProcessActivityTimer, tsShellActivityTimer * 500, pObj, tscTmr, &pObj->pTimer);
|
||||
if (pObj->pHb != NULL) {
|
||||
int32_t waitingDuring = tsShellActivityTimer * 500;
|
||||
tscDebug("%p start heartbeat in %dms", pSql, waitingDuring);
|
||||
|
||||
taosTmrReset(tscProcessActivityTimer, waitingDuring, pObj, tscTmr, &pObj->pTimer);
|
||||
} else {
|
||||
tscDebug("%p start to close tscObj:%p, not send heartbeat again", pSql, pObj);
|
||||
}
|
||||
}
|
||||
|
||||
void tscProcessActivityTimer(void *handle, void *tmrId) {
|
||||
STscObj *pObj = (STscObj *)handle;
|
||||
if (pObj == NULL || pObj->signature != pObj) {
|
||||
|
||||
int ret = taosAcquireRef(tscRefId, pObj);
|
||||
if (ret < 0) {
|
||||
tscTrace("%p failed to acquire TSC obj, reason:%s", pObj, tstrerror(ret));
|
||||
return;
|
||||
}
|
||||
|
||||
SSqlObj* pHB = pObj->pHb;
|
||||
if (pObj->pTimer != tmrId || pHB == NULL) {
|
||||
|
||||
void** p = taosCacheAcquireByKey(tscObjCache, &pHB, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||
if (p == NULL) {
|
||||
tscWarn("%p HB object has been released already", pHB);
|
||||
taosReleaseRef(tscRefId, pObj);
|
||||
return;
|
||||
}
|
||||
|
||||
if (tscShouldFreeHeartBeat(pHB)) {
|
||||
tscDebug("%p free HB object and release connection", pHB);
|
||||
pObj->pHb = 0;
|
||||
taos_free_result(pHB);
|
||||
} else {
|
||||
int32_t code = tscProcessSql(pHB);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("%p failed to sent HB to server, reason:%s", pHB, tstrerror(code));
|
||||
}
|
||||
assert(*pHB->self == pHB);
|
||||
|
||||
int32_t code = tscProcessSql(pHB);
|
||||
taosCacheRelease(tscObjCache, (void**) &p, false);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscError("%p failed to sent HB to server, reason:%s", pHB, tstrerror(code));
|
||||
}
|
||||
|
||||
taosReleaseRef(tscRefId, pObj);
|
||||
}
|
||||
|
||||
int tscSendMsgToServer(SSqlObj *pSql) {
|
||||
|
@ -233,9 +253,8 @@ int tscSendMsgToServer(SSqlObj *pSql) {
|
|||
}
|
||||
|
||||
void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
||||
uint64_t handle = (uint64_t) rpcMsg->ahandle;
|
||||
|
||||
void** p = taosCacheAcquireByKey(tscObjCache, &handle, sizeof(uint64_t));
|
||||
TSDB_CACHE_PTR_TYPE handle = (TSDB_CACHE_PTR_TYPE) rpcMsg->ahandle;
|
||||
void** p = taosCacheAcquireByKey(tscObjCache, &handle, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||
if (p == NULL) {
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
|
@ -249,6 +268,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
assert(*pSql->self == pSql);
|
||||
pSql->pRpcCtx = NULL;
|
||||
|
||||
if (pObj->signature != pObj) {
|
||||
tscDebug("%p DB connection is closed, cmd:%d pObj:%p signature:%p", pSql, pCmd->command, pObj, pObj->signature);
|
||||
|
@ -258,8 +278,6 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
return;
|
||||
}
|
||||
|
||||
pSql->pRpcCtx = NULL; // clear the rpcCtx
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
if (pQueryInfo != NULL && pQueryInfo->type == TSDB_QUERY_TYPE_FREE_RESOURCE) {
|
||||
tscDebug("%p sqlObj needs to be released or DB connection is closed, cmd:%d type:%d, pObj:%p signature:%p",
|
||||
|
@ -454,34 +472,6 @@ int tscProcessSql(SSqlObj *pSql) {
|
|||
return doProcessSql(pSql);
|
||||
}
|
||||
|
||||
void tscKillSTableQuery(SSqlObj *pSql) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
if (!tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
|
||||
for (int i = 0; i < pSql->numOfSubs; ++i) {
|
||||
// NOTE: pSub may have been released already here
|
||||
SSqlObj *pSub = pSql->pSubs[i];
|
||||
if (pSub == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pSub->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
if (pSub->pRpcCtx != NULL) {
|
||||
rpcCancelRequest(pSub->pRpcCtx);
|
||||
}
|
||||
|
||||
tscQueueAsyncRes(pSub); // async res? not other functions?
|
||||
}
|
||||
|
||||
tscDebug("%p super table query cancelled", pSql);
|
||||
}
|
||||
|
||||
int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||
SRetrieveTableMsg *pRetrieveMsg = (SRetrieveTableMsg *) pSql->cmd.payload;
|
||||
pRetrieveMsg->qhandle = htobe64(pSql->res.qhandle);
|
||||
|
@ -494,14 +484,25 @@ int tscBuildFetchMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
|
||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
int32_t vgIndex = pTableMetaInfo->vgroupIndex;
|
||||
|
||||
SVgroupsInfo* pVgroupInfo = pTableMetaInfo->vgroupList;
|
||||
assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
|
||||
if (pTableMetaInfo->pVgroupTables == NULL) {
|
||||
SVgroupsInfo *pVgroupInfo = pTableMetaInfo->vgroupList;
|
||||
assert(pVgroupInfo->vgroups[vgIndex].vgId > 0 && vgIndex < pTableMetaInfo->vgroupList->numOfVgroups);
|
||||
|
||||
pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
|
||||
pRetrieveMsg->header.vgId = htonl(pVgroupInfo->vgroups[vgIndex].vgId);
|
||||
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d", pSql, pVgroupInfo->vgroups[vgIndex].vgId, vgIndex);
|
||||
} else {
|
||||
int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables);
|
||||
assert(vgIndex >= 0 && vgIndex < numOfVgroups);
|
||||
|
||||
SVgroupTableInfo* pTableIdList = taosArrayGet(pTableMetaInfo->pVgroupTables, vgIndex);
|
||||
|
||||
pRetrieveMsg->header.vgId = htonl(pTableIdList->vgInfo.vgId);
|
||||
tscDebug("%p build fetch msg from vgId:%d, vgIndex:%d", pSql, pTableIdList->vgInfo.vgId, vgIndex);
|
||||
}
|
||||
} else {
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
pRetrieveMsg->header.vgId = htonl(pTableMeta->vgroupInfo.vgId);
|
||||
tscDebug("%p build fetch msg from only one vgroup, vgId:%d", pSql, pTableMeta->vgroupInfo.vgId);
|
||||
}
|
||||
|
||||
pSql->cmd.payloadLen = sizeof(SRetrieveTableMsg);
|
||||
|
@ -641,14 +642,14 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
|
||||
size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
|
||||
if (numOfSrcCols <= 0 && !tscQueryTags(pQueryInfo)) {
|
||||
tscError("%p illegal value of numOfCols in query msg: %"PRIu64", table cols:%d", pSql, numOfSrcCols,
|
||||
tscError("%p illegal value of numOfCols in query msg: %" PRIu64 ", table cols:%d", pSql, (uint64_t)numOfSrcCols,
|
||||
tscGetNumOfColumns(pTableMeta));
|
||||
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (pQueryInfo->interval.interval < 0) {
|
||||
tscError("%p illegal value of aggregation time interval in query msg: %ld", pSql, pQueryInfo->interval.interval);
|
||||
tscError("%p illegal value of aggregation time interval in query msg: %" PRId64, pSql, (int64_t)pQueryInfo->interval.interval);
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -675,12 +676,12 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
pQueryMsg->limit = htobe64(pQueryInfo->limit.limit);
|
||||
pQueryMsg->offset = htobe64(pQueryInfo->limit.offset);
|
||||
pQueryMsg->numOfCols = htons((int16_t)taosArrayGetSize(pQueryInfo->colList));
|
||||
pQueryMsg->interval.interval = htobe64(pQueryInfo->interval.interval);
|
||||
pQueryMsg->interval.sliding = htobe64(pQueryInfo->interval.sliding);
|
||||
pQueryMsg->interval.interval = htobe64(pQueryInfo->interval.interval);
|
||||
pQueryMsg->interval.sliding = htobe64(pQueryInfo->interval.sliding);
|
||||
pQueryMsg->interval.offset = htobe64(pQueryInfo->interval.offset);
|
||||
pQueryMsg->interval.intervalUnit = pQueryInfo->interval.intervalUnit;
|
||||
pQueryMsg->interval.slidingUnit = pQueryInfo->interval.slidingUnit;
|
||||
pQueryMsg->interval.offsetUnit = pQueryInfo->interval.offsetUnit;
|
||||
pQueryMsg->interval.slidingUnit = pQueryInfo->interval.slidingUnit;
|
||||
pQueryMsg->interval.offsetUnit = pQueryInfo->interval.offsetUnit;
|
||||
pQueryMsg->numOfGroupCols = htons(pQueryInfo->groupbyExpr.numOfGroupCols);
|
||||
pQueryMsg->numOfTags = htonl(numOfTags);
|
||||
pQueryMsg->tagNameRelType = htons(pQueryInfo->tagCond.relType);
|
||||
|
@ -745,7 +746,6 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
|
||||
if (!tscValidateColumnId(pTableMetaInfo, pExpr->colInfo.colId, pExpr->numOfParams)) {
|
||||
/* column id is not valid according to the cached table meta, the table meta is expired */
|
||||
tscError("%p table schema is not matched with parsed sql", pSql);
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -864,7 +864,8 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
int32_t numOfBlocks = 0;
|
||||
|
||||
if (pQueryInfo->tsBuf != NULL) {
|
||||
STSVnodeBlockInfo *pBlockInfo = tsBufGetVnodeBlockInfo(pQueryInfo->tsBuf, pTableMetaInfo->vgroupIndex);
|
||||
int32_t vnodeId = htonl(pQueryMsg->head.vgId);
|
||||
STSVnodeBlockInfo *pBlockInfo = tsBufGetVnodeBlockInfo(pQueryInfo->tsBuf, vnodeId);
|
||||
assert(QUERY_IS_JOIN_QUERY(pQueryInfo->type) && pBlockInfo != NULL); // this query should not be sent
|
||||
|
||||
// todo refactor
|
||||
|
@ -1382,7 +1383,7 @@ static int tscSetResultPointer(SQueryInfo *pQueryInfo, SSqlRes *pRes) {
|
|||
|
||||
for (int i = 0; i < pQueryInfo->fieldsInfo.numOfOutput; ++i) {
|
||||
int16_t offset = tscFieldInfoGetOffset(pQueryInfo, i);
|
||||
pRes->tsrow[i] = ((char*) pRes->data + offset * pRes->numOfRows);
|
||||
pRes->tsrow[i] = (unsigned char*)((char*) pRes->data + offset * pRes->numOfRows);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1441,7 +1442,7 @@ int tscProcessLocalRetrieveRsp(SSqlObj *pSql) {
|
|||
|
||||
int tscProcessRetrieveLocalMergeRsp(SSqlObj *pSql) {
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
int32_t code = pRes->code;
|
||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -1484,6 +1485,7 @@ int tscBuildConnectMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
|
||||
SCMConnectMsg *pConnect = (SCMConnectMsg*)pCmd->payload;
|
||||
|
||||
// TODO refactor full_name
|
||||
char *db; // ugly code to move the space
|
||||
db = strstr(pObj->db, TS_PATH_DELIMITER);
|
||||
db = (db == NULL) ? pObj->db : db + 1;
|
||||
|
@ -1491,47 +1493,36 @@ int tscBuildConnectMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
tstrncpy(pConnect->clientVersion, version, sizeof(pConnect->clientVersion));
|
||||
tstrncpy(pConnect->msgVersion, "", sizeof(pConnect->msgVersion));
|
||||
|
||||
pConnect->pid = htonl(taosGetPId());
|
||||
taosGetCurrentAPPName(pConnect->appName, NULL);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||
SCMTableInfoMsg *pInfoMsg;
|
||||
char * pMsg;
|
||||
int msgLen = 0;
|
||||
|
||||
char *tmpData = NULL;
|
||||
uint32_t len = pSql->cmd.payloadLen;
|
||||
if (len > 0) {
|
||||
if ((tmpData = calloc(1, len)) == NULL) {
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// STagData is in binary format, strncpy is not available
|
||||
memcpy(tmpData, pSql->cmd.payload, len);
|
||||
}
|
||||
|
||||
SSqlCmd * pCmd = &pSql->cmd;
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
pInfoMsg = (SCMTableInfoMsg *)pCmd->payload;
|
||||
SCMTableInfoMsg* pInfoMsg = (SCMTableInfoMsg *)pCmd->payload;
|
||||
strcpy(pInfoMsg->tableId, pTableMetaInfo->name);
|
||||
pInfoMsg->createFlag = htons(pSql->cmd.autoCreated ? 1 : 0);
|
||||
|
||||
pMsg = (char*)pInfoMsg + sizeof(SCMTableInfoMsg);
|
||||
char* pMsg = (char*)pInfoMsg + sizeof(SCMTableInfoMsg);
|
||||
|
||||
if (pSql->cmd.autoCreated && len > 0) {
|
||||
memcpy(pInfoMsg->tags, tmpData, len);
|
||||
pMsg += len;
|
||||
size_t len = htonl(pCmd->tagData.dataLen);
|
||||
if (pSql->cmd.autoCreated) {
|
||||
if (len > 0) {
|
||||
len += sizeof(pCmd->tagData.name) + sizeof(pCmd->tagData.dataLen);
|
||||
memcpy(pInfoMsg->tags, &pCmd->tagData, len);
|
||||
pMsg += len;
|
||||
}
|
||||
}
|
||||
|
||||
pCmd->payloadLen = (int32_t)(pMsg - (char*)pInfoMsg);
|
||||
pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META;
|
||||
|
||||
taosTFree(tmpData);
|
||||
|
||||
assert(msgLen + minMsgSize() <= (int32_t)pCmd->allocSize);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1657,6 +1648,10 @@ int tscBuildHeartBeatMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
SCMHeartBeatMsg *pHeartbeat = (SCMHeartBeatMsg *)pCmd->payload;
|
||||
pHeartbeat->numOfQueries = numOfQueries;
|
||||
pHeartbeat->numOfStreams = numOfStreams;
|
||||
|
||||
pHeartbeat->pid = htonl(taosGetPId());
|
||||
taosGetCurrentAPPName(pHeartbeat->appName, NULL);
|
||||
|
||||
int msgLen = tscBuildQueryStreamDesc(pHeartbeat, pObj);
|
||||
|
||||
pthread_mutex_unlock(&pObj->mutex);
|
||||
|
@ -1670,7 +1665,7 @@ int tscBuildHeartBeatMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
||||
STableMetaMsg *pMetaMsg = (STableMetaMsg *)pSql->res.pRsp;
|
||||
|
||||
pMetaMsg->sid = htonl(pMetaMsg->sid);
|
||||
pMetaMsg->tid = htonl(pMetaMsg->tid);
|
||||
pMetaMsg->sversion = htons(pMetaMsg->sversion);
|
||||
pMetaMsg->tversion = htons(pMetaMsg->tversion);
|
||||
pMetaMsg->vgroup.vgId = htonl(pMetaMsg->vgroup.vgId);
|
||||
|
@ -1680,9 +1675,9 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
pMetaMsg->numOfColumns = htons(pMetaMsg->numOfColumns);
|
||||
|
||||
if ((pMetaMsg->tableType != TSDB_SUPER_TABLE) &&
|
||||
(pMetaMsg->sid <= 0 || pMetaMsg->vgroup.vgId < 2 || pMetaMsg->vgroup.numOfEps <= 0)) {
|
||||
(pMetaMsg->tid <= 0 || pMetaMsg->vgroup.vgId < 2 || pMetaMsg->vgroup.numOfEps <= 0)) {
|
||||
tscError("invalid value in table numOfEps:%d, vgId:%d tid:%d, name:%s", pMetaMsg->vgroup.numOfEps, pMetaMsg->vgroup.vgId,
|
||||
pMetaMsg->sid, pMetaMsg->tableId);
|
||||
pMetaMsg->tid, pMetaMsg->tableId);
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
|
@ -1861,22 +1856,30 @@ int tscProcessSTableVgroupRsp(SSqlObj *pSql) {
|
|||
SSqlCmd* pCmd = &parent->cmd;
|
||||
for(int32_t i = 0; i < pStableVgroup->numOfTables; ++i) {
|
||||
STableMetaInfo *pInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, i);
|
||||
SVgroupsInfo * pVgroupInfo = (SVgroupsInfo *)pMsg;
|
||||
pVgroupInfo->numOfVgroups = htonl(pVgroupInfo->numOfVgroups);
|
||||
|
||||
size_t size = sizeof(SCMVgroupInfo) * pVgroupInfo->numOfVgroups + sizeof(SVgroupsInfo);
|
||||
pInfo->vgroupList = calloc(1, size);
|
||||
SVgroupsMsg * pVgroupMsg = (SVgroupsMsg *) pMsg;
|
||||
pVgroupMsg->numOfVgroups = htonl(pVgroupMsg->numOfVgroups);
|
||||
|
||||
size_t size = sizeof(SCMVgroupMsg) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsMsg);
|
||||
|
||||
size_t vgroupsz = sizeof(SCMVgroupInfo) * pVgroupMsg->numOfVgroups + sizeof(SVgroupsInfo);
|
||||
pInfo->vgroupList = calloc(1, vgroupsz);
|
||||
assert(pInfo->vgroupList != NULL);
|
||||
|
||||
memcpy(pInfo->vgroupList, pVgroupInfo, size);
|
||||
pInfo->vgroupList->numOfVgroups = pVgroupMsg->numOfVgroups;
|
||||
for (int32_t j = 0; j < pInfo->vgroupList->numOfVgroups; ++j) {
|
||||
//just init, no need to lock
|
||||
SCMVgroupInfo *pVgroups = &pInfo->vgroupList->vgroups[j];
|
||||
pVgroups->vgId = htonl(pVgroups->vgId);
|
||||
assert(pVgroups->numOfEps >= 1);
|
||||
|
||||
SCMVgroupMsg *vmsg = &pVgroupMsg->vgroups[j];
|
||||
pVgroups->vgId = htonl(vmsg->vgId);
|
||||
pVgroups->numOfEps = vmsg->numOfEps;
|
||||
|
||||
assert(pVgroups->numOfEps >= 1 && pVgroups->vgId >= 1);
|
||||
|
||||
for (int32_t k = 0; k < pVgroups->numOfEps; ++k) {
|
||||
pVgroups->epAddr[k].port = htons(pVgroups->epAddr[k].port);
|
||||
pVgroups->epAddr[k].port = htons(vmsg->epAddr[k].port);
|
||||
pVgroups->epAddr[k].fqdn = strndup(vmsg->epAddr[k].fqdn, tListLen(vmsg->epAddr[k].fqdn));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1912,7 +1915,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
|
|||
pMetaMsg->numOfColumns = ntohs(pMetaMsg->numOfColumns);
|
||||
|
||||
pSchema = pMetaMsg->schema;
|
||||
pMetaMsg->sid = ntohs(pMetaMsg->sid);
|
||||
pMetaMsg->tid = ntohs(pMetaMsg->tid);
|
||||
for (int i = 0; i < pMetaMsg->numOfColumns; ++i) {
|
||||
pSchema->bytes = htons(pSchema->bytes);
|
||||
pSchema++;
|
||||
|
@ -1946,7 +1949,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
|
|||
tscColumnListInsert(pQueryInfo->colList, &index);
|
||||
|
||||
TAOS_FIELD f = tscCreateField(pSchema->type, pSchema->name, pSchema->bytes);
|
||||
SFieldSupInfo* pInfo = tscFieldInfoAppend(pFieldInfo, &f);
|
||||
SInternalField* pInfo = tscFieldInfoAppend(pFieldInfo, &f);
|
||||
|
||||
pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index,
|
||||
pTableSchema[i].type, pTableSchema[i].bytes, pTableSchema[i].bytes, false);
|
||||
|
@ -1987,15 +1990,11 @@ static void createHBObj(STscObj* pObj) {
|
|||
pSql->param = pObj;
|
||||
pSql->pTscObj = pObj;
|
||||
pSql->signature = pSql;
|
||||
|
||||
registerSqlObj(pSql);
|
||||
tscDebug("%p HB is allocated, pObj:%p", pSql, pObj);
|
||||
|
||||
pObj->pHb = pSql;
|
||||
|
||||
tscAddSubqueryInfo(&pObj->pHb->cmd);
|
||||
|
||||
int64_t ad = (int64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &ad, sizeof(int64_t), &pSql, sizeof(int64_t), 2 * 60 * 1000);
|
||||
T_REF_INC(pObj);
|
||||
|
||||
tscDebug("%p HB is allocated, pObj:%p", pObj->pHb, pObj);
|
||||
}
|
||||
|
||||
int tscProcessConnectRsp(SSqlObj *pSql) {
|
||||
|
@ -2093,6 +2092,9 @@ int tscProcessAlterDbMsgRsp(SSqlObj *pSql) {
|
|||
UNUSED(pSql);
|
||||
return 0;
|
||||
}
|
||||
int tscProcessShowCreateRsp(SSqlObj *pSql) {
|
||||
return tscLocalResultCommonBuilder(pSql, 1);
|
||||
}
|
||||
|
||||
int tscProcessQueryRsp(SSqlObj *pSql) {
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
@ -2167,11 +2169,7 @@ static int32_t getTableMetaFromMgmt(SSqlObj *pSql, STableMetaInfo *pTableMetaInf
|
|||
pNew->signature = pNew;
|
||||
pNew->cmd.command = TSDB_SQL_META;
|
||||
|
||||
T_REF_INC(pNew->pTscObj);
|
||||
|
||||
// TODO add test case on x86 platform
|
||||
uint64_t adr = (uint64_t) pNew;
|
||||
pNew->self = taosCachePut(tscObjCache, &adr, sizeof(uint64_t), &pNew, sizeof(uint64_t), 2*60*1000);
|
||||
registerSqlObj(pNew);
|
||||
|
||||
tscAddSubqueryInfo(&pNew->cmd);
|
||||
|
||||
|
@ -2189,8 +2187,7 @@ static int32_t getTableMetaFromMgmt(SSqlObj *pSql, STableMetaInfo *pTableMetaInf
|
|||
assert(pNew->cmd.numOfClause == 1 && pNewQueryInfo->numOfTables == 1);
|
||||
|
||||
tstrncpy(pNewMeterMetaInfo->name, pTableMetaInfo->name, sizeof(pNewMeterMetaInfo->name));
|
||||
memcpy(pNew->cmd.payload, pSql->cmd.payload, pSql->cmd.payloadLen); // tag information if table does not exists.
|
||||
pNew->cmd.payloadLen = pSql->cmd.payloadLen;
|
||||
memcpy(&pNew->cmd.tagData, &pSql->cmd.tagData, sizeof(pSql->cmd.tagData));
|
||||
tscDebug("%p new pSqlObj:%p to get tableMeta, auto create:%d", pSql, pNew, pNew->cmd.autoCreated);
|
||||
|
||||
pNew->fp = tscTableMetaCallBack;
|
||||
|
@ -2289,7 +2286,7 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
|
|||
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
|
||||
STableMetaInfo *pMInfo = tscGetMetaInfo(pQueryInfo, i);
|
||||
STableMeta *pTableMeta = taosCacheAcquireByData(tscMetaCache, pMInfo->pTableMeta);
|
||||
tscAddTableMetaInfo(pNewQueryInfo, pMInfo->name, pTableMeta, NULL, pMInfo->tagColList);
|
||||
tscAddTableMetaInfo(pNewQueryInfo, pMInfo->name, pTableMeta, NULL, pMInfo->tagColList, pMInfo->pVgroupTables);
|
||||
}
|
||||
|
||||
if ((code = tscAllocPayload(&pNew->cmd, TSDB_DEFAULT_PAYLOAD_SIZE)) != TSDB_CODE_SUCCESS) {
|
||||
|
@ -2298,10 +2295,8 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
|
|||
}
|
||||
|
||||
pNewQueryInfo->numOfTables = pQueryInfo->numOfTables;
|
||||
T_REF_INC(pNew->pTscObj);
|
||||
registerSqlObj(pNew);
|
||||
|
||||
uint64_t p = (uint64_t) pNew;
|
||||
pNew->self = taosCachePut(tscObjCache, &p, sizeof(uint64_t), &pNew, sizeof(uint64_t), 2 * 600 * 1000);
|
||||
tscDebug("%p new sqlObj:%p to get vgroupInfo, numOfTables:%d", pSql, pNew, pNewQueryInfo->numOfTables);
|
||||
|
||||
pNew->fp = tscTableMetaCallBack;
|
||||
|
@ -2379,6 +2374,10 @@ void tscInitMsgsFp() {
|
|||
tscProcessMsgRsp[TSDB_SQL_ALTER_TABLE] = tscProcessAlterTableMsgRsp;
|
||||
tscProcessMsgRsp[TSDB_SQL_ALTER_DB] = tscProcessAlterDbMsgRsp;
|
||||
|
||||
tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_TABLE] = tscProcessShowCreateRsp;
|
||||
tscProcessMsgRsp[TSDB_SQL_SHOW_CREATE_DATABASE] = tscProcessShowCreateRsp;
|
||||
|
||||
|
||||
tscKeepConn[TSDB_SQL_SHOW] = 1;
|
||||
tscKeepConn[TSDB_SQL_RETRIEVE] = 1;
|
||||
tscKeepConn[TSDB_SQL_SELECT] = 1;
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
#include "tsclient.h"
|
||||
#include "ttokendef.h"
|
||||
#include "tutil.h"
|
||||
#include "ttimer.h"
|
||||
#include "tscProfile.h"
|
||||
#include "ttimer.h"
|
||||
|
||||
static bool validImpl(const char* str, size_t maxsize) {
|
||||
if (str == NULL) {
|
||||
|
@ -49,8 +51,8 @@ static bool validPassword(const char* passwd) {
|
|||
return validImpl(passwd, TSDB_PASSWORD_LEN - 1);
|
||||
}
|
||||
|
||||
SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *auth, const char *db,
|
||||
uint16_t port, void (*fp)(void *, TAOS_RES *, int), void *param, void **taos) {
|
||||
static SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, const char *auth, const char *db,
|
||||
uint16_t port, void (*fp)(void *, TAOS_RES *, int), void *param, TAOS **taos) {
|
||||
taos_init();
|
||||
|
||||
if (!validUserName(user)) {
|
||||
|
@ -156,12 +158,10 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
|
|||
*taos = pObj;
|
||||
}
|
||||
|
||||
T_REF_INC(pSql->pTscObj);
|
||||
|
||||
uint64_t key = (uint64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &key, sizeof(uint64_t), &pSql, sizeof(uint64_t), 2*3600*1000);
|
||||
registerSqlObj(pSql);
|
||||
tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg);
|
||||
|
||||
taosAddRef(tscRefId, pObj);
|
||||
return pSql;
|
||||
}
|
||||
|
||||
|
@ -244,25 +244,39 @@ static void asyncConnCallback(void *param, TAOS_RES *tres, int code) {
|
|||
}
|
||||
|
||||
TAOS *taos_connect_a(char *ip, char *user, char *pass, char *db, uint16_t port, void (*fp)(void *, TAOS_RES *, int),
|
||||
void *param, void **taos) {
|
||||
SSqlObj* pSql = taosConnectImpl(ip, user, pass, NULL, db, port, asyncConnCallback, param, taos);
|
||||
void *param, TAOS **taos) {
|
||||
STscObj *pObj = NULL;
|
||||
SSqlObj *pSql = taosConnectImpl(ip, user, pass, NULL, db, port, asyncConnCallback, param, (void **)&pObj);
|
||||
if (pSql == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
if (taos) *taos = pObj;
|
||||
|
||||
pSql->fetchFp = fp;
|
||||
pSql->res.code = tscProcessSql(pSql);
|
||||
tscDebug("%p DB async connection is opening", taos);
|
||||
return taos;
|
||||
return pObj;
|
||||
}
|
||||
|
||||
void taos_close(TAOS *taos) {
|
||||
STscObj *pObj = (STscObj *)taos;
|
||||
|
||||
if (pObj == NULL || pObj->signature != pObj) {
|
||||
if (pObj == NULL) {
|
||||
tscDebug("(null) try to free tscObj and close dnodeConn");
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p try to free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
|
||||
if (pObj->signature != pObj) {
|
||||
tscDebug("%p already closed or invalid tscObj", pObj);
|
||||
return;
|
||||
}
|
||||
|
||||
// make sure that the close connection can only be executed once.
|
||||
pObj->signature = NULL;
|
||||
taosTmrStopA(&(pObj->pTimer));
|
||||
|
||||
SSqlObj* pHb = pObj->pHb;
|
||||
if (pHb != NULL && atomic_val_compare_exchange_ptr(&pObj->pHb, pHb, 0) == pHb) {
|
||||
if (pHb->pRpcCtx != NULL) { // wait for rsp from dnode
|
||||
|
@ -270,7 +284,7 @@ void taos_close(TAOS *taos) {
|
|||
pHb->pRpcCtx = NULL;
|
||||
}
|
||||
|
||||
tscDebug("%p, HB is freed", pHb);
|
||||
tscDebug("%p HB is freed", pHb);
|
||||
taos_free_result(pHb);
|
||||
}
|
||||
|
||||
|
@ -283,7 +297,8 @@ void taos_close(TAOS *taos) {
|
|||
}
|
||||
|
||||
tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
|
||||
tscCloseTscObj(pObj);
|
||||
|
||||
taosRemoveRef(tscRefId, pObj);
|
||||
}
|
||||
|
||||
void waitForQueryRsp(void *param, TAOS_RES *tres, int code) {
|
||||
|
@ -298,7 +313,7 @@ static void waitForRetrieveRsp(void *param, TAOS_RES *tres, int numOfRows) {
|
|||
tsem_post(&pSql->rspSem);
|
||||
}
|
||||
|
||||
TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen) {
|
||||
TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen, TAOS_RES** res) {
|
||||
STscObj *pObj = (STscObj *)taos;
|
||||
if (pObj == NULL || pObj->signature != pObj) {
|
||||
terrno = TSDB_CODE_TSC_DISCONNECTED;
|
||||
|
@ -323,12 +338,20 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen) {
|
|||
tsem_init(&pSql->rspSem, 0, 0);
|
||||
doAsyncQuery(pObj, pSql, waitForQueryRsp, taos, sqlstr, sqlLen);
|
||||
|
||||
if (res != NULL) {
|
||||
*res = pSql;
|
||||
}
|
||||
|
||||
tsem_wait(&pSql->rspSem);
|
||||
return pSql;
|
||||
}
|
||||
|
||||
TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) {
|
||||
return taos_query_c(taos, sqlstr, (uint32_t)strlen(sqlstr));
|
||||
return taos_query_c(taos, sqlstr, (uint32_t)strlen(sqlstr), NULL);
|
||||
}
|
||||
|
||||
TAOS_RES* taos_query_h(TAOS* taos, const char *sqlstr, TAOS_RES** res) {
|
||||
return taos_query_c(taos, sqlstr, (uint32_t) strlen(sqlstr), res);
|
||||
}
|
||||
|
||||
int taos_result_precision(TAOS_RES *res) {
|
||||
|
@ -352,7 +375,7 @@ int taos_num_fields(TAOS_RES *res) {
|
|||
|
||||
size_t numOfCols = tscNumOfFields(pQueryInfo);
|
||||
for(int32_t i = 0; i < numOfCols; ++i) {
|
||||
SFieldSupInfo* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.pSupportInfo, i);
|
||||
SInternalField* pInfo = taosArrayGet(pQueryInfo->fieldsInfo.internalField, i);
|
||||
if (pInfo->visible) {
|
||||
num++;
|
||||
}
|
||||
|
@ -388,8 +411,24 @@ TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) {
|
|||
if (numOfCols == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pQueryInfo->fieldsInfo.pFields->pData;
|
||||
|
||||
SFieldInfo *pFieldInfo = &pQueryInfo->fieldsInfo;
|
||||
|
||||
if (pFieldInfo->final == NULL) {
|
||||
TAOS_FIELD* f = calloc(pFieldInfo->numOfOutput, sizeof(TAOS_FIELD));
|
||||
|
||||
int32_t j = 0;
|
||||
for(int32_t i = 0; i < pFieldInfo->numOfOutput; ++i) {
|
||||
SInternalField* pField = tscFieldInfoGetInternalField(pFieldInfo, i);
|
||||
if (pField->visible) {
|
||||
f[j++] = pField->field;
|
||||
}
|
||||
}
|
||||
|
||||
pFieldInfo->final = f;
|
||||
}
|
||||
|
||||
return pFieldInfo->final;
|
||||
}
|
||||
|
||||
int taos_retrieve(TAOS_RES *res) {
|
||||
|
@ -462,6 +501,7 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
|
|||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
if (pRes->qhandle == 0 ||
|
||||
pRes->code == TSDB_CODE_TSC_QUERY_CANCELLED ||
|
||||
pCmd->command == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
|
||||
pCmd->command == TSDB_SQL_INSERT) {
|
||||
return NULL;
|
||||
|
@ -477,6 +517,8 @@ TAOS_ROW taos_fetch_row(TAOS_RES *res) {
|
|||
pCmd->command == TSDB_SQL_TABLE_JOIN_RETRIEVE ||
|
||||
pCmd->command == TSDB_SQL_FETCH ||
|
||||
pCmd->command == TSDB_SQL_SHOW ||
|
||||
pCmd->command == TSDB_SQL_SHOW_CREATE_TABLE ||
|
||||
pCmd->command == TSDB_SQL_SHOW_CREATE_DATABASE ||
|
||||
pCmd->command == TSDB_SQL_SELECT ||
|
||||
pCmd->command == TSDB_SQL_DESCRIBE_TABLE ||
|
||||
pCmd->command == TSDB_SQL_SERV_STATUS ||
|
||||
|
@ -523,7 +565,7 @@ int taos_fetch_block(TAOS_RES *res, TAOS_ROW *rows) {
|
|||
pRes->numOfClauseTotal = 0;
|
||||
pRes->rspType = 0;
|
||||
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->subState.numOfSub = 0;
|
||||
taosTFree(pSql->pSubs);
|
||||
|
||||
assert(pSql->fp == NULL);
|
||||
|
@ -567,7 +609,8 @@ static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) {
|
|||
return true;
|
||||
}
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
|
||||
if ((pQueryInfo == NULL) || tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
@ -677,6 +720,46 @@ int* taos_fetch_lengths(TAOS_RES *res) {
|
|||
|
||||
char *taos_get_client_info() { return version; }
|
||||
|
||||
static void tscKillSTableQuery(SSqlObj *pSql) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
if (!tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// set the master sqlObj flag to cancel query
|
||||
pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
|
||||
for (int i = 0; i < pSql->subState.numOfSub; ++i) {
|
||||
// NOTE: pSub may have been released already here
|
||||
SSqlObj *pSub = pSql->pSubs[i];
|
||||
if (pSub == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
void** p = taosCacheAcquireByKey(tscObjCache, &pSub, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||
if (p == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SSqlObj* pSubObj = (SSqlObj*) (*p);
|
||||
assert(pSubObj->self == (SSqlObj**) p);
|
||||
|
||||
pSubObj->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
if (pSubObj->pRpcCtx != NULL) {
|
||||
rpcCancelRequest(pSubObj->pRpcCtx);
|
||||
pSubObj->pRpcCtx = NULL;
|
||||
}
|
||||
|
||||
tscQueueAsyncRes(pSubObj);
|
||||
taosCacheRelease(tscObjCache, (void**) &p, false);
|
||||
}
|
||||
|
||||
tscDebug("%p super table query cancelled", pSql);
|
||||
}
|
||||
|
||||
void taos_stop_query(TAOS_RES *res) {
|
||||
SSqlObj *pSql = (SSqlObj *)res;
|
||||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
|
@ -686,20 +769,27 @@ void taos_stop_query(TAOS_RES *res) {
|
|||
tscDebug("%p start to cancel query", res);
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
// TODO there are multi-thread problem.
|
||||
// It may have been released by the other thread already.
|
||||
// The ref count may fix this problem.
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
// set the error code for master pSqlObj firstly
|
||||
pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
if (tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
|
||||
assert(pSql->pRpcCtx == NULL);
|
||||
tscKillSTableQuery(pSql);
|
||||
} else {
|
||||
if (pSql->cmd.command < TSDB_SQL_LOCAL) {
|
||||
rpcCancelRequest(pSql->pRpcCtx);
|
||||
/*
|
||||
* There is multi-thread problem here, since pSql->pRpcCtx may have been
|
||||
* reset and freed in the processMsgFromServer function, and causes the invalid
|
||||
* write problem for rpcCancelRequest.
|
||||
*/
|
||||
if (pSql->pRpcCtx != NULL) {
|
||||
rpcCancelRequest(pSql->pRpcCtx);
|
||||
pSql->pRpcCtx = NULL;
|
||||
}
|
||||
|
||||
tscQueueAsyncRes(pSql);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -720,15 +810,15 @@ int taos_print_row(char *str, TAOS_ROW row, TAOS_FIELD *fields, int num_fields)
|
|||
|
||||
switch (fields[i].type) {
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
len += sprintf(str + len, "%d", *((char *)row[i]));
|
||||
len += sprintf(str + len, "%d", *((int8_t *)row[i]));
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
len += sprintf(str + len, "%d", *((short *)row[i]));
|
||||
len += sprintf(str + len, "%d", *((int16_t *)row[i]));
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
len += sprintf(str + len, "%d", *((int *)row[i]));
|
||||
len += sprintf(str + len, "%d", *((int32_t *)row[i]));
|
||||
break;
|
||||
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
|
@ -787,14 +877,17 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
|
|||
}
|
||||
|
||||
SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
|
||||
|
||||
pSql->pTscObj = taos;
|
||||
pSql->signature = pSql;
|
||||
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
|
||||
pRes->numOfTotal = 0;
|
||||
pRes->numOfClauseTotal = 0;
|
||||
|
||||
|
||||
tscDebug("%p Valid SQL: %s pObj:%p", pSql, sql, pObj);
|
||||
|
||||
int32_t sqlLen = (int32_t)strlen(sql);
|
||||
|
@ -809,7 +902,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
|
|||
if (pSql->sqlstr == NULL) {
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
tscError("%p failed to malloc sql string buffer", pSql);
|
||||
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
|
||||
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, pRes->code, taos_errstr(pSql), pObj);
|
||||
taosTFree(pSql);
|
||||
return pRes->code;
|
||||
}
|
||||
|
@ -825,16 +918,19 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
|
|||
pSql->fp = asyncCallback;
|
||||
pSql->fetchFp = asyncCallback;
|
||||
pSql->param = pSql;
|
||||
|
||||
registerSqlObj(pSql);
|
||||
int code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
tsem_wait(&pSql->rspSem);
|
||||
code = pSql->res.code;
|
||||
}
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, code, taos_errstr(taos), pObj);
|
||||
}
|
||||
taos_free_result(pSql);
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscDebug("%p Valid SQL result:%d, %s pObj:%p", pSql, code, taos_errstr(pSql), pObj);
|
||||
}
|
||||
|
||||
taos_free_result(pSql);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -933,34 +1029,32 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
|
|||
SSqlObj* pSql = calloc(1, sizeof(SSqlObj));
|
||||
pSql->pTscObj = taos;
|
||||
pSql->signature = pSql;
|
||||
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
pRes->code = 0;
|
||||
pRes->numOfTotal = 0; // the number of getting table meta from server
|
||||
pRes->numOfClauseTotal = 0;
|
||||
|
||||
pRes->code = 0;
|
||||
|
||||
assert(pSql->fp == NULL);
|
||||
tscDebug("%p tableNameList: %s pObj:%p", pSql, tableNameList, pObj);
|
||||
|
||||
int32_t tblListLen = (int32_t)strlen(tableNameList);
|
||||
if (tblListLen > MAX_TABLE_NAME_LENGTH) {
|
||||
tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH);
|
||||
pRes->code = TSDB_CODE_TSC_INVALID_SQL;
|
||||
taosTFree(pSql);
|
||||
return pRes->code;
|
||||
tscFreeSqlObj(pSql);
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
char *str = calloc(1, tblListLen + 1);
|
||||
if (str == NULL) {
|
||||
pRes->code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
tscError("%p failed to malloc sql string buffer", pSql);
|
||||
taosTFree(pSql);
|
||||
return pRes->code;
|
||||
tscFreeSqlObj(pSql);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
strtolower(str, tableNameList);
|
||||
pRes->code = (uint8_t)tscParseTblNameList(pSql, str, tblListLen);
|
||||
int32_t code = (uint8_t) tscParseTblNameList(pSql, str, tblListLen);
|
||||
|
||||
/*
|
||||
* set the qhandle to 0 before return in order to erase the qhandle value assigned in the previous successful query.
|
||||
|
@ -970,17 +1064,17 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) {
|
|||
pRes->qhandle = 0;
|
||||
free(str);
|
||||
|
||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
tscFreeSqlObj(pSql);
|
||||
return pRes->code;
|
||||
return code;
|
||||
}
|
||||
|
||||
tscDoQuery(pSql);
|
||||
|
||||
tscDebug("%p load multi metermeta result:%d %s pObj:%p", pSql, pRes->code, taos_errstr(taos), pObj);
|
||||
if (pRes->code != TSDB_CODE_SUCCESS) {
|
||||
tscPartiallyFreeSqlObj(pSql);
|
||||
tscDebug("%p load multi table meta result:%d %s pObj:%p", pSql, pRes->code, taos_errstr(pSql), pObj);
|
||||
if ((code = pRes->code) != TSDB_CODE_SUCCESS) {
|
||||
tscFreeSqlObj(pSql);
|
||||
}
|
||||
|
||||
return pRes->code;
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -136,7 +136,6 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
|
|||
etime = pStream->stime + (etime - pStream->stime) / pStream->interval.interval * pStream->interval.interval;
|
||||
} else {
|
||||
etime = taosTimeTruncate(etime, &pStream->interval, pStream->precision);
|
||||
//etime = taosGetIntervalStartTimestamp(etime, pStream->interval.sliding, pStream->interval.sliding, pStream->interval.slidingUnit, pStream->precision);
|
||||
}
|
||||
pQueryInfo->window.ekey = etime;
|
||||
if (pQueryInfo->window.skey >= pQueryInfo->window.ekey) {
|
||||
|
@ -169,8 +168,8 @@ static void tscProcessStreamQueryCallback(void *param, TAOS_RES *tres, int numOf
|
|||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pStream->pSql->cmd, 0, 0);
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosTFree(pTableMetaInfo->vgroupList);
|
||||
|
||||
pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList);
|
||||
|
||||
tscSetRetryTimer(pStream, pStream->pSql, retryDelay);
|
||||
return;
|
||||
}
|
||||
|
@ -275,8 +274,8 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
|
|||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), false);
|
||||
tscFreeSqlResult(pSql);
|
||||
taosTFree(pSql->pSubs);
|
||||
pSql->numOfSubs = 0;
|
||||
taosTFree(pTableMetaInfo->vgroupList);
|
||||
pSql->subState.numOfSub = 0;
|
||||
pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList);
|
||||
tscSetNextLaunchTimer(pStream, pSql);
|
||||
}
|
||||
}
|
||||
|
@ -399,8 +398,8 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
|
|||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && pQueryInfo->interval.interval < minIntervalTime) {
|
||||
tscWarn("%p stream:%p, original sample interval:%ld too small, reset to:%" PRId64, pSql, pStream,
|
||||
pQueryInfo->interval.interval, minIntervalTime);
|
||||
tscWarn("%p stream:%p, original sample interval:%" PRId64 " too small, reset to:%" PRId64, pSql, pStream,
|
||||
(int64_t)pQueryInfo->interval.interval, minIntervalTime);
|
||||
pQueryInfo->interval.interval = minIntervalTime;
|
||||
}
|
||||
|
||||
|
@ -454,17 +453,11 @@ static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, in
|
|||
}
|
||||
} else { // timewindow based aggregation stream
|
||||
if (stime == 0) { // no data in meter till now
|
||||
stime = pQueryInfo->window.skey;
|
||||
if (stime == INT64_MIN) {
|
||||
stime = (int64_t)taosGetTimestamp(pStream->precision);
|
||||
stime = taosTimeTruncate(stime, &pStream->interval, pStream->precision);
|
||||
stime = taosTimeTruncate(stime - 1, &pStream->interval, pStream->precision);
|
||||
//stime = taosGetIntervalStartTimestamp(stime, pStream->interval.interval, pStream->interval.interval, pStream->interval.intervalUnit, pStream->precision);
|
||||
//stime = taosGetIntervalStartTimestamp(stime - 1, pStream->interval.interval, pStream->interval.interval, pStream->interval.intervalUnit, pStream->precision);
|
||||
tscWarn("%p stream:%p, last timestamp:0, reset to:%" PRId64, pSql, pStream, stime);
|
||||
if (pQueryInfo->window.skey != INT64_MIN) {
|
||||
stime = pQueryInfo->window.skey;
|
||||
}
|
||||
stime = taosTimeTruncate(stime, &pStream->interval, pStream->precision);
|
||||
} else {
|
||||
//int64_t newStime = taosGetIntervalStartTimestamp(stime, pStream->interval.interval, pStream->interval.interval, pStream->interval.intervalUnit, pStream->precision);
|
||||
int64_t newStime = taosTimeTruncate(stime, &pStream->interval, pStream->precision);
|
||||
if (newStime != stime) {
|
||||
tscWarn("%p stream:%p, last timestamp:%" PRId64 ", reset to:%" PRId64, pSql, pStream, stime, newStime);
|
||||
|
@ -477,8 +470,10 @@ static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, in
|
|||
}
|
||||
|
||||
static int64_t tscGetLaunchTimestamp(const SSqlStream *pStream) {
|
||||
int64_t timer = pStream->stime - taosGetTimestamp(pStream->precision);
|
||||
if (timer < 0) timer = 0;
|
||||
int64_t timer = 0, now = taosGetTimestamp(pStream->precision);
|
||||
if (pStream->stime > now) {
|
||||
timer = pStream->stime - now;
|
||||
}
|
||||
|
||||
int64_t startDelay =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsStreamCompStartDelay * 1000L : tsStreamCompStartDelay;
|
||||
|
@ -515,9 +510,7 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) {
|
|||
return;
|
||||
}
|
||||
|
||||
uint64_t handle = (uint64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &handle, sizeof(uint64_t), &pSql, sizeof(uint64_t), 2*3600*1000);
|
||||
T_REF_INC(pSql->pTscObj);
|
||||
registerSqlObj(pSql);
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
|
|
@ -105,6 +105,7 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
code = TAOS_SYSTEM_ERROR(errno);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
tstrncpy(pSub->topic, topic, sizeof(pSub->topic));
|
||||
pSub->progress = taosArrayInit(32, sizeof(SSubscriptionProgress));
|
||||
if (pSub->progress == NULL) {
|
||||
|
@ -119,6 +120,7 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pSql->signature = pSql;
|
||||
pSql->pTscObj = pObj;
|
||||
pSql->pSubscription = pSub;
|
||||
|
@ -142,6 +144,7 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
strtolower(pSql->sqlstr, pSql->sqlstr);
|
||||
pRes->qhandle = 0;
|
||||
pRes->numOfRows = 1;
|
||||
|
@ -152,15 +155,14 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
goto fail;
|
||||
}
|
||||
|
||||
uint64_t handle = (uint64_t) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &handle, sizeof(uint64_t), &pSql, sizeof(uint64_t), 2*3600*1000);
|
||||
T_REF_INC(pSql->pTscObj);
|
||||
registerSqlObj(pSql);
|
||||
|
||||
code = tsParseSql(pSql, false);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
tsem_wait(&pSub->sem);
|
||||
code = pSql->res.code;
|
||||
}
|
||||
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
line = __LINE__;
|
||||
goto fail;
|
||||
|
@ -182,8 +184,10 @@ fail:
|
|||
} else {
|
||||
tscFreeSqlObj(pSql);
|
||||
}
|
||||
|
||||
pSql = NULL;
|
||||
}
|
||||
|
||||
if (pSub != NULL) {
|
||||
taosArrayDestroy(pSub->progress);
|
||||
tsem_destroy(&pSub->sem);
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -36,6 +36,7 @@ void * tscTmr;
|
|||
void * tscQhandle;
|
||||
void * tscCheckDiskUsageTmr;
|
||||
int tsInsertHeadSize;
|
||||
int tscRefId;
|
||||
|
||||
int tscNumOfThreads;
|
||||
|
||||
|
@ -77,6 +78,7 @@ int32_t tscInitRpc(const char *user, const char *secretEncrypt, void **pDnodeCon
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void taos_init_imp(void) {
|
||||
char temp[128];
|
||||
|
||||
|
@ -122,14 +124,12 @@ void taos_init_imp(void) {
|
|||
tscInitMsgsFp();
|
||||
int queueSize = tsMaxConnections*2;
|
||||
|
||||
if (tscEmbedded == 0) {
|
||||
tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 2.0);
|
||||
} else {
|
||||
tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 4.0);
|
||||
double factor = (tscEmbedded == 0)? 2.0:4.0;
|
||||
tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / factor);
|
||||
if (tscNumOfThreads < 2) {
|
||||
tscNumOfThreads = 2;
|
||||
}
|
||||
|
||||
if (tscNumOfThreads < 2) tscNumOfThreads = 2;
|
||||
|
||||
tscQhandle = taosInitScheduler(queueSize, tscNumOfThreads, "tsc");
|
||||
if (NULL == tscQhandle) {
|
||||
tscError("failed to init scheduler");
|
||||
|
@ -140,16 +140,15 @@ void taos_init_imp(void) {
|
|||
if(0 == tscEmbedded){
|
||||
taosTmrReset(tscCheckDiskUsage, 10, NULL, tscTmr, &tscCheckDiskUsageTmr);
|
||||
}
|
||||
|
||||
int64_t refreshTime = tsTableMetaKeepTimer;
|
||||
refreshTime = refreshTime > 10 ? 10 : refreshTime;
|
||||
refreshTime = refreshTime < 10 ? 10 : refreshTime;
|
||||
|
||||
int64_t refreshTime = 10; // 10 seconds by default
|
||||
if (tscMetaCache == NULL) {
|
||||
tscMetaCache = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, NULL, "tableMeta");
|
||||
tscObjCache = taosCacheInit(TSDB_DATA_TYPE_BIGINT, refreshTime/2, false, tscFreeSqlObjInCache, "sqlObj");
|
||||
tscMetaCache = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, tscFreeTableMetaHelper, "tableMeta");
|
||||
tscObjCache = taosCacheInit(TSDB_CACHE_PTR_KEY, refreshTime / 2, false, tscFreeRegisteredSqlObj, "sqlObj");
|
||||
}
|
||||
|
||||
tscRefId = taosOpenRef(200, tscCloseTscObj);
|
||||
|
||||
tscDebug("client is initialized successfully");
|
||||
}
|
||||
|
||||
|
@ -169,6 +168,7 @@ void taos_cleanup() {
|
|||
tscQhandle = NULL;
|
||||
}
|
||||
|
||||
taosCloseRef(tscRefId);
|
||||
taosCleanupKeywordsTable();
|
||||
taosCloseLog();
|
||||
|
||||
|
|
|
@ -114,9 +114,9 @@ bool tscIsTwoStageSTableQuery(SQueryInfo* pQueryInfo, int32_t tableIndex) {
|
|||
}
|
||||
|
||||
// for select query super table, the super table vgroup list can not be null in any cases.
|
||||
if (pQueryInfo->command == TSDB_SQL_SELECT && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
assert(pTableMetaInfo->vgroupList != NULL);
|
||||
}
|
||||
// if (pQueryInfo->command == TSDB_SQL_SELECT && UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||
// assert(pTableMetaInfo->vgroupList != NULL);
|
||||
// }
|
||||
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_FREE_RESOURCE) == TSDB_QUERY_TYPE_FREE_RESOURCE) {
|
||||
return false;
|
||||
|
@ -360,26 +360,26 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
|
|||
tscFreeSqlResult(pSql);
|
||||
|
||||
taosTFree(pSql->pSubs);
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->subState.numOfSub = 0;
|
||||
pSql->self = 0;
|
||||
|
||||
tscResetSqlCmdObj(pCmd, false);
|
||||
}
|
||||
|
||||
static UNUSED_FUNC void tscFreeSubobj(SSqlObj* pSql) {
|
||||
if (pSql->numOfSubs == 0) {
|
||||
static void tscFreeSubobj(SSqlObj* pSql) {
|
||||
if (pSql->subState.numOfSub == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p start to free sub SqlObj, numOfSub:%d", pSql, pSql->numOfSubs);
|
||||
tscDebug("%p start to free sub SqlObj, numOfSub:%d", pSql, pSql->subState.numOfSub);
|
||||
|
||||
for(int32_t i = 0; i < pSql->numOfSubs; ++i) {
|
||||
for(int32_t i = 0; i < pSql->subState.numOfSub; ++i) {
|
||||
tscDebug("%p free sub SqlObj:%p, index:%d", pSql, pSql->pSubs[i], i);
|
||||
taos_free_result(pSql->pSubs[i]);
|
||||
pSql->pSubs[i] = NULL;
|
||||
}
|
||||
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->subState.numOfSub = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -389,12 +389,41 @@ static UNUSED_FUNC void tscFreeSubobj(SSqlObj* pSql) {
|
|||
*
|
||||
* @param pSql
|
||||
*/
|
||||
void tscFreeSqlObjInCache(void *pSql) {
|
||||
void tscFreeRegisteredSqlObj(void *pSql) {
|
||||
assert(pSql != NULL);
|
||||
|
||||
SSqlObj** p = (SSqlObj**)pSql;
|
||||
STscObj* pTscObj = (*p)->pTscObj;
|
||||
|
||||
assert((*p)->self != 0 && (*p)->self == (p));
|
||||
tscFreeSqlObj(*p);
|
||||
|
||||
int32_t ref = T_REF_DEC(pTscObj);
|
||||
assert(ref >= 0);
|
||||
|
||||
tscDebug("%p free sqlObj completed, tscObj:%p ref:%d", *p, pTscObj, ref);
|
||||
if (ref == 0) {
|
||||
tscDebug("%p all sqlObj freed, free tscObj:%p", *p, pTscObj);
|
||||
taosRemoveRef(tscRefId, pTscObj);
|
||||
}
|
||||
}
|
||||
|
||||
void tscFreeTableMetaHelper(void *pTableMeta) {
|
||||
STableMeta* p = (STableMeta*) pTableMeta;
|
||||
|
||||
int32_t numOfEps = p->vgroupInfo.numOfEps;
|
||||
assert(numOfEps >= 0 && numOfEps <= TSDB_MAX_REPLICA);
|
||||
|
||||
for(int32_t i = 0; i < numOfEps; ++i) {
|
||||
taosTFree(p->vgroupInfo.epAddr[i].fqdn);
|
||||
}
|
||||
|
||||
int32_t numOfEps1 = p->corVgroupInfo.numOfEps;
|
||||
assert(numOfEps1 >= 0 && numOfEps1 <= TSDB_MAX_REPLICA);
|
||||
|
||||
for(int32_t i = 0; i < numOfEps1; ++i) {
|
||||
taosTFree(p->corVgroupInfo.epAddr[i].fqdn);
|
||||
}
|
||||
}
|
||||
|
||||
void tscFreeSqlObj(SSqlObj* pSql) {
|
||||
|
@ -403,9 +432,10 @@ void tscFreeSqlObj(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
tscDebug("%p start to free sqlObj", pSql);
|
||||
STscObj* pTscObj = pSql->pTscObj;
|
||||
|
||||
pSql->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
tscFreeSubobj(pSql);
|
||||
|
||||
tscPartiallyFreeSqlObj(pSql);
|
||||
|
||||
pSql->signature = NULL;
|
||||
|
@ -421,14 +451,6 @@ void tscFreeSqlObj(SSqlObj* pSql) {
|
|||
tsem_destroy(&pSql->rspSem);
|
||||
|
||||
free(pSql);
|
||||
tscDebug("%p free sqlObj completed", pSql);
|
||||
|
||||
int32_t ref = T_REF_DEC(pTscObj);
|
||||
assert(ref >= 0);
|
||||
|
||||
if (ref == 0) {
|
||||
tscCloseTscObj(pTscObj);
|
||||
}
|
||||
}
|
||||
|
||||
void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
|
||||
|
@ -682,16 +704,14 @@ static int32_t getRowExpandSize(STableMeta* pTableMeta) {
|
|||
int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
// the maximum expanded size in byte when a row-wise data is converted to SDataRow format
|
||||
STableDataBlocks* pOneTableBlock = taosArrayGetP(pTableDataBlockList, 0);
|
||||
int32_t expandSize = getRowExpandSize(pOneTableBlock->pTableMeta);
|
||||
|
||||
void* pVnodeDataBlockHashList = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, false);
|
||||
SArray* pVnodeDataBlockList = taosArrayInit(8, POINTER_BYTES);
|
||||
|
||||
size_t total = taosArrayGetSize(pTableDataBlockList);
|
||||
for (int32_t i = 0; i < total; ++i) {
|
||||
pOneTableBlock = taosArrayGetP(pTableDataBlockList, i);
|
||||
// the maximum expanded size in byte when a row-wise data is converted to SDataRow format
|
||||
STableDataBlocks* pOneTableBlock = taosArrayGetP(pTableDataBlockList, i);
|
||||
int32_t expandSize = getRowExpandSize(pOneTableBlock->pTableMeta);
|
||||
STableDataBlocks* dataBuf = NULL;
|
||||
|
||||
int32_t ret =
|
||||
|
@ -766,8 +786,8 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) {
|
|||
}
|
||||
|
||||
// TODO: all subqueries should be freed correctly before close this connection.
|
||||
void tscCloseTscObj(STscObj* pObj) {
|
||||
assert(pObj != NULL);
|
||||
void tscCloseTscObj(void *param) {
|
||||
STscObj *pObj = param;
|
||||
|
||||
pObj->signature = NULL;
|
||||
taosTmrStopA(&(pObj->pTimer));
|
||||
|
@ -825,35 +845,30 @@ TAOS_FIELD tscCreateField(int8_t type, const char* name, int16_t bytes) {
|
|||
return f;
|
||||
}
|
||||
|
||||
SFieldSupInfo* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) {
|
||||
SInternalField* tscFieldInfoAppend(SFieldInfo* pFieldInfo, TAOS_FIELD* pField) {
|
||||
assert(pFieldInfo != NULL);
|
||||
taosArrayPush(pFieldInfo->pFields, pField);
|
||||
pFieldInfo->numOfOutput++;
|
||||
|
||||
struct SFieldSupInfo info = {
|
||||
struct SInternalField info = {
|
||||
.pSqlExpr = NULL,
|
||||
.pArithExprInfo = NULL,
|
||||
.visible = true,
|
||||
};
|
||||
|
||||
return taosArrayPush(pFieldInfo->pSupportInfo, &info);
|
||||
|
||||
info.field = *pField;
|
||||
return taosArrayPush(pFieldInfo->internalField, &info);
|
||||
}
|
||||
|
||||
SFieldSupInfo* tscFieldInfoGetSupp(SFieldInfo* pFieldInfo, int32_t index) {
|
||||
return TARRAY_GET_ELEM(pFieldInfo->pSupportInfo, index);
|
||||
}
|
||||
|
||||
SFieldSupInfo* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* field) {
|
||||
taosArrayInsert(pFieldInfo->pFields, index, field);
|
||||
SInternalField* tscFieldInfoInsert(SFieldInfo* pFieldInfo, int32_t index, TAOS_FIELD* field) {
|
||||
pFieldInfo->numOfOutput++;
|
||||
|
||||
struct SFieldSupInfo info = {
|
||||
struct SInternalField info = {
|
||||
.pSqlExpr = NULL,
|
||||
.pArithExprInfo = NULL,
|
||||
.visible = true,
|
||||
};
|
||||
|
||||
return taosArrayInsert(pFieldInfo->pSupportInfo, index, &info);
|
||||
|
||||
info.field = *field;
|
||||
return taosArrayInsert(pFieldInfo->internalField, index, &info);
|
||||
}
|
||||
|
||||
void tscFieldInfoUpdateOffset(SQueryInfo* pQueryInfo) {
|
||||
|
@ -887,29 +902,18 @@ void tscFieldInfoUpdateOffsetForInterResult(SQueryInfo* pQueryInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
void tscFieldInfoCopy(SFieldInfo* dst, const SFieldInfo* src) {
|
||||
dst->numOfOutput = src->numOfOutput;
|
||||
|
||||
if (dst->pFields == NULL) {
|
||||
dst->pFields = taosArrayClone(src->pFields);
|
||||
} else {
|
||||
taosArrayCopy(dst->pFields, src->pFields);
|
||||
}
|
||||
|
||||
if (dst->pSupportInfo == NULL) {
|
||||
dst->pSupportInfo = taosArrayClone(src->pSupportInfo);
|
||||
} else {
|
||||
taosArrayCopy(dst->pSupportInfo, src->pSupportInfo);
|
||||
}
|
||||
SInternalField* tscFieldInfoGetInternalField(SFieldInfo* pFieldInfo, int32_t index) {
|
||||
assert(index < pFieldInfo->numOfOutput);
|
||||
return TARRAY_GET_ELEM(pFieldInfo->internalField, index);
|
||||
}
|
||||
|
||||
TAOS_FIELD* tscFieldInfoGetField(SFieldInfo* pFieldInfo, int32_t index) {
|
||||
assert(index < pFieldInfo->numOfOutput);
|
||||
return TARRAY_GET_ELEM(pFieldInfo->pFields, index);
|
||||
return &((SInternalField*)TARRAY_GET_ELEM(pFieldInfo->internalField, index))->field;
|
||||
}
|
||||
|
||||
int16_t tscFieldInfoGetOffset(SQueryInfo* pQueryInfo, int32_t index) {
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, index);
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pQueryInfo->fieldsInfo, index);
|
||||
assert(pInfo != NULL && pInfo->pSqlExpr != NULL);
|
||||
|
||||
return pInfo->pSqlExpr->offset;
|
||||
|
@ -956,10 +960,8 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
|
|||
return;
|
||||
}
|
||||
|
||||
taosArrayDestroy(pFieldInfo->pFields);
|
||||
|
||||
for(int32_t i = 0; i < pFieldInfo->numOfOutput; ++i) {
|
||||
SFieldSupInfo* pInfo = taosArrayGet(pFieldInfo->pSupportInfo, i);
|
||||
SInternalField* pInfo = taosArrayGet(pFieldInfo->internalField, i);
|
||||
|
||||
if (pInfo->pArithExprInfo != NULL) {
|
||||
tExprTreeDestroy(&pInfo->pArithExprInfo->pExpr, NULL);
|
||||
|
@ -967,7 +969,9 @@ void tscFieldInfoClear(SFieldInfo* pFieldInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
taosArrayDestroy(pFieldInfo->pSupportInfo);
|
||||
taosArrayDestroy(pFieldInfo->internalField);
|
||||
taosTFree(pFieldInfo->final);
|
||||
|
||||
memset(pFieldInfo, 0, sizeof(SFieldInfo));
|
||||
}
|
||||
|
||||
|
@ -1117,6 +1121,8 @@ int32_t tscSqlExprCopy(SArray* dst, const SArray* src, uint64_t uid, bool deepco
|
|||
}
|
||||
|
||||
*p1 = *pExpr;
|
||||
memset(p1->param, 0, sizeof(tVariant) * tListLen(p1->param));
|
||||
|
||||
for (int32_t j = 0; j < pExpr->numOfParams; ++j) {
|
||||
tVariantAssign(&p1->param[j], &pExpr->param[j]);
|
||||
}
|
||||
|
@ -1265,6 +1271,51 @@ static int32_t validateQuoteToken(SStrToken* pToken) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void tscDequoteAndTrimToken(SStrToken* pToken) {
|
||||
assert(pToken->type == TK_STRING);
|
||||
|
||||
uint32_t first = 0, last = pToken->n;
|
||||
|
||||
// trim leading spaces
|
||||
while (first < last) {
|
||||
char c = pToken->z[first];
|
||||
if (c != ' ' && c != '\t') {
|
||||
break;
|
||||
}
|
||||
first++;
|
||||
}
|
||||
|
||||
// trim ending spaces
|
||||
while (first < last) {
|
||||
char c = pToken->z[last - 1];
|
||||
if (c != ' ' && c != '\t') {
|
||||
break;
|
||||
}
|
||||
last--;
|
||||
}
|
||||
|
||||
// there are still at least two characters
|
||||
if (first < last - 1) {
|
||||
char c = pToken->z[first];
|
||||
// dequote
|
||||
if ((c == '\'' || c == '"') && c == pToken->z[last - 1]) {
|
||||
first++;
|
||||
last--;
|
||||
}
|
||||
}
|
||||
|
||||
// left shift the string and pad spaces
|
||||
for (uint32_t i = 0; i + first < last; i++) {
|
||||
pToken->z[i] = pToken->z[first + i];
|
||||
}
|
||||
for (uint32_t i = last - first; i < pToken->n; i++) {
|
||||
pToken->z[i] = ' ';
|
||||
}
|
||||
|
||||
// adjust token length
|
||||
pToken->n = last - first;
|
||||
}
|
||||
|
||||
int32_t tscValidateName(SStrToken* pToken) {
|
||||
if (pToken->type != TK_STRING && pToken->type != TK_ID) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
|
@ -1469,13 +1520,6 @@ void tscSetFreeHeatBeat(STscObj* pObj) {
|
|||
pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
|
||||
}
|
||||
|
||||
bool tscShouldFreeHeartBeat(SSqlObj* pHb) {
|
||||
assert(pHb == pHb->signature);
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pHb->cmd, 0);
|
||||
return pQueryInfo->type == TSDB_QUERY_TYPE_FREE_RESOURCE;
|
||||
}
|
||||
|
||||
/*
|
||||
* the following four kinds of SqlObj should not be freed
|
||||
* 1. SqlObj for stream computing
|
||||
|
@ -1573,11 +1617,8 @@ STableMetaInfo* tscGetTableMetaInfoByUid(SQueryInfo* pQueryInfo, uint64_t uid, i
|
|||
}
|
||||
|
||||
void tscInitQueryInfo(SQueryInfo* pQueryInfo) {
|
||||
assert(pQueryInfo->fieldsInfo.pFields == NULL);
|
||||
pQueryInfo->fieldsInfo.pFields = taosArrayInit(4, sizeof(TAOS_FIELD));
|
||||
|
||||
assert(pQueryInfo->fieldsInfo.pSupportInfo == NULL);
|
||||
pQueryInfo->fieldsInfo.pSupportInfo = taosArrayInit(4, sizeof(SFieldSupInfo));
|
||||
assert(pQueryInfo->fieldsInfo.internalField == NULL);
|
||||
pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField));
|
||||
|
||||
assert(pQueryInfo->exprList == NULL);
|
||||
pQueryInfo->exprList = taosArrayInit(4, POINTER_BYTES);
|
||||
|
@ -1639,13 +1680,62 @@ void tscClearSubqueryInfo(SSqlCmd* pCmd) {
|
|||
}
|
||||
|
||||
void tscFreeVgroupTableInfo(SArray* pVgroupTables) {
|
||||
if (pVgroupTables != NULL) {
|
||||
for (size_t i = 0; i < taosArrayGetSize(pVgroupTables); i++) {
|
||||
SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
|
||||
taosArrayDestroy(pInfo->itemList);
|
||||
}
|
||||
taosArrayDestroy(pVgroupTables);
|
||||
if (pVgroupTables == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t num = taosArrayGetSize(pVgroupTables);
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
|
||||
|
||||
for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
|
||||
taosTFree(pInfo->vgInfo.epAddr[j].fqdn);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pInfo->itemList);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pVgroupTables);
|
||||
}
|
||||
|
||||
void tscRemoveVgroupTableGroup(SArray* pVgroupTable, int32_t index) {
|
||||
assert(pVgroupTable != NULL && index >= 0);
|
||||
|
||||
size_t size = taosArrayGetSize(pVgroupTable);
|
||||
assert(size > index);
|
||||
|
||||
SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTable, index);
|
||||
for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
|
||||
taosTFree(pInfo->vgInfo.epAddr[j].fqdn);
|
||||
}
|
||||
|
||||
taosArrayDestroy(pInfo->itemList);
|
||||
taosArrayRemove(pVgroupTable, index);
|
||||
}
|
||||
|
||||
SArray* tscCloneVgroupTableInfo(SArray* pVgroupTables) {
|
||||
if (pVgroupTables == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t num = taosArrayGetSize(pVgroupTables);
|
||||
SArray* pa = taosArrayInit(num, sizeof(SVgroupTableInfo));
|
||||
|
||||
SVgroupTableInfo info;
|
||||
for (size_t i = 0; i < num; i++) {
|
||||
SVgroupTableInfo* pInfo = taosArrayGet(pVgroupTables, i);
|
||||
memset(&info, 0, sizeof(SVgroupTableInfo));
|
||||
|
||||
info.vgInfo = pInfo->vgInfo;
|
||||
for(int32_t j = 0; j < pInfo->vgInfo.numOfEps; ++j) {
|
||||
info.vgInfo.epAddr[j].fqdn = strdup(pInfo->vgInfo.epAddr[j].fqdn);
|
||||
}
|
||||
|
||||
info.itemList = taosArrayClone(pInfo->itemList);
|
||||
taosArrayPush(pa, &info);
|
||||
}
|
||||
|
||||
return pa;
|
||||
}
|
||||
|
||||
void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool removeFromCache) {
|
||||
|
@ -1653,6 +1743,7 @@ void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool rem
|
|||
|
||||
for(int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, i);
|
||||
|
||||
tscFreeVgroupTableInfo(pTableMetaInfo->pVgroupTables);
|
||||
tscClearTableMetaInfo(pTableMetaInfo, removeFromCache);
|
||||
free(pTableMetaInfo);
|
||||
|
@ -1662,7 +1753,7 @@ void clearAllTableMetaInfo(SQueryInfo* pQueryInfo, const char* address, bool rem
|
|||
}
|
||||
|
||||
STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, STableMeta* pTableMeta,
|
||||
SVgroupsInfo* vgroupList, SArray* pTagCols) {
|
||||
SVgroupsInfo* vgroupList, SArray* pTagCols, SArray* pVgroupTables) {
|
||||
void* pAlloc = realloc(pQueryInfo->pTableMetaInfo, (pQueryInfo->numOfTables + 1) * POINTER_BYTES);
|
||||
if (pAlloc == NULL) {
|
||||
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
|
@ -1685,13 +1776,7 @@ STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, ST
|
|||
pTableMetaInfo->pTableMeta = pTableMeta;
|
||||
|
||||
if (vgroupList != NULL) {
|
||||
size_t size = sizeof(SVgroupsInfo) + sizeof(SCMVgroupInfo) * vgroupList->numOfVgroups;
|
||||
pTableMetaInfo->vgroupList = malloc(size);
|
||||
if (pTableMetaInfo->vgroupList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy(pTableMetaInfo->vgroupList, vgroupList, size);
|
||||
pTableMetaInfo->vgroupList = tscVgroupInfoClone(vgroupList);
|
||||
}
|
||||
|
||||
pTableMetaInfo->tagColList = taosArrayInit(4, POINTER_BYTES);
|
||||
|
@ -1702,13 +1787,15 @@ STableMetaInfo* tscAddTableMetaInfo(SQueryInfo* pQueryInfo, const char* name, ST
|
|||
if (pTagCols != NULL) {
|
||||
tscColumnListCopy(pTableMetaInfo->tagColList, pTagCols, -1);
|
||||
}
|
||||
|
||||
pTableMetaInfo->pVgroupTables = tscCloneVgroupTableInfo(pVgroupTables);
|
||||
|
||||
pQueryInfo->numOfTables += 1;
|
||||
return pTableMetaInfo;
|
||||
}
|
||||
|
||||
STableMetaInfo* tscAddEmptyMetaInfo(SQueryInfo* pQueryInfo) {
|
||||
return tscAddTableMetaInfo(pQueryInfo, NULL, NULL, NULL, NULL);
|
||||
return tscAddTableMetaInfo(pQueryInfo, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache) {
|
||||
|
@ -1720,8 +1807,7 @@ void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache)
|
|||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), removeFromCache);
|
||||
}
|
||||
|
||||
taosTFree(pTableMetaInfo->vgroupList);
|
||||
|
||||
pTableMetaInfo->vgroupList = tscVgroupInfoClear(pTableMetaInfo->vgroupList);
|
||||
tscColumnListDestroy(pTableMetaInfo->tagColList);
|
||||
pTableMetaInfo->tagColList = NULL;
|
||||
}
|
||||
|
@ -1735,6 +1821,16 @@ void tscResetForNextRetrieve(SSqlRes* pRes) {
|
|||
pRes->numOfRows = 0;
|
||||
}
|
||||
|
||||
void registerSqlObj(SSqlObj* pSql) {
|
||||
int32_t DEFAULT_LIFE_TIME = 2 * 600 * 1000; // 1200 sec
|
||||
|
||||
int32_t ref = T_REF_INC(pSql->pTscObj);
|
||||
tscDebug("%p add to tscObj:%p, ref:%d", pSql, pSql->pTscObj, ref);
|
||||
|
||||
TSDB_CACHE_PTR_TYPE p = (TSDB_CACHE_PTR_TYPE) pSql;
|
||||
pSql->self = taosCachePut(tscObjCache, &p, sizeof(TSDB_CACHE_PTR_TYPE), &p, sizeof(TSDB_CACHE_PTR_TYPE), DEFAULT_LIFE_TIME);
|
||||
}
|
||||
|
||||
SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cmd) {
|
||||
SSqlObj* pNew = (SSqlObj*)calloc(1, sizeof(SSqlObj));
|
||||
if (pNew == NULL) {
|
||||
|
@ -1748,6 +1844,8 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cm
|
|||
SSqlCmd* pCmd = &pNew->cmd;
|
||||
pCmd->command = cmd;
|
||||
pCmd->parseFinished = 1;
|
||||
pCmd->autoCreated = pSql->cmd.autoCreated;
|
||||
memcpy(&pCmd->tagData, &pSql->cmd.tagData, sizeof(pCmd->tagData));
|
||||
|
||||
if (tscAddSubqueryInfo(pCmd) != TSDB_CODE_SUCCESS) {
|
||||
tscFreeSqlObj(pNew);
|
||||
|
@ -1762,8 +1860,7 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cm
|
|||
pNew->sqlstr = strdup(pSql->sqlstr);
|
||||
if (pNew->sqlstr == NULL) {
|
||||
tscError("%p new subquery failed", pSql);
|
||||
|
||||
free(pNew);
|
||||
tscFreeSqlObj(pNew);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1772,62 +1869,29 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cm
|
|||
assert(pSql->cmd.clauseIndex == 0);
|
||||
STableMetaInfo* pMasterTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
|
||||
|
||||
tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL);
|
||||
tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL, NULL);
|
||||
|
||||
T_REF_INC(pNew->pTscObj);
|
||||
uint64_t p = (uint64_t) pNew;
|
||||
pNew->self = taosCachePut(tscObjCache, &p, sizeof(uint64_t), &pNew, sizeof(uint64_t), 2 * 600 * 1000);
|
||||
registerSqlObj(pNew);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
// current sql function is not direct output result, so create a dummy output field
|
||||
static void doSetNewFieldInfo(SQueryInfo* pNewQueryInfo, SSqlExpr* pExpr) {
|
||||
TAOS_FIELD f = {.type = (uint8_t)pExpr->resType, .bytes = pExpr->resBytes};
|
||||
tstrncpy(f.name, pExpr->aliasName, sizeof(f.name));
|
||||
|
||||
SFieldSupInfo* pInfo1 = tscFieldInfoAppend(&pNewQueryInfo->fieldsInfo, &f);
|
||||
|
||||
pInfo1->pSqlExpr = pExpr;
|
||||
pInfo1->visible = false;
|
||||
}
|
||||
|
||||
static void doSetSqlExprAndResultFieldInfo(SQueryInfo* pQueryInfo, SQueryInfo* pNewQueryInfo, int64_t uid) {
|
||||
int32_t numOfOutput = (int32_t)tscSqlExprNumOfExprs(pNewQueryInfo);
|
||||
if (numOfOutput == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo);
|
||||
SFieldInfo* pFieldInfo = &pQueryInfo->fieldsInfo;
|
||||
|
||||
// set the field info in pNewQueryInfo object
|
||||
// set the field info in pNewQueryInfo object according to sqlExpr information
|
||||
size_t numOfExprs = tscSqlExprNumOfExprs(pNewQueryInfo);
|
||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pNewQueryInfo, i);
|
||||
|
||||
if (pExpr->uid == uid) {
|
||||
if (i < pFieldInfo->numOfOutput) {
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(pFieldInfo, i);
|
||||
|
||||
if (pInfo->pSqlExpr != NULL) {
|
||||
TAOS_FIELD* p = tscFieldInfoGetField(pFieldInfo, i);
|
||||
assert(strcmp(p->name, pExpr->aliasName) == 0);
|
||||
|
||||
SFieldSupInfo* pInfo1 = tscFieldInfoAppend(&pNewQueryInfo->fieldsInfo, p);
|
||||
*pInfo1 = *pInfo;
|
||||
} else {
|
||||
assert(pInfo->pArithExprInfo != NULL);
|
||||
doSetNewFieldInfo(pNewQueryInfo, pExpr);
|
||||
}
|
||||
} else { // it is a arithmetic column, does not have actual field for sqlExpr, so build it
|
||||
doSetNewFieldInfo(pNewQueryInfo, pExpr);
|
||||
}
|
||||
}
|
||||
TAOS_FIELD f = tscCreateField((int8_t) pExpr->resType, pExpr->aliasName, pExpr->resBytes);
|
||||
SInternalField* pInfo1 = tscFieldInfoAppend(&pNewQueryInfo->fieldsInfo, &f);
|
||||
pInfo1->pSqlExpr = pExpr;
|
||||
}
|
||||
|
||||
// make sure the the sqlExpr for each fields is correct
|
||||
numOfExprs = tscSqlExprNumOfExprs(pNewQueryInfo);
|
||||
|
||||
// update the pSqlExpr pointer in SFieldSupInfo according the field name
|
||||
// update the pSqlExpr pointer in SInternalField according the field name
|
||||
// make sure the pSqlExpr point to the correct SqlExpr in pNewQueryInfo, not SqlExpr in pQueryInfo
|
||||
for (int32_t f = 0; f < pNewQueryInfo->fieldsInfo.numOfOutput; ++f) {
|
||||
TAOS_FIELD* field = tscFieldInfoGetField(&pNewQueryInfo->fieldsInfo, f);
|
||||
|
@ -1837,7 +1901,7 @@ static void doSetSqlExprAndResultFieldInfo(SQueryInfo* pQueryInfo, SQueryInfo* p
|
|||
SSqlExpr* pExpr1 = tscSqlExprGet(pNewQueryInfo, k1);
|
||||
|
||||
if (strcmp(field->name, pExpr1->aliasName) == 0) { // establish link according to the result field name
|
||||
SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pNewQueryInfo->fieldsInfo, f);
|
||||
SInternalField* pInfo = tscFieldInfoGetInternalField(&pNewQueryInfo->fieldsInfo, f);
|
||||
pInfo->pSqlExpr = pExpr1;
|
||||
|
||||
matched = true;
|
||||
|
@ -1866,7 +1930,6 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
|
||||
pNew->pTscObj = pSql->pTscObj;
|
||||
pNew->signature = pNew;
|
||||
T_REF_INC(pNew->pTscObj);
|
||||
|
||||
pNew->sqlstr = strdup(pSql->sqlstr);
|
||||
if (pNew->sqlstr == NULL) {
|
||||
|
@ -1971,14 +2034,16 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
STableMeta* pTableMeta = taosCacheAcquireByData(tscMetaCache, pTableMetaInfo->pTableMeta); // get by name may failed due to the cache cleanup
|
||||
assert(pTableMeta != NULL);
|
||||
|
||||
pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pTableMeta, pTableMetaInfo->vgroupList, pTableMetaInfo->tagColList);
|
||||
pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pTableMeta, pTableMetaInfo->vgroupList,
|
||||
pTableMetaInfo->tagColList, pTableMetaInfo->pVgroupTables);
|
||||
} else { // transfer the ownership of pTableMeta to the newly create sql object.
|
||||
STableMetaInfo* pPrevInfo = tscGetTableMetaInfoFromCmd(&pPrevSql->cmd, pPrevSql->cmd.clauseIndex, 0);
|
||||
|
||||
STableMeta* pPrevTableMeta = taosCacheTransfer(tscMetaCache, (void**)&pPrevInfo->pTableMeta);
|
||||
|
||||
SVgroupsInfo* pVgroupsInfo = pPrevInfo->vgroupList;
|
||||
pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pPrevTableMeta, pVgroupsInfo, pTableMetaInfo->tagColList);
|
||||
pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pPrevTableMeta, pVgroupsInfo, pTableMetaInfo->tagColList,
|
||||
pTableMetaInfo->pVgroupTables);
|
||||
}
|
||||
|
||||
if (pFinalInfo->pTableMeta == NULL) {
|
||||
|
@ -2015,10 +2080,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
tscDebug("%p new sub insertion: %p, vnodeIdx:%d", pSql, pNew, pTableMetaInfo->vgroupIndex);
|
||||
}
|
||||
|
||||
T_REF_INC(pNew->pTscObj);
|
||||
|
||||
uint64_t p = (uint64_t) pNew;
|
||||
pNew->self = taosCachePut(tscObjCache, &p, sizeof(uint64_t), &pNew, sizeof(uint64_t), 2 * 600 * 10);
|
||||
registerSqlObj(pNew);
|
||||
return pNew;
|
||||
|
||||
_error:
|
||||
|
@ -2239,7 +2301,7 @@ void tscTryQueryNextVnode(SSqlObj* pSql, __async_cb_func_t fp) {
|
|||
*
|
||||
* For super table join with projection query, if anyone of the subquery is exhausted, the query completed.
|
||||
*/
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->subState.numOfSub = 0;
|
||||
pCmd->command = TSDB_SQL_SELECT;
|
||||
|
||||
tscResetForNextRetrieve(pRes);
|
||||
|
@ -2271,7 +2333,7 @@ void tscTryQueryNextClause(SSqlObj* pSql, __async_cb_func_t fp) {
|
|||
pRes->numOfTotal = num;
|
||||
|
||||
taosTFree(pSql->pSubs);
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->subState.numOfSub = 0;
|
||||
pSql->fp = fp;
|
||||
|
||||
tscDebug("%p try data in the next subclause:%d, total subclause:%d", pSql, pCmd->clauseIndex, pCmd->numOfClause);
|
||||
|
@ -2356,3 +2418,58 @@ void tscClearSqlOwner(SSqlObj* pSql) {
|
|||
assert(taosCheckPthreadValid(pSql->owner));
|
||||
atomic_store_64(&pSql->owner, 0);
|
||||
}
|
||||
|
||||
SVgroupsInfo* tscVgroupInfoClone(SVgroupsInfo *vgroupList) {
|
||||
if (vgroupList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t size = sizeof(SVgroupsInfo) + sizeof(SCMVgroupInfo) * vgroupList->numOfVgroups;
|
||||
SVgroupsInfo* pNew = calloc(1, size);
|
||||
if (pNew == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pNew->numOfVgroups = vgroupList->numOfVgroups;
|
||||
|
||||
for(int32_t i = 0; i < vgroupList->numOfVgroups; ++i) {
|
||||
SCMVgroupInfo* pNewVInfo = &pNew->vgroups[i];
|
||||
|
||||
SCMVgroupInfo* pvInfo = &vgroupList->vgroups[i];
|
||||
pNewVInfo->vgId = pvInfo->vgId;
|
||||
pNewVInfo->numOfEps = pvInfo->numOfEps;
|
||||
|
||||
for(int32_t j = 0; j < pvInfo->numOfEps; ++j) {
|
||||
pNewVInfo->epAddr[j].fqdn = strdup(pvInfo->epAddr[j].fqdn);
|
||||
pNewVInfo->epAddr[j].port = pvInfo->epAddr[j].port;
|
||||
}
|
||||
}
|
||||
|
||||
return pNew;
|
||||
}
|
||||
|
||||
void* tscVgroupInfoClear(SVgroupsInfo *vgroupList) {
|
||||
if (vgroupList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for(int32_t i = 0; i < vgroupList->numOfVgroups; ++i) {
|
||||
SCMVgroupInfo* pVgroupInfo = &vgroupList->vgroups[i];
|
||||
|
||||
for(int32_t j = 0; j < pVgroupInfo->numOfEps; ++j) {
|
||||
taosTFree(pVgroupInfo->epAddr[j].fqdn);
|
||||
}
|
||||
}
|
||||
|
||||
taosTFree(vgroupList);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tscSCMVgroupInfoCopy(SCMVgroupInfo* dst, const SCMVgroupInfo* src) {
|
||||
dst->vgId = src->vgId;
|
||||
dst->numOfEps = src->numOfEps;
|
||||
for(int32_t i = 0; i < dst->numOfEps; ++i) {
|
||||
dst->epAddr[i].port = src->epAddr[i].port;
|
||||
dst->epAddr[i].fqdn = strdup(src->epAddr[i].fqdn);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,9 @@ enum {
|
|||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_RETRIEVE_LOCALMERGE, "retrieve-localmerge" )
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_TABLE_JOIN_RETRIEVE, "join-retrieve" )
|
||||
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SHOW_CREATE_TABLE, "show-create-table")
|
||||
TSDB_DEFINE_SQL_TYPE( TSDB_SQL_SHOW_CREATE_DATABASE, "show-create-database")
|
||||
|
||||
/*
|
||||
* build empty result instead of accessing dnode to fetch result
|
||||
* reset the client cache
|
||||
|
|
|
@ -34,6 +34,7 @@ extern int32_t tsStatusInterval;
|
|||
extern int32_t tsNumOfMnodes;
|
||||
extern int32_t tsEnableVnodeBak;
|
||||
extern int32_t tsEnableTelemetryReporting;
|
||||
extern char tsEmail[];
|
||||
|
||||
// common
|
||||
extern int tsRpcTimer;
|
||||
|
@ -43,14 +44,17 @@ extern int32_t tsMaxShellConns;
|
|||
extern int32_t tsShellActivityTimer;
|
||||
extern uint32_t tsMaxTmrCtrl;
|
||||
extern float tsNumOfThreadsPerCore;
|
||||
extern float tsRatioOfQueryThreads;
|
||||
extern float tsRatioOfQueryThreads; // todo remove it
|
||||
extern int8_t tsDaylight;
|
||||
extern char tsTimezone[];
|
||||
extern char tsLocale[];
|
||||
extern char tsCharset[]; // default encode string
|
||||
extern char tsCharset[]; // default encode string
|
||||
extern int32_t tsEnableCoreFile;
|
||||
extern int32_t tsCompressMsgSize;
|
||||
|
||||
//query buffer management
|
||||
extern int32_t tsQueryBufferSize; // maximum allowed usage buffer for each data node during query processing
|
||||
|
||||
// client
|
||||
extern int32_t tsTableMetaKeepTimer;
|
||||
extern int32_t tsMaxSQLStringLen;
|
||||
|
|
|
@ -316,13 +316,13 @@ void dataColSetOffset(SDataCol *pCol, int nEle) {
|
|||
SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) {
|
||||
SDataCols *pCols = (SDataCols *)calloc(1, sizeof(SDataCols));
|
||||
if (pCols == NULL) {
|
||||
uDebug("malloc failure, size:%"PRId64" failed, reason:%s", sizeof(SDataCols), strerror(errno));
|
||||
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pCols->cols = (SDataCol *)calloc(maxCols, sizeof(SDataCol));
|
||||
if (pCols->cols == NULL) {
|
||||
uDebug("malloc failure, size:%"PRId64" failed, reason:%s", sizeof(SDataCol) * maxCols, strerror(errno));
|
||||
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCol) * maxCols, strerror(errno));
|
||||
tdFreeDataCols(pCols);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -334,7 +334,7 @@ SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) {
|
|||
|
||||
pCols->buf = malloc(pCols->bufSize);
|
||||
if (pCols->buf == NULL) {
|
||||
uDebug("malloc failure, size:%"PRId64" failed, reason:%s", sizeof(SDataCol) * maxCols, strerror(errno));
|
||||
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCol) * maxCols, strerror(errno));
|
||||
tdFreeDataCols(pCols);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -588,7 +588,7 @@ int tdSetKVRowDataOfCol(SKVRow *orow, int16_t colId, int8_t type, void *value) {
|
|||
SKVRow nrow = NULL;
|
||||
void * ptr = taosbsearch(&colId, kvRowColIdx(row), kvRowNCols(row), sizeof(SColIdx), comparTagId, TD_GE);
|
||||
|
||||
if (ptr == NULL || ((SColIdx *)ptr)->colId < colId) { // need to add a column value to the row
|
||||
if (ptr == NULL || ((SColIdx *)ptr)->colId > colId) { // need to add a column value to the row
|
||||
int diff = IS_VAR_DATA_TYPE(type) ? varDataTLen(value) : TYPE_BYTES[type];
|
||||
nrow = malloc(kvRowLen(row) + sizeof(SColIdx) + diff);
|
||||
if (nrow == NULL) return -1;
|
||||
|
@ -738,4 +738,4 @@ SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder) {
|
|||
memcpy(kvRowValues(row), pBuilder->buf, pBuilder->size);
|
||||
|
||||
return row;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,16 +42,17 @@ int32_t tsStatusInterval = 1; // second
|
|||
int32_t tsNumOfMnodes = 3;
|
||||
int32_t tsEnableVnodeBak = 1;
|
||||
int32_t tsEnableTelemetryReporting = 1;
|
||||
char tsEmail[TSDB_FQDN_LEN] = {0};
|
||||
|
||||
// common
|
||||
int32_t tsRpcTimer = 1000;
|
||||
int32_t tsRpcMaxTime = 600; // seconds;
|
||||
int32_t tsMaxShellConns = 5000;
|
||||
int32_t tsRpcTimer = 1000;
|
||||
int32_t tsRpcMaxTime = 600; // seconds;
|
||||
int32_t tsMaxShellConns = 5000;
|
||||
int32_t tsMaxConnections = 5000;
|
||||
int32_t tsShellActivityTimer = 3; // second
|
||||
float tsNumOfThreadsPerCore = 1.0;
|
||||
float tsRatioOfQueryThreads = 0.5;
|
||||
int8_t tsDaylight = 0;
|
||||
int32_t tsShellActivityTimer = 3; // second
|
||||
float tsNumOfThreadsPerCore = 1.0f;
|
||||
float tsRatioOfQueryThreads = 0.5f;
|
||||
int8_t tsDaylight = 0;
|
||||
char tsTimezone[TSDB_TIMEZONE_LEN] = {0};
|
||||
char tsLocale[TSDB_LOCALE_LEN] = {0};
|
||||
char tsCharset[TSDB_LOCALE_LEN] = {0}; // default encode string
|
||||
|
@ -98,6 +99,12 @@ float tsStreamComputDelayRatio = 0.1f;
|
|||
int32_t tsProjectExecInterval = 10000; // every 10sec, the projection will be executed once
|
||||
int64_t tsMaxRetentWindow = 24 * 3600L; // maximum time window tolerance
|
||||
|
||||
// the maximum allowed query buffer size during query processing for each data node.
|
||||
// -1 no limit (default)
|
||||
// 0 no query allowed, queries are disabled
|
||||
// positive value (in MB)
|
||||
int32_t tsQueryBufferSize = -1;
|
||||
|
||||
// db parameters
|
||||
int32_t tsCacheBlockSize = TSDB_DEFAULT_CACHE_BLOCK_SIZE;
|
||||
int32_t tsBlocksPerVnode = TSDB_DEFAULT_TOTAL_BLOCKS;
|
||||
|
@ -132,7 +139,7 @@ uint16_t tsHttpPort = 6041; // only tcp, range tcp[6041]
|
|||
int32_t tsHttpCacheSessions = 1000;
|
||||
int32_t tsHttpSessionExpire = 36000;
|
||||
int32_t tsHttpMaxThreads = 2;
|
||||
int32_t tsHttpEnableCompress = 0;
|
||||
int32_t tsHttpEnableCompress = 1;
|
||||
int32_t tsHttpEnableRecordSql = 0;
|
||||
int32_t tsTelegrafUseFieldNum = 0;
|
||||
|
||||
|
@ -308,6 +315,8 @@ bool taosCfgDynamicOptions(char *msg) {
|
|||
|
||||
static void doInitGlobalConfig(void) {
|
||||
osInit();
|
||||
srand(taosSafeRand());
|
||||
|
||||
SGlobalCfg cfg = {0};
|
||||
|
||||
// ip address
|
||||
|
@ -674,7 +683,7 @@ static void doInitGlobalConfig(void) {
|
|||
cfg.minValue = TSDB_MIN_CACHE_BLOCK_SIZE;
|
||||
cfg.maxValue = TSDB_MAX_CACHE_BLOCK_SIZE;
|
||||
cfg.ptrLength = 0;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_Mb;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_MB;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
cfg.option = "blocks";
|
||||
|
@ -847,6 +856,16 @@ static void doInitGlobalConfig(void) {
|
|||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
cfg.option = "queryBufferSize";
|
||||
cfg.ptr = &tsQueryBufferSize;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW;
|
||||
cfg.minValue = -1;
|
||||
cfg.maxValue = 500000000000.0f;
|
||||
cfg.ptrLength = 0;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_BYTE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
// locale & charset
|
||||
cfg.option = "timezone";
|
||||
cfg.ptr = tsTimezone;
|
||||
|
@ -1025,7 +1044,7 @@ static void doInitGlobalConfig(void) {
|
|||
cfg.ptr = &tsLogKeepDays;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_LOG | TSDB_CFG_CTYPE_B_CLIENT;
|
||||
cfg.minValue = 0;
|
||||
cfg.minValue = -365000;
|
||||
cfg.maxValue = 365000;
|
||||
cfg.ptrLength = 0;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
|
|
|
@ -219,7 +219,7 @@ static void getStatics_f(const TSKEY *primaryKey, const void *pData, int32_t num
|
|||
}
|
||||
|
||||
float fv = 0;
|
||||
fv = GET_FLOAT_VAL(&(data[i]));
|
||||
fv = GET_FLOAT_VAL((const char*)&(data[i]));
|
||||
dsum += fv;
|
||||
if (fmin > fv) {
|
||||
fmin = fv;
|
||||
|
@ -233,17 +233,12 @@ static void getStatics_f(const TSKEY *primaryKey, const void *pData, int32_t num
|
|||
}
|
||||
|
||||
double csum = 0;
|
||||
csum = GET_DOUBLE_VAL(sum);
|
||||
csum = GET_DOUBLE_VAL((const char *)sum);
|
||||
csum += dsum;
|
||||
#ifdef _TD_ARM_32_
|
||||
SET_DOUBLE_VAL_ALIGN(sum, &csum);
|
||||
SET_DOUBLE_VAL_ALIGN(max, &fmax);
|
||||
SET_DOUBLE_VAL_ALIGN(min, &fmin);
|
||||
#else
|
||||
*(double*)sum = csum;
|
||||
*(double*)max = fmax;
|
||||
*(double*)min = fmin;
|
||||
#endif
|
||||
|
||||
SET_DOUBLE_VAL(sum, csum);
|
||||
SET_DOUBLE_VAL(max, fmax);
|
||||
SET_DOUBLE_VAL(min, fmin);
|
||||
}
|
||||
|
||||
static void getStatics_d(const TSKEY *primaryKey, const void *pData, int32_t numOfRow, int64_t *min, int64_t *max,
|
||||
|
@ -264,7 +259,7 @@ static void getStatics_d(const TSKEY *primaryKey, const void *pData, int32_t num
|
|||
}
|
||||
|
||||
double dv = 0;
|
||||
dv = GET_DOUBLE_VAL(&(data[i]));
|
||||
dv = GET_DOUBLE_VAL((const char*)&(data[i]));
|
||||
dsum += dv;
|
||||
if (dmin > dv) {
|
||||
dmin = dv;
|
||||
|
@ -278,19 +273,12 @@ static void getStatics_d(const TSKEY *primaryKey, const void *pData, int32_t num
|
|||
}
|
||||
|
||||
double csum = 0;
|
||||
csum = GET_DOUBLE_VAL(sum);
|
||||
csum = GET_DOUBLE_VAL((const char *)sum);
|
||||
csum += dsum;
|
||||
|
||||
|
||||
#ifdef _TD_ARM_32_
|
||||
SET_DOUBLE_VAL_ALIGN(sum, &csum);
|
||||
SET_DOUBLE_VAL_ALIGN(max, &dmax);
|
||||
SET_DOUBLE_VAL_ALIGN(min, &dmin);
|
||||
#else
|
||||
*(double*) sum = csum;
|
||||
*(double*) max = dmax;
|
||||
*(double*) min = dmin;
|
||||
#endif
|
||||
SET_DOUBLE_PTR(sum, &csum);
|
||||
SET_DOUBLE_PTR(max, &dmax);
|
||||
SET_DOUBLE_PTR(min, &dmin);
|
||||
}
|
||||
|
||||
static void getStatics_bin(const TSKEY *primaryKey, const void *pData, int32_t numOfRow, int64_t *min, int64_t *max,
|
||||
|
@ -493,46 +481,29 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) {
|
|||
*((int32_t *)val) = GET_INT32_VAL(src);
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_FLOAT: {
|
||||
#ifdef _TD_ARM_32_
|
||||
float fv = GET_FLOAT_VAL(src);
|
||||
SET_FLOAT_VAL_ALIGN(val, &fv);
|
||||
#else
|
||||
*((float *)val) = GET_FLOAT_VAL(src);
|
||||
#endif
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
SET_FLOAT_VAL(val, GET_FLOAT_VAL(src));
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
#ifdef _TD_ARM_32_
|
||||
double dv = GET_DOUBLE_VAL(src);
|
||||
SET_DOUBLE_VAL_ALIGN(val, &dv);
|
||||
#else
|
||||
*((double *)val) = GET_DOUBLE_VAL(src);
|
||||
#endif
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
SET_DOUBLE_VAL(val, GET_DOUBLE_VAL(src));
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||
case TSDB_DATA_TYPE_BIGINT: {
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
*((int64_t *)val) = GET_INT64_VAL(src);
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_SMALLINT: {
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
*((int16_t *)val) = GET_INT16_VAL(src);
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
case TSDB_DATA_TYPE_TINYINT: {
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
*((int8_t *)val) = GET_INT8_VAL(src);
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_BINARY: {
|
||||
case TSDB_DATA_TYPE_BINARY:
|
||||
varDataCopy(val, src);
|
||||
break;
|
||||
};
|
||||
case TSDB_DATA_TYPE_NCHAR: {
|
||||
case TSDB_DATA_TYPE_NCHAR:
|
||||
varDataCopy(val, src);
|
||||
break;
|
||||
};
|
||||
default: {
|
||||
memcpy(val, src, len);
|
||||
break;
|
||||
|
@ -579,4 +550,4 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -144,21 +144,24 @@ void tVariantDestroy(tVariant *pVar) {
|
|||
void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
|
||||
if (pSrc == NULL || pDst == NULL) return;
|
||||
|
||||
*pDst = *pSrc;
|
||||
|
||||
pDst->nType = pSrc->nType;
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_BINARY || pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
int32_t len = pSrc->nLen + 1;
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_NCHAR) {
|
||||
len = len * TSDB_NCHAR_SIZE;
|
||||
}
|
||||
|
||||
pDst->pz = calloc(1, len);
|
||||
memcpy(pDst->pz, pSrc->pz, len);
|
||||
int32_t len = pSrc->nLen + TSDB_NCHAR_SIZE;
|
||||
char* p = realloc(pDst->pz, len);
|
||||
assert(p);
|
||||
|
||||
memset(p, 0, len);
|
||||
pDst->pz = p;
|
||||
|
||||
memcpy(pDst->pz, pSrc->pz, pSrc->nLen);
|
||||
pDst->nLen = pSrc->nLen;
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// this is only for string array
|
||||
if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) {
|
||||
if (pSrc->nType >= TSDB_DATA_TYPE_BOOL && pSrc->nType <= TSDB_DATA_TYPE_DOUBLE) {
|
||||
pDst->i64Key = pSrc->i64Key;
|
||||
} else if (pSrc->nType == TSDB_DATA_TYPE_ARRAY) { // this is only for string array
|
||||
size_t num = taosArrayGetSize(pSrc->arr);
|
||||
pDst->arr = taosArrayInit(num, sizeof(char*));
|
||||
for(size_t i = 0; i < num; i++) {
|
||||
|
@ -166,8 +169,6 @@ void tVariantAssign(tVariant *pDst, const tVariant *pSrc) {
|
|||
char* n = strdup(p);
|
||||
taosArrayPush(pDst->arr, &n);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
pDst->nLen = tDataTypeDesc[pDst->nType].nSize;
|
||||
|
@ -709,46 +710,21 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _TD_ARM_32_
|
||||
//memcpy(&payload, &value, sizeof(float));
|
||||
float fv = (float)value;
|
||||
SET_FLOAT_VAL_ALIGN(payload, &fv);
|
||||
#else
|
||||
*((float *)payload) = (float)value;
|
||||
#endif
|
||||
SET_FLOAT_VAL(payload, value);
|
||||
}
|
||||
} else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
#ifdef _TD_ARM_32_
|
||||
//memcpy(&payload, &pVariant->i64Key, sizeof(float));
|
||||
float fv = (float)pVariant->i64Key;
|
||||
SET_FLOAT_VAL_ALIGN(payload, &fv);
|
||||
#else
|
||||
*((float *)payload) = (float)pVariant->i64Key;
|
||||
#endif
|
||||
SET_FLOAT_VAL(payload, pVariant->i64Key);
|
||||
} else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
|
||||
#ifdef _TD_ARM_32_
|
||||
//memcpy(&payload, &pVariant->dKey, sizeof(float));
|
||||
float fv = (float)pVariant->dKey;
|
||||
SET_FLOAT_VAL_ALIGN(payload, &fv);
|
||||
#else
|
||||
*((float *)payload) = (float)pVariant->dKey;
|
||||
#endif
|
||||
SET_FLOAT_VAL(payload, pVariant->dKey);
|
||||
} else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
|
||||
*((int32_t *)payload) = TSDB_DATA_FLOAT_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _TD_ARM_32_
|
||||
float fv = GET_FLOAT_VAL(payload);
|
||||
if (isinf(fv) || isnan(fv) || fv > FLT_MAX || fv < -FLT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (isinf(*((float *)payload)) || isnan(*((float *)payload)) || *((float *)payload) > FLT_MAX ||
|
||||
*((float *)payload) < -FLT_MAX) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case TSDB_DATA_TYPE_DOUBLE: {
|
||||
|
@ -765,42 +741,21 @@ int32_t tVariantDump(tVariant *pVariant, char *payload, int16_t type, bool inclu
|
|||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _TD_ARM_32_
|
||||
SET_DOUBLE_VAL_ALIGN(payload, &value);
|
||||
#else
|
||||
*((double *)payload) = value;
|
||||
#endif
|
||||
SET_DOUBLE_VAL(payload, value);
|
||||
}
|
||||
} else if (pVariant->nType >= TSDB_DATA_TYPE_BOOL && pVariant->nType <= TSDB_DATA_TYPE_BIGINT) {
|
||||
#ifdef _TD_ARM_32_
|
||||
double dv = (double)(pVariant->i64Key);
|
||||
SET_DOUBLE_VAL_ALIGN(payload, &dv);
|
||||
#else
|
||||
*((double *)payload) = (double)pVariant->i64Key;
|
||||
#endif
|
||||
SET_DOUBLE_VAL(payload, pVariant->i64Key);
|
||||
} else if (pVariant->nType == TSDB_DATA_TYPE_DOUBLE || pVariant->nType == TSDB_DATA_TYPE_FLOAT) {
|
||||
#ifdef _TD_ARM_32_
|
||||
double dv = (double)(pVariant->dKey);
|
||||
SET_DOUBLE_VAL_ALIGN(payload, &dv);
|
||||
#else
|
||||
*((double *)payload) = pVariant->dKey;
|
||||
#endif
|
||||
SET_DOUBLE_VAL(payload, pVariant->dKey);
|
||||
} else if (pVariant->nType == TSDB_DATA_TYPE_NULL) {
|
||||
*((int64_t *)payload) = TSDB_DATA_DOUBLE_NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef _TD_ARM_32_
|
||||
double dv = GET_DOUBLE_VAL(payload);
|
||||
if (isinf(dv) || isnan(dv) || dv > DBL_MAX || dv < -DBL_MAX) {
|
||||
return -1;
|
||||
}
|
||||
#else
|
||||
if (isinf(*((double *)payload)) || isnan(*((double *)payload)) || *((double *)payload) > DBL_MAX ||
|
||||
*((double *)payload) < -DBL_MAX) {
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 06ec30a0f1762e8169bf6b9045c82bcaa52bcdf0
|
||||
Subproject commit 8c58c512b6acda8bcdfa48fdc7140227b5221766
|
|
@ -0,0 +1 @@
|
|||
Subproject commit b62a26ecc164a310104df57691691b237e091c89
|
|
@ -8,7 +8,7 @@ IF (TD_MVN_INSTALLED)
|
|||
ADD_CUSTOM_COMMAND(OUTPUT ${JDBC_CMD_NAME}
|
||||
POST_BUILD
|
||||
COMMAND mvn -Dmaven.test.skip=true install -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.0-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_CURRENT_SOURCE_DIR}/target/taos-jdbcdriver-2.0.8-dist.jar ${LIBRARY_OUTPUT_PATH}
|
||||
COMMAND mvn -Dmaven.test.skip=true clean -f ${CMAKE_CURRENT_SOURCE_DIR}/pom.xml
|
||||
COMMENT "build jdbc driver")
|
||||
ADD_CUSTOM_TARGET(${JDBC_TARGET_NAME} ALL WORKING_DIRECTORY ${EXECUTABLE_OUTPUT_PATH} DEPENDS ${JDBC_CMD_NAME})
|
||||
|
|
|
@ -5,10 +5,9 @@
|
|||
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
<version>2.0.6</version>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
<description>TDengine JDBC Driver</description>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.taosdata.jdbc</groupId>
|
||||
<artifactId>taos-jdbcdriver</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<version>2.0.8</version>
|
||||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
@ -55,6 +55,7 @@
|
|||
<version>4.13</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
|
|
|
@ -67,14 +67,23 @@ public class DatabaseMetaDataResultSet implements ResultSet {
|
|||
|
||||
@Override
|
||||
public boolean next() throws SQLException {
|
||||
// boolean ret = false;
|
||||
// if (rowDataList.size() > 0) {
|
||||
// ret = rowDataList.iterator().hasNext();
|
||||
// if (ret) {
|
||||
// rowCursor = rowDataList.iterator().next();
|
||||
// cursorRowNumber++;
|
||||
// }
|
||||
// }
|
||||
// return ret;
|
||||
|
||||
/**** add by zyyang 2020-09-29 ****************/
|
||||
boolean ret = false;
|
||||
if (rowDataList.size() > 0) {
|
||||
ret = rowDataList.iterator().hasNext();
|
||||
if (ret) {
|
||||
rowCursor = rowDataList.iterator().next();
|
||||
cursorRowNumber++;
|
||||
}
|
||||
if (!rowDataList.isEmpty() && cursorRowNumber < rowDataList.size()) {
|
||||
rowCursor = rowDataList.get(cursorRowNumber++);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -91,7 +100,8 @@ public class DatabaseMetaDataResultSet implements ResultSet {
|
|||
@Override
|
||||
public String getString(int columnIndex) throws SQLException {
|
||||
columnIndex--;
|
||||
return rowCursor.getString(columnIndex, columnMetaDataList.get(columnIndex).getColType());
|
||||
int colType = columnMetaDataList.get(columnIndex).getColType();
|
||||
return rowCursor.getString(columnIndex, colType);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -179,7 +179,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
}
|
||||
|
||||
//load taos.cfg start
|
||||
if (info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null && info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null){
|
||||
if (info.getProperty(TSDBDriver.PROPERTY_KEY_HOST) == null && info.getProperty(TSDBDriver.PROPERTY_KEY_PORT) == null) {
|
||||
File cfgDir = loadConfigDir(info.getProperty(TSDBDriver.PROPERTY_KEY_CONFIG_DIR));
|
||||
File cfgFile = cfgDir.listFiles((dir, name) -> "taos.cfg".equalsIgnoreCase(name))[0];
|
||||
List<String> endpoints = loadConfigEndpoints(cfgFile);
|
||||
|
@ -244,7 +244,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
}
|
||||
|
||||
public boolean acceptsURL(String url) throws SQLException {
|
||||
return (url != null && url.length() > 0 && url.trim().length() > 0) && url.toLowerCase().startsWith(URL_PREFIX);
|
||||
return (url != null && url.length() > 0 && url.trim().length() > 0) && url.startsWith(URL_PREFIX);
|
||||
}
|
||||
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
|
||||
|
@ -291,8 +291,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
return null;
|
||||
}
|
||||
|
||||
String lowerUrl = url.toLowerCase();
|
||||
if (!lowerUrl.startsWith(URL_PREFIX) && !lowerUrl.startsWith(URL_PREFIX1)) {
|
||||
if (!url.startsWith(URL_PREFIX) && !url.startsWith(URL_PREFIX1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_LINUX_64)
|
||||
find_program(HAVE_ODBCINST NAMES odbcinst)
|
||||
|
||||
IF (HAVE_ODBCINST)
|
||||
include(CheckSymbolExists)
|
||||
# shall we revert CMAKE_REQUIRED_LIBRARIES and how?
|
||||
set(CMAKE_REQUIRED_LIBRARIES odbc)
|
||||
check_symbol_exists(SQLExecute "sql.h" HAVE_ODBC_DEV)
|
||||
if(NOT (HAVE_ODBC_DEV))
|
||||
unset(HAVE_ODBC_DEV CACHE)
|
||||
message(WARNING "unixodbc-dev is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc-dev")
|
||||
else ()
|
||||
message(STATUS "unixodbc/unixodbc-dev are installed, and odbc connector will be built")
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
|
||||
# generate dynamic library (*.so)
|
||||
ADD_LIBRARY(todbc SHARED ${SRC})
|
||||
SET_TARGET_PROPERTIES(todbc PROPERTIES CLEAN_DIRECT_OUTPUT 1)
|
||||
SET_TARGET_PROPERTIES(todbc PROPERTIES VERSION ${TD_VER_NUMBER} SOVERSION 1)
|
||||
TARGET_LINK_LIBRARIES(todbc taos)
|
||||
|
||||
install(CODE "execute_process(COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/src/install.sh ${CMAKE_BINARY_DIR})")
|
||||
|
||||
ADD_SUBDIRECTORY(tests)
|
||||
endif()
|
||||
ELSE ()
|
||||
message(WARNING "unixodbc is not installed yet, you may install it under ubuntu by typing: sudo apt install unixodbc")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -u
|
||||
|
||||
BLD_DIR="$1"
|
||||
|
||||
rm -f "${BLD_DIR}/template.ini"
|
||||
rm -f "${BLD_DIR}/template.dsn"
|
||||
|
||||
cat > "${BLD_DIR}/template.ini" <<EOF
|
||||
[TAOS]
|
||||
Description = taos odbc driver
|
||||
Driver = ${BLD_DIR}/build/lib/libtodbc.so
|
||||
EOF
|
||||
|
||||
cat > "${BLD_DIR}/template.dsn" <<EOF
|
||||
[TAOS_DSN]
|
||||
Description=Connection to TAOS
|
||||
Driver=TAOS
|
||||
EOF
|
||||
|
||||
sudo odbcinst -i -d -f "${BLD_DIR}/template.ini" &&
|
||||
odbcinst -i -s -f "${BLD_DIR}/template.dsn" &&
|
||||
echo "odbc install done"
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,238 @@
|
|||
/*
|
||||
* 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 "todbc_util.h"
|
||||
|
||||
#include "iconv.h"
|
||||
|
||||
#include <sql.h>
|
||||
#include <sqltypes.h>
|
||||
#include <sqlext.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
const char* sql_sql_type(int type) {
|
||||
switch (type) {
|
||||
case SQL_BIT: return "SQL_BIT";
|
||||
case SQL_TINYINT: return "SQL_TINYINT";
|
||||
case SQL_SMALLINT: return "SQL_SMALLINT";
|
||||
case SQL_INTEGER: return "SQL_INTEGER";
|
||||
case SQL_BIGINT: return "SQL_BIGINT";
|
||||
case SQL_FLOAT: return "SQL_FLOAT";
|
||||
case SQL_DOUBLE: return "SQL_DOUBLE";
|
||||
case SQL_DECIMAL: return "SQL_DECIMAL";
|
||||
case SQL_NUMERIC: return "SQL_NUMERIC";
|
||||
case SQL_REAL: return "SQL_REAL";
|
||||
case SQL_CHAR: return "SQL_CHAR";
|
||||
case SQL_VARCHAR: return "SQL_VARCHAR";
|
||||
case SQL_LONGVARCHAR: return "SQL_LONGVARCHAR";
|
||||
case SQL_WCHAR: return "SQL_WCHAR";
|
||||
case SQL_WVARCHAR: return "SQL_WVARCHAR";
|
||||
case SQL_WLONGVARCHAR: return "SQL_WLONGVARCHAR";
|
||||
case SQL_BINARY: return "SQL_BINARY";
|
||||
case SQL_VARBINARY: return "SQL_VARBINARY";
|
||||
case SQL_LONGVARBINARY: return "SQL_LONGVARBINARY";
|
||||
case SQL_DATE: return "SQL_DATE";
|
||||
case SQL_TIME: return "SQL_TIME";
|
||||
case SQL_TIMESTAMP: return "SQL_TIMESTAMP";
|
||||
case SQL_TYPE_DATE: return "SQL_TYPE_DATE";
|
||||
case SQL_TYPE_TIME: return "SQL_TYPE_TIME";
|
||||
case SQL_TYPE_TIMESTAMP: return "SQL_TYPE_TIMESTAMP";
|
||||
case SQL_INTERVAL_MONTH: return "SQL_INTERVAL_MONTH";
|
||||
case SQL_INTERVAL_YEAR: return "SQL_INTERVAL_YEAR";
|
||||
case SQL_INTERVAL_YEAR_TO_MONTH: return "SQL_INTERVAL_YEAR_TO_MONTH";
|
||||
case SQL_INTERVAL_DAY: return "SQL_INTERVAL_DAY";
|
||||
case SQL_INTERVAL_HOUR: return "SQL_INTERVAL_HOUR";
|
||||
case SQL_INTERVAL_MINUTE: return "SQL_INTERVAL_MINUTE";
|
||||
case SQL_INTERVAL_SECOND: return "SQL_INTERVAL_SECOND";
|
||||
case SQL_INTERVAL_DAY_TO_HOUR: return "SQL_INTERVAL_DAY_TO_HOUR";
|
||||
case SQL_INTERVAL_DAY_TO_MINUTE: return "SQL_INTERVAL_DAY_TO_MINUTE";
|
||||
case SQL_INTERVAL_DAY_TO_SECOND: return "SQL_INTERVAL_DAY_TO_SECOND";
|
||||
case SQL_INTERVAL_HOUR_TO_MINUTE: return "SQL_INTERVAL_HOUR_TO_MINUTE";
|
||||
case SQL_INTERVAL_HOUR_TO_SECOND: return "SQL_INTERVAL_HOUR_TO_SECOND";
|
||||
case SQL_INTERVAL_MINUTE_TO_SECOND: return "SQL_INTERVAL_MINUTE_TO_SECOND";
|
||||
case SQL_GUID: return "SQL_GUID";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
const char* sql_c_type(int type) {
|
||||
switch (type) {
|
||||
case SQL_C_CHAR: return "SQL_C_CHAR";
|
||||
case SQL_C_WCHAR: return "SQL_C_WCHAR";
|
||||
case SQL_C_SHORT: return "SQL_C_SHORT";
|
||||
case SQL_C_SSHORT: return "SQL_C_SSHORT";
|
||||
case SQL_C_USHORT: return "SQL_C_USHORT";
|
||||
case SQL_C_LONG: return "SQL_C_LONG";
|
||||
case SQL_C_SLONG: return "SQL_C_SLONG";
|
||||
case SQL_C_ULONG: return "SQL_C_ULONG";
|
||||
case SQL_C_FLOAT: return "SQL_C_FLOAT";
|
||||
case SQL_C_DOUBLE: return "SQL_C_DOUBLE";
|
||||
case SQL_C_BIT: return "SQL_C_BIT";
|
||||
case SQL_C_TINYINT: return "SQL_C_TINYINT";
|
||||
case SQL_C_STINYINT: return "SQL_C_STINYINT";
|
||||
case SQL_C_UTINYINT: return "SQL_C_UTINYINT";
|
||||
case SQL_C_SBIGINT: return "SQL_C_SBIGINT";
|
||||
case SQL_C_UBIGINT: return "SQL_C_UBIGINT";
|
||||
case SQL_C_BINARY: return "SQL_C_BINARY";
|
||||
case SQL_C_DATE: return "SQL_C_DATE";
|
||||
case SQL_C_TIME: return "SQL_C_TIME";
|
||||
case SQL_C_TIMESTAMP: return "SQL_C_TIMESTAMP";
|
||||
case SQL_C_TYPE_DATE: return "SQL_C_TYPE_DATE";
|
||||
case SQL_C_TYPE_TIME: return "SQL_C_TYPE_TIME";
|
||||
case SQL_C_TYPE_TIMESTAMP: return "SQL_C_TYPE_TIMESTAMP";
|
||||
case SQL_C_NUMERIC: return "SQL_C_NUMERIC";
|
||||
case SQL_C_GUID: return "SQL_C_GUID";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
int is_valid_sql_c_type(int type) {
|
||||
const char *ctype = sql_c_type(type);
|
||||
if (strcmp(ctype, "UNKNOWN")==0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int is_valid_sql_sql_type(int type) {
|
||||
const char *sqltype = sql_sql_type(type);
|
||||
if (strcmp(sqltype, "UNKNOWN")==0) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int string_conv(const char *fromcode, const char *tocode,
|
||||
const unsigned char *src, size_t sbytes,
|
||||
unsigned char *dst, size_t dbytes,
|
||||
size_t *consumed, size_t *generated)
|
||||
{
|
||||
if (consumed) *consumed = 0;
|
||||
if (generated) *generated = 0;
|
||||
|
||||
if (dbytes <= 0) return -1;
|
||||
dst[0] = '\0';
|
||||
|
||||
iconv_t conv = iconv_open(tocode, fromcode);
|
||||
if (!conv) return -1;
|
||||
|
||||
int r = 0;
|
||||
do {
|
||||
char *s = (char*)src;
|
||||
char *d = (char*)dst;
|
||||
size_t sl = sbytes;
|
||||
size_t dl = dbytes;
|
||||
|
||||
r = iconv(conv, &s, &sl, &d, &dl);
|
||||
*d = '\0';
|
||||
|
||||
if (consumed) *consumed = sbytes - sl;
|
||||
if (generated) *generated = dbytes - dl;
|
||||
|
||||
} while (0);
|
||||
|
||||
iconv_close(conv);
|
||||
return r;
|
||||
}
|
||||
|
||||
int utf8_chars(const char *src)
|
||||
{
|
||||
const char *fromcode = "UTF-8";
|
||||
const char *tocode = "UCS-2LE";
|
||||
iconv_t conv = iconv_open(tocode, fromcode);
|
||||
if (!conv) return -1;
|
||||
|
||||
size_t slen = strlen(src);
|
||||
char buf[4096];
|
||||
size_t dlen = sizeof(buf);
|
||||
char *ps = (char*)src;
|
||||
char *pd = buf;
|
||||
iconv(conv, &ps, &slen, &pd, &dlen);
|
||||
DASSERT(slen==0);
|
||||
|
||||
size_t chars = (sizeof(buf) - dlen) / 2;
|
||||
iconv_close(conv);
|
||||
return chars;
|
||||
}
|
||||
|
||||
unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars)
|
||||
{
|
||||
const char *tocode = "UCS-4LE";
|
||||
const char *fromcode = "UTF-8";
|
||||
|
||||
iconv_t conv = iconv_open(tocode, fromcode);
|
||||
if (!conv) return NULL;
|
||||
|
||||
unsigned char *ucs4le = NULL;
|
||||
|
||||
do {
|
||||
size_t slen = strlen(utf8);
|
||||
size_t dlen = slen * 4;
|
||||
|
||||
ucs4le = (unsigned char*)malloc(dlen+1);
|
||||
if (!ucs4le) break;
|
||||
|
||||
char *src = (char*)utf8;
|
||||
char *dst = (char*)ucs4le;
|
||||
size_t s = slen;
|
||||
size_t d = dlen;
|
||||
iconv(conv, &src, &s, &dst, &d);
|
||||
dst[0] = '\0';
|
||||
|
||||
if (chars) *chars = (dlen - d) / 4;
|
||||
} while (0);
|
||||
|
||||
iconv_close(conv);
|
||||
return ucs4le;
|
||||
}
|
||||
|
||||
char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars)
|
||||
{
|
||||
const char *fromcode = "UCS-4LE";
|
||||
const char *tocode = "UTF-8";
|
||||
|
||||
iconv_t conv = iconv_open(tocode, fromcode);
|
||||
if (!conv) return NULL;
|
||||
|
||||
char *utf8 = NULL;
|
||||
|
||||
do {
|
||||
size_t dlen = slen;
|
||||
|
||||
utf8 = (char*)malloc(dlen+1);
|
||||
if (!utf8) break;
|
||||
|
||||
char *dst = utf8;
|
||||
char *src = (char*)ucs4le;
|
||||
size_t s = slen;
|
||||
size_t d = dlen;
|
||||
iconv(conv, &src, &s, &dst, &d);
|
||||
dst[0] = '\0';
|
||||
|
||||
if (chars) *chars = (slen - s) / 4;
|
||||
} while (0);
|
||||
|
||||
iconv_close(conv);
|
||||
return utf8;
|
||||
}
|
||||
|
||||
SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes)
|
||||
{
|
||||
size_t dlen = chs * 4;
|
||||
SQLCHAR *dst = (SQLCHAR*)malloc(dlen + 1);
|
||||
if (!dst) return NULL;
|
||||
|
||||
string_conv("UCS-2LE", "UTF-8", (const unsigned char*)wchars, chs * sizeof(*wchars), dst, dlen + 1, NULL, bytes);
|
||||
|
||||
return dst;
|
||||
}
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef _TODBC_UTIL_H_
|
||||
#define _TODBC_UTIL_H_
|
||||
|
||||
#include <libgen.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sql.h>
|
||||
|
||||
#define D(fmt, ...) \
|
||||
fprintf(stderr, \
|
||||
"%s[%d]:%s() " fmt "\n", \
|
||||
basename((char*)__FILE__), __LINE__, __func__, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
#define DASSERT(statement) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s", #statement); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
#define DASSERTX(statement, fmt, ...) \
|
||||
do { \
|
||||
if (statement) break; \
|
||||
D("Assertion failure: %s, " fmt "", #statement, ##__VA_ARGS__); \
|
||||
abort(); \
|
||||
} while (0)
|
||||
|
||||
|
||||
|
||||
const char* sql_sql_type(int type);
|
||||
const char* sql_c_type(int type);
|
||||
|
||||
int is_valid_sql_c_type(int type);
|
||||
int is_valid_sql_sql_type(int type);
|
||||
|
||||
int string_conv(const char *fromcode, const char *tocode,
|
||||
const unsigned char *src, size_t sbytes,
|
||||
unsigned char *dst, size_t dbytes,
|
||||
size_t *consumed, size_t *generated);
|
||||
int utf8_chars(const char *src);
|
||||
|
||||
unsigned char* utf8_to_ucs4le(const char *utf8, size_t *chars);
|
||||
char* ucs4le_to_utf8(const unsigned char *ucs4le, size_t slen, size_t *chars);
|
||||
SQLCHAR* wchars_to_chars(const SQLWCHAR *wchars, size_t chs, size_t *bytes);
|
||||
|
||||
#endif // _TODBC_UTIL_H_
|
|
@ -0,0 +1,7 @@
|
|||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_LINUX)
|
||||
AUX_SOURCE_DIRECTORY(. SRC)
|
||||
ADD_EXECUTABLE(tcodbc main.c)
|
||||
TARGET_LINK_LIBRARIES(tcodbc odbc)
|
||||
ENDIF ()
|
|
@ -0,0 +1,231 @@
|
|||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "os.h"
|
||||
|
||||
// static const char *dsn = "TAOS_DSN";
|
||||
// static const char *uid = "root";
|
||||
// static const char *pwd = "taosdata";
|
||||
|
||||
typedef struct data_s data_t;
|
||||
struct data_s {
|
||||
int64_t ts;
|
||||
int8_t b;
|
||||
int8_t v1;
|
||||
int16_t v2;
|
||||
int32_t v4;
|
||||
int64_t v8;
|
||||
float f4;
|
||||
double f8;
|
||||
char bin[40+1];
|
||||
char blob[40+1]; // why 80? ref: tests/examples/c/apitest.c
|
||||
};
|
||||
|
||||
static const char *pre_stmts[] = {
|
||||
"create database db",
|
||||
"use db",
|
||||
"create table t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))"
|
||||
};
|
||||
|
||||
static const char *pro_stmts[] = {
|
||||
// "insert into t values ('2019-07-15 00:00:00', 1)",
|
||||
// "insert into t values ('2019-07-15 01:00:00', 2)",
|
||||
"select * from t"
|
||||
// "drop database db"
|
||||
};
|
||||
|
||||
#define CHK_RESULT(r, ht, h) \
|
||||
do { \
|
||||
if (r==0) break; \
|
||||
SQLCHAR ss[10]; \
|
||||
SQLINTEGER ne = 0; \
|
||||
SQLCHAR es[4096]; \
|
||||
SQLSMALLINT n = 0; \
|
||||
ss[0] = '\0'; \
|
||||
es[0] = '\0'; \
|
||||
SQLRETURN ret = SQLGetDiagRec(ht, h, 1, ss, &ne, es, sizeof(es), &n); \
|
||||
if (ret) break; \
|
||||
fprintf(stderr, "%s%s\n", ss, es); \
|
||||
} while (0)
|
||||
|
||||
static int do_statement(SQLHSTMT stmt, const char *statement) {
|
||||
SQLRETURN r = 0;
|
||||
do {
|
||||
fprintf(stderr, "prepare [%s]\n", statement);
|
||||
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
fprintf(stderr, "execute [%s]\n", statement);
|
||||
r = SQLExecute(stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
fprintf(stderr, "done\n");
|
||||
} while (0);
|
||||
fprintf(stderr, "r: [%x][%d]\n", r, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
static int do_insert(SQLHSTMT stmt, data_t data) {
|
||||
SQLRETURN r = 0;
|
||||
SQLLEN lbin;
|
||||
SQLLEN lblob;
|
||||
|
||||
const char *statement = "insert into t values (?, ?, ?, ?, ?, ?, ?, ?, ?,?)";
|
||||
int ignored = 0;
|
||||
|
||||
do {
|
||||
fprintf(stderr, "prepare [%s]\n", statement);
|
||||
r = SQLPrepare(stmt, (SQLCHAR*)statement, strlen(statement));
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 1 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_TIMESTAMP, ignored, ignored, &data.ts, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 2 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_BIT, SQL_BIT, ignored, ignored, &data.b, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 3 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 3, SQL_PARAM_INPUT, SQL_C_TINYINT, SQL_TINYINT, ignored, ignored, &data.v1, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 4 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 4, SQL_PARAM_INPUT, SQL_C_SHORT, SQL_SMALLINT, ignored, ignored, &data.v2, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 5 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 5, SQL_PARAM_INPUT, SQL_C_LONG, SQL_INTEGER, ignored, ignored, &data.v4, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 6 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 6, SQL_PARAM_INPUT, SQL_C_SBIGINT, SQL_BIGINT, ignored, ignored, &data.v8, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 7 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 7, SQL_PARAM_INPUT, SQL_C_FLOAT, SQL_FLOAT, ignored, ignored, &data.f4, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 8 [%s]\n", statement);
|
||||
r = SQLBindParameter(stmt, 8, SQL_PARAM_INPUT, SQL_C_DOUBLE, SQL_DOUBLE, ignored, ignored, &data.f8, ignored, NULL);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 9 [%s]\n", statement);
|
||||
lbin = SQL_NTS;
|
||||
r = SQLBindParameter(stmt, 9, SQL_PARAM_INPUT, SQL_C_BINARY, SQL_VARBINARY, sizeof(data.bin)-1, ignored, &data.bin, ignored, &lbin);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "bind 10 [%s]\n", statement);
|
||||
lblob = SQL_NTS;
|
||||
r = SQLBindParameter(stmt, 10, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(data.blob)-1, ignored, &data.blob, ignored, &lblob);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
fprintf(stderr, "execute [%s]\n", statement);
|
||||
r = SQLExecute(stmt);
|
||||
CHK_RESULT(r, SQL_HANDLE_STMT, stmt);
|
||||
if (r) break;
|
||||
|
||||
// ts += 1;
|
||||
// v = 2;
|
||||
// fprintf(stderr, "execute [%s]\n", statement);
|
||||
// r = SQLExecute(stmt);
|
||||
// if (r) break;
|
||||
|
||||
fprintf(stderr, "done\n");
|
||||
} while (0);
|
||||
fprintf(stderr, "r: [%x][%d]\n", r, r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
if (argc < 4) return 1;
|
||||
const char *dsn = argv[1];
|
||||
const char *uid = argv[2];
|
||||
const char *pwd = argv[3];
|
||||
SQLRETURN r;
|
||||
SQLHENV env = {0};
|
||||
SQLHDBC conn = {0};
|
||||
r = SQLAllocEnv(&env);
|
||||
if (r!=SQL_SUCCESS) return 1;
|
||||
do {
|
||||
r = SQLAllocConnect(env, &conn);
|
||||
CHK_RESULT(r, SQL_HANDLE_ENV, env);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
r = SQLConnect(conn, (SQLCHAR*)dsn, strlen(dsn),
|
||||
(SQLCHAR*)uid, strlen(uid),
|
||||
(SQLCHAR*)pwd, strlen(pwd));
|
||||
CHK_RESULT(r, SQL_HANDLE_DBC, conn);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
do_statement(stmt, "drop database db");
|
||||
for (size_t i=0; i<sizeof(pre_stmts)/sizeof(pre_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pre_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
do {
|
||||
data_t data = {0};
|
||||
data.ts = 1591060628001;
|
||||
data.b = 1;
|
||||
data.v1 = 127;
|
||||
data.v2 = 32767;
|
||||
data.v4 = 2147483647;
|
||||
data.v8 = 9223372036854775807;
|
||||
data.f4 = 123.456;
|
||||
data.f8 = 9999999.999999;
|
||||
memset(data.bin, 0, sizeof(data.bin));
|
||||
memset(data.blob, 0, sizeof(data.blob));
|
||||
snprintf(data.bin, sizeof(data.bin), "hel我lo");
|
||||
snprintf(data.blob, sizeof(data.blob), "world");
|
||||
snprintf(data.blob, sizeof(data.blob), "wo人rld");
|
||||
SQLHSTMT stmt = {0};
|
||||
r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
do {
|
||||
r = do_insert(stmt, data);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
} while (0);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
|
||||
// r = SQLAllocHandle(SQL_HANDLE_STMT, conn, &stmt);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// do {
|
||||
// r = do_insert(stmt, ts++, v++);
|
||||
// if (r!=SQL_SUCCESS) break;
|
||||
// } while (0);
|
||||
// SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
for (size_t i=0; i<sizeof(pro_stmts)/sizeof(pro_stmts[0]); ++i) {
|
||||
r = do_statement(stmt, pro_stmts[i]);
|
||||
if (r!=SQL_SUCCESS) break;
|
||||
}
|
||||
} while (0);
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, stmt);
|
||||
} while (0);
|
||||
SQLDisconnect(conn);
|
||||
} while (0);
|
||||
SQLFreeConnect(conn);
|
||||
} while (0);
|
||||
SQLFreeEnv(env);
|
||||
return r ? 1 : 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
import pyodbc
|
||||
cnxn = pyodbc.connect('DSN=TAOS_DSN;UID=root;PWD=taosdata', autocommit=True)
|
||||
cnxn.setdecoding(pyodbc.SQL_CHAR, encoding='utf-8')
|
||||
#cnxn.setdecoding(pyodbc.SQL_WCHAR, encoding='utf-8')
|
||||
#cnxn.setencoding(encoding='utf-8')
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.t")
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
||||
#cursor = cnxn.cursor()
|
||||
#cursor.execute("""
|
||||
#INSERT INTO db.t values (?,?,?,?,?,?,?,?,?,?)
|
||||
#""",
|
||||
#"2020-12-12 00:00:00",
|
||||
#1,
|
||||
#27,
|
||||
#32767,
|
||||
#147483647,
|
||||
#223372036854775807,
|
||||
#23.456,
|
||||
#899.999999,
|
||||
#"foo",
|
||||
#"bar")
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("drop database if exists db");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("create database db");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(40), blob nchar(10))");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hello', 'world')")
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("insert into db.t values(?,?,?,?,?,?,?,?,?,?)", "2020-10-13 07:06:00", 0, 127, 32767, 32768, 32769, 123.456, 789.987, "hel后lo", "wo哈rld");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.t")
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("drop database if exists db");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("create database db");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("create table db.t (ts timestamp, b bool, v1 tinyint, v2 smallint, v4 int, v8 bigint, f4 float, f8 double, bin binary(4), blob nchar(4))");
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("insert into db.t values('2020-10-13 06:44:00', 1, 127, 32767, 32768, 32769, 123.456, 789.987, 'hell', 'worl')")
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.t")
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("create table db.v (ts timestamp, v1 tinyint)")
|
||||
cursor.close()
|
||||
|
||||
params = [ ('A', 1), ('B', 2), ('C', 3) ]
|
||||
params = [ ('A', 1), ('B', 2), ('C', 3) ]
|
||||
params = [ ('2020-10-16 00:00:00', 1),
|
||||
('2020-10-16 00:00:01', 4),
|
||||
('2020-10-16 00:00:02', 5),
|
||||
('2020-10-16 00:00:03.009', 6) ]
|
||||
cursor = cnxn.cursor()
|
||||
cursor.fast_executemany = True
|
||||
cursor.executemany("insert into db.v values (?, ?)", params)
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.v")
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.v where v1 > ?", 4)
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
||||
cursor = cnxn.cursor()
|
||||
cursor.execute("SELECT * from db.v where v1 > ?", '5')
|
||||
row = cursor.fetchone()
|
||||
while row:
|
||||
print(row)
|
||||
row = cursor.fetchone()
|
||||
cursor.close()
|
||||
|
|
@ -225,6 +225,7 @@ class CTaosInterface(object):
|
|||
|
||||
if connection.value == None:
|
||||
print('connect to TDengine failed')
|
||||
raise ConnectionError("connect to TDengine failed")
|
||||
# sys.exit(1)
|
||||
else:
|
||||
print('connect to TDengine success')
|
||||
|
|
|
@ -192,8 +192,10 @@ class TDengineCursor(object):
|
|||
buffer = [[] for i in range(len(self._fields))]
|
||||
self._rowcount = 0
|
||||
while True:
|
||||
block, num_of_fields = CTaosInterface.fetchBlock(
|
||||
self._result, self._fields)
|
||||
block, num_of_fields = CTaosInterface.fetchBlock(self._result, self._fields)
|
||||
errno = CTaosInterface.libtaos.taos_errno(self._result)
|
||||
if errno != 0:
|
||||
raise ProgrammingError(CTaosInterface.errStr(self._result), errno)
|
||||
if num_of_fields == 0:
|
||||
break
|
||||
self._rowcount += num_of_fields
|
||||
|
|
|
@ -225,6 +225,7 @@ class CTaosInterface(object):
|
|||
|
||||
if connection.value == None:
|
||||
print('connect to TDengine failed')
|
||||
raise ConnectionError("connect to TDengine failed")
|
||||
# sys.exit(1)
|
||||
#else:
|
||||
# print('connect to TDengine success')
|
||||
|
@ -414,4 +415,4 @@ if __name__ == '__main__':
|
|||
print(data)
|
||||
|
||||
cinter.freeResult(result)
|
||||
cinter.close(conn)
|
||||
cinter.close(conn)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue