Merge branch 'develop' into xiaoping/CI_update
This commit is contained in:
commit
cc5c78824b
|
@ -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
|
|
@ -0,0 +1,70 @@
|
|||
pipeline {
|
||||
agent any
|
||||
stages {
|
||||
stage('build TDengine') {
|
||||
steps {
|
||||
sh '''cd ${WORKSPACE}
|
||||
export TZ=Asia/Harbin
|
||||
date
|
||||
rm -rf ${WORKSPACE}/debug
|
||||
mkdir debug
|
||||
cd debug
|
||||
cmake .. > /dev/null
|
||||
make > /dev/null
|
||||
cd ${WORKSPACE}/debug'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('test_tsim') {
|
||||
parallel {
|
||||
stage('test') {
|
||||
steps {
|
||||
sh '''cd ${WORKSPACE}/tests
|
||||
#./test-all.sh smoke
|
||||
sudo ./test-all.sh full'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('test_crash_gen') {
|
||||
steps {
|
||||
sh '''cd ${WORKSPACE}/tests/pytest
|
||||
sudo ./crash_gen.sh -a -p -t 4 -s 2000'''
|
||||
}
|
||||
}
|
||||
|
||||
stage('test_valgrind') {
|
||||
steps {
|
||||
sh '''cd ${WORKSPACE}/tests/pytest
|
||||
sudo ./valgrind-test.sh 2>&1 > mem-error-out.log
|
||||
grep \'start to execute\\|ERROR SUMMARY\' mem-error-out.log|grep -v \'grep\'|uniq|tee uniq-mem-error-out.log
|
||||
|
||||
for memError in `grep \'ERROR SUMMARY\' uniq-mem-error-out.log | awk \'{print $4}\'`
|
||||
do
|
||||
if [ -n "$memError" ]; then
|
||||
if [ "$memError" -gt 12 ]; then
|
||||
echo -e "${RED} ## Memory errors number valgrind reports is $memError.\\
|
||||
More than our threshold! ## ${NC}"
|
||||
travis_terminate $memError
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
grep \'start to execute\\|definitely lost:\' mem-error-out.log|grep -v \'grep\'|uniq|tee uniq-definitely-lost-out.log
|
||||
for defiMemError in `grep \'definitely lost:\' uniq-definitely-lost-out.log | awk \'{print $7}\'`
|
||||
do
|
||||
if [ -n "$defiMemError" ]; then
|
||||
if [ "$defiMemError" -gt 13 ]; then
|
||||
echo -e "${RED} ## Memory errors number valgrind reports \\
|
||||
Definitely lost is $defiMemError. More than our threshold! ## ${NC}"
|
||||
travis_terminate $defiMemError
|
||||
fi
|
||||
fi
|
||||
done'''
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
39
README.md
39
README.md
|
@ -2,7 +2,6 @@
|
|||
[](https://ci.appveyor.com/project/sangshuduo/tdengine-2n8ge/branch/master)
|
||||
[](https://coveralls.io/github/taosdata/TDengine?branch=develop)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4201)
|
||||
[](https://hub.docker.com/repository/docker/tdengine/tdengine)
|
||||
[](https://snapcraft.io/tdengine)
|
||||
|
||||
[](https://www.taosdata.com)
|
||||
|
@ -84,14 +83,22 @@ 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
|
||||
|
||||
```bash
|
||||
mkdir debug && cd debug
|
||||
cmake .. && cmake --build .
|
||||
|
@ -109,6 +116,34 @@ aarch32:
|
|||
cmake .. -DCPUTYPE=aarch32 && cmake --build .
|
||||
```
|
||||
|
||||
### On Windows platform
|
||||
|
||||
If you use the Visual Studio 2013, please open a command window by executing "cmd.exe".
|
||||
Please specify "x86_amd64" for 64 bits Windows or specify "x86" is for 32 bits Windows when you execute vcvarsall.bat.
|
||||
```
|
||||
mkdir debug && cd debug
|
||||
"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat" < x86_amd64 | x86 >
|
||||
cmake .. -G "NMake Makefiles"
|
||||
nmake
|
||||
```
|
||||
|
||||
If you use the Visual Studio 2019, please open a command window by executing "cmd.exe".
|
||||
Please specify "x64" for 64 bits Windows or specify "x86" is for 32 bits Windows when you execute vcvarsall.bat.
|
||||
```
|
||||
mkdir debug && cd debug
|
||||
"c:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvarsall.bat" < x64 | x86 >
|
||||
cmake .. -G "NMake Makefiles"
|
||||
nmake
|
||||
```
|
||||
|
||||
Or, you can open a command window by clicking Visual Studio 2019 menu "Tools -> Command Line -> Developer Command Prompt" or "Tools -> Command Line -> Developer PowerShell" then execute commands as follows:
|
||||
```
|
||||
mkdir debug && cd debug
|
||||
cmake .. -G "NMake Makefiles"
|
||||
nmake
|
||||
```
|
||||
|
||||
# Quick Run
|
||||
# Quick Run
|
||||
To quickly start a TDengine server after building, run the command below in terminal:
|
||||
```cmd
|
||||
|
|
|
@ -9,9 +9,7 @@ set -e
|
|||
script_dir=$(dirname $(readlink -f "$0"))
|
||||
# Dynamic directory
|
||||
lib_link_dir="/usr/lib"
|
||||
|
||||
#install main path
|
||||
install_main_dir="/usr/local/taos"
|
||||
lib64_link_dir="/usr/lib64"
|
||||
|
||||
# Color setting
|
||||
RED='\033[0;31m'
|
||||
|
@ -25,24 +23,23 @@ if command -v sudo > /dev/null; then
|
|||
csudo="sudo"
|
||||
fi
|
||||
|
||||
function clean_driver() {
|
||||
${csudo} rm -f /usr/lib/libtaos.so || :
|
||||
}
|
||||
|
||||
function install_driver() {
|
||||
echo
|
||||
if [[ -d ${lib_link_dir} && ! -e ${lib_link_dir}/libtaos.so ]]; then
|
||||
echo -e "${GREEN}Start to install TDengine client driver ...${NC}"
|
||||
${csudo} ln -s ${script_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1 || :
|
||||
${csudo} ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so || :
|
||||
|
||||
#create install main dir and all sub dir
|
||||
${csudo} mkdir -p ${install_main_dir}
|
||||
${csudo} mkdir -p ${install_main_dir}/driver
|
||||
|
||||
${csudo} rm -f ${lib_link_dir}/libtaos.* || :
|
||||
${csudo} cp -rf ${script_dir}/driver/* ${install_main_dir}/driver && ${csudo} chmod 777 ${install_main_dir}/driver/*
|
||||
${csudo} ln -s ${install_main_dir}/driver/libtaos.* ${lib_link_dir}/libtaos.so.1
|
||||
${csudo} ln -s ${lib_link_dir}/libtaos.so.1 ${lib_link_dir}/libtaos.so
|
||||
if [[ -d ${lib64_link_dir} && ! -e ${lib64_link_dir}/libtaos.so ]]; then
|
||||
${csudo} ln -s ${script_dir}/driver/libtaos.* ${lib64_link_dir}/libtaos.so.1 || :
|
||||
${csudo} ln -s ${lib64_link_dir}/libtaos.so.1 ${lib64_link_dir}/libtaos.so || :
|
||||
fi
|
||||
|
||||
echo
|
||||
echo -e "\033[44;32;1mTDengine client driver is successfully installed!${NC}"
|
||||
echo -e "${GREEN}TDengine client driver is successfully installed!${NC}"
|
||||
else
|
||||
echo -e "${GREEN}TDengine client driver already exists, Please confirm whether the alert version matches the client driver version!${NC}"
|
||||
fi
|
||||
}
|
||||
|
||||
install_driver
|
||||
|
|
|
@ -119,7 +119,7 @@ WantedBy=multi-user.target
|
|||
return nil
|
||||
}
|
||||
|
||||
const version = "TDengine alert v2.0.0.1"
|
||||
var version = "2.0.0.1s"
|
||||
|
||||
func main() {
|
||||
var (
|
||||
|
@ -133,7 +133,7 @@ func main() {
|
|||
flag.Parse()
|
||||
|
||||
if showVersion {
|
||||
fmt.Println(version)
|
||||
fmt.Println("TDengine alert v" + version)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -6,9 +6,9 @@ set -e
|
|||
# set parameters by default value
|
||||
cpuType=amd64 # [armv6l | arm64 | amd64 | 386]
|
||||
osType=linux # [linux | darwin | windows]
|
||||
|
||||
version=""
|
||||
declare -A archMap=(["armv6l"]="arm" ["arm64"]="arm64" ["amd64"]="x64" ["386"]="x86")
|
||||
while getopts "h:c:o:" arg
|
||||
while getopts "h:c:o:n:" arg
|
||||
do
|
||||
case $arg in
|
||||
c)
|
||||
|
@ -19,6 +19,10 @@ do
|
|||
#echo "osType=$OPTARG"
|
||||
osType=$(echo $OPTARG)
|
||||
;;
|
||||
n)
|
||||
#echo "version=$OPTARG"
|
||||
version=$(echo $OPTARG)
|
||||
;;
|
||||
h)
|
||||
echo "Usage: `basename $0` -c [armv6l | arm64 | amd64 | 386] -o [linux | darwin | windows]"
|
||||
exit 0
|
||||
|
@ -30,18 +34,27 @@ do
|
|||
esac
|
||||
done
|
||||
|
||||
if [ "$version" == "" ]; then
|
||||
echo "Please input the correct version!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
startdir=$(pwd)
|
||||
scriptdir=$(dirname $(readlink -f $0))
|
||||
cd ${scriptdir}/cmd/alert
|
||||
version=$(grep 'const version =' main.go | awk '{print $NF}')
|
||||
version=${version%\"}
|
||||
version=${version:1}
|
||||
|
||||
echo "cpuType=${cpuType}"
|
||||
echo "osType=${osType}"
|
||||
echo "version=${version}"
|
||||
|
||||
GOOS=${osType} GOARCH=${cpuType} go build
|
||||
GOOS=${osType} GOARCH=${cpuType} go build -ldflags '-X main.version='${version}
|
||||
|
||||
mkdir -p TDengine-alert/driver
|
||||
|
||||
cp alert alert.cfg install_driver.sh ./TDengine-alert/.
|
||||
cp ../../../debug/build/lib/libtaos.so.${version} ./TDengine-alert/driver/.
|
||||
chmod 777 ./TDengine-alert/install_driver.sh
|
||||
|
||||
tar -I 'gzip -9' -cf ${startdir}/TDengine-alert-${version}-${osType^}-${archMap[${cpuType}]}.tar.gz TDengine-alert/
|
||||
rm -rf ./TDengine-alert
|
||||
|
||||
tar -I 'gzip -9' -cf ${startdir}/TDengine-alert-${version}-${osType^}-${archMap[${cpuType}]}.tar.gz alert alert.cfg install_driver.sh driver/
|
||||
|
|
|
@ -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,12 +105,12 @@ 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 ()
|
||||
|
||||
SET(DEBUG_FLAGS "-O0 -DDEBUG")
|
||||
SET(RELEASE_FLAGS "-O0")
|
||||
SET(RELEASE_FLAGS "-O0 -Wno-unused-variable -Wunused-but-set-variable")
|
||||
|
||||
IF (${COVER} MATCHES "true")
|
||||
MESSAGE(STATUS "Test coverage mode, add extra flags")
|
||||
|
@ -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)
|
||||
|
|
|
@ -10,10 +10,9 @@ 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}/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)
|
||||
|
@ -25,6 +24,7 @@ ELSEIF (TD_WINDOWS)
|
|||
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)
|
||||
|
@ -32,10 +32,6 @@ ELSEIF (TD_WINDOWS)
|
|||
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)
|
||||
ENDIF ()
|
||||
ELSEIF (TD_DARWIN)
|
||||
SET(TD_MAKE_INSTALL_SH "${TD_COMMUNITY_DIR}/packaging/tools/make_install.sh")
|
||||
INSTALL(CODE "MESSAGE(\"make install script: ${TD_MAKE_INSTALL_SH}\")")
|
||||
|
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
|||
IF (DEFINED VERNUMBER)
|
||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||
ELSE ()
|
||||
SET(TD_VER_NUMBER "2.0.3.0")
|
||||
SET(TD_VER_NUMBER "2.0.4.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)
|
||||
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})
|
||||
ENDIF ()
|
|
@ -11,7 +11,7 @@ TDengine能够与开源数据可视化系统[Grafana](https://www.grafana.com/)
|
|||
|
||||
### 配置Grafana
|
||||
|
||||
TDengine的Grafana插件在安装包的/usr/local/taos/connector/grafana目录下。
|
||||
TDengine的Grafana插件在安装包的/usr/local/taos/connector/grafanaplugin目录下。
|
||||
|
||||
以CentOS 7.2操作系统为例,将tdengine目录拷贝到/var/lib/grafana/plugins目录下,重新启动grafana即可。
|
||||
|
||||
|
|
|
@ -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,否则对具体表操作前,需要使用“库名.表名”来指定库的名字。
|
||||
|
||||
**注意:**
|
||||
|
||||
|
@ -56,4 +56,4 @@ INSERT INTO d1001 USING METERS TAGS ("Beijng.Chaoyang", 2) VALUES (now, 10.2, 21
|
|||
## 多列模型 vs 单列模型
|
||||
TDengine支持多列模型,只要物理量是一个数据采集点同时采集的(时间戳一致),这些量就可以作为不同列放在一张超级表里。但还有一种极限的设计,单列模型,每个采集的物理量都单独建表,因此每种类型的物理量都单独建立一超级表。比如电流、电压、相位,就建三张超级表。
|
||||
|
||||
TDengine建议尽可能采用多列模型,因为插入效率以及存储效率更高。但对于有些场景,一个采集点的采集量的种类经常变化,这个时候,如果采用多列模型,就需要频繁修改超级表的结构定义,让应用变的复杂,这个时候,采用单列模型就会显得简单。
|
||||
TDengine建议尽可能采用多列模型,因为插入效率以及存储效率更高。但对于有些场景,一个采集点的采集量的种类经常变化,这个时候,如果采用多列模型,就需要频繁修改超级表的结构定义,让应用变的复杂,这个时候,采用单列模型会显得简单。
|
||||
|
|
|
@ -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发送状态信息。
|
||||
|
||||
|
|
|
@ -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 |
|
||||
|
@ -78,6 +76,18 @@ taos> SELECT SUM(current) FROM meters INTERVAL(1s);
|
|||
2018-10-03 14:38:16.000 | 36.000000000 |
|
||||
Query OK, 5 row(s) in set (0.001538s)
|
||||
```
|
||||
降采样操作也支持时间偏移,比如:将所有智能电表采集的电流值每秒钟求和,但要求每个时间窗口从 500 毫秒开始
|
||||
```mysql
|
||||
taos> SELECT SUM(current) FROM meters INTERVAL(1s, 500a);
|
||||
ts | sum(current) |
|
||||
======================================================
|
||||
2018-10-03 14:38:04.500 | 11.189999809 |
|
||||
2018-10-03 14:38:05.500 | 31.900000572 |
|
||||
2018-10-03 14:38:06.500 | 11.600000000 |
|
||||
2018-10-03 14:38:15.500 | 12.300000381 |
|
||||
2018-10-03 14:38:16.500 | 35.000000000 |
|
||||
Query OK, 5 row(s) in set (0.001521s)
|
||||
```
|
||||
|
||||
物联网场景里,每个数据采集点采集数据的时间是难同步的,但很多分析算法(比如FFT)需要把采集的数据严格按照时间等间隔的对齐,在很多系统里,需要应用自己写程序来处理,但使用TDengine的降采样操作就轻松解决。如果一个时间间隔里,没有采集的数据,TDengine还提供插值计算的功能。
|
||||
|
||||
|
|
|
@ -148,7 +148,7 @@ INSERT INTO <tb1_name> USING <stb1_name> TAGS (<tag1_value1>, ...) VALUES (<fiel
|
|||
SELECT function<field_name>,…
|
||||
FROM <stable_name>
|
||||
WHERE <tag_name> <[=|<=|>=|<>] values..> ([AND|OR] …)
|
||||
INTERVAL (<time range>)
|
||||
INTERVAL (<interval> [, offset])
|
||||
GROUP BY <tag_name>, <tag_name>…
|
||||
ORDER BY <tag_name> <asc|desc>
|
||||
SLIMIT <group_limit>
|
||||
|
|
|
@ -33,8 +33,7 @@ taos> DESCRIBE meters;
|
|||
- 内部函数now是服务器的当前时间
|
||||
- 插入记录时,如果时间戳为now,插入数据时使用服务器当前时间
|
||||
- Epoch Time: 时间戳也可以是一个长整数,表示从1970-01-01 08:00:00.000开始的毫秒数
|
||||
- 时间可以加减,比如 now-2h,表明查询时刻向前推2个小时(最近2小时)。数字后面的时间单位:a(毫秒), s(秒), m(分), h(小时), d(天),w(周), n(月), y(年)。比如select * from t1 where ts > now-2w and ts <= now-1w, 表示查询两周前整整一周的数据
|
||||
- TDengine暂不支持时间窗口按照自然年和自然月切分。Where条件中的时间窗口单位的换算关系如下:interval(1y) 等效于 interval(365d), interval(1n) 等效于 interval(30d), interval(1w) 等效于 interval(7d)
|
||||
- 时间可以加减,比如 now-2h,表明查询时刻向前推2个小时(最近2小时)。 数字后面的时间单位可以是 a(毫秒)、s(秒)、 m(分)、h(小时)、d(天)、w(周)。 比如select * from t1 where ts > now-2w and ts <= now-1w, 表示查询两周前整整一周的数据。 在指定降频操作(down sampling)的时间窗口(interval)时,时间单位还可以使用 n(自然月) 和 y(自然年)。
|
||||
|
||||
TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMicrosecond就可支持微秒。
|
||||
|
||||
|
@ -99,17 +98,18 @@ 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]。
|
||||
|
||||
**Tips**: 以上所有参数修改后都可以用show databases来确认是否修改成功。
|
||||
|
||||
|
||||
- **显示系统所有数据库**
|
||||
```mysql
|
||||
SHOW DATABASES;
|
||||
|
@ -125,6 +125,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
|
|||
1) 表的第一个字段必须是TIMESTAMP,并且系统自动将其设为主键;
|
||||
2) 表名最大长度为193;
|
||||
3) 表的每行长度不能超过16k个字符;
|
||||
4) 子表名只能由字母、数字和下划线组成,且不能以数字开头
|
||||
5) 使用数据类型binary或nchar,需指定其最长的字节数,如binary(20),表示20字节;
|
||||
|
||||
- **删除数据表**
|
||||
|
@ -298,7 +299,7 @@ TDengine缺省的时间戳是毫秒精度,但通过修改配置参数enableMic
|
|||
SELECT select_expr [, select_expr ...]
|
||||
FROM {tb_name_list}
|
||||
[WHERE where_condition]
|
||||
[INTERVAL [interval_offset,] interval_val]
|
||||
[INTERVAL (interval_val [, interval_offset])]
|
||||
[FILL fill_val]
|
||||
[SLIDING fill_val]
|
||||
[GROUP BY col_list]
|
||||
|
@ -971,17 +972,17 @@ TDengine支持按时间段进行聚合,可以将表中数据按照时间段进
|
|||
```mysql
|
||||
SELECT function_list FROM tb_name
|
||||
[WHERE where_condition]
|
||||
INTERVAL (interval)
|
||||
INTERVAL (interval [, offset])
|
||||
[FILL ({NONE | VALUE | PREV | NULL | LINEAR})]
|
||||
|
||||
SELECT function_list FROM stb_name
|
||||
[WHERE where_condition]
|
||||
INTERVAL (interval)
|
||||
INTERVAL (interval [, offset])
|
||||
[FILL ({ VALUE | PREV | NULL | LINEAR})]
|
||||
[GROUP BY tags]
|
||||
```
|
||||
|
||||
- 聚合时间段的长度由关键词INTERVAL指定,最短时间间隔10毫秒(10a)。聚合查询中,能够同时执行的聚合和选择函数仅限于单个输出的函数:count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last,不能使用具有多行输出结果的函数(例如:top、bottom、diff以及四则运算)。
|
||||
- 聚合时间段的长度由关键词INTERVAL指定,最短时间间隔10毫秒(10a),并且支持偏移(偏移必须小于间隔)。聚合查询中,能够同时执行的聚合和选择函数仅限于单个输出的函数:count、avg、sum 、stddev、leastsquares、percentile、min、max、first、last,不能使用具有多行输出结果的函数(例如:top、bottom、diff以及四则运算)。
|
||||
- WHERE语句可以指定查询的起止时间和其他过滤条件
|
||||
- FILL语句指定某一时间区间数据缺失的情况下的填充模式。填充模式包括以下几种:
|
||||
1. 不进行填充:NONE(默认填充模式)。
|
||||
|
@ -1019,5 +1020,5 @@ SELECT AVG(current),MAX(current),LEASTSQUARES(current, start_val, step_val), PER
|
|||
- 表名最大长度为193,每行数据最大长度16k个字符
|
||||
- 列名最大长度为65,最多允许1024列,最少需要2列,第一列必须是时间戳
|
||||
- 标签最多允许128个,可以0个,标签总长度不超过16k个字符
|
||||
- SQL语句最大长度65480个字符,但可通过系统配置参数maxSQLLength修改,最长可配置为8M
|
||||
- SQL语句最大长度65480个字符,但可通过系统配置参数maxSQLLength修改,最长可配置为1M
|
||||
- 库的数目,超级表的数目、表的数目,系统不做限制,仅受系统资源限制
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# TDengine 2.0 错误码以及对应的十进制码
|
||||
|
||||
|
||||
| Code | bit | error code | 错误描述 | 十进制错误码 |
|
||||
| 状态码 | 模 | 错误码(十六进制) | 错误描述 | 错误码(十进制) |
|
||||
|-----------------------| :---: | :---------: | :------------------------ | ---------------- |
|
||||
|TSDB_CODE_RPC_ACTION_IN_PROGRESS| 0 | 0x0001| "Action in progress"| -2147483647|
|
||||
|TSDB_CODE_RPC_AUTH_REQUIRED| 0 | 0x0002 | "Authentication required"| -2147483646|
|
||||
|
@ -87,7 +87,7 @@
|
|||
|TSDB_CODE_MND_INVALID_ACCT_OPTION| 0 | 0x0342 | "Invalid account options"| -2147482814|
|
||||
|TSDB_CODE_MND_USER_ALREADY_EXIST| 0 | 0x0350 | "User already exists"| -2147482800|
|
||||
|TSDB_CODE_MND_INVALID_USER |0 | 0x0351 | "Invalid user" |-2147482799|
|
||||
|TSDB_CODE_MND_INVALID_USER_FORMAT| |0 |0x0352 |"Invalid user format" |-2147482798|
|
||||
|TSDB_CODE_MND_INVALID_USER_FORMAT| 0 |0x0352 |"Invalid user format" |-2147482798|
|
||||
|TSDB_CODE_MND_INVALID_PASS_FORMAT| 0| 0x0353 | "Invalid password format"| -2147482797|
|
||||
|TSDB_CODE_MND_NO_USER_FROM_CONN| 0 | 0x0354 | "Can not get user from conn"| -2147482796|
|
||||
|TSDB_CODE_MND_TOO_MANY_USERS| 0 | 0x0355| "Too many users"| -2147482795|
|
||||
|
@ -107,7 +107,7 @@
|
|||
|TSDB_CODE_MND_DB_NOT_SELECTED| 0 | 0x0380 | "Database not specified or available"| -2147482752|
|
||||
|TSDB_CODE_MND_DB_ALREADY_EXIST| 0 | 0x0381 | "Database already exists"| -2147482751|
|
||||
|TSDB_CODE_MND_INVALID_DB_OPTION| 0 | 0x0382 | "Invalid database options"| -2147482750|
|
||||
|TSDB_CODE_MND_INVALID_DB| |0 | 0x0383 | "Invalid database name"| -2147482749|
|
||||
|TSDB_CODE_MND_INVALID_DB| 0 | 0x0383 | "Invalid database name"| -2147482749|
|
||||
|TSDB_CODE_MND_MONITOR_DB_FORBIDDEN| 0 | 0x0384 | "Cannot delete monitor database"| -2147482748|
|
||||
|TSDB_CODE_MND_TOO_MANY_DATABASES| 0| 0x0385 | "Too many databases for account"| -2147482747|
|
||||
|TSDB_CODE_MND_DB_IN_DROPPING| 0 | 0x0386| "Database not available" |-2147482746|
|
||||
|
|
|
@ -130,9 +130,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 文件中使用到的参数。
|
||||
|
@ -233,6 +249,12 @@ ALTER USER <user_name> PASS <'password'>;
|
|||
|
||||
修改用户密码, 为避免被转换为小写,密码需要用单引号引用,单引号为英文半角
|
||||
|
||||
```
|
||||
ALTER USER <user_name> PRIVILEDGE <super|write|read>;
|
||||
```
|
||||
|
||||
修改用户权限为:super/write/read,不需要添加单引号
|
||||
|
||||
```
|
||||
SHOW USERS;
|
||||
```
|
||||
|
@ -386,5 +408,5 @@ 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)来标识。
|
||||
**物理节点(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
|
||||
|
@ -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)有异曲同工之妙。
|
||||
|
|
|
@ -1,48 +1,70 @@
|
|||
# TDengine 集群安装、管理
|
||||
|
||||
多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。而且在安装集群之前,请按照[《立即开始》](https://www.taosdata.com/cn/getting-started20/)一章安装并体验过单节点功能。
|
||||
多个TDengine服务器,也就是多个taosd的运行实例可以组成一个集群,以保证TDengine的高可靠运行,并提供水平扩展能力。要了解TDengine 2.0的集群管理,需要对集群的基本概念有所了解,请看TDengine 2.0整体架构一章。而且在安装集群之前,先请按照[《立即开始》](https://www.taosdata.com/cn/getting-started20/)一章安装并体验单节点功能。
|
||||
|
||||
集群的每个节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令`hostname -f`获取,FQDN配置参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html)。端口是这个节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。一个节点可能配置了多个hostname, TDengine会自动获取第一个,但也可以通过taos.cfg里配置参数fqdn进行指定。如果习惯IP地址直接访问,可以将参数fqdn设置为本节点的IP地址。
|
||||
集群的每个数据节点是由End Point来唯一标识的,End Point是由FQDN(Fully Qualified Domain Name)外加Port组成,比如 h1.taosdata.com:6030。一般FQDN就是服务器的hostname,可通过Linux命令`hostname -f`获取(如何配置FQDN,请参考:[一篇文章说清楚TDengine的FQDN](https://www.taosdata.com/blog/2020/09/11/1824.html))。端口是这个数据节点对外服务的端口号,缺省是6030,但可以通过taos.cfg里配置参数serverPort进行修改。一个物理节点可能配置了多个hostname, TDengine会自动获取第一个,但也可以通过taos.cfg里配置参数fqdn进行指定。如果习惯IP地址直接访问,可以将参数fqdn设置为本节点的IP地址。
|
||||
|
||||
TDengine的集群管理极其简单,除添加和删除节点需要人工干预之外,其他全部是自动完成,最大程度的降低了运维的工作量。本章对集群管理的操作做详细的描述。
|
||||
|
||||
## 准备工作
|
||||
|
||||
**第一步**:如果搭建集群的节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html )
|
||||
**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/)
|
||||
**注意2:**客户端也需要配置,并且把集群中所有服务器的FQDN配置到客户端中(windows中 C:\Windows\System32\drivers\etc\hosts)。
|
||||
**第零步**:规划集群所有物理节点的FQDN,将规划好的FQDN分别添加到每个物理节点的/etc/hostname;修改每个物理节点的/etc/hosts,将所有集群物理节点的IP与FQDN的对应添加好。【如部署了DNS,请联系网络管理员在DNS上做好相关配置】
|
||||
|
||||
**第二步**:建议关闭防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口;
|
||||
**第一步**:如果搭建集群的物理节点中,存有之前的测试数据、装过1.X的版本,或者装过其他版本的TDengine,请先将其删除,并清空所有数据,具体步骤请参考博客[《TDengine多种安装包的安装和卸载》](https://www.taosdata.com/blog/2019/08/09/566.html )
|
||||
**注意1:**因为FQDN的信息会写进文件,如果之前没有配置或者更改FQDN,且启动了TDengine。请一定在确保数据无用或者备份的前提下,清理一下之前的数据(rm -rf /var/lib/taos/);
|
||||
**注意2:**客户端也需要配置,确保它可以正确解析每个节点的FQDN配置,不管是通过DNS服务,还是 Host 文件。
|
||||
|
||||
**第三步**:在所有节点安装TDengine,且版本必须是一致的,**但不要启动taosd**;
|
||||
**第二步**:建议关闭所有物理节点的防火墙,至少保证端口:6030 - 6042的TCP和UDP端口都是开放的。**强烈建议**先关闭防火墙,集群搭建完毕之后,再来配置端口;
|
||||
|
||||
**第四步**:检查、配置所有节点的FQDN:
|
||||
**第三步**:在所有物理节点安装TDengine,且版本必须是一致的,**但不要启动taosd**。安装时,提示输入是否要加入一个已经存在的TDengine集群时,第一个物理节点直接回车创建新集群,后续物理节点则输入该集群任何一个在线的物理节点的FQDN:端口号(默认6030);
|
||||
|
||||
1. 每个节点上执行命令`hostname -f`,查看和确认所有节点的hostname是不相同的;
|
||||
2. 每个节点上执行`ping host`, 其中host是其他节点的hostname, 看能否ping通其它节点; 如果不能ping通,需要检查网络设置, 或/etc/hosts文件,或DNS的配置。如果无法ping通,是无法组成集群的。
|
||||
3. 每个节点的FQDN就是输出的hostname外加端口号,比如h1.taosdata.com:6030
|
||||
**第四步**:检查所有数据节点,以及应用程序所在物理节点的网络设置:
|
||||
|
||||
**第五步**:修改TDengine的配置文件(所有节点的文件/etc/taos/taos.cfg都需要修改)。假设准备启动的第一个节点End Point为 h1.taosdata.com:6030, 那么以下几个参数与集群相关:
|
||||
1. 每个物理节点上执行命令`hostname -f`,查看和确认所有节点的hostname是不相同的(应用驱动所在节点无需做此项检查);
|
||||
2. 每个物理节点上执行`ping host`, 其中host是其他物理节点的hostname, 看能否ping通其它物理节点; 如果不能ping通,需要检查网络设置, 或/etc/hosts文件(Windows系统默认路径为C:\Windows\system32\drivers\etc\hosts),或DNS的配置。如果无法ping通,是无法组成集群的;
|
||||
3. 从应用运行的物理节点,ping taosd运行的数据节点,如果无法ping通,应用是无法连接taosd的,请检查应用所在物理节点的DNS设置或hosts文件;
|
||||
4. 每个数据节点的End Point就是输出的hostname外加端口号,比如h1.taosdata.com:6030
|
||||
|
||||
**第五步**:修改TDengine的配置文件(所有节点的文件/etc/taos/taos.cfg都需要修改)。假设准备启动的第一个数据节点End Point为 h1.taosdata.com:6030, 其与集群配置相关参数如下:
|
||||
|
||||
```
|
||||
// firstEp 是每个节点启动后连接的第一个节点
|
||||
// firstEp 是每个数据节点首次启动后连接的第一个数据节点
|
||||
firstEp h1.taosdata.com:6030
|
||||
|
||||
// 配置本节点的FQDN,如果本机只有一个hostname, 无需配置
|
||||
// 必须配置为本数据节点的FQDN,如果本机只有一个hostname, 可注释掉本配置
|
||||
fqdn h1.taosdata.com
|
||||
|
||||
// 配置本节点的端口号,缺省是6030
|
||||
// 配置本数据节点的端口号,缺省是6030
|
||||
serverPort 6030
|
||||
|
||||
// 副本数为偶数的时候,需要配置,请参考《Arbitrator的使用》的部分
|
||||
// 服务端节点数为偶数的时候,需要配置,请参考《Arbitrator的使用》的部分
|
||||
arbitrator ha.taosdata.com:6042
|
||||
```
|
||||
|
||||
一定要修改的参数是firstEp, 其他参数可不做任何修改,除非你很清楚为什么要修改。
|
||||
一定要修改的参数是firstEp和fqdn。在每个数据节点,firstEp需全部配置成一样,**但fqdn一定要配置成其所在数据节点的值**。其他参数可不做任何修改,除非你很清楚为什么要修改。
|
||||
|
||||
## 启动第一个节点
|
||||
**加入到集群中的数据节点dnode,涉及集群相关的下表11项参数必须完全相同,否则不能成功加入到集群中。**
|
||||
|
||||
| **#** | **配置参数名称** | **含义** |
|
||||
| ----- | ------------------ | ---------------------------------------- |
|
||||
| 1 | numOfMnodes | 系统中管理节点个数 |
|
||||
| 2 | mnodeEqualVnodeNum | 一个mnode等同于vnode消耗的个数 |
|
||||
| 3 | offlineThreshold | dnode离线阈值,超过该时间将导致Dnode离线 |
|
||||
| 4 | statusInterval | dnode向mnode报告状态时长 |
|
||||
| 5 | arbitrator | 系统中裁决器的end point |
|
||||
| 6 | timezone | 时区 |
|
||||
| 7 | locale | 系统区位信息及编码格式 |
|
||||
| 8 | charset | 字符集编码 |
|
||||
| 9 | balance | 是否启动负载均衡 |
|
||||
| 10 | maxTablesPerVnode | 每个vnode中能够创建的最大表个数 |
|
||||
| 11 | maxVgroupsPerDb | 每个DB中 能够使用的最大vnode个数 |
|
||||
|
||||
|
||||
|
||||
## 启动第一个数据节点
|
||||
|
||||
按照[《立即开始》](https://www.taosdata.com/cn/getting-started20/)里的指示,启动第一个数据节点,例如h1.taosdata.com,然后执行taos, 启动taos shell,从shell里执行命令"show dnodes;",如下所示:
|
||||
|
||||
按照[《立即开始》](https://www.taosdata.com/cn/getting-started20/)里的指示,启动第一个节点h1.taosdata.com,然后执行taos, 启动taos shell,从shell里执行命令"show dnodes;",如下所示:
|
||||
```
|
||||
Welcome to the TDengine shell from Linux, Client Version:2.0.0.0
|
||||
Copyright (c) 2017 by TAOS Data, Inc. All rights reserved.
|
||||
|
@ -55,74 +77,88 @@ Query OK, 1 row(s) in set (0.006385s)
|
|||
|
||||
taos>
|
||||
```
|
||||
上述命令里,可以看到这个刚启动的这个节点的End Point是:h1.taos.com:6030
|
||||
|
||||
## 启动后续节点
|
||||
上述命令里,可以看到这个刚启动的这个数据节点的End Point是:h1.taos.com:6030,就是这个新集群的firstEP。
|
||||
|
||||
将后续的节点添加到现有集群,具体有以下几步:
|
||||
## 启动后续数据节点
|
||||
|
||||
1. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法在每个节点启动taosd。
|
||||
将后续的数据节点添加到现有集群,具体有以下几步:
|
||||
|
||||
2. 在第一个节点,使用CLI程序taos, 登录进TDengine系统, 执行命令:
|
||||
1. 按照["立即开始“](https://www.taosdata.com/cn/getting-started/)一章的方法在每个物理节点启动taosd;
|
||||
|
||||
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。
|
||||
将新数据节点的End Point (准备工作中第四步获知的) 添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。请注意将示例的“h2.taos.com:6030" 替换为这个新数据节点的End Point。
|
||||
|
||||
3. 然后执行命令
|
||||
|
||||
```
|
||||
SHOW DNODES;
|
||||
SHOW DNODES;
|
||||
```
|
||||
|
||||
查看新节点是否被成功加入。如果该被加入的节点处于离线状态,请做两个检查
|
||||
查看新节点是否被成功加入。如果该被加入的数据节点处于离线状态,请做两个检查
|
||||
|
||||
- 查看该节点的taosd是否正常工作,如果没有正常运行,需要先检查为什么
|
||||
- 查看该节点taosd日志文件taosdlog.0里前面几行日志(一般在/var/log/taos目录),看日志里输出的该节点fqdn以及端口号是否为刚添加的End Point。如果不一致,需要将正确的End Point添加进去。
|
||||
- 查看该数据节点的taosd是否正常工作,如果没有正常运行,需要先检查为什么
|
||||
- 查看该数据节点taosd日志文件taosdlog.0里前面几行日志(一般在/var/log/taos目录),看日志里输出的该数据节点fqdn以及端口号是否为刚添加的End Point。如果不一致,需要将正确的End Point添加进去。
|
||||
|
||||
按照上述步骤可以源源不断的将新的节点加入到集群。
|
||||
按照上述步骤可以源源不断的将新的数据节点加入到集群。
|
||||
|
||||
**提示:**
|
||||
|
||||
- firstEp这个参数仅仅在该节点第一次加入集群时有作用,加入集群后,该节点会保存最新的mnode的End Point列表,不再依赖这两个参数。
|
||||
- 两个没有配置firstEp参数的dnode启动后,会独立运行起来。这个时候,无法将其中一个节点加入到另外一个节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
|
||||
- 任何已经加入集群在线的数据节点,都可以作为后续待加入节点的firstEP。
|
||||
- firstEp这个参数仅仅在该数据节点首次加入集群时有作用,加入集群后,该数据节点会保存最新的mnode的End Point列表,不再依赖这个参数。
|
||||
- 两个没有配置firstEp参数的数据节点dnode启动后,会独立运行起来。这个时候,无法将其中一个数据节点加入到另外一个数据节点,形成集群。**无法将两个独立的集群合并成为新的集群**。
|
||||
|
||||
## 节点管理
|
||||
## 数据节点管理
|
||||
|
||||
上面已经介绍如何从零开始搭建集群。集群组建完后,还可以随时添加新的数据节点进行扩容,或删除数据节点,并检查集群当前状态。
|
||||
|
||||
### 添加数据节点
|
||||
|
||||
### 添加节点
|
||||
执行CLI程序taos, 使用root账号登录进系统, 执行:
|
||||
```
|
||||
CREATE DNODE "fqdn:port";
|
||||
```
|
||||
将新节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。
|
||||
|
||||
### 删除节点
|
||||
```
|
||||
CREATE DNODE "fqdn:port";
|
||||
```
|
||||
|
||||
将新数据节点的End Point添加进集群的EP列表。**"fqdn:port"需要用双引号引起来**,否则出错。一个数据节点对外服务的fqdn和port可以通过配置文件taos.cfg进行配置,缺省是自动获取。【强烈不建议用自动获取方式来配置FQDN,可能导致生成的数据节点的End Point不是所期望的】
|
||||
|
||||
### 删除数据节点
|
||||
|
||||
执行CLI程序taos, 使用root账号登录进TDengine系统,执行:
|
||||
|
||||
```
|
||||
DROP DNODE "fqdn:port";
|
||||
```
|
||||
|
||||
其中fqdn是被删除的节点的FQDN,port是其对外服务器的端口号
|
||||
|
||||
### 查看节点
|
||||
### 查看数据节点
|
||||
|
||||
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
|
||||
|
||||
```
|
||||
SHOW DNODES;
|
||||
```
|
||||
它将列出集群中所有的dnode,每个dnode的fqdn:port, 状态(ready, offline等),vnode数目,还未使用的vnode数目等信息。在添加或删除一个节点后,可以使用该命令查看。
|
||||
|
||||
它将列出集群中所有的dnode,每个dnode的fqdn:port, 状态(ready, offline等),vnode数目,还未使用的vnode数目等信息。在添加或删除一个数据节点后,可以使用该命令查看。
|
||||
|
||||
### 查看虚拟节点组
|
||||
|
||||
为充分利用多核技术,并提供scalability,数据需要分片处理。因此TDengine会将一个DB的数据切分成多份,存放在多个vnode里。这些vnode可能分布在多个dnode里,这样就实现了水平扩展。一个vnode仅仅属于一个DB,但一个DB可以有多个vnode。vnode的是mnode根据当前系统资源的情况,自动进行分配的,无需任何人工干预。
|
||||
为充分利用多核技术,并提供scalability,数据需要分片处理。因此TDengine会将一个DB的数据切分成多份,存放在多个vnode里。这些vnode可能分布在多个数据节点dnode里,这样就实现了水平扩展。一个vnode仅仅属于一个DB,但一个DB可以有多个vnode。vnode的是mnode根据当前系统资源的情况,自动进行分配的,无需任何人工干预。
|
||||
|
||||
执行CLI程序taos,使用root账号登录进TDengine系统,执行:
|
||||
|
||||
```
|
||||
SHOW VGROUPS;
|
||||
```
|
||||
|
||||
## vnode的高可用性
|
||||
|
||||
TDengine通过多副本的机制来提供系统的高可用性,包括vnode和mnode的高可用性。
|
||||
|
||||
vnode的副本数是与DB关联的,一个集群里可以有多个DB,根据运营的需求,每个DB可以配置不同的副本数。创建数据库时,通过参数replica 指定副本数(缺省为1)。如果副本数为1,系统的可靠性无法保证,只要数据所在的节点宕机,就将无法提供服务。集群的节点数必须大于等于副本数,否则创建表时将返回错误“more dnodes are needed"。比如下面的命令将创建副本数为3的数据库demo:
|
||||
|
@ -130,21 +166,25 @@ vnode的副本数是与DB关联的,一个集群里可以有多个DB,根据
|
|||
```
|
||||
CREATE DATABASE demo replica 3;
|
||||
```
|
||||
一个DB里的数据会被切片分到多个vnode group,vnode group里的vnode数目就是DB的副本数,同一个vnode group里各vnode的数据是完全一致的。为保证高可用性,vnode group里的vnode一定要分布在不同的dnode里(实际部署时,需要在不同的物理机上),只要一个vgroup里超过半数的vnode处于工作状态,这个vgroup就能正常的对外服务。
|
||||
|
||||
一个dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的读写操作。
|
||||
一个DB里的数据会被切片分到多个vnode group,vnode group里的vnode数目就是DB的副本数,同一个vnode group里各vnode的数据是完全一致的。为保证高可用性,vnode group里的vnode一定要分布在不同的数据节点dnode里(实际部署时,需要在不同的物理机上),只要一个vgroup里超过半数的vnode处于工作状态,这个vgroup就能正常的对外服务。
|
||||
|
||||
因为vnode的引入,无法简单的给出结论:“集群中过半dnode工作,集群就应该工作”。但是对于简单的情形,很好下结论。比如副本数为3,只有三个dnode,那如果仅有一个节点不工作,整个集群还是可以正常工作的,但如果有两个节点不工作,那整个集群就无法正常工作了。
|
||||
一个数据节点dnode里可能有多个DB的数据,因此一个dnode离线时,可能会影响到多个DB。如果一个vnode group里的一半或一半以上的vnode不工作,那么该vnode group就无法对外服务,无法插入或读取数据,这样会影响到它所属的DB的一部分表的读写操作。
|
||||
|
||||
因为vnode的引入,无法简单的给出结论:“集群中过半数据节点dnode工作,集群就应该工作”。但是对于简单的情形,很好下结论。比如副本数为3,只有三个dnode,那如果仅有一个节点不工作,整个集群还是可以正常工作的,但如果有两个数据节点不工作,那整个集群就无法正常工作了。
|
||||
|
||||
## Mnode的高可用性
|
||||
TDengine集群是由mnode (taosd的一个模块,逻辑节点) 负责管理的,为保证mnode的高可用,可以配置多个mnode副本,副本数由系统配置参数numOfMnodes决定,有效范围为1-3。为保证元数据的强一致性,mnode副本之间是通过同步的方式进行数据复制的。
|
||||
|
||||
一个集群有多个dnode, 但一个dnode至多运行一个mnode实例。多个dnode情况下,哪个dnode可以作为mnode呢?这是完全由系统根据整个系统资源情况,自动指定的。用户可通过CLI程序taos,在TDengine的console里,执行如下命令:
|
||||
TDengine集群是由mnode (taosd的一个模块,管理节点) 负责管理的,为保证mnode的高可用,可以配置多个mnode副本,副本数由系统配置参数numOfMnodes决定,有效范围为1-3。为保证元数据的强一致性,mnode副本之间是通过同步的方式进行数据复制的。
|
||||
|
||||
一个集群有多个数据节点dnode, 但一个dnode至多运行一个mnode实例。多个dnode情况下,哪个dnode可以作为mnode呢?这是完全由系统根据整个系统资源情况,自动指定的。用户可通过CLI程序taos,在TDengine的console里,执行如下命令:
|
||||
|
||||
```
|
||||
SHOW MNODES;
|
||||
```
|
||||
|
||||
来查看mnode列表,该列表将列出mnode所处的dnode的End Point和角色(master, slave, unsynced 或offline)。
|
||||
当集群中第一个节点启动时,该节点一定会运行一个mnode实例,否则该dnode无法正常工作,因为一个系统是必须有至少一个mnode的。如果numOfMnodes配置为2,启动第二个dnode时,该dnode也将运行一个mnode实例。
|
||||
当集群中第一个数据节点启动时,该数据节点一定会运行一个mnode实例,否则该数据节点dnode无法正常工作,因为一个系统是必须有至少一个mnode的。如果numOfMnodes配置为2,启动第二个dnode时,该dnode也将运行一个mnode实例。
|
||||
|
||||
为保证mnode服务的高可用性,numOfMnodes必须设置为2或更大。因为mnode保存的元数据必须是强一致的,如果numOfMnodes大于2,复制参数quorum自动设为2,也就是说,至少要保证有两个副本写入数据成功,才通知客户端应用写入成功。
|
||||
|
||||
|
@ -154,22 +194,25 @@ SHOW MNODES;
|
|||
|
||||
有三种情况,将触发负载均衡,而且都无需人工干预。
|
||||
|
||||
- 当一个新节点添加进集群时,系统将自动触发负载均衡,一些节点上的数据将被自动转移到新节点上,无需任何人工干预。
|
||||
- 当一个节点从集群中移除时,系统将自动把该节点上的数据转移到其他节点,无需任何人工干预。
|
||||
- 如果一个节点过热(数据量过大),系统将自动进行负载均衡,将该节点的一些vnode自动挪到其他节点。
|
||||
- 当一个新数据节点添加进集群时,系统将自动触发负载均衡,一些节点上的数据将被自动转移到新数据节点上,无需任何人工干预。
|
||||
- 当一个数据节点从集群中移除时,系统将自动把该数据节点上的数据转移到其他数据节点,无需任何人工干预。
|
||||
- 如果一个数据节点过热(数据量过大),系统将自动进行负载均衡,将该数据节点的一些vnode自动挪到其他节点。
|
||||
|
||||
当上述三种情况发生时,系统将启动一各个节点的负载计算,从而决定如何挪动。
|
||||
当上述三种情况发生时,系统将启动一各个数据节点的负载计算,从而决定如何挪动。
|
||||
|
||||
##节点离线处理
|
||||
如果一个节点离线,TDengine集群将自动检测到。有如下两种情况:
|
||||
- 改节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
|
||||
**【提示】负载均衡由参数balance控制,它决定是否启动自动负载均衡。**
|
||||
|
||||
## 数据节点离线处理
|
||||
|
||||
如果一个数据节点离线,TDengine集群将自动检测到。有如下两种情况:
|
||||
|
||||
- 该数据节点离线超过一定时间(taos.cfg里配置参数offlineThreshold控制时长),系统将自动把该数据节点删除,产生系统报警信息,触发负载均衡流程。如果该被删除的数据节点重现上线时,它将无法加入集群,需要系统管理员重新将其添加进集群才会开始工作。
|
||||
- 离线后,在offlineThreshold的时长内重新上线,系统将自动启动数据恢复流程,等数据完全恢复后,该节点将开始正常工作。
|
||||
|
||||
**注意:**如果一个虚拟节点组(包括mnode组)里每个节点都处于离线或unsynced状态,必须等该虚拟节点组里的所有节点都上线、都能交换状态信息后,才能选出Master,该虚拟节点组才能对外提供服务。比如整个集群有3个节点,副本数为3,如果3个节点都宕机,然后2个节点重启,是无法工作的,只有等3个节点都重启成功,才能对外服务。
|
||||
**注意:**如果一个虚拟节点组(包括mnode组)里所归属的每个数据节点都处于离线或unsynced状态,必须等该虚拟节点组里的所有数据节点都上线、都能交换状态信息后,才能选出Master,该虚拟节点组才能对外提供服务。比如整个集群有3个数据节点,副本数为3,如果3个数据节点都宕机,然后2个数据节点重启,是无法工作的,只有等3个数据节点都重启成功,才能对外服务。
|
||||
|
||||
## 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就能正常工作。
|
||||
|
||||
TDengine安装包里带有一个执行程序tarbitrator, 找任何一台Linux服务器运行它即可。该程序对系统资源几乎没有要求,只需要保证有网络连接即可。该应用的命令行参数`-p`可以指定其对外服务的端口号,缺省是6042。配置每个taosd实例时,可以在配置文件taos.cfg里将参数arbitrator设置为arbitrator的End Point。如果该参数配置了,当副本数为偶数数,系统将自动连接配置的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
|
||||
|
|
|
@ -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,9 +22,10 @@ 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天的数据。
|
||||
|
||||
## Prometheus直接写入
|
||||
[Prometheus](https://www.prometheus.io/)作为Cloud Native Computing Fundation毕业的项目,在性能监控以及K8S性能监控领域有着非常广泛的应用。TDengine提供一个小工具[Bailongma](https://github.com/taosdata/Bailongma),只需在Prometheus做简单配置,无需任何代码,就可将Prometheus采集的数据直接写入TDengine,并按规则在TDengine自动创建库和相关表项。博文[用Docker容器快速搭建一个Devops监控Demo](https://www.taosdata.com/blog/2020/02/03/1189.html)即是采用bailongma将Prometheus和Telegraf的数据写入TDengine中的示例,可以参考。
|
||||
|
|
|
@ -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等。
|
||||
- 数据节点的管理,包括
|
||||
|
|
|
@ -57,6 +57,7 @@ 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 -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}/
|
||||
|
|
|
@ -64,6 +64,7 @@ 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 -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
@ -113,6 +115,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
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}/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.
|
||||
|
@ -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
|
||||
|
@ -126,6 +128,7 @@ if [[ "$pagMode" != "lite" ]] && [[ "$cpuType" != "aarch32" ]]; then
|
|||
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}/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.
|
||||
|
@ -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
|
||||
|
|
|
@ -389,6 +389,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,6 +552,7 @@ 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;
|
||||
pDnode->offlineReason = TAOS_DN_OFF_STATUS_MSG_TIMEOUT;
|
||||
mInfo("dnode:%d, set to offline state", pDnode->dnodeId);
|
||||
balanceSetVgroupOffline(pDnode);
|
||||
}
|
||||
|
|
|
@ -69,17 +69,13 @@ typedef struct SJoinSupporter {
|
|||
SSubqueryState* pState;
|
||||
SSqlObj* pObj; // parent SqlObj
|
||||
int32_t subqueryIndex; // index of sub query
|
||||
char intervalTimeUnit;
|
||||
char slidingTimeUnit;
|
||||
int64_t intervalTime; // interval time
|
||||
int64_t slidingTime; // sliding time
|
||||
SInterval interval;
|
||||
SLimitVal limit; // limit info
|
||||
uint64_t uid; // query meter uid
|
||||
uint64_t uid; // query table uid
|
||||
SArray* colList; // previous query information, no need to use this attribute, and the corresponding attribution
|
||||
SArray* exprList;
|
||||
SFieldInfo fieldsInfo;
|
||||
STagCond tagCond;
|
||||
SSqlGroupbyExpr groupbyExpr;
|
||||
struct STSBuf* pTSBuf; // the TSBuf struct that holds the compressed timestamp array
|
||||
FILE* f; // temporary file in order to create TSBuf
|
||||
char path[PATH_MAX]; // temporary file path, todo dynamic allocate memory
|
||||
|
@ -195,6 +191,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);
|
||||
|
@ -261,6 +258,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);
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ extern "C" {
|
|||
#include "tglobal.h"
|
||||
#include "tsqlfunction.h"
|
||||
#include "tutil.h"
|
||||
#include "tcache.h"
|
||||
|
||||
#include "qExecutor.h"
|
||||
#include "qSqlparser.h"
|
||||
|
@ -98,6 +99,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;
|
||||
|
@ -225,13 +227,8 @@ 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
|
||||
char intervalTimeUnit;
|
||||
char slidingTimeUnit;
|
||||
STimeWindow window; // query time window
|
||||
int64_t intervalTime; // aggregation time window range
|
||||
int64_t slidingTime; // sliding window in mseconds
|
||||
int64_t intervalOffset;// start offset of each time window
|
||||
int32_t tz; // query client timezone
|
||||
SInterval interval;
|
||||
|
||||
SSqlGroupbyExpr groupbyExpr; // group by tags info
|
||||
SArray * colList; // SArray<SColumn*>
|
||||
|
@ -279,6 +276,7 @@ typedef struct {
|
|||
|
||||
int8_t dataSourceType; // load data from file or not
|
||||
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;
|
||||
|
@ -333,6 +331,7 @@ typedef struct STscObj {
|
|||
struct SSqlStream *streamList;
|
||||
void* pDnodeConn;
|
||||
pthread_mutex_t mutex;
|
||||
T_REF_DECLARE()
|
||||
} STscObj;
|
||||
|
||||
typedef struct SSqlObj {
|
||||
|
@ -359,6 +358,8 @@ typedef struct SSqlObj {
|
|||
uint16_t numOfSubs;
|
||||
struct SSqlObj **pSubs;
|
||||
struct SSqlObj * prev, *next;
|
||||
|
||||
struct SSqlObj **self;
|
||||
} SSqlObj;
|
||||
|
||||
typedef struct SSqlStream {
|
||||
|
@ -366,8 +367,6 @@ typedef struct SSqlStream {
|
|||
uint32_t streamId;
|
||||
char listed;
|
||||
bool isProject;
|
||||
char intervalTimeUnit;
|
||||
char slidingTimeUnit;
|
||||
int16_t precision;
|
||||
int64_t num; // number of computing count
|
||||
|
||||
|
@ -381,8 +380,7 @@ typedef struct SSqlStream {
|
|||
int64_t ctime; // stream created time
|
||||
int64_t stime; // stream next executed time
|
||||
int64_t etime; // stream end query time, when time is larger then etime, the stream will be closed
|
||||
int64_t intervalTime;
|
||||
int64_t slidingTime;
|
||||
SInterval interval;
|
||||
void * pTimer;
|
||||
|
||||
void (*fp)();
|
||||
|
@ -413,7 +411,6 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo *pQueryInfo);
|
|||
void tscRestoreSQLFuncForSTableQuery(SQueryInfo *pQueryInfo);
|
||||
|
||||
int32_t tscCreateResPointerInfo(SSqlRes *pRes, SQueryInfo *pQueryInfo);
|
||||
void tscDestroyResPointerInfo(SSqlRes *pRes);
|
||||
|
||||
void tscResetSqlCmdObj(SSqlCmd *pCmd, bool removeFromCache);
|
||||
|
||||
|
@ -425,17 +422,19 @@ void tscFreeSqlResult(SSqlObj *pSql);
|
|||
|
||||
/**
|
||||
* only free part of resources allocated during query.
|
||||
* TODO remove it later
|
||||
* Note: this function is multi-thread safe.
|
||||
* @param pObj
|
||||
*/
|
||||
void tscPartiallyFreeSqlObj(SSqlObj *pObj);
|
||||
void tscPartiallyFreeSqlObj(SSqlObj *pSql);
|
||||
|
||||
/**
|
||||
* free sql object, release allocated resource
|
||||
* @param pObj Free metric/meta information, dynamically allocated payload, and
|
||||
* response buffer, object itself
|
||||
* @param pObj
|
||||
*/
|
||||
void tscFreeSqlObj(SSqlObj *pObj);
|
||||
void tscFreeSqlObj(SSqlObj *pSql);
|
||||
|
||||
void tscFreeSqlObjInCache(void *pSql);
|
||||
|
||||
void tscCloseTscObj(STscObj *pObj);
|
||||
|
||||
|
@ -451,9 +450,6 @@ void tscInitResObjForLocalQuery(SSqlObj *pObj, int32_t numOfRes, int32_t rowLen)
|
|||
bool tscIsUpdateQuery(SSqlObj* pSql);
|
||||
bool tscHasReachLimitation(SQueryInfo *pQueryInfo, SSqlRes *pRes);
|
||||
|
||||
// todo remove this function.
|
||||
bool tscResultsetFetchCompleted(TAOS_RES *result);
|
||||
|
||||
char *tscGetErrorMsgPayload(SSqlCmd *pCmd);
|
||||
|
||||
int32_t tscInvalidSQLErrMsg(char *msg, const char *additionalInfo, const char *sql);
|
||||
|
@ -468,7 +464,7 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField
|
|||
int32_t type = pInfo->pSqlExpr->resType;
|
||||
int32_t bytes = pInfo->pSqlExpr->resBytes;
|
||||
|
||||
char* pData = pRes->data + pInfo->pSqlExpr->offset * pRes->numOfRows + bytes * pRes->row;
|
||||
char* pData = pRes->data + (int32_t)(pInfo->pSqlExpr->offset * pRes->numOfRows + bytes * pRes->row);
|
||||
|
||||
// user defined constant value output columns
|
||||
if (TSDB_COL_IS_UD_COL(pInfo->pSqlExpr->colInfo.flag)) {
|
||||
|
@ -502,7 +498,8 @@ static FORCE_INLINE void tscGetResultColumnChr(SSqlRes* pRes, SFieldInfo* pField
|
|||
}
|
||||
}
|
||||
|
||||
extern void * tscCacheHandle;
|
||||
extern SCacheObj* tscMetaCache;
|
||||
extern SCacheObj* tscObjCache;
|
||||
extern void * tscTmr;
|
||||
extern void * tscQhandle;
|
||||
extern int tscKeepConn[];
|
||||
|
|
|
@ -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]));
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
#include "tnote.h"
|
||||
#include "trpc.h"
|
||||
#include "tcache.h"
|
||||
#include "tscLog.h"
|
||||
#include "tscSubquery.h"
|
||||
#include "tscLocalMerge.h"
|
||||
|
@ -40,6 +41,8 @@ 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) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
|
||||
pSql->signature = pSql;
|
||||
pSql->param = param;
|
||||
pSql->pTscObj = pObj;
|
||||
|
@ -48,6 +51,8 @@ void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const
|
|||
pSql->fp = fp;
|
||||
pSql->fetchFp = fp;
|
||||
|
||||
registerSqlObj(pSql);
|
||||
|
||||
pSql->sqlstr = calloc(1, sqlLen + 1);
|
||||
if (pSql->sqlstr == NULL) {
|
||||
tscError("%p failed to malloc sql string buffer", pSql);
|
||||
|
@ -59,7 +64,7 @@ void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const
|
|||
strntolower(pSql->sqlstr, sqlstr, (int32_t)sqlLen);
|
||||
|
||||
tscDebugL("%p SQL: %s", pSql, pSql->sqlstr);
|
||||
pSql->cmd.curSql = pSql->sqlstr;
|
||||
pCmd->curSql = pSql->sqlstr;
|
||||
|
||||
int32_t code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) return;
|
||||
|
@ -504,7 +509,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) {
|
||||
|
|
|
@ -117,6 +117,10 @@ typedef struct SFirstLastInfo {
|
|||
typedef struct SFirstLastInfo SLastrowInfo;
|
||||
typedef struct SPercentileInfo {
|
||||
tMemBucket *pMemBucket;
|
||||
int32_t stage;
|
||||
double minval;
|
||||
double maxval;
|
||||
int64_t numOfElems;
|
||||
} SPercentileInfo;
|
||||
|
||||
typedef struct STopBotInfo {
|
||||
|
@ -302,7 +306,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
|
|||
} else if (functionId == TSDB_FUNC_PERCT) {
|
||||
*type = (int16_t)TSDB_DATA_TYPE_DOUBLE;
|
||||
*bytes = (int16_t)sizeof(double);
|
||||
*interBytes = (int16_t)sizeof(double);
|
||||
*interBytes = (int16_t)sizeof(SPercentileInfo);
|
||||
} else if (functionId == TSDB_FUNC_LEASTSQR) {
|
||||
*type = TSDB_DATA_TYPE_BINARY;
|
||||
*bytes = TSDB_AVG_FUNCTION_INTER_BUFFER_SIZE; // string
|
||||
|
@ -322,7 +326,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI
|
|||
} else if (functionId == TSDB_FUNC_LAST_ROW) {
|
||||
*type = (int16_t)dataType;
|
||||
*bytes = (int16_t)dataBytes;
|
||||
*interBytes = dataBytes + sizeof(SLastrowInfo);
|
||||
*interBytes = dataBytes;
|
||||
} else {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -521,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);
|
||||
|
@ -708,12 +712,15 @@ static int32_t firstDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY en
|
|||
return BLK_DATA_ALL_NEEDED;
|
||||
}
|
||||
|
||||
SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
|
||||
if (pInfo->hasResult != DATA_SET_FLAG) {
|
||||
return BLK_DATA_ALL_NEEDED;
|
||||
} else { // data in current block is not earlier than current result
|
||||
return (pInfo->ts <= start) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
|
||||
}
|
||||
// TODO pCtx->aOutputBuf is the previous windowRes output buffer, not current unloaded block. so the following filter
|
||||
// is invalid
|
||||
// SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
|
||||
// if (pInfo->hasResult != DATA_SET_FLAG) {
|
||||
// return BLK_DATA_ALL_NEEDED;
|
||||
// } else { // data in current block is not earlier than current result
|
||||
// return (pInfo->ts <= start) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
|
||||
// }
|
||||
}
|
||||
|
||||
static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end, int32_t colId) {
|
||||
|
@ -726,12 +733,16 @@ static int32_t lastDistFuncRequired(SQLFunctionCtx *pCtx, TSKEY start, TSKEY end
|
|||
return BLK_DATA_ALL_NEEDED;
|
||||
}
|
||||
|
||||
SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
|
||||
if (pInfo->hasResult != DATA_SET_FLAG) {
|
||||
return BLK_DATA_ALL_NEEDED;
|
||||
} else {
|
||||
return (pInfo->ts > end) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
|
||||
}
|
||||
// TODO pCtx->aOutputBuf is the previous windowRes output buffer, not current unloaded block. so the following filter
|
||||
// is invalid
|
||||
|
||||
// SFirstLastInfo *pInfo = (SFirstLastInfo*) (pCtx->aOutputBuf + pCtx->inputBytes);
|
||||
// if (pInfo->hasResult != DATA_SET_FLAG) {
|
||||
// return BLK_DATA_ALL_NEEDED;
|
||||
// } else {
|
||||
// return (pInfo->ts > end) ? BLK_DATA_NO_NEEDED : BLK_DATA_ALL_NEEDED;
|
||||
// }
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -757,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);
|
||||
|
@ -1832,6 +1843,8 @@ static void last_row_function(SQLFunctionCtx *pCtx) {
|
|||
pInfo1->hasResult = DATA_SET_FLAG;
|
||||
|
||||
DO_UPDATE_TAG_COLUMNS(pCtx, pInfo1->ts);
|
||||
} else {
|
||||
DO_UPDATE_TAG_COLUMNS(pCtx, pCtx->ptsList[pCtx->size - 1]);
|
||||
}
|
||||
|
||||
SET_VAL(pCtx, pCtx->size, 1);
|
||||
|
@ -2429,10 +2442,12 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) {
|
|||
return false;
|
||||
}
|
||||
|
||||
// in the first round, get the min-max value of all involved data
|
||||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
|
||||
((SPercentileInfo *)(pResInfo->interResultBuf))->pMemBucket =
|
||||
tMemBucketCreate(pCtx->inputBytes, pCtx->inputType);
|
||||
SPercentileInfo *pInfo = pResInfo->interResultBuf;
|
||||
pInfo->minval = DBL_MAX;
|
||||
pInfo->maxval = -DBL_MAX;
|
||||
pInfo->numOfElems = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2443,6 +2458,64 @@ static void percentile_function(SQLFunctionCtx *pCtx) {
|
|||
SResultInfo * pResInfo = GET_RES_INFO(pCtx);
|
||||
SPercentileInfo *pInfo = pResInfo->interResultBuf;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (pInfo->maxval < pCtx->preAggVals.statis.max) {
|
||||
pInfo->maxval = (double)pCtx->preAggVals.statis.max;
|
||||
}
|
||||
|
||||
pInfo->numOfElems += (pCtx->size - pCtx->preAggVals.statis.numOfNull);
|
||||
} else {
|
||||
for (int32_t i = 0; i < pCtx->size; ++i) {
|
||||
char *data = GET_INPUT_CHAR_INDEX(pCtx, i);
|
||||
if (pCtx->hasNull && isNull(data, pCtx->inputType)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO extract functions
|
||||
double v = 0;
|
||||
switch (pCtx->inputType) {
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
v = GET_INT8_VAL(data);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
v = GET_INT16_VAL(data);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
v = (double)(GET_INT64_VAL(data));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
v = GET_FLOAT_VAL(data);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
v = GET_DOUBLE_VAL(data);
|
||||
break;
|
||||
default:
|
||||
v = GET_INT32_VAL(data);
|
||||
break;
|
||||
}
|
||||
|
||||
if (v < pInfo->minval) {
|
||||
pInfo->minval = v;
|
||||
}
|
||||
|
||||
if (v > pInfo->maxval) {
|
||||
pInfo->maxval = v;
|
||||
}
|
||||
|
||||
pInfo->numOfElems += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// the second stage, calculate the true percentile value
|
||||
for (int32_t i = 0; i < pCtx->size; ++i) {
|
||||
char *data = GET_INPUT_CHAR_INDEX(pCtx, i);
|
||||
if (pCtx->hasNull && isNull(data, pCtx->inputType)) {
|
||||
|
@ -2466,6 +2539,43 @@ static void percentile_function_f(SQLFunctionCtx *pCtx, int32_t index) {
|
|||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
|
||||
SPercentileInfo *pInfo = (SPercentileInfo *)pResInfo->interResultBuf;
|
||||
|
||||
if (pInfo->stage == 0) {
|
||||
// TODO extract functions
|
||||
double v = 0;
|
||||
switch (pCtx->inputType) {
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
v = GET_INT8_VAL(pData);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
v = GET_INT16_VAL(pData);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
v = (double)(GET_INT64_VAL(pData));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_FLOAT:
|
||||
v = GET_FLOAT_VAL(pData);
|
||||
break;
|
||||
case TSDB_DATA_TYPE_DOUBLE:
|
||||
v = GET_DOUBLE_VAL(pData);
|
||||
break;
|
||||
default:
|
||||
v = GET_INT32_VAL(pData);
|
||||
break;
|
||||
}
|
||||
|
||||
if (v < pInfo->minval) {
|
||||
pInfo->minval = v;
|
||||
}
|
||||
|
||||
if (v > pInfo->maxval) {
|
||||
pInfo->maxval = v;
|
||||
}
|
||||
|
||||
pInfo->numOfElems += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
tMemBucketPut(pInfo->pMemBucket, pData, 1);
|
||||
|
||||
SET_VAL(pCtx, 1, 1);
|
||||
|
@ -2488,6 +2598,23 @@ static void percentile_finalizer(SQLFunctionCtx *pCtx) {
|
|||
doFinalizer(pCtx);
|
||||
}
|
||||
|
||||
static void percentile_next_step(SQLFunctionCtx *pCtx) {
|
||||
SResultInfo * pResInfo = GET_RES_INFO(pCtx);
|
||||
SPercentileInfo *pInfo = pResInfo->interResultBuf;
|
||||
|
||||
if (pInfo->stage == 0) {
|
||||
// all data are null, set it completed
|
||||
if (pInfo->numOfElems == 0) {
|
||||
pResInfo->complete = true;
|
||||
}
|
||||
|
||||
pInfo->stage += 1;
|
||||
pInfo->pMemBucket = tMemBucketCreate(pCtx->inputBytes, pCtx->inputType, pInfo->minval, pInfo->maxval);
|
||||
} else {
|
||||
pResInfo->complete = true;
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////
|
||||
static SAPercentileInfo *getAPerctInfo(SQLFunctionCtx *pCtx) {
|
||||
SResultInfo *pResInfo = GET_RES_INFO(pCtx);
|
||||
|
@ -3389,12 +3516,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4513,7 +4640,7 @@ SQLAggFuncElem aAggs[] = {{
|
|||
percentile_function_setup,
|
||||
percentile_function,
|
||||
percentile_function_f,
|
||||
no_next_step,
|
||||
percentile_next_step,
|
||||
percentile_finalizer,
|
||||
noop1,
|
||||
noop1,
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include "os.h"
|
||||
#include "taosmsg.h"
|
||||
|
||||
#include "qExtbuffer.h"
|
||||
#include "taosdef.h"
|
||||
#include "tcache.h"
|
||||
#include "tname.h"
|
||||
|
@ -24,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) {
|
||||
|
@ -273,7 +295,504 @@ 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 = 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));
|
||||
}
|
||||
|
||||
SFieldSupInfo* 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);
|
||||
|
||||
|
@ -337,6 +856,7 @@ static int32_t tscProcessServerVer(SSqlObj *pSql) {
|
|||
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);
|
||||
|
@ -344,6 +864,7 @@ static int32_t tscProcessServerVer(SSqlObj *pSql) {
|
|||
|
||||
free(vx);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static int32_t tscProcessClientVer(SSqlObj *pSql) {
|
||||
|
@ -358,6 +879,7 @@ static int32_t tscProcessClientVer(SSqlObj *pSql) {
|
|||
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);
|
||||
|
@ -365,6 +887,7 @@ static int32_t tscProcessClientVer(SSqlObj *pSql) {
|
|||
|
||||
free(v);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
}
|
||||
|
||||
static int32_t tscProcessServStatus(SSqlObj *pSql) {
|
||||
|
@ -429,8 +952,12 @@ 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(tscCacheHandle);
|
||||
taosCacheEmpty(tscMetaCache);
|
||||
pRes->code = TSDB_CODE_SUCCESS;
|
||||
} else if (pCmd->command == TSDB_SQL_SERV_VERSION) {
|
||||
pRes->code = tscProcessServerVer(pSql);
|
||||
|
@ -448,12 +975,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;
|
||||
}
|
||||
|
|
|
@ -368,13 +368,12 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd
|
|||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
TSKEY stime = (pQueryInfo->order.order == TSDB_ORDER_ASC)? pQueryInfo->window.skey : pQueryInfo->window.ekey;
|
||||
int64_t revisedSTime =
|
||||
taosGetIntervalStartTimestamp(stime, pQueryInfo->slidingTime, pQueryInfo->intervalTime, pQueryInfo->slidingTimeUnit, tinfo.precision);
|
||||
int64_t revisedSTime = taosTimeTruncate(stime, &pQueryInfo->interval, tinfo.precision);
|
||||
|
||||
if (pQueryInfo->fillType != TSDB_FILL_NONE) {
|
||||
SFillColInfo* pFillCol = createFillColInfo(pQueryInfo);
|
||||
pReducer->pFillInfo = taosInitFillInfo(pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols,
|
||||
4096, (int32_t)numOfCols, pQueryInfo->slidingTime, pQueryInfo->slidingTimeUnit,
|
||||
4096, (int32_t)numOfCols, pQueryInfo->interval.sliding, pQueryInfo->interval.slidingUnit,
|
||||
tinfo.precision, pQueryInfo->fillType, pFillCol);
|
||||
}
|
||||
}
|
||||
|
@ -472,10 +471,8 @@ void tscDestroyLocalReducer(SSqlObj *pSql) {
|
|||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p start to free local reducer", pSql);
|
||||
SSqlRes *pRes = &(pSql->res);
|
||||
if (pRes->pLocalReducer == NULL) {
|
||||
tscDebug("%p local reducer has been freed, abort", pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -553,7 +550,7 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
|
|||
}
|
||||
|
||||
// primary timestamp column is involved in final result
|
||||
if (pQueryInfo->intervalTime != 0 || tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||
if (pQueryInfo->interval.interval != 0 || tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||
numOfGroupByCols++;
|
||||
}
|
||||
|
||||
|
@ -570,7 +567,7 @@ static int32_t createOrderDescriptor(tOrderDescriptor **pOrderDesc, SSqlCmd *pCm
|
|||
orderIdx[i] = startCols++;
|
||||
}
|
||||
|
||||
if (pQueryInfo->intervalTime != 0) {
|
||||
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;
|
||||
}
|
||||
|
@ -614,12 +611,12 @@ bool isSameGroup(SSqlCmd *pCmd, SLocalReducer *pReducer, char *pPrev, tFilePage
|
|||
* super table interval query
|
||||
* if the order columns is the primary timestamp, all result data belongs to one group
|
||||
*/
|
||||
assert(pQueryInfo->intervalTime > 0);
|
||||
assert(pQueryInfo->interval.interval > 0);
|
||||
if (numOfCols == 1) {
|
||||
return true;
|
||||
}
|
||||
} else { // simple group by query
|
||||
assert(pQueryInfo->intervalTime == 0);
|
||||
assert(pQueryInfo->interval.interval == 0);
|
||||
}
|
||||
|
||||
// only one row exists
|
||||
|
@ -827,8 +824,7 @@ void savePrevRecordAndSetupFillInfo(SLocalReducer *pLocalReducer, SQueryInfo *pQ
|
|||
|
||||
if (pFillInfo != NULL) {
|
||||
int64_t stime = (pQueryInfo->window.skey < pQueryInfo->window.ekey) ? pQueryInfo->window.skey : pQueryInfo->window.ekey;
|
||||
int64_t revisedSTime =
|
||||
taosGetIntervalStartTimestamp(stime, pQueryInfo->slidingTime, pQueryInfo->intervalTime, pQueryInfo->slidingTimeUnit, tinfo.precision);
|
||||
int64_t revisedSTime = taosTimeTruncate(stime, &pQueryInfo->interval, tinfo.precision);
|
||||
|
||||
taosResetFillInfo(pFillInfo, revisedSTime);
|
||||
}
|
||||
|
@ -841,7 +837,7 @@ void savePrevRecordAndSetupFillInfo(SLocalReducer *pLocalReducer, SQueryInfo *pQ
|
|||
}
|
||||
|
||||
static void genFinalResWithoutFill(SSqlRes* pRes, SLocalReducer *pLocalReducer, SQueryInfo* pQueryInfo) {
|
||||
assert(pQueryInfo->intervalTime == 0 || pQueryInfo->fillType == TSDB_FILL_NONE);
|
||||
assert(pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE);
|
||||
|
||||
tFilePage * pBeforeFillData = pLocalReducer->pResultBuf;
|
||||
|
||||
|
@ -1222,7 +1218,7 @@ bool genFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool noMoreCur
|
|||
#endif
|
||||
|
||||
// no interval query, no fill operation
|
||||
if (pQueryInfo->intervalTime == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) {
|
||||
if (pQueryInfo->interval.interval == 0 || pQueryInfo->fillType == TSDB_FILL_NONE) {
|
||||
genFinalResWithoutFill(pRes, pLocalReducer, pQueryInfo);
|
||||
} else {
|
||||
SFillInfo* pFillInfo = pLocalReducer->pFillInfo;
|
||||
|
@ -1260,13 +1256,10 @@ static void resetEnvForNewResultset(SSqlRes *pRes, SSqlCmd *pCmd, SLocalReducer
|
|||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(pCmd, pCmd->clauseIndex, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
int8_t precision = tinfo.precision;
|
||||
|
||||
// for group result interpolation, do not return if not data is generated
|
||||
if (pQueryInfo->fillType != TSDB_FILL_NONE) {
|
||||
TSKEY skey = (pQueryInfo->order.order == TSDB_ORDER_ASC)? pQueryInfo->window.skey:pQueryInfo->window.ekey;//MIN(pQueryInfo->window.skey, pQueryInfo->window.ekey);
|
||||
int64_t newTime =
|
||||
taosGetIntervalStartTimestamp(skey, pQueryInfo->slidingTime, pQueryInfo->intervalTime, pQueryInfo->slidingTimeUnit, precision);
|
||||
int64_t newTime = taosTimeTruncate(skey, &pQueryInfo->interval, tinfo.precision);
|
||||
taosResetFillInfo(pLocalReducer->pFillInfo, newTime);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,7 +142,7 @@ int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int1
|
|||
return tscInvalidSQLErrMsg(error, "value expected in timestamp", sToken.z);
|
||||
}
|
||||
|
||||
if (getTimestampInUsFromStr(valueToken.z, valueToken.n, &interval) != TSDB_CODE_SUCCESS) {
|
||||
if (parseAbsoluteDuration(valueToken.z, valueToken.n, &interval) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -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,11 +526,11 @@ 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;
|
||||
|
||||
int16_t numOfRows = 0;
|
||||
int32_t numOfRows = 0;
|
||||
|
||||
SSchema *pSchema = tscGetTableSchema(pTableMeta);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMeta);
|
||||
|
@ -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) {
|
||||
|
@ -514,7 +509,6 @@ 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;
|
||||
|
@ -546,6 +540,8 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
|||
pSql->cmd.numOfParams = 0;
|
||||
pSql->cmd.batchSize = 0;
|
||||
|
||||
registerSqlObj(pSql);
|
||||
|
||||
int32_t code = tsParseSql(pSql, true);
|
||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
// wait for the callback function to post the semaphore
|
||||
|
@ -574,7 +570,7 @@ int taos_stmt_close(TAOS_STMT* stmt) {
|
|||
free(normal->sql);
|
||||
}
|
||||
|
||||
tscFreeSqlObj(pStmt->pSql);
|
||||
taos_free_result(pStmt->pSql);
|
||||
free(pStmt);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -259,11 +259,11 @@ int tscBuildQueryStreamDesc(void *pMsg, STscObj *pObj) {
|
|||
pSdesc->num = htobe64(pStream->num);
|
||||
|
||||
pSdesc->useconds = htobe64(pStream->useconds);
|
||||
pSdesc->stime = htobe64(pStream->stime - pStream->intervalTime);
|
||||
pSdesc->stime = htobe64(pStream->stime - pStream->interval.interval);
|
||||
pSdesc->ctime = htobe64(pStream->ctime);
|
||||
|
||||
pSdesc->slidingTime = htobe64(pStream->slidingTime);
|
||||
pSdesc->interval = htobe64(pStream->intervalTime);
|
||||
pSdesc->slidingTime = htobe64(pStream->interval.sliding);
|
||||
pSdesc->interval = htobe64(pStream->interval.interval);
|
||||
|
||||
pHeartbeat->numOfStreams++;
|
||||
pSdesc++;
|
||||
|
|
|
@ -81,6 +81,7 @@ static void setColumnOffsetValueInResultset(SQueryInfo* pQueryInfo);
|
|||
static int32_t parseGroupbyClause(SQueryInfo* pQueryInfo, tVariantList* pList, SSqlCmd* pCmd);
|
||||
|
||||
static int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
|
||||
static int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
|
||||
static int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql);
|
||||
|
||||
static int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExprItem* pItem);
|
||||
|
@ -92,7 +93,6 @@ static int32_t parseOrderbyClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQueryS
|
|||
static int32_t tsRewriteFieldNameIfNecessary(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
|
||||
static int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo);
|
||||
static int32_t validateSqlFunctionInStreamSql(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
|
||||
static int32_t arithmeticExprToString(tSQLExpr* pExpr, char** exprString);
|
||||
static int32_t validateFunctionsInIntervalOrGroupbyQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo);
|
||||
static int32_t validateArithmeticSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type);
|
||||
static int32_t validateEp(char* ep);
|
||||
|
@ -103,6 +103,7 @@ static int32_t setKillInfo(SSqlObj* pSql, struct SSqlInfo* pInfo, int32_t killTy
|
|||
|
||||
static bool validateOneTags(SSqlCmd* pCmd, TAOS_FIELD* pTagField);
|
||||
static bool hasTimestampForPointInterpQuery(SQueryInfo* pQueryInfo);
|
||||
static bool hasNormalColumnFilter(SQueryInfo* pQueryInfo);
|
||||
|
||||
static int32_t parseLimitClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t index, SQuerySQL* pQuerySql, SSqlObj* pSql);
|
||||
static int32_t parseCreateDBOptions(SSqlCmd* pCmd, SCreateDBInfo* pCreateDbSql);
|
||||
|
@ -348,6 +349,27 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
}
|
||||
|
||||
case TSDB_SQL_DESCRIBE_TABLE: {
|
||||
SStrToken* pToken = &pInfo->pDCLInfo->a[0];
|
||||
const char* msg1 = "invalid table name";
|
||||
const char* msg2 = "table name too long";
|
||||
|
||||
if (tscValidateName(pToken) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (!tscValidateTableNameLength(pToken->n)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
// additional msg has been attached already
|
||||
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";
|
||||
|
@ -360,13 +382,26 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
if (tscSetTableFullName(pTableMetaInfo, pToken, pSql) != TSDB_CODE_SUCCESS) {
|
||||
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";
|
||||
|
@ -408,7 +443,6 @@ int32_t tscToSQLCmd(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
|||
const char* msg3 = "name too long";
|
||||
|
||||
pCmd->command = pInfo->type;
|
||||
// tDCLSQL* pDCL = pInfo->pDCLInfo;
|
||||
|
||||
SUserInfo* pUser = &pInfo->pDCLInfo->user;
|
||||
SStrToken* pName = &pUser->user;
|
||||
|
@ -594,24 +628,28 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
|
|||
|
||||
// interval is not null
|
||||
SStrToken* t = &pQuerySql->interval;
|
||||
if (parseDuration(t->z, t->n, &pQueryInfo->intervalTime, &pQueryInfo->intervalTimeUnit) != TSDB_CODE_SUCCESS) {
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.interval, &pQueryInfo->interval.intervalUnit) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (pQueryInfo->intervalTimeUnit != 'n' && pQueryInfo->intervalTimeUnit != 'y') {
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
// if the unit of time window value is millisecond, change the value from microsecond
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->intervalTime = pQueryInfo->intervalTime / 1000;
|
||||
pQueryInfo->interval.interval = pQueryInfo->interval.interval / 1000;
|
||||
}
|
||||
|
||||
// interval cannot be less than 10 milliseconds
|
||||
if (pQueryInfo->intervalTime < tsMinIntervalTime) {
|
||||
if (pQueryInfo->interval.interval < tsMinIntervalTime) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
}
|
||||
|
||||
// for top/bottom + interval query, we do not add additional timestamp column in the front
|
||||
if (isTopBottomQuery(pQueryInfo)) {
|
||||
if (parseOffsetClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (parseSlidingClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -635,7 +673,7 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
|
|||
* check invalid SQL:
|
||||
* select tbname, tags_fields from super_table_name interval(1s)
|
||||
*/
|
||||
if (tscQueryTags(pQueryInfo) && pQueryInfo->intervalTime > 0) {
|
||||
if (tscQueryTags(pQueryInfo) && pQueryInfo->interval.interval > 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
|
@ -661,6 +699,10 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
|
|||
SColumnIndex index = {tableIndex, PRIMARYKEY_TIMESTAMP_COL_INDEX};
|
||||
tscAddSpecialColumnForSelect(pQueryInfo, 0, TSDB_FUNC_TS, &index, &s, TSDB_COL_NORMAL);
|
||||
|
||||
if (parseOffsetClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (parseSlidingClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -668,6 +710,57 @@ int32_t parseIntervalClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQ
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t parseOffsetClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
|
||||
const char* msg1 = "interval offset cannot be negative";
|
||||
const char* msg2 = "interval offset should be shorter than interval";
|
||||
const char* msg3 = "cannot use 'year' as offset when interval is 'month'";
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
SStrToken* t = &pQuerySql->offset;
|
||||
if (t->n == 0) {
|
||||
pQueryInfo->interval.offsetUnit = pQueryInfo->interval.intervalUnit;
|
||||
pQueryInfo->interval.offset = 0;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (parseNatualDuration(t->z, t->n, &pQueryInfo->interval.offset, &pQueryInfo->interval.offsetUnit) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
if (pQueryInfo->interval.offset < 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if (pQueryInfo->interval.offsetUnit != 'n' && pQueryInfo->interval.offsetUnit != 'y') {
|
||||
// if the unit of time window value is millisecond, change the value from microsecond
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->interval.offset = pQueryInfo->interval.offset / 1000;
|
||||
}
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
if (pQueryInfo->interval.offset >= pQueryInfo->interval.interval) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
}
|
||||
} else if (pQueryInfo->interval.offsetUnit == pQueryInfo->interval.intervalUnit) {
|
||||
if (pQueryInfo->interval.offset >= pQueryInfo->interval.interval) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
} else if (pQueryInfo->interval.intervalUnit == 'n' && pQueryInfo->interval.offsetUnit == 'y') {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
} else if (pQueryInfo->interval.intervalUnit == 'y' && pQueryInfo->interval.offsetUnit == 'n') {
|
||||
if (pQueryInfo->interval.interval * 12 <= pQueryInfo->interval.offset) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
} else {
|
||||
// TODO: offset should be shorter than interval, but how to check
|
||||
// conflicts like 30days offset and 1 month interval
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuerySql) {
|
||||
const char* msg0 = "sliding value too small";
|
||||
const char* msg1 = "sliding value no larger than the interval value";
|
||||
|
@ -681,29 +774,29 @@ int32_t parseSlidingClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQu
|
|||
|
||||
SStrToken* pSliding = &pQuerySql->sliding;
|
||||
if (pSliding->n == 0) {
|
||||
pQueryInfo->slidingTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
pQueryInfo->slidingTime = pQueryInfo->intervalTime;
|
||||
pQueryInfo->interval.slidingUnit = pQueryInfo->interval.intervalUnit;
|
||||
pQueryInfo->interval.sliding = pQueryInfo->interval.interval;
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (pQueryInfo->intervalTimeUnit == 'n' || pQueryInfo->intervalTimeUnit == 'y') {
|
||||
if (pQueryInfo->interval.intervalUnit == 'n' || pQueryInfo->interval.intervalUnit == 'y') {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
getTimestampInUsFromStr(pSliding->z, pSliding->n, &pQueryInfo->slidingTime);
|
||||
parseAbsoluteDuration(pSliding->z, pSliding->n, &pQueryInfo->interval.sliding);
|
||||
if (tinfo.precision == TSDB_TIME_PRECISION_MILLI) {
|
||||
pQueryInfo->slidingTime /= 1000;
|
||||
pQueryInfo->interval.sliding /= 1000;
|
||||
}
|
||||
|
||||
if (pQueryInfo->slidingTime < tsMinSlidingTime) {
|
||||
if (pQueryInfo->interval.sliding < tsMinSlidingTime) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
|
||||
}
|
||||
|
||||
if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) {
|
||||
if (pQueryInfo->interval.sliding > pQueryInfo->interval.interval) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
if ((pQueryInfo->intervalTime != 0) && (pQueryInfo->intervalTime/pQueryInfo->slidingTime > INTERVAL_SLIDING_FACTOR)) {
|
||||
if ((pQueryInfo->interval.interval != 0) && (pQueryInfo->interval.interval/pQueryInfo->interval.sliding > INTERVAL_SLIDING_FACTOR)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
|
@ -712,49 +805,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 = "invalid db name";
|
||||
const char *msg = msg1;
|
||||
|
||||
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);
|
||||
} else { // get current DB name first, then set it into path
|
||||
if (code != 0) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
} else { // get current DB name first, and then set it into path
|
||||
SStrToken t = {0};
|
||||
getCurrentDBName(pSql, &t);
|
||||
if (t.n == 0) {
|
||||
msg = msg2;
|
||||
}
|
||||
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) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
free(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) {
|
||||
if (strlen(oldName) > 0 && strncasecmp(oldName, pTableMetaInfo->name, tListLen(pTableMetaInfo->name)) != 0) {
|
||||
tscClearTableMetaInfo(pTableMetaInfo, false);
|
||||
}
|
||||
} else {
|
||||
assert(pTableMetaInfo->pTableMeta == NULL);
|
||||
}
|
||||
|
||||
taosTFree(oldName);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
|
@ -1181,13 +1269,14 @@ static int32_t handleArithmeticExpr(SSqlCmd* pCmd, int32_t clauseIndex, int32_t
|
|||
} END_TRY
|
||||
|
||||
len = tbufTell(&bw);
|
||||
char* c = tbufGetData(&bw, true);
|
||||
char* c = tbufGetData(&bw, false);
|
||||
|
||||
// set the serialized binary string as the parameter of arithmetic expression
|
||||
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);
|
||||
|
||||
tbufCloseWriter(&bw);
|
||||
taosArrayDestroy(colList);
|
||||
tExprTreeDestroy(&pNode, NULL);
|
||||
} else {
|
||||
|
@ -1331,7 +1420,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel
|
|||
|
||||
/*
|
||||
* transfer sql functions that need secondary merge into another format
|
||||
* in dealing with metric queries such as: count/first/last
|
||||
* in dealing with super table queries such as: count/first/last
|
||||
*/
|
||||
if (isSTable) {
|
||||
tscTansformSQLFuncForSTableQuery(pQueryInfo);
|
||||
|
@ -1516,16 +1605,16 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t
|
|||
|
||||
static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSchema* pSchema, SConvertFunc cvtFunc, char* aliasName,
|
||||
int32_t resColIdx, SColumnIndex* pColIndex) {
|
||||
const char* msg1 = "not support column types";
|
||||
|
||||
int16_t type = 0;
|
||||
int16_t bytes = 0;
|
||||
char columnName[TSDB_COL_NAME_LEN] = {0};
|
||||
const char* msg1 = "not support column types";
|
||||
int32_t functionID = cvtFunc.execFuncId;
|
||||
|
||||
if (functionID == TSDB_FUNC_SPREAD) {
|
||||
if (pSchema[pColIndex->columnIndex].type == TSDB_DATA_TYPE_BINARY ||
|
||||
pSchema[pColIndex->columnIndex].type == TSDB_DATA_TYPE_NCHAR ||
|
||||
pSchema[pColIndex->columnIndex].type == TSDB_DATA_TYPE_BOOL) {
|
||||
int32_t t1 = pSchema[pColIndex->columnIndex].type;
|
||||
if (t1 == TSDB_DATA_TYPE_BINARY || t1 == TSDB_DATA_TYPE_NCHAR || t1 == TSDB_DATA_TYPE_BOOL) {
|
||||
invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
return -1;
|
||||
} else {
|
||||
|
@ -1543,7 +1632,6 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS
|
|||
getRevisedName(columnName, cvtFunc.originFuncId, sizeof(columnName) - 1, pSchema[pColIndex->columnIndex].name);
|
||||
}
|
||||
|
||||
|
||||
SSqlExpr* pExpr = tscSqlExprAppend(pQueryInfo, functionID, pColIndex, type, bytes, bytes, false);
|
||||
tstrncpy(pExpr->aliasName, columnName, sizeof(pExpr->aliasName));
|
||||
|
||||
|
@ -1600,7 +1688,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);
|
||||
|
@ -1800,10 +1888,13 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
|||
if (changeFunctionID(optr, &functionID) != TSDB_CODE_SUCCESS) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg9);
|
||||
}
|
||||
|
||||
// NOTE: has time range condition or normal column filter condition, the last_row query will be transferred to last query
|
||||
SConvertFunc cvtFunc = {.originFuncId = functionID, .execFuncId = functionID};
|
||||
if (functionID == TSDB_FUNC_LAST_ROW && TSWINDOW_IS_EQUAL(pQueryInfo->window,TSWINDOW_INITIALIZER)) {
|
||||
if (functionID == TSDB_FUNC_LAST_ROW && ((!TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER)) || (hasNormalColumnFilter(pQueryInfo)))) {
|
||||
cvtFunc.execFuncId = TSDB_FUNC_LAST;
|
||||
}
|
||||
|
||||
if (!requireAllFields) {
|
||||
if (pItem->pNode->pParam->nExpr < 1) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
|
@ -2591,7 +2682,7 @@ static bool functionCompatibleCheck(SQueryInfo* pQueryInfo, bool joinQuery) {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (functionId == TSDB_FUNC_PRJ && pExpr1->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||
if (functionId == TSDB_FUNC_PRJ && (pExpr1->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX || TSDB_COL_IS_UD_COL(pExpr1->colInfo.flag))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2803,6 +2894,12 @@ static int32_t doExtractColumnFilterInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo,
|
|||
case TK_LIKE:
|
||||
pColumnFilter->lowerRelOptr = TSDB_RELATION_LIKE;
|
||||
break;
|
||||
case TK_ISNULL:
|
||||
pColumnFilter->lowerRelOptr = TSDB_RELATION_ISNULL;
|
||||
break;
|
||||
case TK_NOTNULL:
|
||||
pColumnFilter->lowerRelOptr = TSDB_RELATION_NOTNULL;
|
||||
break;
|
||||
default:
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg);
|
||||
}
|
||||
|
@ -2848,19 +2945,19 @@ static int32_t tSQLExprNodeToString(tSQLExpr* pExpr, char** str) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
// pExpr->nSQLOptr == 0 while handling "is null" query
|
||||
static bool isExprLeafNode(tSQLExpr* pExpr) {
|
||||
return (pExpr->pRight == NULL && pExpr->pLeft == NULL) &&
|
||||
(pExpr->nSQLOptr == TK_ID || (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_NCHAR) ||
|
||||
pExpr->nSQLOptr == TK_SET);
|
||||
(pExpr->nSQLOptr == 0 || pExpr->nSQLOptr == TK_ID || (pExpr->nSQLOptr >= TK_BOOL && pExpr->nSQLOptr <= TK_NCHAR) || pExpr->nSQLOptr == TK_SET);
|
||||
}
|
||||
|
||||
static bool isExprDirectParentOfLeaftNode(tSQLExpr* pExpr) {
|
||||
static bool isExprDirectParentOfLeafNode(tSQLExpr* pExpr) {
|
||||
return (pExpr->pLeft != NULL && pExpr->pRight != NULL) &&
|
||||
(isExprLeafNode(pExpr->pLeft) && isExprLeafNode(pExpr->pRight));
|
||||
}
|
||||
|
||||
static int32_t tSQLExprLeafToString(tSQLExpr* pExpr, bool addParentheses, char** output) {
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) {
|
||||
if (!isExprDirectParentOfLeafNode(pExpr)) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -3071,7 +3168,7 @@ static int32_t getTagCondString(tSQLExpr* pExpr, char** str) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) {
|
||||
if (!isExprDirectParentOfLeafNode(pExpr)) {
|
||||
*(*str) = '(';
|
||||
*str += 1;
|
||||
|
||||
|
@ -3127,7 +3224,7 @@ static int32_t getColumnQueryCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQ
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) { // internal node
|
||||
if (!isExprDirectParentOfLeafNode(pExpr)) { // internal node
|
||||
int32_t ret = getColumnQueryCondInfo(pCmd, pQueryInfo, pExpr->pLeft, pExpr->nSQLOptr);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
|
@ -3153,7 +3250,7 @@ static int32_t getJoinCondInfo(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr*
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) {
|
||||
if (!isExprDirectParentOfLeafNode(pExpr)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
||||
|
@ -3225,19 +3322,6 @@ int32_t doArithmeticExprToString(tSQLExpr* pExpr, char** exprString) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static UNUSED_FUNC int32_t arithmeticExprToString(tSQLExpr* pExpr, char** str) {
|
||||
char* start = *str;
|
||||
|
||||
int32_t code = doArithmeticExprToString(pExpr, str);
|
||||
if (code == TSDB_CODE_SUCCESS) { // remove out the parenthesis
|
||||
int32_t len = (int32_t)strlen(start);
|
||||
memmove(start, start + 1, len - 2);
|
||||
start[len - 2] = 0;
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQueryInfo, SColumnList* pList, int32_t* type) {
|
||||
if (pExpr->nSQLOptr == TK_ID) {
|
||||
if (*type == NON_ARITHMEIC_EXPR) {
|
||||
|
@ -3485,7 +3569,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
|
|||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
assert(isExprDirectParentOfLeaftNode(*pExpr));
|
||||
assert(isExprDirectParentOfLeafNode(*pExpr));
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, index.tableIndex);
|
||||
STableMeta* pTableMeta = pTableMetaInfo->pTableMeta;
|
||||
|
@ -3531,7 +3615,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
|
|||
}
|
||||
}
|
||||
|
||||
// in case of in operator, keep it in a seperate attribute
|
||||
// in case of in operator, keep it in a seprate attribute
|
||||
if (index.columnIndex == TSDB_TBNAME_COLUMN_INDEX) {
|
||||
if (!validTableNameOptr(*pExpr)) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||
|
@ -3552,7 +3636,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQL
|
|||
*type = TSQL_EXPR_TBNAME;
|
||||
*pExpr = NULL;
|
||||
} else {
|
||||
if (pRight->nSQLOptr == TK_ID) { // join on tag columns for stable query
|
||||
if (pRight != NULL && pRight->nSQLOptr == TK_ID) { // join on tag columns for stable query
|
||||
if (!validateJoinExprNode(pCmd, pQueryInfo, *pExpr, &index)) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -3605,7 +3689,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr
|
|||
int32_t leftType = -1;
|
||||
int32_t rightType = -1;
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(*pExpr)) {
|
||||
if (!isExprDirectParentOfLeafNode(*pExpr)) {
|
||||
int32_t ret = getQueryCondExpr(pCmd, pQueryInfo, &(*pExpr)->pLeft, pCondExpr, &leftType, (*pExpr)->nSQLOptr);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
return ret;
|
||||
|
@ -3636,7 +3720,7 @@ int32_t getQueryCondExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLExpr** pExpr
|
|||
}
|
||||
|
||||
static void doCompactQueryExpr(tSQLExpr** pExpr) {
|
||||
if (*pExpr == NULL || isExprDirectParentOfLeaftNode(*pExpr)) {
|
||||
if (*pExpr == NULL || isExprDirectParentOfLeafNode(*pExpr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3667,7 +3751,7 @@ static void doCompactQueryExpr(tSQLExpr** pExpr) {
|
|||
}
|
||||
|
||||
static void doExtractExprForSTable(SSqlCmd* pCmd, tSQLExpr** pExpr, SQueryInfo* pQueryInfo, tSQLExpr** pOut, int32_t tableIndex) {
|
||||
if (isExprDirectParentOfLeaftNode(*pExpr)) {
|
||||
if (isExprDirectParentOfLeafNode(*pExpr)) {
|
||||
tSQLExpr* pLeft = (*pExpr)->pLeft;
|
||||
|
||||
SColumnIndex index = COLUMN_INDEX_INITIALIZER;
|
||||
|
@ -3826,7 +3910,7 @@ static int32_t getTimeRangeFromExpr(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSQLE
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (!isExprDirectParentOfLeaftNode(pExpr)) {
|
||||
if (!isExprDirectParentOfLeafNode(pExpr)) {
|
||||
if (pExpr->nSQLOptr == TK_OR) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
|
@ -3996,7 +4080,6 @@ int32_t parseWhereClause(SQueryInfo* pQueryInfo, tSQLExpr** pExpr, SSqlObj* pSql
|
|||
const char* msg2 = "invalid filter expression";
|
||||
|
||||
int32_t ret = TSDB_CODE_SUCCESS;
|
||||
pQueryInfo->window = TSWINDOW_INITIALIZER;
|
||||
|
||||
// tags query condition may be larger than 512bytes, therefore, we need to prepare enough large space
|
||||
SStringBuilder sb; memset(&sb, 0, sizeof(sb));
|
||||
|
@ -4472,6 +4555,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);
|
||||
|
@ -4482,13 +4567,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;
|
||||
|
@ -4714,9 +4800,9 @@ int32_t validateSqlFunctionInStreamSql(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
|
|||
const char* msg0 = "sample interval can not be less than 10ms.";
|
||||
const char* msg1 = "functions not allowed in select clause";
|
||||
|
||||
if (pQueryInfo->intervalTime != 0 && pQueryInfo->intervalTime < 10 &&
|
||||
pQueryInfo->intervalTimeUnit != 'n' &&
|
||||
pQueryInfo->intervalTimeUnit != 'y') {
|
||||
if (pQueryInfo->interval.interval != 0 && pQueryInfo->interval.interval < 10 &&
|
||||
pQueryInfo->interval.intervalUnit != 'n' &&
|
||||
pQueryInfo->interval.intervalUnit != 'y') {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg0);
|
||||
}
|
||||
|
||||
|
@ -4812,6 +4898,7 @@ int32_t validateDNodeConfig(tDCLSQL* pOptions) {
|
|||
{"cDebugFlag", 10}, {"httpDebugFlag", 13}, {"qDebugflag", 10}, {"sdbDebugFlag", 12},
|
||||
{"uDebugFlag", 10}, {"tsdbDebugFlag", 13}, {"sDebugflag", 10}, {"rpcDebugFlag", 12},
|
||||
{"dDebugFlag", 10}, {"mqttDebugFlag", 13}, {"wDebugFlag", 10}, {"tmrDebugFlag", 12},
|
||||
{"cqDebugFlag", 11},
|
||||
};
|
||||
|
||||
SStrToken* pOptionToken = &pOptions->a[1];
|
||||
|
@ -5225,9 +5312,12 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) {
|
|||
|
||||
static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
|
||||
int32_t tagLength = 0;
|
||||
|
||||
size_t size = taosArrayGetSize(pQueryInfo->exprList);
|
||||
|
||||
//todo is 0??
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
bool isSTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo);
|
||||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr->functionId == TSDB_FUNC_TAGPRJ || pExpr->functionId == TSDB_FUNC_TAG) {
|
||||
|
@ -5239,25 +5329,26 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
SSchema* pSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
|
||||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr->functionId != TSDB_FUNC_TAG_DUMMY && pExpr->functionId != TSDB_FUNC_TS_DUMMY) {
|
||||
if ((pExpr->functionId != TSDB_FUNC_TAG_DUMMY && pExpr->functionId != TSDB_FUNC_TS_DUMMY) &&
|
||||
!(pExpr->functionId == TSDB_FUNC_PRJ && TSDB_COL_IS_UD_COL(pExpr->colInfo.flag))) {
|
||||
SSchema* pColSchema = &pSchema[pExpr->colInfo.colIndex];
|
||||
getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->functionId, (int32_t)pExpr->param[0].i64Key, &pExpr->resType,
|
||||
&pExpr->resBytes, &pExpr->interBytes, tagLength, true);
|
||||
&pExpr->resBytes, &pExpr->interBytes, tagLength, isSTable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void doUpdateSqlFunctionForColPrj(SQueryInfo* pQueryInfo) {
|
||||
static int32_t doUpdateSqlFunctionForColPrj(SQueryInfo* pQueryInfo) {
|
||||
size_t size = taosArrayGetSize(pQueryInfo->exprList);
|
||||
|
||||
for (int32_t i = 0; i < size; ++i) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
if (pExpr->functionId == TSDB_FUNC_PRJ) {
|
||||
|
||||
if (pExpr->functionId == TSDB_FUNC_PRJ && (!TSDB_COL_IS_UD_COL(pExpr->colInfo.flag) && (pExpr->colInfo.colId != PRIMARYKEY_TIMESTAMP_COL_INDEX))) {
|
||||
bool qualifiedCol = false;
|
||||
for (int32_t j = 0; j < pQueryInfo->groupbyExpr.numOfGroupCols; ++j) {
|
||||
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, j);
|
||||
|
@ -5270,11 +5361,16 @@ static void doUpdateSqlFunctionForColPrj(SQueryInfo* pQueryInfo) {
|
|||
}
|
||||
}
|
||||
|
||||
assert(qualifiedCol);
|
||||
// it is not a tag column/tbname column/user-defined column, return error
|
||||
if (!qualifiedCol) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
static bool tagColumnInGroupby(SSqlGroupbyExpr* pGroupbyExpr, int16_t columnId) {
|
||||
for (int32_t j = 0; j < pGroupbyExpr->numOfGroupCols; ++j) {
|
||||
SColIndex* pColIndex = taosArrayGet(pGroupbyExpr->columnInfo, j);
|
||||
|
@ -5346,7 +5442,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, SSqlCmd* pCmd)
|
|||
const char* msg1 = "only one selectivity function allowed in presence of tags function";
|
||||
const char* msg3 = "aggregation function should not be mixed up with projection";
|
||||
|
||||
bool tagColExists = false;
|
||||
bool tagTsColExists = false;
|
||||
int16_t numOfSelectivity = 0;
|
||||
int16_t numOfAggregation = 0;
|
||||
|
||||
|
@ -5355,7 +5451,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, SSqlCmd* pCmd)
|
|||
SSqlExpr* pExpr = taosArrayGetP(pQueryInfo->exprList, i);
|
||||
if (pExpr->functionId == TSDB_FUNC_TAGPRJ ||
|
||||
(pExpr->functionId == TSDB_FUNC_PRJ && pExpr->colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX)) {
|
||||
tagColExists = true;
|
||||
tagTsColExists = true; // selectivity + ts/tag column
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5376,7 +5472,7 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, SSqlCmd* pCmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (tagColExists) { // check if the selectivity function exists
|
||||
if (tagTsColExists) { // check if the selectivity function exists
|
||||
// When the tag projection function on tag column that is not in the group by clause, aggregation function and
|
||||
// selectivity function exist in select clause is not allowed.
|
||||
if (numOfAggregation > 0) {
|
||||
|
@ -5388,26 +5484,36 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, SSqlCmd* pCmd)
|
|||
*/
|
||||
if (numOfSelectivity == 1) {
|
||||
doUpdateSqlFunctionForTagPrj(pQueryInfo);
|
||||
doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
int32_t code = doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
|
||||
} else if (numOfSelectivity > 1) {
|
||||
/*
|
||||
* If more than one selectivity functions exist, all the selectivity functions must be last_row.
|
||||
* Otherwise, return with error code.
|
||||
*/
|
||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||
|
||||
int16_t functionId = tscSqlExprGet(pQueryInfo, i)->functionId;
|
||||
if (functionId == TSDB_FUNC_TAGPRJ) {
|
||||
SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i);
|
||||
int16_t functionId = pExpr->functionId;
|
||||
if (functionId == TSDB_FUNC_TAGPRJ || (aAggs[functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (((aAggs[functionId].nStatus & TSDB_FUNCSTATE_SELECTIVITY) != 0) && (functionId != TSDB_FUNC_LAST_ROW)) {
|
||||
if ((functionId == TSDB_FUNC_LAST_ROW) ||
|
||||
(functionId == TSDB_FUNC_LAST_DST && (pExpr->colInfo.flag & TSDB_COL_NULL) != 0)) {
|
||||
// do nothing
|
||||
} else {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
||||
}
|
||||
}
|
||||
|
||||
doUpdateSqlFunctionForTagPrj(pQueryInfo);
|
||||
doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
int32_t code = doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_PROJECTION_QUERY) != 0) {
|
||||
|
@ -5418,7 +5524,10 @@ static int32_t checkUpdateTagPrjFunctions(SQueryInfo* pQueryInfo, SSqlCmd* pCmd)
|
|||
if (numOfAggregation > 0 || numOfSelectivity > 0) {
|
||||
// clear the projection type flag
|
||||
pQueryInfo->type &= (~TSDB_QUERY_TYPE_PROJECTION_QUERY);
|
||||
doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
int32_t code = doUpdateSqlFunctionForColPrj(pQueryInfo);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
return code;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5474,7 +5583,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo
|
|||
insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr);
|
||||
} else {
|
||||
// if this query is "group by" normal column, interval is not allowed
|
||||
if (pQueryInfo->intervalTime > 0) {
|
||||
if (pQueryInfo->interval.interval > 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
||||
}
|
||||
|
||||
|
@ -5507,7 +5616,7 @@ int32_t doFunctionsCompatibleCheck(SSqlCmd* pCmd, SQueryInfo* pQueryInfo) {
|
|||
|
||||
// only retrieve tags, group by is not supportted
|
||||
if (tscQueryTags(pQueryInfo)) {
|
||||
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->intervalTime > 0) {
|
||||
if (pQueryInfo->groupbyExpr.numOfGroupCols > 0 || pQueryInfo->interval.interval > 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||
} else {
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -5638,7 +5747,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);
|
||||
}
|
||||
|
||||
|
@ -5763,8 +5872,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) ||
|
||||
|
@ -5818,15 +5928,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;
|
||||
}
|
||||
|
@ -5903,7 +6014,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
|
||||
|
@ -5935,11 +6045,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;
|
||||
}
|
||||
|
@ -5959,15 +6070,16 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
if (parseIntervalClause(pCmd, pQueryInfo, pQuerySql) != TSDB_CODE_SUCCESS) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
} else {
|
||||
if ((pQueryInfo->intervalTime > 0) &&
|
||||
if ((pQueryInfo->interval.interval > 0) &&
|
||||
(validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
@ -5989,7 +6101,7 @@ int32_t doCheckForStream(SSqlObj* pSql, SSqlInfo* pInfo) {
|
|||
* not here.
|
||||
*/
|
||||
if (pQuerySql->fillType != NULL) {
|
||||
if (pQueryInfo->intervalTime == 0) {
|
||||
if (pQueryInfo->interval.interval == 0) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
||||
}
|
||||
|
||||
|
@ -6011,7 +6123,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";
|
||||
|
@ -6083,11 +6194,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);
|
||||
|
@ -6128,30 +6244,6 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
int32_t joinQuery = (pQuerySql->from != NULL && pQuerySql->from->nExpr > 2);
|
||||
|
||||
if (pQuerySql->pWhere) {
|
||||
pQueryInfo->window = TSWINDOW_INITIALIZER;
|
||||
}
|
||||
if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery) != 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;
|
||||
} else {
|
||||
if ((pQueryInfo->intervalTime > 0) &&
|
||||
(validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
|
||||
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 where info
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
||||
|
@ -6166,12 +6258,32 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
pQueryInfo->window.ekey = pQueryInfo->window.ekey / 1000;
|
||||
}
|
||||
} else { // set the time rang
|
||||
pQueryInfo->window = TSWINDOW_INITIALIZER;
|
||||
if (pQuerySql->from->nExpr > 2) { // it is a join query, no wher clause is not allowed.
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), "condition missing for join query ");
|
||||
}
|
||||
}
|
||||
|
||||
int32_t joinQuery = (pQuerySql->from != NULL && pQuerySql->from->nExpr > 2);
|
||||
|
||||
if (parseSelectClause(pCmd, index, pQuerySql->pSelection, isSTable, joinQuery) != 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;
|
||||
} else {
|
||||
if ((pQueryInfo->interval.interval > 0) &&
|
||||
(validateFunctionsInIntervalOrGroupbyQuery(pCmd, pQueryInfo) != TSDB_CODE_SUCCESS)) {
|
||||
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;
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
|
@ -6212,14 +6324,19 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) {
|
|||
* the columns may be increased due to group by operation
|
||||
*/
|
||||
if (pQuerySql->fillType != NULL) {
|
||||
if (pQueryInfo->intervalTime == 0 && (!tscIsPointInterpQuery(pQueryInfo))) {
|
||||
if (pQueryInfo->interval.interval == 0 && (!tscIsPointInterpQuery(pQueryInfo))) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||
}
|
||||
|
||||
if (pQueryInfo->intervalTime > 0 && pQueryInfo->intervalTimeUnit != 'n' && pQueryInfo->intervalTimeUnit != 'y') {
|
||||
if (pQueryInfo->interval.interval > 0 && pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit != 'y') {
|
||||
bool initialWindows = TSWINDOW_IS_EQUAL(pQueryInfo->window, TSWINDOW_INITIALIZER);
|
||||
if (initialWindows) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
|
||||
int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey);
|
||||
// number of result is not greater than 10,000,000
|
||||
if ((timeRange == 0) || (timeRange / pQueryInfo->intervalTime) > MAX_INTERVAL_TIME_WINDOW) {
|
||||
if ((timeRange == 0) || (timeRange / pQueryInfo->interval.interval) > MAX_INTERVAL_TIME_WINDOW) {
|
||||
return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||
}
|
||||
}
|
||||
|
@ -6251,6 +6368,11 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
|||
}
|
||||
}
|
||||
|
||||
if (pSqlExpr->pLeft == NULL && pSqlExpr->pRight == NULL && pSqlExpr->nSQLOptr == 0) {
|
||||
*pExpr = calloc(1, sizeof(tExprNode));
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
if (pSqlExpr->pLeft == NULL) {
|
||||
if (pSqlExpr->nSQLOptr >= TK_BOOL && pSqlExpr->nSQLOptr <= TK_STRING) {
|
||||
*pExpr = calloc(1, sizeof(tExprNode));
|
||||
|
@ -6323,6 +6445,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
|||
|
||||
assert((*pExpr)->_node.optr != 0);
|
||||
|
||||
// check for dividing by 0
|
||||
if ((*pExpr)->_node.optr == TSDB_BINARY_OP_DIVIDE) {
|
||||
if (pRight->nodeType == TSQL_NODE_VALUE) {
|
||||
if (pRight->pVal->nType == TSDB_DATA_TYPE_INT && pRight->pVal->i64Key == 0) {
|
||||
|
@ -6335,7 +6458,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
|||
|
||||
// NOTE: binary|nchar data allows the >|< type filter
|
||||
if ((*pExpr)->_node.optr != TSDB_RELATION_EQUAL && (*pExpr)->_node.optr != TSDB_RELATION_NOT_EQUAL) {
|
||||
if (pRight->nodeType == TSQL_NODE_VALUE) {
|
||||
if (pRight != NULL && pRight->nodeType == TSQL_NODE_VALUE) {
|
||||
if (pRight->pVal->nType == TSDB_DATA_TYPE_BOOL) {
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
@ -6345,3 +6468,15 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS
|
|||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
bool hasNormalColumnFilter(SQueryInfo* pQueryInfo) {
|
||||
size_t numOfCols = taosArrayGetSize(pQueryInfo->colList);
|
||||
for (int32_t i = 0; i < numOfCols; ++i) {
|
||||
SColumn* pCol = taosArrayGetP(pQueryInfo->colList, i);
|
||||
if (pCol->numOfFilters > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -170,6 +170,7 @@ STableMeta* tscCreateTableMetaFromMsg(STableMetaMsg* pTableMetaMsg, size_t* size
|
|||
|
||||
pTableMeta->sversion = pTableMetaMsg->sversion;
|
||||
pTableMeta->tversion = pTableMetaMsg->tversion;
|
||||
tstrncpy(pTableMeta->sTableId, pTableMetaMsg->sTableId, TSDB_TABLE_FNAME_LEN);
|
||||
|
||||
memcpy(pTableMeta->schema, pTableMetaMsg->schema, schemaSize);
|
||||
|
||||
|
|
|
@ -27,10 +27,7 @@
|
|||
#include "tutil.h"
|
||||
#include "tlockfree.h"
|
||||
|
||||
#define TSC_MGMT_VNODE 999
|
||||
|
||||
SRpcCorEpSet tscMgmtEpSet;
|
||||
SRpcEpSet tscDnodeEpSet;
|
||||
|
||||
int (*tscBuildMsg[TSDB_SQL_MAX])(SSqlObj *pSql, SSqlInfo *pInfo) = {0};
|
||||
|
||||
|
@ -56,7 +53,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;
|
||||
|
@ -131,6 +131,7 @@ static void tscUpdateVgroupInfo(SSqlObj *pObj, SRpcEpSet *pEpSet) {
|
|||
tscDebug("after: EndPoint in use: %d", pVgroupInfo->inUse);
|
||||
taosCorEndWrite(&pVgroupInfo->version);
|
||||
}
|
||||
|
||||
void tscPrintMgmtEp() {
|
||||
SRpcEpSet dump;
|
||||
tscDumpMgmtEpSet(&dump);
|
||||
|
@ -146,12 +147,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) {
|
||||
|
@ -175,7 +177,14 @@ void tscProcessHeartBeatRsp(void *param, TAOS_RES *tres, int 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) {
|
||||
|
@ -191,8 +200,8 @@ void tscProcessActivityTimer(void *handle, void *tmrId) {
|
|||
|
||||
if (tscShouldFreeHeartBeat(pHB)) {
|
||||
tscDebug("%p free HB object and release connection", pHB);
|
||||
tscFreeSqlObj(pHB);
|
||||
tscCloseTscObj(pObj);
|
||||
pObj->pHb = 0;
|
||||
taos_free_result(pHB);
|
||||
} else {
|
||||
int32_t code = tscProcessSql(pHB);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
|
@ -236,32 +245,40 @@ int tscSendMsgToServer(SSqlObj *pSql) {
|
|||
}
|
||||
|
||||
void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
||||
SSqlObj *pSql = (SSqlObj *)rpcMsg->ahandle;
|
||||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
tscError("%p sql is already released", pSql);
|
||||
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;
|
||||
}
|
||||
|
||||
SSqlObj* pSql = *p;
|
||||
assert(pSql != NULL);
|
||||
|
||||
STscObj *pObj = pSql->pTscObj;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
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);
|
||||
|
||||
tscFreeSqlObj(pSql);
|
||||
taosCacheRelease(tscObjCache, (void**) &p, true);
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
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",
|
||||
pSql, pCmd->command, pQueryInfo->type, pObj, pObj->signature);
|
||||
|
||||
tscFreeSqlObj(pSql);
|
||||
void** p1 = p;
|
||||
taosCacheRelease(tscObjCache, (void**) &p1, false);
|
||||
|
||||
taosCacheRelease(tscObjCache, (void**) &p, true);
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
}
|
||||
|
@ -294,7 +311,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
if (pSql->retry > pSql->maxRetry) {
|
||||
tscError("%p max retry %d reached, give up", pSql, pSql->maxRetry);
|
||||
} else {
|
||||
// wait for a little bit moment and then retry
|
||||
// wait for a little bit moment and then retry, todo do not sleep in rpc callback thread
|
||||
if (rpcMsg->code == TSDB_CODE_APP_NOT_READY || rpcMsg->code == TSDB_CODE_VND_INVALID_VGROUP_ID) {
|
||||
int32_t duration = getWaitingTimeInterval(pSql->retry);
|
||||
taosMsleep(duration);
|
||||
|
@ -304,6 +321,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
|
||||
// if there is an error occurring, proceed to the following error handling procedure.
|
||||
if (rpcMsg->code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
taosCacheRelease(tscObjCache, (void**) &p, false);
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
return;
|
||||
}
|
||||
|
@ -365,16 +383,18 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) {
|
|||
rpcMsg->code = (*tscProcessMsgRsp[pCmd->command])(pSql);
|
||||
}
|
||||
|
||||
bool shouldFree = tscShouldBeFreed(pSql);
|
||||
if (rpcMsg->code != TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||
rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code;
|
||||
|
||||
bool shouldFree = tscShouldBeFreed(pSql);
|
||||
(*pSql->fp)(pSql->param, pSql, rpcMsg->code);
|
||||
|
||||
if (shouldFree) {
|
||||
tscDebug("%p sqlObj is automatically freed", pSql);
|
||||
tscFreeSqlObj(pSql);
|
||||
}
|
||||
|
||||
void** p1 = p;
|
||||
taosCacheRelease(tscObjCache, (void**) &p1, false);
|
||||
|
||||
if (shouldFree) { // in case of table-meta/vgrouplist query, automatically free it
|
||||
taosCacheRelease(tscObjCache, (void **)&p, true);
|
||||
tscDebug("%p sqlObj is automatically freed", pSql);
|
||||
}
|
||||
|
||||
rpcFreeCont(rpcMsg->pCont);
|
||||
|
@ -464,6 +484,7 @@ void tscKillSTableQuery(SSqlObj *pSql) {
|
|||
pSub->res.code = TSDB_CODE_TSC_QUERY_CANCELLED;
|
||||
if (pSub->pRpcCtx != NULL) {
|
||||
rpcCancelRequest(pSub->pRpcCtx);
|
||||
pSub->pRpcCtx = NULL;
|
||||
}
|
||||
|
||||
tscQueueAsyncRes(pSub); // async res? not other functions?
|
||||
|
@ -631,14 +652,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->intervalTime < 0) {
|
||||
tscError("%p illegal value of aggregation time interval in query msg: %ld", pSql, pQueryInfo->intervalTime);
|
||||
if (pQueryInfo->interval.interval < 0) {
|
||||
tscError("%p illegal value of aggregation time interval in query msg: %" PRId64, pSql, (int64_t)pQueryInfo->interval.interval);
|
||||
return TSDB_CODE_TSC_INVALID_SQL;
|
||||
}
|
||||
|
||||
|
@ -665,10 +686,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->intervalTime = htobe64(pQueryInfo->intervalTime);
|
||||
pQueryMsg->slidingTime = htobe64(pQueryInfo->slidingTime);
|
||||
pQueryMsg->intervalTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
pQueryMsg->slidingTimeUnit = pQueryInfo->slidingTimeUnit;
|
||||
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->numOfGroupCols = htons(pQueryInfo->groupbyExpr.numOfGroupCols);
|
||||
pQueryMsg->numOfTags = htonl(numOfTags);
|
||||
pQueryMsg->tagNameRelType = htons(pQueryInfo->tagCond.relType);
|
||||
|
@ -733,7 +756,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;
|
||||
}
|
||||
|
@ -1483,43 +1505,29 @@ int tscBuildConnectMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
|||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1667,8 +1675,10 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
pMetaMsg->contLen = htons(pMetaMsg->contLen);
|
||||
pMetaMsg->numOfColumns = htons(pMetaMsg->numOfColumns);
|
||||
|
||||
if (pMetaMsg->sid < 0 || pMetaMsg->vgroup.numOfEps < 0) {
|
||||
tscError("invalid meter vgId:%d, sid%d", pMetaMsg->vgroup.numOfEps, pMetaMsg->sid);
|
||||
if ((pMetaMsg->tableType != TSDB_SUPER_TABLE) &&
|
||||
(pMetaMsg->sid <= 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);
|
||||
return TSDB_CODE_TSC_INVALID_VALUE;
|
||||
}
|
||||
|
||||
|
@ -1708,7 +1718,7 @@ int tscProcessTableMetaRsp(SSqlObj *pSql) {
|
|||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
|
||||
assert(pTableMetaInfo->pTableMeta == NULL);
|
||||
|
||||
pTableMetaInfo->pTableMeta = (STableMeta *) taosCachePut(tscCacheHandle, pTableMetaInfo->name,
|
||||
pTableMetaInfo->pTableMeta = (STableMeta *) taosCachePut(tscMetaCache, pTableMetaInfo->name,
|
||||
strlen(pTableMetaInfo->name), pTableMeta, size, tsTableMetaKeepTimer * 1000);
|
||||
|
||||
// todo handle out of memory case
|
||||
|
@ -1820,7 +1830,7 @@ int tscProcessMultiMeterMetaRsp(SSqlObj *pSql) {
|
|||
// int32_t size = (int32_t)(rsp - ((char *)pMeta)); // Consistent with STableMeta in cache
|
||||
//
|
||||
// pMeta->index = 0;
|
||||
// (void)taosCachePut(tscCacheHandle, pMeta->tableId, (char *)pMeta, size, tsTableMetaKeepTimer);
|
||||
// (void)taosCachePut(tscMetaCache, pMeta->tableId, (char *)pMeta, size, tsTableMetaKeepTimer);
|
||||
// }
|
||||
}
|
||||
|
||||
|
@ -1907,12 +1917,14 @@ int tscProcessShowRsp(SSqlObj *pSql) {
|
|||
key[0] = pCmd->msgType + 'a';
|
||||
strcpy(key + 1, "showlist");
|
||||
|
||||
taosCacheRelease(tscCacheHandle, (void *)&(pTableMetaInfo->pTableMeta), false);
|
||||
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
taosCacheRelease(tscMetaCache, (void *)&(pTableMetaInfo->pTableMeta), false);
|
||||
}
|
||||
|
||||
size_t size = 0;
|
||||
STableMeta* pTableMeta = tscCreateTableMetaFromMsg(pMetaMsg, &size);
|
||||
|
||||
pTableMetaInfo->pTableMeta = taosCachePut(tscCacheHandle, key, strlen(key), (char *)pTableMeta, size,
|
||||
pTableMetaInfo->pTableMeta = taosCachePut(tscMetaCache, key, strlen(key), (char *)pTableMeta, size,
|
||||
tsTableMetaKeepTimer * 1000);
|
||||
SSchema *pTableSchema = tscGetTableSchema(pTableMetaInfo->pTableMeta);
|
||||
|
||||
|
@ -1943,6 +1955,7 @@ int tscProcessShowRsp(SSqlObj *pSql) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// TODO multithread problem
|
||||
static void createHBObj(STscObj* pObj) {
|
||||
if (pObj->pHb != NULL) {
|
||||
return;
|
||||
|
@ -1970,10 +1983,11 @@ static void createHBObj(STscObj* pObj) {
|
|||
pSql->param = pObj;
|
||||
pSql->pTscObj = pObj;
|
||||
pSql->signature = pSql;
|
||||
pObj->pHb = pSql;
|
||||
tscAddSubqueryInfo(&pObj->pHb->cmd);
|
||||
|
||||
tscDebug("%p HB is allocated, pObj:%p", pObj->pHb, pObj);
|
||||
registerSqlObj(pSql);
|
||||
tscDebug("%p HB is allocated, pObj:%p", pSql, pObj);
|
||||
|
||||
pObj->pHb = pSql;
|
||||
}
|
||||
|
||||
int tscProcessConnectRsp(SSqlObj *pSql) {
|
||||
|
@ -1999,7 +2013,6 @@ int tscProcessConnectRsp(SSqlObj *pSql) {
|
|||
pObj->connId = htonl(pConnect->connId);
|
||||
|
||||
createHBObj(pObj);
|
||||
|
||||
taosTmrReset(tscProcessActivityTimer, tsShellActivityTimer * 500, pObj, tscTmr, &pObj->pTimer);
|
||||
|
||||
return 0;
|
||||
|
@ -2015,14 +2028,14 @@ int tscProcessUseDbRsp(SSqlObj *pSql) {
|
|||
|
||||
int tscProcessDropDbRsp(SSqlObj *pSql) {
|
||||
pSql->pTscObj->db[0] = 0;
|
||||
taosCacheEmpty(tscCacheHandle);
|
||||
taosCacheEmpty(tscMetaCache);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int tscProcessDropTableRsp(SSqlObj *pSql) {
|
||||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
|
||||
|
||||
STableMeta *pTableMeta = taosCacheAcquireByKey(tscCacheHandle, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
STableMeta *pTableMeta = taosCacheAcquireByKey(tscMetaCache, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
if (pTableMeta == NULL) { /* not in cache, abort */
|
||||
return 0;
|
||||
}
|
||||
|
@ -2035,10 +2048,10 @@ int tscProcessDropTableRsp(SSqlObj *pSql) {
|
|||
* instead.
|
||||
*/
|
||||
tscDebug("%p force release table meta after drop table:%s", pSql, pTableMetaInfo->name);
|
||||
taosCacheRelease(tscCacheHandle, (void **)&pTableMeta, true);
|
||||
taosCacheRelease(tscMetaCache, (void **)&pTableMeta, true);
|
||||
|
||||
if (pTableMetaInfo->pTableMeta) {
|
||||
taosCacheRelease(tscCacheHandle, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosCacheRelease(tscMetaCache, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -2047,21 +2060,21 @@ int tscProcessDropTableRsp(SSqlObj *pSql) {
|
|||
int tscProcessAlterTableMsgRsp(SSqlObj *pSql) {
|
||||
STableMetaInfo *pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, 0, 0);
|
||||
|
||||
STableMeta *pTableMeta = taosCacheAcquireByKey(tscCacheHandle, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
STableMeta *pTableMeta = taosCacheAcquireByKey(tscMetaCache, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
if (pTableMeta == NULL) { /* not in cache, abort */
|
||||
return 0;
|
||||
}
|
||||
|
||||
tscDebug("%p force release metermeta in cache after alter-table: %s", pSql, pTableMetaInfo->name);
|
||||
taosCacheRelease(tscCacheHandle, (void **)&pTableMeta, true);
|
||||
taosCacheRelease(tscMetaCache, (void **)&pTableMeta, true);
|
||||
|
||||
if (pTableMetaInfo->pTableMeta) {
|
||||
bool isSuperTable = UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo);
|
||||
taosCacheRelease(tscCacheHandle, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosCacheRelease(tscMetaCache, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
|
||||
if (isSuperTable) { // if it is a super table, reset whole query cache
|
||||
tscDebug("%p reset query cache since table:%s is stable", pSql, pTableMetaInfo->name);
|
||||
taosCacheEmpty(tscCacheHandle);
|
||||
taosCacheEmpty(tscMetaCache);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2072,6 +2085,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;
|
||||
|
@ -2146,6 +2162,8 @@ static int32_t getTableMetaFromMgmt(SSqlObj *pSql, STableMetaInfo *pTableMetaInf
|
|||
pNew->signature = pNew;
|
||||
pNew->cmd.command = TSDB_SQL_META;
|
||||
|
||||
registerSqlObj(pNew);
|
||||
|
||||
tscAddSubqueryInfo(&pNew->cmd);
|
||||
|
||||
SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetailSafely(&pNew->cmd, 0);
|
||||
|
@ -2162,8 +2180,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;
|
||||
|
@ -2182,10 +2199,10 @@ int32_t tscGetTableMeta(SSqlObj *pSql, STableMetaInfo *pTableMetaInfo) {
|
|||
|
||||
// If this STableMetaInfo owns a table meta, release it first
|
||||
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
taosCacheRelease(tscCacheHandle, (void **)&(pTableMetaInfo->pTableMeta), false);
|
||||
taosCacheRelease(tscMetaCache, (void **)&(pTableMetaInfo->pTableMeta), false);
|
||||
}
|
||||
|
||||
pTableMetaInfo->pTableMeta = (STableMeta *)taosCacheAcquireByKey(tscCacheHandle, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
pTableMetaInfo->pTableMeta = (STableMeta *)taosCacheAcquireByKey(tscMetaCache, pTableMetaInfo->name, strlen(pTableMetaInfo->name));
|
||||
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
tscDebug("%p retrieve table Meta from cache, the number of columns:%d, numOfTags:%d, %p", pSql, tinfo.numOfColumns,
|
||||
|
@ -2220,7 +2237,7 @@ int tscRenewTableMeta(SSqlObj *pSql, int32_t tableIndex) {
|
|||
tscGetNumOfTags(pTableMeta), tscGetNumOfColumns(pTableMeta), pTableMeta->id.uid, pTableMeta);
|
||||
}
|
||||
|
||||
taosCacheRelease(tscCacheHandle, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosCacheRelease(tscMetaCache, (void **)&(pTableMetaInfo->pTableMeta), true);
|
||||
return getTableMetaFromMgmt(pSql, pTableMetaInfo);
|
||||
}
|
||||
|
||||
|
@ -2251,6 +2268,7 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
|
|||
|
||||
pNew->cmd.command = TSDB_SQL_STABLEVGROUP;
|
||||
|
||||
// TODO TEST IT
|
||||
SQueryInfo *pNewQueryInfo = tscGetQueryInfoDetailSafely(&pNew->cmd, 0);
|
||||
if (pNewQueryInfo == NULL) {
|
||||
tscFreeSqlObj(pNew);
|
||||
|
@ -2260,7 +2278,7 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
|
|||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex);
|
||||
for (int32_t i = 0; i < pQueryInfo->numOfTables; ++i) {
|
||||
STableMetaInfo *pMInfo = tscGetMetaInfo(pQueryInfo, i);
|
||||
STableMeta *pTableMeta = taosCacheAcquireByData(tscCacheHandle, pMInfo->pTableMeta);
|
||||
STableMeta *pTableMeta = taosCacheAcquireByData(tscMetaCache, pMInfo->pTableMeta);
|
||||
tscAddTableMetaInfo(pNewQueryInfo, pMInfo->name, pTableMeta, NULL, pMInfo->tagColList);
|
||||
}
|
||||
|
||||
|
@ -2270,6 +2288,8 @@ int tscGetSTableVgroupInfo(SSqlObj *pSql, int32_t clauseIndex) {
|
|||
}
|
||||
|
||||
pNewQueryInfo->numOfTables = pQueryInfo->numOfTables;
|
||||
registerSqlObj(pNew);
|
||||
|
||||
tscDebug("%p new sqlObj:%p to get vgroupInfo, numOfTables:%d", pSql, pNew, pNewQueryInfo->numOfTables);
|
||||
|
||||
pNew->fp = tscTableMetaCallBack;
|
||||
|
@ -2347,6 +2367,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,6 +26,7 @@
|
|||
#include "tsclient.h"
|
||||
#include "ttokendef.h"
|
||||
#include "tutil.h"
|
||||
#include "tscProfile.h"
|
||||
|
||||
static bool validImpl(const char* str, size_t maxsize) {
|
||||
if (str == NULL) {
|
||||
|
@ -100,6 +101,8 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
|
|||
}
|
||||
|
||||
pObj->signature = pObj;
|
||||
pObj->pDnodeConn = pDnodeConn;
|
||||
T_REF_INIT_VAL(pObj, 1);
|
||||
|
||||
tstrncpy(pObj->user, user, sizeof(pObj->user));
|
||||
secretEncryptLen = MIN(secretEncryptLen, sizeof(pObj->pass));
|
||||
|
@ -135,17 +138,12 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
|
|||
pSql->pTscObj = pObj;
|
||||
pSql->signature = pSql;
|
||||
pSql->maxRetry = TSDB_MAX_REPLICA;
|
||||
tsem_init(&pSql->rspSem, 0, 0);
|
||||
|
||||
pObj->pDnodeConn = pDnodeConn;
|
||||
|
||||
pSql->fp = fp;
|
||||
pSql->param = param;
|
||||
if (taos != NULL) {
|
||||
*taos = pObj;
|
||||
}
|
||||
|
||||
pSql->cmd.command = TSDB_SQL_CONNECT;
|
||||
|
||||
tsem_init(&pSql->rspSem, 0, 0);
|
||||
|
||||
if (TSDB_CODE_SUCCESS != tscAllocPayload(&pSql->cmd, TSDB_DEFAULT_PAYLOAD_SIZE)) {
|
||||
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
rpcClose(pDnodeConn);
|
||||
|
@ -154,7 +152,13 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con
|
|||
return NULL;
|
||||
}
|
||||
|
||||
if (taos != NULL) {
|
||||
*taos = pObj;
|
||||
}
|
||||
|
||||
registerSqlObj(pSql);
|
||||
tsInsertHeadSize = sizeof(SMsgDesc) + sizeof(SSubmitMsg);
|
||||
|
||||
return pSql;
|
||||
}
|
||||
|
||||
|
@ -229,13 +233,21 @@ TAOS *taos_connect_c(const char *ip, uint8_t ipLen, const char *user, uint8_t us
|
|||
return taos_connect(ipBuf, userBuf, passBuf, dbBuf, port);
|
||||
}
|
||||
|
||||
static void asyncConnCallback(void *param, TAOS_RES *tres, int code) {
|
||||
SSqlObj *pSql = (SSqlObj *) tres;
|
||||
assert(pSql != NULL);
|
||||
|
||||
pSql->fetchFp(pSql->param, tres, 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, fp, param, taos);
|
||||
SSqlObj* pSql = taosConnectImpl(ip, user, pass, NULL, db, port, asyncConnCallback, param, taos);
|
||||
if (pSql == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pSql->fetchFp = fp;
|
||||
pSql->res.code = tscProcessSql(pSql);
|
||||
tscDebug("%p DB async connection is opening", taos);
|
||||
return taos;
|
||||
|
@ -248,15 +260,26 @@ void taos_close(TAOS *taos) {
|
|||
return;
|
||||
}
|
||||
|
||||
if (pObj->pHb != NULL) {
|
||||
if (pObj->pHb->pRpcCtx != NULL) { // wait for rsp from dnode
|
||||
rpcCancelRequest(pObj->pHb->pRpcCtx);
|
||||
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
|
||||
rpcCancelRequest(pHb->pRpcCtx);
|
||||
pHb->pRpcCtx = NULL;
|
||||
}
|
||||
|
||||
tscSetFreeHeatBeat(pObj);
|
||||
tscFreeSqlObj(pObj->pHb);
|
||||
tscDebug("%p HB is freed", pHb);
|
||||
taos_free_result(pHb);
|
||||
}
|
||||
|
||||
int32_t ref = T_REF_DEC(pObj);
|
||||
assert(ref >= 0);
|
||||
|
||||
if (ref > 0) {
|
||||
tscDebug("%p %d remain sqlObjs, not free tscObj and dnodeConn:%p", pObj, ref, pObj->pDnodeConn);
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p all sqlObj are freed, free tscObj and close dnodeConn:%p", pObj, pObj->pDnodeConn);
|
||||
tscCloseTscObj(pObj);
|
||||
}
|
||||
|
||||
|
@ -451,6 +474,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 ||
|
||||
|
@ -533,57 +558,51 @@ int taos_select_db(TAOS *taos, const char *db) {
|
|||
}
|
||||
|
||||
// send free message to vnode to free qhandle and corresponding resources in vnode
|
||||
static bool tscKillQueryInVnode(SSqlObj* pSql) {
|
||||
static UNUSED_FUNC bool tscKillQueryInDnode(SSqlObj* pSql) {
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
SSqlRes* pRes = &pSql->res;
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
|
||||
if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && !tscIsTwoStageSTableQuery(pQueryInfo, 0) &&
|
||||
(pCmd->command == TSDB_SQL_SELECT ||
|
||||
pCmd->command == TSDB_SQL_SHOW ||
|
||||
pCmd->command == TSDB_SQL_RETRIEVE ||
|
||||
pCmd->command == TSDB_SQL_FETCH) &&
|
||||
(pSql->pStream == NULL && pTableMetaInfo->pTableMeta != NULL)) {
|
||||
|
||||
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
|
||||
tscDebug("%p send msg to dnode to free qhandle ASAP, command:%s, ", pSql, sqlCmd[pCmd->command]);
|
||||
tscProcessSql(pSql);
|
||||
if (pRes == NULL || pRes->qhandle == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
if ((pQueryInfo == NULL) || tscIsTwoStageSTableQuery(pQueryInfo, 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
tscRemoveFromSqlList(pSql);
|
||||
|
||||
int32_t cmd = pCmd->command;
|
||||
if (pRes->code == TSDB_CODE_SUCCESS && pRes->completed == false && pSql->pStream == NULL && (pTableMetaInfo->pTableMeta != NULL) &&
|
||||
(cmd == TSDB_SQL_SELECT ||
|
||||
cmd == TSDB_SQL_SHOW ||
|
||||
cmd == TSDB_SQL_RETRIEVE ||
|
||||
cmd == TSDB_SQL_FETCH)) {
|
||||
pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
|
||||
pCmd->command = (pCmd->command > TSDB_SQL_MGMT) ? TSDB_SQL_RETRIEVE : TSDB_SQL_FETCH;
|
||||
tscDebug("%p send msg to dnode to free qhandle ASAP before free sqlObj, command:%s", pSql, sqlCmd[pCmd->command]);
|
||||
|
||||
tscProcessSql(pSql);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void taos_free_result(TAOS_RES *res) {
|
||||
SSqlObj* pSql = (SSqlObj*) res;
|
||||
|
||||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
tscDebug("%p sqlObj has been freed", pSql);
|
||||
tscError("%p already released sqlObj", res);
|
||||
return;
|
||||
}
|
||||
|
||||
// The semaphore can not be changed while freeing async sub query objects.
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
if (pRes == NULL || pRes->qhandle == 0) {
|
||||
tscFreeSqlObj(pSql);
|
||||
tscDebug("%p SqlObj is freed by app, qhandle is null", pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
// set freeFlag to 1 in retrieve message if there are un-retrieved results data in node
|
||||
SQueryInfo *pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
if (pQueryInfo == NULL) {
|
||||
tscFreeSqlObj(pSql);
|
||||
tscDebug("%p SqlObj is freed by app", pSql);
|
||||
return;
|
||||
}
|
||||
|
||||
pQueryInfo->type = TSDB_QUERY_TYPE_FREE_RESOURCE;
|
||||
if (!tscKillQueryInVnode(pSql)) {
|
||||
tscFreeSqlObj(pSql);
|
||||
tscDebug("%p sqlObj is freed by app", pSql);
|
||||
bool freeNow = tscKillQueryInDnode(pSql);
|
||||
if (freeNow) {
|
||||
tscDebug("%p free sqlObj in cache", pSql);
|
||||
SSqlObj** p = pSql->self;
|
||||
taosCacheRelease(tscObjCache, (void**) &p, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -679,6 +698,7 @@ void taos_stop_query(TAOS_RES *res) {
|
|||
tscKillSTableQuery(pSql);
|
||||
} else {
|
||||
if (pSql->cmd.command < TSDB_SQL_LOCAL) {
|
||||
assert(pSql->pRpcCtx != NULL);
|
||||
rpcCancelRequest(pSql->pRpcCtx);
|
||||
}
|
||||
}
|
||||
|
@ -700,15 +720,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:
|
||||
|
@ -767,14 +787,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);
|
||||
|
@ -810,11 +833,12 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
|
|||
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);
|
||||
|
||||
taos_free_result(pSql);
|
||||
return code;
|
||||
}
|
||||
|
||||
|
@ -913,34 +937,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.
|
||||
|
@ -950,17 +972,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(taos), pObj);
|
||||
if ((code = pRes->code) != TSDB_CODE_SUCCESS) {
|
||||
tscFreeSqlObj(pSql);
|
||||
}
|
||||
|
||||
return pRes->code;
|
||||
return code;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ static int64_t tscGetRetryDelayTime(SSqlStream* pStream, int64_t slidingTime, in
|
|||
int64_t retryDelta = (int64_t)(tsStreamCompRetryDelay * retryRangeFactor);
|
||||
retryDelta = ((rand() % retryDelta) + tsStreamCompRetryDelay) * 1000L;
|
||||
|
||||
if (pStream->intervalTimeUnit != 'n' && pStream->intervalTimeUnit != 'y') {
|
||||
if (pStream->interval.intervalUnit != 'n' && pStream->interval.intervalUnit != 'y') {
|
||||
// change to ms
|
||||
if (prec == TSDB_TIME_PRECISION_MICRO) {
|
||||
slidingTime = slidingTime / 1000;
|
||||
|
@ -87,7 +87,7 @@ static void tscProcessStreamLaunchQuery(SSchedMsg *pMsg) {
|
|||
|
||||
// failed to get meter/metric meta, retry in 10sec.
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->slidingTime, pStream->precision);
|
||||
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->interval.sliding, pStream->precision);
|
||||
tscDebug("%p stream:%p,get metermeta failed, retry in %" PRId64 "ms", pStream->pSql, pStream, retryDelayTime);
|
||||
tscSetRetryTimer(pStream, pSql, retryDelayTime);
|
||||
|
||||
|
@ -132,15 +132,15 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
|
|||
}
|
||||
if (etime > pStream->etime) {
|
||||
etime = pStream->etime;
|
||||
} else if (pStream->intervalTimeUnit != 'y' && pStream->intervalTimeUnit != 'n') {
|
||||
etime = pStream->stime + (etime - pStream->stime) / pStream->intervalTime * pStream->intervalTime;
|
||||
} else if (pStream->interval.intervalUnit != 'y' && pStream->interval.intervalUnit != 'n') {
|
||||
etime = pStream->stime + (etime - pStream->stime) / pStream->interval.interval * pStream->interval.interval;
|
||||
} else {
|
||||
etime = taosGetIntervalStartTimestamp(etime, pStream->slidingTime, pStream->intervalTime, pStream->slidingTimeUnit, pStream->precision);
|
||||
etime = taosTimeTruncate(etime, &pStream->interval, pStream->precision);
|
||||
}
|
||||
pQueryInfo->window.ekey = etime;
|
||||
if (pQueryInfo->window.skey >= pQueryInfo->window.ekey) {
|
||||
int64_t timer = pStream->slidingTime;
|
||||
if (pStream->intervalTimeUnit == 'y' || pStream->intervalTimeUnit == 'n') {
|
||||
int64_t timer = pStream->interval.sliding;
|
||||
if (pStream->interval.intervalUnit == 'y' || pStream->interval.intervalUnit == 'n') {
|
||||
timer = 86400 * 1000l;
|
||||
} else if (pStream->precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
timer /= 1000l;
|
||||
|
@ -162,12 +162,12 @@ static void tscProcessStreamTimer(void *handle, void *tmrId) {
|
|||
static void tscProcessStreamQueryCallback(void *param, TAOS_RES *tres, int numOfRows) {
|
||||
SSqlStream *pStream = (SSqlStream *)param;
|
||||
if (tres == NULL || numOfRows < 0) {
|
||||
int64_t retryDelay = tscGetRetryDelayTime(pStream, pStream->slidingTime, pStream->precision);
|
||||
int64_t retryDelay = tscGetRetryDelayTime(pStream, pStream->interval.sliding, pStream->precision);
|
||||
tscError("%p stream:%p, query data failed, code:0x%08x, retry in %" PRId64 "ms", pStream->pSql, pStream, numOfRows,
|
||||
retryDelay);
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pStream->pSql->cmd, 0, 0);
|
||||
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), true);
|
||||
taosTFree(pTableMetaInfo->vgroupList);
|
||||
|
||||
tscSetRetryTimer(pStream, pStream->pSql, retryDelay);
|
||||
|
@ -223,7 +223,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
|
|||
SSqlObj * pSql = (SSqlObj *)res;
|
||||
|
||||
if (pSql == NULL || numOfRows < 0) {
|
||||
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->slidingTime, pStream->precision);
|
||||
int64_t retryDelayTime = tscGetRetryDelayTime(pStream, pStream->interval.sliding, pStream->precision);
|
||||
tscError("%p stream:%p, retrieve data failed, code:0x%08x, retry in %" PRId64 "ms", pSql, pStream, numOfRows, retryDelayTime);
|
||||
|
||||
tscSetRetryTimer(pStream, pStream->pSql, retryDelayTime);
|
||||
|
@ -246,11 +246,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
|
|||
}
|
||||
|
||||
if (!pStream->isProject) {
|
||||
if (pStream->intervalTimeUnit == 'y' || pStream->intervalTimeUnit == 'n') {
|
||||
pStream->stime = taosAddNatualInterval(pStream->stime, pStream->slidingTime, pStream->slidingTimeUnit, pStream->precision);
|
||||
} else {
|
||||
pStream->stime += pStream->slidingTime;
|
||||
}
|
||||
pStream->stime = taosTimeAdd(pStream->stime, pStream->interval.sliding, pStream->interval.slidingUnit, pStream->precision);
|
||||
}
|
||||
// actually only one row is returned. this following is not necessary
|
||||
taos_fetch_rows_a(res, tscProcessStreamRetrieveResult, pStream);
|
||||
|
@ -275,7 +271,7 @@ static void tscProcessStreamRetrieveResult(void *param, TAOS_RES *res, int numOf
|
|||
|
||||
// release the metric/meter meta information reference, so data in cache can be updated
|
||||
|
||||
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), false);
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), false);
|
||||
tscFreeSqlResult(pSql);
|
||||
taosTFree(pSql->pSubs);
|
||||
pSql->numOfSubs = 0;
|
||||
|
@ -310,7 +306,7 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer)
|
|||
now + timer, timer, delay, pStream->stime, etime);
|
||||
} else {
|
||||
tscDebug("%p stream:%p, next start at %" PRId64 ", in %" PRId64 "ms. delay:%" PRId64 "ms qrange %" PRId64 "-%" PRId64, pStream->pSql, pStream,
|
||||
pStream->stime, timer, delay, pStream->stime - pStream->intervalTime, pStream->stime - 1);
|
||||
pStream->stime, timer, delay, pStream->stime - pStream->interval.interval, pStream->stime - 1);
|
||||
}
|
||||
|
||||
pSql->cmd.command = TSDB_SQL_SELECT;
|
||||
|
@ -324,12 +320,12 @@ static int64_t getLaunchTimeDelay(const SSqlStream* pStream) {
|
|||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMaxStreamComputDelay * 1000L : tsMaxStreamComputDelay;
|
||||
|
||||
int64_t delayDelta = maxDelay;
|
||||
if (pStream->intervalTimeUnit != 'n' && pStream->intervalTimeUnit != 'y') {
|
||||
delayDelta = (int64_t)(pStream->slidingTime * tsStreamComputDelayRatio);
|
||||
if (pStream->interval.intervalUnit != 'n' && pStream->interval.intervalUnit != 'y') {
|
||||
delayDelta = (int64_t)(pStream->interval.sliding * tsStreamComputDelayRatio);
|
||||
if (delayDelta > maxDelay) {
|
||||
delayDelta = maxDelay;
|
||||
}
|
||||
int64_t remainTimeWindow = pStream->slidingTime - delayDelta;
|
||||
int64_t remainTimeWindow = pStream->interval.sliding - delayDelta;
|
||||
if (maxDelay > remainTimeWindow) {
|
||||
maxDelay = (int64_t)(remainTimeWindow / 1.5f);
|
||||
}
|
||||
|
@ -337,8 +333,8 @@ static int64_t getLaunchTimeDelay(const SSqlStream* pStream) {
|
|||
|
||||
int64_t currentDelay = (rand() % maxDelay); // a random number
|
||||
currentDelay += delayDelta;
|
||||
if (pStream->intervalTimeUnit != 'n' && pStream->intervalTimeUnit != 'y') {
|
||||
assert(currentDelay < pStream->slidingTime);
|
||||
if (pStream->interval.intervalUnit != 'n' && pStream->interval.intervalUnit != 'y') {
|
||||
assert(currentDelay < pStream->interval.sliding);
|
||||
}
|
||||
|
||||
return currentDelay;
|
||||
|
@ -353,7 +349,7 @@ static void tscSetNextLaunchTimer(SSqlStream *pStream, SSqlObj *pSql) {
|
|||
* for project query, no mater fetch data successfully or not, next launch will issue
|
||||
* more than the sliding time window
|
||||
*/
|
||||
timer = pStream->slidingTime;
|
||||
timer = pStream->interval.sliding;
|
||||
if (pStream->stime > pStream->etime) {
|
||||
tscDebug("%p stream:%p, stime:%" PRId64 " is larger than end time: %" PRId64 ", stop the stream", pStream->pSql, pStream,
|
||||
pStream->stime, pStream->etime);
|
||||
|
@ -366,7 +362,8 @@ static void tscSetNextLaunchTimer(SSqlStream *pStream, SSqlObj *pSql) {
|
|||
return;
|
||||
}
|
||||
} else {
|
||||
int64_t stime = taosGetIntervalStartTimestamp(pStream->stime - 1, pStream->intervalTime, pStream->intervalTime, pStream->intervalTimeUnit, pStream->precision);
|
||||
int64_t stime = taosTimeTruncate(pStream->stime - 1, &pStream->interval, pStream->precision);
|
||||
//int64_t stime = taosGetIntervalStartTimestamp(pStream->stime - 1, pStream->interval.interval, pStream->interval.interval, pStream->interval.intervalUnit, pStream->precision);
|
||||
if (stime >= pStream->etime) {
|
||||
tscDebug("%p stream:%p, stime:%" PRId64 " is larger than end time: %" PRId64 ", stop the stream", pStream->pSql, pStream,
|
||||
pStream->stime, pStream->etime);
|
||||
|
@ -400,43 +397,43 @@ static void tscSetSlidingWindowInfo(SSqlObj *pSql, SSqlStream *pStream) {
|
|||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, 0);
|
||||
|
||||
if (pQueryInfo->intervalTimeUnit != 'n' && pQueryInfo->intervalTimeUnit != 'y' && pQueryInfo->intervalTime < minIntervalTime) {
|
||||
tscWarn("%p stream:%p, original sample interval:%ld too small, reset to:%" PRId64, pSql, pStream,
|
||||
pQueryInfo->intervalTime, minIntervalTime);
|
||||
pQueryInfo->intervalTime = minIntervalTime;
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && 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;
|
||||
}
|
||||
|
||||
pStream->intervalTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
pStream->intervalTime = pQueryInfo->intervalTime; // it shall be derived from sql string
|
||||
pStream->interval.intervalUnit = pQueryInfo->interval.intervalUnit;
|
||||
pStream->interval.interval = pQueryInfo->interval.interval; // it shall be derived from sql string
|
||||
|
||||
if (pQueryInfo->slidingTime <= 0) {
|
||||
pQueryInfo->slidingTime = pQueryInfo->intervalTime;
|
||||
pQueryInfo->slidingTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
if (pQueryInfo->interval.sliding <= 0) {
|
||||
pQueryInfo->interval.sliding = pQueryInfo->interval.interval;
|
||||
pQueryInfo->interval.slidingUnit = pQueryInfo->interval.intervalUnit;
|
||||
}
|
||||
|
||||
int64_t minSlidingTime =
|
||||
(pStream->precision == TSDB_TIME_PRECISION_MICRO) ? tsMinSlidingTime * 1000L : tsMinSlidingTime;
|
||||
|
||||
if (pQueryInfo->intervalTimeUnit != 'n' && pQueryInfo->intervalTimeUnit != 'y' && pQueryInfo->slidingTime < minSlidingTime) {
|
||||
if (pQueryInfo->interval.intervalUnit != 'n' && pQueryInfo->interval.intervalUnit!= 'y' && pQueryInfo->interval.sliding < minSlidingTime) {
|
||||
tscWarn("%p stream:%p, original sliding value:%" PRId64 " too small, reset to:%" PRId64, pSql, pStream,
|
||||
pQueryInfo->slidingTime, minSlidingTime);
|
||||
pQueryInfo->interval.sliding, minSlidingTime);
|
||||
|
||||
pQueryInfo->slidingTime = minSlidingTime;
|
||||
pQueryInfo->interval.sliding = minSlidingTime;
|
||||
}
|
||||
|
||||
if (pQueryInfo->slidingTime > pQueryInfo->intervalTime) {
|
||||
if (pQueryInfo->interval.sliding > pQueryInfo->interval.interval) {
|
||||
tscWarn("%p stream:%p, sliding value:%" PRId64 " can not be larger than interval range, reset to:%" PRId64, pSql, pStream,
|
||||
pQueryInfo->slidingTime, pQueryInfo->intervalTime);
|
||||
pQueryInfo->interval.sliding, pQueryInfo->interval.interval);
|
||||
|
||||
pQueryInfo->slidingTime = pQueryInfo->intervalTime;
|
||||
pQueryInfo->interval.sliding = pQueryInfo->interval.interval;
|
||||
}
|
||||
|
||||
pStream->slidingTimeUnit = pQueryInfo->slidingTimeUnit;
|
||||
pStream->slidingTime = pQueryInfo->slidingTime;
|
||||
pStream->interval.slidingUnit = pQueryInfo->interval.slidingUnit;
|
||||
pStream->interval.sliding = pQueryInfo->interval.sliding;
|
||||
|
||||
if (pStream->isProject) {
|
||||
pQueryInfo->intervalTime = 0; // clear the interval value to avoid the force time window split by query processor
|
||||
pQueryInfo->slidingTime = 0;
|
||||
pQueryInfo->interval.interval = 0; // clear the interval value to avoid the force time window split by query processor
|
||||
pQueryInfo->interval.sliding = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -445,8 +442,8 @@ static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, in
|
|||
|
||||
if (pStream->isProject) {
|
||||
// no data in table, flush all data till now to destination meter, 10sec delay
|
||||
pStream->intervalTime = tsProjectExecInterval;
|
||||
pStream->slidingTime = tsProjectExecInterval;
|
||||
pStream->interval.interval = tsProjectExecInterval;
|
||||
pStream->interval.sliding = tsProjectExecInterval;
|
||||
|
||||
if (stime != 0) { // first projection start from the latest event timestamp
|
||||
assert(stime >= pQueryInfo->window.skey);
|
||||
|
@ -456,15 +453,12 @@ static int64_t tscGetStreamStartTimestamp(SSqlObj *pSql, SSqlStream *pStream, in
|
|||
}
|
||||
} else { // timewindow based aggregation stream
|
||||
if (stime == 0) { // no data in meter till now
|
||||
if (pQueryInfo->window.skey != INT64_MIN) {
|
||||
stime = pQueryInfo->window.skey;
|
||||
if (stime == INT64_MIN) {
|
||||
stime = (int64_t)taosGetTimestamp(pStream->precision);
|
||||
stime = taosGetIntervalStartTimestamp(stime, pStream->intervalTime, pStream->intervalTime, pStream->intervalTimeUnit, pStream->precision);
|
||||
stime = taosGetIntervalStartTimestamp(stime - 1, pStream->intervalTime, pStream->intervalTime, pStream->intervalTimeUnit, pStream->precision);
|
||||
tscWarn("%p stream:%p, last timestamp:0, reset to:%" PRId64, pSql, pStream, stime);
|
||||
}
|
||||
stime = taosTimeTruncate(stime, &pStream->interval, pStream->precision);
|
||||
} else {
|
||||
int64_t newStime = taosGetIntervalStartTimestamp(stime, pStream->intervalTime, pStream->intervalTime, pStream->intervalTimeUnit, 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);
|
||||
stime = newStime;
|
||||
|
@ -476,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;
|
||||
|
@ -514,6 +510,8 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) {
|
|||
return;
|
||||
}
|
||||
|
||||
registerSqlObj(pSql);
|
||||
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, 0);
|
||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||
STableComInfo tinfo = tscGetTableInfo(pTableMetaInfo->pTableMeta);
|
||||
|
@ -534,7 +532,7 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) {
|
|||
taosTmrReset(tscProcessStreamTimer, (int32_t)starttime, pStream, tscTmr, &pStream->pTimer);
|
||||
|
||||
tscDebug("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql,
|
||||
pStream, pTableMetaInfo->name, pStream->intervalTime, pStream->slidingTime, starttime, pSql->sqlstr);
|
||||
pStream, pTableMetaInfo->name, pStream->interval.interval, pStream->interval.sliding, starttime, pSql->sqlstr);
|
||||
}
|
||||
|
||||
TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *param, TAOS_RES *, TAOS_ROW row),
|
||||
|
@ -567,6 +565,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
|
|||
pStream->pSql = pSql;
|
||||
pSql->pStream = pStream;
|
||||
pSql->param = pStream;
|
||||
pSql->maxRetry = TSDB_MAX_REPLICA;
|
||||
|
||||
pSql->sqlstr = calloc(1, strlen(sqlstr) + 1);
|
||||
if (pSql->sqlstr == NULL) {
|
||||
|
@ -574,6 +573,7 @@ TAOS_STREAM *taos_open_stream(TAOS *taos, const char *sqlstr, void (*fp)(void *p
|
|||
tscFreeSqlObj(pSql);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
strtolower(pSql->sqlstr, sqlstr);
|
||||
|
||||
tscDebugL("%p SQL: %s", pSql, pSql->sqlstr);
|
||||
|
@ -614,10 +614,9 @@ void taos_close_stream(TAOS_STREAM *handle) {
|
|||
tscDebug("%p stream:%p is closed", pSql, pStream);
|
||||
// notify CQ to release the pStream object
|
||||
pStream->fp(pStream->param, NULL, NULL);
|
||||
|
||||
tscFreeSqlObj(pSql);
|
||||
pStream->pSql = NULL;
|
||||
|
||||
taos_free_result(pSql);
|
||||
taosTFree(pStream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,11 +155,14 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
goto fail;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -173,9 +179,15 @@ static SSub* tscCreateSubscription(STscObj* pObj, const char* topic, const char*
|
|||
fail:
|
||||
tscError("tscCreateSubscription failed at line %d, reason: %s", line, tstrerror(code));
|
||||
if (pSql != NULL) {
|
||||
if (pSql->self != NULL) {
|
||||
taos_free_result(pSql);
|
||||
} else {
|
||||
tscFreeSqlObj(pSql);
|
||||
}
|
||||
|
||||
pSql = NULL;
|
||||
}
|
||||
|
||||
if (pSub != NULL) {
|
||||
taosArrayDestroy(pSub->progress);
|
||||
tsem_destroy(&pSub->sem);
|
||||
|
@ -494,6 +506,10 @@ void taos_unsubscribe(TAOS_SUB *tsub, int keepProgress) {
|
|||
}
|
||||
}
|
||||
|
||||
if (pSub->pSql != NULL) {
|
||||
taos_free_result(pSub->pSql);
|
||||
}
|
||||
|
||||
tscFreeSqlObj(pSub->pSql);
|
||||
taosArrayDestroy(pSub->progress);
|
||||
tsem_destroy(&pSub->sem);
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "tscSubquery.h"
|
||||
#include "tschemautil.h"
|
||||
#include "tsclient.h"
|
||||
#include "tscSubquery.h"
|
||||
|
||||
typedef struct SInsertSupporter {
|
||||
SSubqueryState* pState;
|
||||
|
@ -92,7 +93,7 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
|
|||
STSElem elem2 = tsBufGetElem(pSupporter2->pTSBuf);
|
||||
|
||||
#ifdef _DEBUG_VIEW
|
||||
tscInfo("%" PRId64 ", tags:%d \t %" PRId64 ", tags:%d", elem1.ts, elem1.tag, elem2.ts, elem2.tag);
|
||||
tscInfo("%" PRId64 ", tags:%"PRId64" \t %" PRId64 ", tags:%"PRId64, elem1.ts, elem1.tag.i64Key, elem2.ts, elem2.tag.i64Key);
|
||||
#endif
|
||||
|
||||
int32_t res = tVariantCompare(&elem1.tag, &elem2.tag);
|
||||
|
@ -113,7 +114,7 @@ static int64_t doTSBlockIntersect(SSqlObj* pSql, SJoinSupporter* pSupporter1, SJ
|
|||
* in case of stable query, limit/offset is not applied here. the limit/offset is applied to the
|
||||
* final results which is acquired after the secondry merge of in the client.
|
||||
*/
|
||||
if (pLimit->offset == 0 || pQueryInfo->intervalTime > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
|
||||
if (pLimit->offset == 0 || pQueryInfo->interval.interval > 0 || QUERY_IS_STABLE_QUERY(pQueryInfo->type)) {
|
||||
if (win->skey > elem1.ts) {
|
||||
win->skey = elem1.ts;
|
||||
}
|
||||
|
@ -178,10 +179,7 @@ SJoinSupporter* tscCreateJoinSupporter(SSqlObj* pSql, SSubqueryState* pState, in
|
|||
pSupporter->subqueryIndex = index;
|
||||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, pSql->cmd.clauseIndex);
|
||||
|
||||
pSupporter->intervalTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
pSupporter->slidingTime = pQueryInfo->slidingTimeUnit;
|
||||
pSupporter->intervalTime = pQueryInfo->intervalTime;
|
||||
pSupporter->slidingTime = pQueryInfo->slidingTime;
|
||||
memcpy(&pSupporter->interval, &pQueryInfo->interval, sizeof(pSupporter->interval));
|
||||
pSupporter->limit = pQueryInfo->limit;
|
||||
|
||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, index);
|
||||
|
@ -281,7 +279,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
|
|||
tscDebug("%p subIndex: %d, no need to launch query, ignore it", pSql, i);
|
||||
|
||||
tscDestroyJoinSupporter(pSupporter);
|
||||
tscFreeSqlObj(pPrevSub);
|
||||
taos_free_result(pPrevSub);
|
||||
|
||||
pSql->pSubs[i] = NULL;
|
||||
continue;
|
||||
|
@ -311,11 +309,7 @@ static int32_t tscLaunchRealSubqueries(SSqlObj* pSql) {
|
|||
// set the second stage sub query for join process
|
||||
TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE);
|
||||
|
||||
pQueryInfo->intervalTimeUnit = pSupporter->intervalTimeUnit;
|
||||
pQueryInfo->slidingTimeUnit = pSupporter->slidingTimeUnit;
|
||||
pQueryInfo->intervalTime = pSupporter->intervalTime;
|
||||
pQueryInfo->slidingTime = pSupporter->slidingTime;
|
||||
pQueryInfo->groupbyExpr = pSupporter->groupbyExpr;
|
||||
memcpy(&pQueryInfo->interval, &pSupporter->interval, sizeof(pQueryInfo->interval));
|
||||
|
||||
tscTagCondCopy(&pQueryInfo->tagCond, &pSupporter->tagCond);
|
||||
|
||||
|
@ -1214,14 +1208,13 @@ int32_t tscCreateJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter
|
|||
}
|
||||
|
||||
pNew->cmd.numOfCols = 0;
|
||||
pNewQueryInfo->intervalTime = 0;
|
||||
pNewQueryInfo->interval.interval = 0;
|
||||
pSupporter->limit = pNewQueryInfo->limit;
|
||||
|
||||
pNewQueryInfo->limit.limit = -1;
|
||||
pNewQueryInfo->limit.offset = 0;
|
||||
|
||||
// backup the data and clear it in the sqlcmd object
|
||||
pSupporter->groupbyExpr = pNewQueryInfo->groupbyExpr;
|
||||
memset(&pNewQueryInfo->groupbyExpr, 0, sizeof(SSqlGroupbyExpr));
|
||||
|
||||
tscInitQueryInfo(pNewQueryInfo);
|
||||
|
@ -1391,7 +1384,7 @@ static void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs, SSubqueryState
|
|||
taosTFree(pSupport->localBuffer);
|
||||
taosTFree(pSupport);
|
||||
|
||||
tscFreeSqlObj(pSub);
|
||||
taos_free_result(pSub);
|
||||
}
|
||||
|
||||
free(pState);
|
||||
|
@ -1523,9 +1516,9 @@ static void tscFreeSubSqlObj(SRetrieveSupport *trsupport, SSqlObj *pSql) {
|
|||
SSqlObj *pParentSql = trsupport->pParentSql;
|
||||
|
||||
assert(pSql == pParentSql->pSubs[index]);
|
||||
pParentSql->pSubs[index] = NULL;
|
||||
|
||||
taos_free_result(pSql);
|
||||
// pParentSql->pSubs[index] = NULL;
|
||||
//
|
||||
// taos_free_result(pSql);
|
||||
taosTFree(trsupport->localBuffer);
|
||||
taosTFree(trsupport);
|
||||
}
|
||||
|
@ -1739,10 +1732,6 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR
|
|||
|
||||
assert(tres != NULL);
|
||||
SSqlObj *pSql = (SSqlObj *)tres;
|
||||
// if (pSql == NULL) { // sql object has been released in error process, return immediately
|
||||
// tscDebug("%p subquery has been released, idx:%d, abort", pParentSql, idx);
|
||||
// return;
|
||||
// }
|
||||
|
||||
SSubqueryState* pState = trsupport->pState;
|
||||
assert(pState->numOfRemain <= pState->numOfTotal && pState->numOfRemain >= 0 && pParentSql->numOfSubs == pState->numOfTotal);
|
||||
|
@ -1918,9 +1907,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows)
|
|||
pParentObj->res.code = pSql->res.code;
|
||||
}
|
||||
|
||||
taos_free_result(tres);
|
||||
taosTFree(pSupporter);
|
||||
|
||||
if (atomic_sub_fetch_32(&pState->numOfRemain, 1) > 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -1964,28 +1951,27 @@ int32_t tscHandleInsertRetry(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) {
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
SSqlCmd *pCmd = &pSql->cmd;
|
||||
SSqlRes *pRes = &pSql->res;
|
||||
|
||||
size_t size = taosArrayGetSize(pCmd->pDataBlocks);
|
||||
assert(size > 0);
|
||||
pSql->numOfSubs = (uint16_t)taosArrayGetSize(pCmd->pDataBlocks);
|
||||
assert(pSql->numOfSubs > 0);
|
||||
|
||||
pRes->code = TSDB_CODE_SUCCESS;
|
||||
|
||||
// the number of already initialized subqueries
|
||||
int32_t numOfSub = 0;
|
||||
|
||||
pSql->numOfSubs = (uint16_t)size;
|
||||
pSql->pSubs = calloc(size, POINTER_BYTES);
|
||||
if (pSql->pSubs == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
tscDebug("%p submit data to %" PRIzu " vnode(s)", pSql, size);
|
||||
|
||||
SSubqueryState *pState = calloc(1, sizeof(SSubqueryState));
|
||||
pState->numOfTotal = pSql->numOfSubs;
|
||||
pState->numOfRemain = pSql->numOfSubs;
|
||||
|
||||
pRes->code = TSDB_CODE_SUCCESS;
|
||||
pSql->pSubs = calloc(pSql->numOfSubs, POINTER_BYTES);
|
||||
if (pSql->pSubs == NULL) {
|
||||
goto _error;
|
||||
}
|
||||
|
||||
tscDebug("%p submit data to %d vnode(s)", pSql, pSql->numOfSubs);
|
||||
|
||||
while(numOfSub < pSql->numOfSubs) {
|
||||
SInsertSupporter* pSupporter = calloc(1, sizeof(SInsertSupporter));
|
||||
|
@ -2016,8 +2002,8 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) {
|
|||
tscDebug("%p sub:%p create subObj success. orderOfSub:%d", pSql, pNew, numOfSub);
|
||||
numOfSub++;
|
||||
} else {
|
||||
tscDebug("%p prepare submit data block failed in async insertion, vnodeIdx:%d, total:%" PRIzu ", code:%s", pSql, numOfSub,
|
||||
size, tstrerror(pRes->code));
|
||||
tscDebug("%p prepare submit data block failed in async insertion, vnodeIdx:%d, total:%d, code:%s", pSql, numOfSub,
|
||||
pSql->numOfSubs, tstrerror(pRes->code));
|
||||
goto _error;
|
||||
}
|
||||
}
|
||||
|
@ -2040,11 +2026,6 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
|
||||
_error:
|
||||
for(int32_t j = 0; j < numOfSub; ++j) {
|
||||
taosTFree(pSql->pSubs[j]->param);
|
||||
taos_free_result(pSql->pSubs[j]);
|
||||
}
|
||||
|
||||
taosTFree(pState);
|
||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||
}
|
||||
|
@ -2208,7 +2189,7 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) {
|
|||
}
|
||||
|
||||
// primary key column cannot be null in interval query, no need to check
|
||||
if (i == 0 && pQueryInfo->intervalTime > 0) {
|
||||
if (i == 0 && pQueryInfo->interval.interval > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2220,16 +2201,15 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) {
|
|||
// calculate the result from several other columns
|
||||
if (pSup->pArithExprInfo != NULL) {
|
||||
if (pRes->pArithSup == NULL) {
|
||||
SArithmeticSupport *sas = (SArithmeticSupport *) calloc(1, sizeof(SArithmeticSupport));
|
||||
sas->offset = 0;
|
||||
sas->pArithExpr = pSup->pArithExprInfo;
|
||||
sas->numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
|
||||
sas->exprList = pQueryInfo->exprList;
|
||||
sas->data = calloc(sas->numOfCols, POINTER_BYTES);
|
||||
|
||||
pRes->pArithSup = sas;
|
||||
pRes->pArithSup = (SArithmeticSupport*)calloc(1, sizeof(SArithmeticSupport));
|
||||
}
|
||||
|
||||
pRes->pArithSup->offset = 0;
|
||||
pRes->pArithSup->pArithExpr = pSup->pArithExprInfo;
|
||||
pRes->pArithSup->numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo);
|
||||
pRes->pArithSup->exprList = pQueryInfo->exprList;
|
||||
pRes->pArithSup->data = calloc(pRes->pArithSup->numOfCols, POINTER_BYTES);
|
||||
|
||||
if (pRes->buffer[i] == NULL) {
|
||||
TAOS_FIELD* field = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, i);
|
||||
pRes->buffer[i] = malloc(field->bytes);
|
||||
|
|
|
@ -30,7 +30,8 @@
|
|||
#include "tlocale.h"
|
||||
|
||||
// global, not configurable
|
||||
void * tscCacheHandle;
|
||||
SCacheObj* tscMetaCache;
|
||||
SCacheObj* tscObjCache;
|
||||
void * tscTmr;
|
||||
void * tscQhandle;
|
||||
void * tscCheckDiskUsageTmr;
|
||||
|
@ -121,11 +122,8 @@ 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;
|
||||
|
||||
|
@ -140,12 +138,10 @@ void taos_init_imp(void) {
|
|||
taosTmrReset(tscCheckDiskUsage, 10, NULL, tscTmr, &tscCheckDiskUsageTmr);
|
||||
}
|
||||
|
||||
int64_t refreshTime = tsTableMetaKeepTimer;
|
||||
refreshTime = refreshTime > 10 ? 10 : refreshTime;
|
||||
refreshTime = refreshTime < 10 ? 10 : refreshTime;
|
||||
|
||||
if (tscCacheHandle == NULL) {
|
||||
tscCacheHandle = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, NULL, "tableMeta");
|
||||
int64_t refreshTime = 10; // 10 seconds by default
|
||||
if (tscMetaCache == NULL) {
|
||||
tscMetaCache = taosCacheInit(TSDB_DATA_TYPE_BINARY, refreshTime, false, NULL, "tableMeta");
|
||||
tscObjCache = taosCacheInit(TSDB_CACHE_PTR_KEY, refreshTime / 2, false, tscFreeSqlObjInCache, "sqlObj");
|
||||
}
|
||||
|
||||
tscDebug("client is initialized successfully");
|
||||
|
@ -154,9 +150,12 @@ void taos_init_imp(void) {
|
|||
void taos_init() { pthread_once(&tscinit, taos_init_imp); }
|
||||
|
||||
void taos_cleanup() {
|
||||
if (tscCacheHandle != NULL) {
|
||||
taosCacheCleanup(tscCacheHandle);
|
||||
tscCacheHandle = NULL;
|
||||
if (tscMetaCache != NULL) {
|
||||
taosCacheCleanup(tscMetaCache);
|
||||
tscMetaCache = NULL;
|
||||
|
||||
taosCacheCleanup(tscObjCache);
|
||||
tscObjCache = NULL;
|
||||
}
|
||||
|
||||
if (tscQhandle != NULL) {
|
||||
|
|
|
@ -268,7 +268,7 @@ int32_t tscCreateResPointerInfo(SSqlRes* pRes, SQueryInfo* pQueryInfo) {
|
|||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
void tscDestroyResPointerInfo(SSqlRes* pRes) {
|
||||
static void tscDestroyResPointerInfo(SSqlRes* pRes) {
|
||||
if (pRes->buffer != NULL) { // free all buffers containing the multibyte string
|
||||
for (int i = 0; i < pRes->numOfCols; i++) {
|
||||
taosTFree(pRes->buffer[i]);
|
||||
|
@ -344,8 +344,6 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
SSqlCmd* pCmd = &pSql->cmd;
|
||||
STscObj* pObj = pSql->pTscObj;
|
||||
|
||||
int32_t cmd = pCmd->command;
|
||||
if (cmd < TSDB_SQL_INSERT || cmd == TSDB_SQL_RETRIEVE_LOCALMERGE || cmd == TSDB_SQL_RETRIEVE_EMPTY_RESULT ||
|
||||
cmd == TSDB_SQL_TABLE_JOIN_RETRIEVE) {
|
||||
|
@ -353,26 +351,71 @@ void tscPartiallyFreeSqlObj(SSqlObj* pSql) {
|
|||
}
|
||||
|
||||
// pSql->sqlstr will be used by tscBuildQueryStreamDesc
|
||||
if (pObj->signature == pObj) {
|
||||
// if (pObj->signature == pObj) {
|
||||
//pthread_mutex_lock(&pObj->mutex);
|
||||
taosTFree(pSql->sqlstr);
|
||||
//pthread_mutex_unlock(&pObj->mutex);
|
||||
}
|
||||
// }
|
||||
|
||||
tscFreeSqlResult(pSql);
|
||||
|
||||
taosTFree(pSql->pSubs);
|
||||
pSql->numOfSubs = 0;
|
||||
pSql->self = 0;
|
||||
|
||||
tscResetSqlCmdObj(pCmd, false);
|
||||
}
|
||||
|
||||
static UNUSED_FUNC void tscFreeSubobj(SSqlObj* pSql) {
|
||||
if (pSql->numOfSubs == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p start to free sub SqlObj, numOfSub:%d", pSql, pSql->numOfSubs);
|
||||
|
||||
for(int32_t i = 0; i < pSql->numOfSubs; ++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;
|
||||
}
|
||||
|
||||
/**
|
||||
* The free operation will cause the pSql to be removed from hash table and free it in
|
||||
* the function of processmsgfromserver is impossible in this case, since it will fail
|
||||
* to retrieve pSqlObj in hashtable.
|
||||
*
|
||||
* @param pSql
|
||||
*/
|
||||
void tscFreeSqlObjInCache(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);
|
||||
tscCloseTscObj(pTscObj);
|
||||
}
|
||||
}
|
||||
|
||||
void tscFreeSqlObj(SSqlObj* pSql) {
|
||||
if (pSql == NULL || pSql->signature != pSql) {
|
||||
return;
|
||||
}
|
||||
|
||||
tscDebug("%p start to free sql object", pSql);
|
||||
tscDebug("%p start to free sqlObj", pSql);
|
||||
|
||||
tscFreeSubobj(pSql);
|
||||
tscPartiallyFreeSqlObj(pSql);
|
||||
|
||||
pSql->signature = NULL;
|
||||
|
@ -399,7 +442,10 @@ void tscDestroyDataBlock(STableDataBlocks* pDataBlock) {
|
|||
taosTFree(pDataBlock->params);
|
||||
|
||||
// free the refcount for metermeta
|
||||
taosCacheRelease(tscCacheHandle, (void**)&(pDataBlock->pTableMeta), false);
|
||||
if (pDataBlock->pTableMeta != NULL) {
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pDataBlock->pTableMeta), false);
|
||||
}
|
||||
|
||||
taosTFree(pDataBlock);
|
||||
}
|
||||
|
||||
|
@ -454,9 +500,12 @@ int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) {
|
|||
// set the correct table meta object, the table meta has been locked in pDataBlocks, so it must be in the cache
|
||||
if (pTableMetaInfo->pTableMeta != pDataBlock->pTableMeta) {
|
||||
tstrncpy(pTableMetaInfo->name, pDataBlock->tableId, sizeof(pTableMetaInfo->name));
|
||||
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), false);
|
||||
|
||||
pTableMetaInfo->pTableMeta = taosCacheTransfer(tscCacheHandle, (void**)&pDataBlock->pTableMeta);
|
||||
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), false);
|
||||
}
|
||||
|
||||
pTableMetaInfo->pTableMeta = taosCacheTransfer(tscMetaCache, (void**)&pDataBlock->pTableMeta);
|
||||
} else {
|
||||
assert(strncmp(pTableMetaInfo->name, pDataBlock->tableId, tListLen(pDataBlock->tableId)) == 0);
|
||||
}
|
||||
|
@ -527,7 +576,7 @@ int32_t tscCreateDataBlock(size_t initialSize, int32_t rowSize, int32_t startOff
|
|||
* due to operation such as drop database. So here we add the reference count directly instead of invoke
|
||||
* taosGetDataFromCache, which may return NULL value.
|
||||
*/
|
||||
dataBuf->pTableMeta = taosCacheAcquireByData(tscCacheHandle, pTableMeta);
|
||||
dataBuf->pTableMeta = taosCacheAcquireByData(tscMetaCache, pTableMeta);
|
||||
assert(initialSize > 0 && pTableMeta != NULL && dataBuf->pTableMeta != NULL);
|
||||
|
||||
*dataBlocks = dataBuf;
|
||||
|
@ -724,14 +773,16 @@ void tscCloseTscObj(STscObj* pObj) {
|
|||
|
||||
pObj->signature = NULL;
|
||||
taosTmrStopA(&(pObj->pTimer));
|
||||
pthread_mutex_destroy(&pObj->mutex);
|
||||
|
||||
void* p = pObj->pDnodeConn;
|
||||
if (pObj->pDnodeConn != NULL) {
|
||||
rpcClose(pObj->pDnodeConn);
|
||||
pObj->pDnodeConn = NULL;
|
||||
}
|
||||
|
||||
tscDebug("%p DB connection is closed, dnodeConn:%p", pObj, pObj->pDnodeConn);
|
||||
pthread_mutex_destroy(&pObj->mutex);
|
||||
|
||||
tscDebug("%p DB connection is closed, dnodeConn:%p", pObj, p);
|
||||
taosTFree(pObj);
|
||||
}
|
||||
|
||||
|
@ -1216,6 +1267,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;
|
||||
|
@ -1554,6 +1650,8 @@ int32_t tscAddSubqueryInfo(SSqlCmd* pCmd) {
|
|||
}
|
||||
|
||||
tscInitQueryInfo(pQueryInfo);
|
||||
|
||||
pQueryInfo->window = TSWINDOW_INITIALIZER;
|
||||
pQueryInfo->msg = pCmd->payload; // pointer to the parent error message buffer
|
||||
|
||||
pCmd->pQueryInfo[pCmd->numOfClause++] = pQueryInfo;
|
||||
|
@ -1665,7 +1763,10 @@ void tscClearTableMetaInfo(STableMetaInfo* pTableMetaInfo, bool removeFromCache)
|
|||
return;
|
||||
}
|
||||
|
||||
taosCacheRelease(tscCacheHandle, (void**)&(pTableMetaInfo->pTableMeta), removeFromCache);
|
||||
if (pTableMetaInfo->pTableMeta != NULL) {
|
||||
taosCacheRelease(tscMetaCache, (void**)&(pTableMetaInfo->pTableMeta), removeFromCache);
|
||||
}
|
||||
|
||||
taosTFree(pTableMetaInfo->vgroupList);
|
||||
|
||||
tscColumnListDestroy(pTableMetaInfo->tagColList);
|
||||
|
@ -1681,6 +1782,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) {
|
||||
|
@ -1694,6 +1805,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);
|
||||
|
@ -1708,8 +1821,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;
|
||||
}
|
||||
|
||||
|
@ -1719,6 +1831,8 @@ SSqlObj* createSimpleSubObj(SSqlObj* pSql, void (*fp)(), void* param, int32_t cm
|
|||
STableMetaInfo* pMasterTableMetaInfo = tscGetTableMetaInfoFromCmd(&pSql->cmd, pSql->cmd.clauseIndex, 0);
|
||||
|
||||
tscAddTableMetaInfo(pQueryInfo, pMasterTableMetaInfo->name, NULL, NULL, NULL);
|
||||
|
||||
registerSqlObj(pNew);
|
||||
return pNew;
|
||||
}
|
||||
|
||||
|
@ -1788,6 +1902,7 @@ static void doSetSqlExprAndResultFieldInfo(SQueryInfo* pQueryInfo, SQueryInfo* p
|
|||
}
|
||||
|
||||
assert(matched);
|
||||
(void)matched;
|
||||
}
|
||||
|
||||
tscFieldInfoUpdateOffset(pNewQueryInfo);
|
||||
|
@ -1837,10 +1952,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(pCmd, pCmd->clauseIndex);
|
||||
|
||||
pNewQueryInfo->command = pQueryInfo->command;
|
||||
pNewQueryInfo->intervalTimeUnit = pQueryInfo->intervalTimeUnit;
|
||||
pNewQueryInfo->slidingTimeUnit = pQueryInfo->slidingTimeUnit;
|
||||
pNewQueryInfo->intervalTime = pQueryInfo->intervalTime;
|
||||
pNewQueryInfo->slidingTime = pQueryInfo->slidingTime;
|
||||
memcpy(&pNewQueryInfo->interval, &pQueryInfo->interval, sizeof(pNewQueryInfo->interval));
|
||||
pNewQueryInfo->type = pQueryInfo->type;
|
||||
pNewQueryInfo->window = pQueryInfo->window;
|
||||
pNewQueryInfo->limit = pQueryInfo->limit;
|
||||
|
@ -1911,14 +2023,14 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
STableMetaInfo* pFinalInfo = NULL;
|
||||
|
||||
if (pPrevSql == NULL) {
|
||||
STableMeta* pTableMeta = taosCacheAcquireByData(tscCacheHandle, pTableMetaInfo->pTableMeta); // get by name may failed due to the cache cleanup
|
||||
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);
|
||||
} else { // transfer the ownership of pTableMeta to the newly create sql object.
|
||||
STableMetaInfo* pPrevInfo = tscGetTableMetaInfoFromCmd(&pPrevSql->cmd, pPrevSql->cmd.clauseIndex, 0);
|
||||
|
||||
STableMeta* pPrevTableMeta = taosCacheTransfer(tscCacheHandle, (void**)&pPrevInfo->pTableMeta);
|
||||
STableMeta* pPrevTableMeta = taosCacheTransfer(tscMetaCache, (void**)&pPrevInfo->pTableMeta);
|
||||
|
||||
SVgroupsInfo* pVgroupsInfo = pPrevInfo->vgroupList;
|
||||
pFinalInfo = tscAddTableMetaInfo(pNewQueryInfo, name, pPrevTableMeta, pVgroupsInfo, pTableMetaInfo->tagColList);
|
||||
|
@ -1958,6 +2070,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void
|
|||
tscDebug("%p new sub insertion: %p, vnodeIdx:%d", pSql, pNew, pTableMetaInfo->vgroupIndex);
|
||||
}
|
||||
|
||||
registerSqlObj(pNew);
|
||||
return pNew;
|
||||
|
||||
_error:
|
||||
|
@ -2069,6 +2182,7 @@ int32_t tscSQLSyntaxErrMsg(char* msg, const char* additionalInfo, const char* s
|
|||
return TSDB_CODE_TSC_SQL_SYNTAX_ERROR;
|
||||
|
||||
}
|
||||
|
||||
int32_t tscInvalidSQLErrMsg(char* msg, const char* additionalInfo, const char* sql) {
|
||||
const char* msgFormat1 = "invalid SQL: %s";
|
||||
const char* msgFormat2 = "invalid SQL: \'%s\' (%s)";
|
||||
|
@ -2099,11 +2213,6 @@ bool tscHasReachLimitation(SQueryInfo* pQueryInfo, SSqlRes* pRes) {
|
|||
return (pQueryInfo->clauseLimit > 0 && pRes->numOfClauseTotal >= pQueryInfo->clauseLimit);
|
||||
}
|
||||
|
||||
bool tscResultsetFetchCompleted(TAOS_RES *result) {
|
||||
SSqlRes* pRes = result;
|
||||
return pRes->completed;
|
||||
}
|
||||
|
||||
char* tscGetErrorMsgPayload(SSqlCmd* pCmd) { return pCmd->payload; }
|
||||
|
||||
/**
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -174,6 +174,7 @@ extern int32_t rpcDebugFlag;
|
|||
extern int32_t odbcDebugFlag;
|
||||
extern int32_t qDebugFlag;
|
||||
extern int32_t wDebugFlag;
|
||||
extern int32_t cqDebugFlag;
|
||||
extern int32_t debugFlag;
|
||||
|
||||
#define NEEDTO_COMPRESSS_MSG(size) (tsCompressMsgSize != -1 && (size) > tsCompressMsgSize)
|
||||
|
|
|
@ -35,8 +35,6 @@ bool tscValidateTableNameLength(size_t len);
|
|||
|
||||
SColumnFilterInfo* tscFilterInfoClone(const SColumnFilterInfo* src, int32_t numOfFilters);
|
||||
|
||||
int64_t taosAddNatualInterval(int64_t key, int64_t intervalTime, char timeUnit, int16_t precision);
|
||||
int32_t taosCountNatualInterval(int64_t skey, int64_t ekey, int64_t intervalTime, char timeUnit, int16_t precision);
|
||||
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision);
|
||||
// int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision);
|
||||
|
||||
#endif // TDENGINE_NAME_H
|
||||
|
|
|
@ -313,13 +313,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;
|
||||
}
|
||||
|
@ -331,7 +331,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;
|
||||
}
|
||||
|
|
|
@ -131,7 +131,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;
|
||||
|
||||
|
@ -203,6 +203,7 @@ int32_t debugFlag = 0;
|
|||
int32_t sDebugFlag = 135;
|
||||
int32_t wDebugFlag = 135;
|
||||
int32_t tsdbDebugFlag = 131;
|
||||
int32_t cqDebugFlag = 135;
|
||||
|
||||
int32_t (*monitorStartSystemFp)() = NULL;
|
||||
void (*monitorStopSystemFp)() = NULL;
|
||||
|
@ -222,12 +223,13 @@ void taosSetAllDebugFlag() {
|
|||
httpDebugFlag = debugFlag;
|
||||
mqttDebugFlag = debugFlag;
|
||||
monitorDebugFlag = debugFlag;
|
||||
qDebugFlag = debugFlag;
|
||||
rpcDebugFlag = debugFlag;
|
||||
uDebugFlag = debugFlag;
|
||||
sDebugFlag = debugFlag;
|
||||
wDebugFlag = debugFlag;
|
||||
tsdbDebugFlag = debugFlag;
|
||||
qDebugFlag = debugFlag;
|
||||
cqDebugFlag = debugFlag;
|
||||
uInfo("all debug flag are set to %d", debugFlag);
|
||||
}
|
||||
}
|
||||
|
@ -957,17 +959,6 @@ static void doInitGlobalConfig(void) {
|
|||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
// http configs
|
||||
cfg.option = "httpCacheSessions";
|
||||
cfg.ptr = &tsHttpCacheSessions;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG;
|
||||
cfg.minValue = 1;
|
||||
cfg.maxValue = 100000;
|
||||
cfg.ptrLength = 0;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
cfg.option = "httpEnableRecordSql";
|
||||
cfg.ptr = &tsHttpEnableRecordSql;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
|
@ -1023,7 +1014,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;
|
||||
|
@ -1220,6 +1211,16 @@ static void doInitGlobalConfig(void) {
|
|||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
cfg.option = "cqDebugFlag";
|
||||
cfg.ptr = &cqDebugFlag;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_LOG;
|
||||
cfg.minValue = 0;
|
||||
cfg.maxValue = 255;
|
||||
cfg.ptrLength = 0;
|
||||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||
taosInitConfigOption(cfg);
|
||||
|
||||
cfg.option = "tscEnableRecordSql";
|
||||
cfg.ptr = &tsTscEnableRecordSql;
|
||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||
|
|
|
@ -62,10 +62,9 @@ SSchema tGetUserSpecifiedColumnSchema(tVariant* pVal, SStrToken* exprStr, const
|
|||
if (name != NULL) {
|
||||
tstrncpy(s.name, name, sizeof(s.name));
|
||||
} else {
|
||||
size_t len = strdequote(exprStr->z);
|
||||
size_t tlen = MIN(sizeof(s.name), len + 1);
|
||||
|
||||
size_t tlen = MIN(sizeof(s.name), exprStr->n + 1);
|
||||
tstrncpy(s.name, exprStr->z, tlen);
|
||||
strdequote(s.name);
|
||||
}
|
||||
|
||||
return s;
|
||||
|
@ -100,62 +99,7 @@ SColumnFilterInfo* tscFilterInfoClone(const SColumnFilterInfo* src, int32_t numO
|
|||
return pFilter;
|
||||
}
|
||||
|
||||
int64_t taosAddNatualInterval(int64_t key, int64_t intervalTime, char timeUnit, int16_t precision) {
|
||||
key /= 1000;
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
key /= 1000;
|
||||
}
|
||||
|
||||
struct tm tm;
|
||||
time_t t = (time_t)key;
|
||||
localtime_r(&t, &tm);
|
||||
|
||||
if (timeUnit == 'y') {
|
||||
intervalTime *= 12;
|
||||
}
|
||||
|
||||
int mon = (int)(tm.tm_year * 12 + tm.tm_mon + intervalTime);
|
||||
tm.tm_year = mon / 12;
|
||||
tm.tm_mon = mon % 12;
|
||||
|
||||
key = mktime(&tm) * 1000L;
|
||||
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
key *= 1000L;
|
||||
}
|
||||
|
||||
return key;
|
||||
}
|
||||
|
||||
int32_t taosCountNatualInterval(int64_t skey, int64_t ekey, int64_t intervalTime, char timeUnit, int16_t precision) {
|
||||
skey /= 1000;
|
||||
ekey /= 1000;
|
||||
if (precision == TSDB_TIME_PRECISION_MICRO) {
|
||||
skey /= 1000;
|
||||
ekey /= 1000;
|
||||
}
|
||||
if (ekey < skey) {
|
||||
int64_t tmp = ekey;
|
||||
ekey = skey;
|
||||
skey = tmp;
|
||||
}
|
||||
|
||||
struct tm tm;
|
||||
time_t t = (time_t)skey;
|
||||
localtime_r(&t, &tm);
|
||||
int smon = tm.tm_year * 12 + tm.tm_mon;
|
||||
|
||||
t = (time_t)ekey;
|
||||
localtime_r(&t, &tm);
|
||||
int emon = tm.tm_year * 12 + tm.tm_mon;
|
||||
|
||||
if (timeUnit == 'y') {
|
||||
intervalTime *= 12;
|
||||
}
|
||||
|
||||
return (emon - smon) / (int32_t)intervalTime;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, int64_t intervalTime, char timeUnit, int16_t precision) {
|
||||
if (slidingTime == 0) {
|
||||
return startTime;
|
||||
|
@ -220,6 +164,8 @@ int64_t taosGetIntervalStartTimestamp(int64_t startTime, int64_t slidingTime, in
|
|||
return start;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* tablePrefix.columnName
|
||||
* extract table name and save it in pTable, with only column name in pToken
|
||||
|
|
|
@ -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;
|
||||
|
@ -540,9 +511,7 @@ void assignVal(char *val, const char *src, int32_t len, int32_t type) {
|
|||
}
|
||||
}
|
||||
|
||||
void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size) {
|
||||
char tmpBuf[4096] = {0};
|
||||
|
||||
void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf) {
|
||||
switch (type) {
|
||||
case TSDB_DATA_TYPE_INT: {
|
||||
SWAP(*(int32_t *)(pLeft), *(int32_t *)(pRight), int32_t);
|
||||
|
@ -575,10 +544,9 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size) {
|
|||
}
|
||||
|
||||
default: {
|
||||
assert(size <= 4096);
|
||||
memcpy(tmpBuf, pLeft, size);
|
||||
memcpy(buf, pLeft, size);
|
||||
memcpy(pLeft, pRight, size);
|
||||
memcpy(pRight, tmpBuf, size);
|
||||
memcpy(pRight, buf, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -709,46 +709,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 +740,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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
<packaging>jar</packaging>
|
||||
<name>JDBCDriver</name>
|
||||
<url>https://github.com/taosdata/TDengine/tree/master/src/connector/jdbc</url>
|
||||
|
||||
<description>TDengine JDBC Driver</description>
|
||||
<licenses>
|
||||
<license>
|
||||
|
@ -48,17 +49,13 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-lang3</artifactId>
|
||||
<version>${commons-lang3.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<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
|
||||
|
|
|
@ -53,66 +53,12 @@ public class TSDBConnection implements Connection {
|
|||
public TSDBConnection(Properties info, TSDBDatabaseMetaData meta) throws SQLException {
|
||||
this.dbMetaData = meta;
|
||||
|
||||
//load taos.cfg start
|
||||
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);
|
||||
if (!endpoints.isEmpty()) {
|
||||
info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]);
|
||||
info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]);
|
||||
}
|
||||
//load taos.cfg end
|
||||
|
||||
connect(info.getProperty(TSDBDriver.PROPERTY_KEY_HOST),
|
||||
Integer.parseInt(info.getProperty(TSDBDriver.PROPERTY_KEY_PORT, "0")),
|
||||
info.getProperty(TSDBDriver.PROPERTY_KEY_DBNAME), info.getProperty(TSDBDriver.PROPERTY_KEY_USER),
|
||||
info.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD));
|
||||
}
|
||||
|
||||
private List<String> loadConfigEndpoints(File cfgFile) {
|
||||
List<String> endpoints = new ArrayList<>();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) {
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) {
|
||||
endpoints.add(line.substring(line.indexOf('p') + 1).trim());
|
||||
}
|
||||
if (endpoints.size() > 1)
|
||||
break;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cfgDirPath
|
||||
* @return return the config dir
|
||||
**/
|
||||
private File loadConfigDir(String cfgDirPath) {
|
||||
if (cfgDirPath == null)
|
||||
return loadDefaultConfigDir();
|
||||
File cfgDir = new File(cfgDirPath);
|
||||
if (!cfgDir.exists())
|
||||
return loadDefaultConfigDir();
|
||||
return cfgDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return search the default config dir, if the config dir is not exist will return null
|
||||
*/
|
||||
private File loadDefaultConfigDir() {
|
||||
File cfgDir;
|
||||
File cfgDir_linux = new File("/etc/taos");
|
||||
cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null;
|
||||
File cfgDir_windows = new File("C:\\TDengine\\cfg");
|
||||
cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir;
|
||||
return cfgDir;
|
||||
}
|
||||
|
||||
private void connect(String host, int port, String dbName, String user, String password) throws SQLException {
|
||||
this.connector = new TSDBJNIConnector();
|
||||
this.connector.connect(host, port, dbName, user, password);
|
||||
|
|
|
@ -68,15 +68,15 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
|
|||
}
|
||||
|
||||
public boolean nullsAreSortedLow() throws SQLException {
|
||||
return false;
|
||||
return !nullsAreSortedHigh();
|
||||
}
|
||||
|
||||
public boolean nullsAreSortedAtStart() throws SQLException {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean nullsAreSortedAtEnd() throws SQLException {
|
||||
return false;
|
||||
return !nullsAreSortedAtStart();
|
||||
}
|
||||
|
||||
public String getDatabaseProductName() throws SQLException {
|
||||
|
@ -586,7 +586,171 @@ public class TSDBDatabaseMetaData implements java.sql.DatabaseMetaData {
|
|||
|
||||
public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern)
|
||||
throws SQLException {
|
||||
return getEmptyResultSet();
|
||||
|
||||
|
||||
/** add by zyyang **********/
|
||||
Statement stmt = null;
|
||||
if (null != conn && !conn.isClosed()) {
|
||||
stmt = conn.createStatement();
|
||||
if (catalog == null || catalog.length() < 1) {
|
||||
catalog = conn.getCatalog();
|
||||
}
|
||||
stmt.executeUpdate("use " + catalog);
|
||||
|
||||
DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
|
||||
// set up ColumnMetaDataList
|
||||
List<ColumnMetaData> columnMetaDataList = new ArrayList<>(24);
|
||||
columnMetaDataList.add(null);
|
||||
columnMetaDataList.add(null);
|
||||
// add TABLE_NAME
|
||||
ColumnMetaData colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(3);
|
||||
colMetaData.setColName("TABLE_NAME");
|
||||
colMetaData.setColSize(193);
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add COLUMN_NAME
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(4);
|
||||
colMetaData.setColName("COLUMN_NAME");
|
||||
colMetaData.setColSize(65);
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add DATA_TYPE
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(5);
|
||||
colMetaData.setColName("DATA_TYPE");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add TYPE_NAME
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(6);
|
||||
colMetaData.setColName("TYPE_NAME");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_BINARY);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add COLUMN_SIZE
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(7);
|
||||
colMetaData.setColName("COLUMN_SIZE");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add BUFFER_LENGTH ,not used
|
||||
columnMetaDataList.add(null);
|
||||
// add DECIMAL_DIGITS
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(9);
|
||||
colMetaData.setColName("DECIMAL_DIGITS");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add NUM_PREC_RADIX
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(10);
|
||||
colMetaData.setColName("NUM_PREC_RADIX");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
// add NULLABLE
|
||||
colMetaData = new ColumnMetaData();
|
||||
colMetaData.setColIndex(11);
|
||||
colMetaData.setColName("NULLABLE");
|
||||
colMetaData.setColType(TSDBConstants.TSDB_DATA_TYPE_INT);
|
||||
columnMetaDataList.add(colMetaData);
|
||||
|
||||
resultSet.setColumnMetaDataList(columnMetaDataList);
|
||||
|
||||
// set up rowDataList
|
||||
ResultSet resultSet0 = stmt.executeQuery("describe " + tableNamePattern);
|
||||
List<TSDBResultSetRowData> rowDataList = new ArrayList<>();
|
||||
int index = 0;
|
||||
while (resultSet0.next()) {
|
||||
TSDBResultSetRowData rowData = new TSDBResultSetRowData(24);
|
||||
// set TABLE_NAME
|
||||
rowData.setString(2, tableNamePattern);
|
||||
// set COLUMN_NAME
|
||||
rowData.setString(3, resultSet0.getString(1));
|
||||
// set DATA_TYPE
|
||||
String typeName = resultSet0.getString(2);
|
||||
rowData.setInt(4, getDataType(typeName));
|
||||
// set TYPE_NAME
|
||||
rowData.setString(5, typeName);
|
||||
// set COLUMN_SIZE
|
||||
int length = resultSet0.getInt(3);
|
||||
rowData.setInt(6, getColumnSize(typeName, length));
|
||||
// set DECIMAL_DIGITS
|
||||
rowData.setInt(8, getDecimalDigits(typeName));
|
||||
// set NUM_PREC_RADIX
|
||||
rowData.setInt(9, 10);
|
||||
// set NULLABLE
|
||||
rowData.setInt(10, getNullable(index, typeName));
|
||||
rowDataList.add(rowData);
|
||||
index++;
|
||||
}
|
||||
resultSet.setRowDataList(rowDataList);
|
||||
|
||||
// GetColumnsResultSet getColumnsResultSet = new GetColumnsResultSet(resultSet0, catalog, schemaPattern, tableNamePattern, columnNamePattern);
|
||||
// return getColumnsResultSet;
|
||||
// DatabaseMetaDataResultSet resultSet = new DatabaseMetaDataResultSet();
|
||||
return resultSet;
|
||||
} else {
|
||||
throw new SQLException(TSDBConstants.FixErrMsg(TSDBConstants.JNI_CONNECTION_NULL));
|
||||
}
|
||||
|
||||
/*************************/
|
||||
|
||||
// return getEmptyResultSet();
|
||||
}
|
||||
|
||||
private int getNullable(int index, String typeName) {
|
||||
if (index == 0 && "TIMESTAMP".equals(typeName))
|
||||
return DatabaseMetaData.columnNoNulls;
|
||||
return DatabaseMetaData.columnNullable;
|
||||
}
|
||||
|
||||
private int getColumnSize(String typeName, int length) {
|
||||
switch (typeName) {
|
||||
case "TIMESTAMP":
|
||||
return 23;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int getDecimalDigits(String typeName) {
|
||||
switch (typeName) {
|
||||
case "FLOAT":
|
||||
return 5;
|
||||
case "DOUBLE":
|
||||
return 9;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private int getDataType(String typeName) {
|
||||
switch (typeName) {
|
||||
case "TIMESTAMP":
|
||||
return Types.TIMESTAMP;
|
||||
case "INT":
|
||||
return Types.INTEGER;
|
||||
case "BIGINT":
|
||||
return Types.BIGINT;
|
||||
case "FLOAT":
|
||||
return Types.FLOAT;
|
||||
case "DOUBLE":
|
||||
return Types.DOUBLE;
|
||||
case "BINARY":
|
||||
return Types.BINARY;
|
||||
case "SMALLINT":
|
||||
return Types.SMALLINT;
|
||||
case "TINYINT":
|
||||
return Types.TINYINT;
|
||||
case "BOOL":
|
||||
return Types.BOOLEAN;
|
||||
case "NCHAR":
|
||||
return Types.NCHAR;
|
||||
default:
|
||||
return Types.NULL;
|
||||
}
|
||||
}
|
||||
|
||||
public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern)
|
||||
|
|
|
@ -14,9 +14,12 @@
|
|||
*****************************************************************************/
|
||||
package com.taosdata.jdbc;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
|
@ -41,6 +44,7 @@ import java.util.logging.Logger;
|
|||
*/
|
||||
public class TSDBDriver implements java.sql.Driver {
|
||||
|
||||
|
||||
@Deprecated
|
||||
private static final String URL_PREFIX1 = "jdbc:TSDB://";
|
||||
|
||||
|
@ -75,6 +79,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
*/
|
||||
public static final String PROPERTY_KEY_USER = "user";
|
||||
|
||||
|
||||
/**
|
||||
* Key for the configuration file directory of TSDB client in properties instance
|
||||
*/
|
||||
|
@ -98,6 +103,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
|
||||
public static final String PROPERTY_KEY_PROTOCOL = "protocol";
|
||||
|
||||
|
||||
/**
|
||||
* Index for port coming out of parseHostPortPair().
|
||||
*/
|
||||
|
@ -118,17 +124,71 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
}
|
||||
}
|
||||
|
||||
private List<String> loadConfigEndpoints(File cfgFile) {
|
||||
List<String> endpoints = new ArrayList<>();
|
||||
try (BufferedReader reader = new BufferedReader(new FileReader(cfgFile))) {
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
if (line.trim().startsWith("firstEp") || line.trim().startsWith("secondEp")) {
|
||||
endpoints.add(line.substring(line.indexOf('p') + 1).trim());
|
||||
}
|
||||
if (endpoints.size() > 1)
|
||||
break;
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return endpoints;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param cfgDirPath
|
||||
* @return return the config dir
|
||||
**/
|
||||
private File loadConfigDir(String cfgDirPath) {
|
||||
if (cfgDirPath == null)
|
||||
return loadDefaultConfigDir();
|
||||
File cfgDir = new File(cfgDirPath);
|
||||
if (!cfgDir.exists())
|
||||
return loadDefaultConfigDir();
|
||||
return cfgDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return search the default config dir, if the config dir is not exist will return null
|
||||
*/
|
||||
private File loadDefaultConfigDir() {
|
||||
File cfgDir;
|
||||
File cfgDir_linux = new File("/etc/taos");
|
||||
cfgDir = cfgDir_linux.exists() ? cfgDir_linux : null;
|
||||
File cfgDir_windows = new File("C:\\TDengine\\cfg");
|
||||
cfgDir = (cfgDir == null && cfgDir_windows.exists()) ? cfgDir_windows : cfgDir;
|
||||
return cfgDir;
|
||||
}
|
||||
|
||||
public Connection connect(String url, Properties info) throws SQLException {
|
||||
if (url == null) {
|
||||
throw new SQLException(TSDBConstants.WrapErrMsg("url is not set!"));
|
||||
}
|
||||
|
||||
Properties props = null;
|
||||
|
||||
if ((props = parseURL(url, info)) == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//load taos.cfg start
|
||||
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);
|
||||
if (!endpoints.isEmpty()) {
|
||||
info.setProperty(TSDBDriver.PROPERTY_KEY_HOST, endpoints.get(0).split(":")[0]);
|
||||
info.setProperty(TSDBDriver.PROPERTY_KEY_PORT, endpoints.get(0).split(":")[1]);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE), (String) props.get(PROPERTY_KEY_CHARSET),
|
||||
(String) props.get(PROPERTY_KEY_TIME_ZONE));
|
||||
|
@ -153,13 +213,9 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
* and the element of index PORT_NUMBER_INDEX being the port (or null if not
|
||||
* specified).
|
||||
*
|
||||
* @param hostPortPair
|
||||
* host and port in form of of [host][:port]
|
||||
*
|
||||
* @param hostPortPair host and port in form of of [host][:port]
|
||||
* @return array containing host and port as Strings
|
||||
*
|
||||
* @throws SQLException
|
||||
* if a parse error occurs
|
||||
* @throws SQLException if a parse error occurs
|
||||
*/
|
||||
protected static String[] parseHostPortPair(String hostPortPair) throws SQLException {
|
||||
String[] splitValues = new String[2];
|
||||
|
@ -188,7 +244,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
}
|
||||
|
||||
public boolean acceptsURL(String url) throws SQLException {
|
||||
return StringUtils.isNotBlank(url) && url.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 {
|
||||
|
@ -203,8 +259,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
DriverPropertyInfo hostProp = new DriverPropertyInfo(PROPERTY_KEY_HOST, info.getProperty(PROPERTY_KEY_HOST));
|
||||
hostProp.required = true;
|
||||
|
||||
DriverPropertyInfo portProp = new DriverPropertyInfo(PROPERTY_KEY_PORT,
|
||||
info.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
|
||||
DriverPropertyInfo portProp = new DriverPropertyInfo(PROPERTY_KEY_PORT, info.getProperty(PROPERTY_KEY_PORT, TSDBConstants.DEFAULT_PORT));
|
||||
portProp.required = false;
|
||||
|
||||
DriverPropertyInfo dbProp = new DriverPropertyInfo(PROPERTY_KEY_DBNAME, info.getProperty(PROPERTY_KEY_DBNAME));
|
||||
|
@ -214,8 +269,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
DriverPropertyInfo userProp = new DriverPropertyInfo(PROPERTY_KEY_USER, info.getProperty(PROPERTY_KEY_USER));
|
||||
userProp.required = true;
|
||||
|
||||
DriverPropertyInfo passwordProp = new DriverPropertyInfo(PROPERTY_KEY_PASSWORD,
|
||||
info.getProperty(PROPERTY_KEY_PASSWORD));
|
||||
DriverPropertyInfo passwordProp = new DriverPropertyInfo(PROPERTY_KEY_PASSWORD, info.getProperty(PROPERTY_KEY_PASSWORD));
|
||||
passwordProp.required = true;
|
||||
|
||||
DriverPropertyInfo[] propertyInfo = new DriverPropertyInfo[5];
|
||||
|
@ -231,14 +285,13 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
/**
|
||||
* example: jdbc:TSDB://127.0.0.1:0/db?user=root&password=your_password
|
||||
*/
|
||||
|
||||
public Properties parseURL(String url, Properties defaults) throws java.sql.SQLException {
|
||||
Properties urlProps = (defaults != null) ? defaults : new Properties();
|
||||
if (url == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (!StringUtils.startsWithIgnoreCase(url, URL_PREFIX) && !StringUtils.startsWithIgnoreCase(url, URL_PREFIX1)) {
|
||||
if (!url.startsWith(URL_PREFIX) && !url.startsWith(URL_PREFIX1)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -339,9 +392,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
/**
|
||||
* Returns the host property
|
||||
*
|
||||
* @param props
|
||||
* the java.util.Properties instance to retrieve the hostname from.
|
||||
*
|
||||
* @param props the java.util.Properties instance to retrieve the hostname from.
|
||||
* @return the host
|
||||
*/
|
||||
public String host(Properties props) {
|
||||
|
@ -351,9 +402,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
/**
|
||||
* Returns the port number property
|
||||
*
|
||||
* @param props
|
||||
* the properties to get the port number from
|
||||
*
|
||||
* @param props the properties to get the port number from
|
||||
* @return the port number
|
||||
*/
|
||||
public int port(Properties props) {
|
||||
|
@ -363,9 +412,7 @@ public class TSDBDriver implements java.sql.Driver {
|
|||
/**
|
||||
* Returns the database property from <code>props</code>
|
||||
*
|
||||
* @param props
|
||||
* the Properties to look for the database property.
|
||||
*
|
||||
* @param props the Properties to look for the database property.
|
||||
* @return the database name.
|
||||
*/
|
||||
public String database(Properties props) {
|
||||
|
|
|
@ -242,7 +242,7 @@ public class TSDBStatement implements Statement {
|
|||
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
if (batchedArgs == null) {
|
||||
batchedArgs = new ArrayList<String>();
|
||||
batchedArgs = new ArrayList<>();
|
||||
}
|
||||
batchedArgs.add(sql);
|
||||
}
|
||||
|
|
|
@ -10,8 +10,6 @@ import java.sql.SQLException;
|
|||
import java.sql.Statement;
|
||||
import java.util.Properties;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class SubscribeTest extends BaseTest {
|
||||
Connection connection = null;
|
||||
Statement statement = null;
|
||||
|
|
|
@ -2,6 +2,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
|||
PROJECT(TDengine)
|
||||
|
||||
INCLUDE_DIRECTORIES(inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc)
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC)
|
||||
|
||||
IF (TD_LINUX)
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
#include <string.h>
|
||||
|
||||
#include "taos.h"
|
||||
#include "tsclient.h"
|
||||
#include "taosdef.h"
|
||||
#include "taosmsg.h"
|
||||
#include "ttimer.h"
|
||||
|
@ -30,10 +31,12 @@
|
|||
#include "tlog.h"
|
||||
#include "twal.h"
|
||||
|
||||
#define cError(...) { if (cqDebugFlag & DEBUG_ERROR) { taosPrintLog("ERROR CQ ", cqDebugFlag, __VA_ARGS__); }}
|
||||
#define cWarn(...) { if (cqDebugFlag & DEBUG_WARN) { taosPrintLog("WARN CQ ", cqDebugFlag, __VA_ARGS__); }}
|
||||
#define cFatal(...) { if (cqDebugFlag & DEBUG_FATAL) { taosPrintLog("CQ FATAL ", 255, __VA_ARGS__); }}
|
||||
#define cError(...) { if (cqDebugFlag & DEBUG_ERROR) { taosPrintLog("CQ ERROR ", 255, __VA_ARGS__); }}
|
||||
#define cWarn(...) { if (cqDebugFlag & DEBUG_WARN) { taosPrintLog("CQ WARN ", 255, __VA_ARGS__); }}
|
||||
#define cInfo(...) { if (cqDebugFlag & DEBUG_INFO) { taosPrintLog("CQ ", 255, __VA_ARGS__); }}
|
||||
#define cDebug(...) { if (cqDebugFlag & DEBUG_DEBUG) { taosPrintLog("CQ ", cqDebugFlag, __VA_ARGS__); }}
|
||||
#define cTrace(...) { if (cqDebugFlag & DEBUG_TRACE) { taosPrintLog("CQ ", cqDebugFlag, __VA_ARGS__); }}
|
||||
#define cPrint(...) { taosPrintLog("CQ ", 255, __VA_ARGS__); }
|
||||
|
||||
typedef struct {
|
||||
int vgId;
|
||||
|
@ -63,8 +66,6 @@ typedef struct SCqObj {
|
|||
SCqContext * pContext;
|
||||
} SCqObj;
|
||||
|
||||
int cqDebugFlag = 135;
|
||||
|
||||
static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row);
|
||||
static void cqCreateStream(SCqContext *pContext, SCqObj *pObj);
|
||||
|
||||
|
@ -94,7 +95,7 @@ void *cqOpen(void *ahandle, const SCqCfg *pCfg) {
|
|||
|
||||
pthread_mutex_init(&pContext->mutex, NULL);
|
||||
|
||||
cTrace("vgId:%d, CQ is opened", pContext->vgId);
|
||||
cInfo("vgId:%d, CQ is opened", pContext->vgId);
|
||||
|
||||
return pContext;
|
||||
}
|
||||
|
@ -125,7 +126,7 @@ void cqClose(void *handle) {
|
|||
taosTmrCleanUp(pContext->tmrCtrl);
|
||||
pContext->tmrCtrl = NULL;
|
||||
|
||||
cTrace("vgId:%d, CQ is closed", pContext->vgId);
|
||||
cInfo("vgId:%d, CQ is closed", pContext->vgId);
|
||||
free(pContext);
|
||||
}
|
||||
|
||||
|
@ -133,7 +134,7 @@ void cqStart(void *handle) {
|
|||
SCqContext *pContext = handle;
|
||||
if (pContext->dbConn || pContext->master) return;
|
||||
|
||||
cTrace("vgId:%d, start all CQs", pContext->vgId);
|
||||
cInfo("vgId:%d, start all CQs", pContext->vgId);
|
||||
pthread_mutex_lock(&pContext->mutex);
|
||||
|
||||
pContext->master = 1;
|
||||
|
@ -149,7 +150,7 @@ void cqStart(void *handle) {
|
|||
|
||||
void cqStop(void *handle) {
|
||||
SCqContext *pContext = handle;
|
||||
cTrace("vgId:%d, stop all CQs", pContext->vgId);
|
||||
cInfo("vgId:%d, stop all CQs", pContext->vgId);
|
||||
if (pContext->dbConn == NULL || pContext->master == 0) return;
|
||||
|
||||
pthread_mutex_lock(&pContext->mutex);
|
||||
|
@ -160,7 +161,7 @@ void cqStop(void *handle) {
|
|||
if (pObj->pStream) {
|
||||
taos_close_stream(pObj->pStream);
|
||||
pObj->pStream = NULL;
|
||||
cTrace("vgId:%d, id:%d CQ:%s is closed", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
cInfo("vgId:%d, id:%d CQ:%s is closed", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
} else {
|
||||
taosTmrStop(pObj->tmrId);
|
||||
pObj->tmrId = 0;
|
||||
|
@ -188,7 +189,7 @@ void *cqCreate(void *handle, uint64_t uid, int tid, char *sqlStr, STSchema *pSch
|
|||
pObj->pSchema = tdDupSchema(pSchema);
|
||||
pObj->rowSize = schemaTLen(pSchema);
|
||||
|
||||
cTrace("vgId:%d, id:%d CQ:%s is created", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
cInfo("vgId:%d, id:%d CQ:%s is created", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
|
||||
pthread_mutex_lock(&pContext->mutex);
|
||||
|
||||
|
@ -228,7 +229,7 @@ void cqDrop(void *handle) {
|
|||
pObj->tmrId = 0;
|
||||
}
|
||||
|
||||
cTrace("vgId:%d, id:%d CQ:%s is dropped", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
cInfo("vgId:%d, id:%d CQ:%s is dropped", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
tdFreeSchema(pObj->pSchema);
|
||||
free(pObj->sqlStr);
|
||||
free(pObj);
|
||||
|
@ -236,24 +237,31 @@ void cqDrop(void *handle) {
|
|||
pthread_mutex_unlock(&pContext->mutex);
|
||||
}
|
||||
|
||||
static void doCreateStream(void *param, TAOS_RES *result, int code) {
|
||||
SCqObj* pObj = (SCqObj*)param;
|
||||
SCqContext* pContext = pObj->pContext;
|
||||
SSqlObj* pSql = (SSqlObj*)result;
|
||||
pContext->dbConn = pSql->pTscObj;
|
||||
cqCreateStream(pContext, pObj);
|
||||
}
|
||||
|
||||
static void cqProcessCreateTimer(void *param, void *tmrId) {
|
||||
SCqObj* pObj = (SCqObj*)param;
|
||||
SCqContext* pContext = pObj->pContext;
|
||||
|
||||
if (pContext->dbConn == NULL) {
|
||||
pContext->dbConn = taos_connect("localhost", pContext->user, pContext->pass, pContext->db, 0);
|
||||
if (pContext->dbConn == NULL) {
|
||||
cError("vgId:%d, failed to connect to TDengine(%s)", pContext->vgId, tstrerror(terrno));
|
||||
}
|
||||
}
|
||||
|
||||
cDebug("vgId:%d, try connect to TDengine", pContext->vgId);
|
||||
taos_connect_a(NULL, pContext->user, pContext->pass, pContext->db, 0, doCreateStream, param, NULL);
|
||||
} else {
|
||||
cqCreateStream(pContext, pObj);
|
||||
}
|
||||
}
|
||||
|
||||
static void cqCreateStream(SCqContext *pContext, SCqObj *pObj) {
|
||||
pObj->pContext = pContext;
|
||||
|
||||
if (pContext->dbConn == NULL) {
|
||||
cDebug("vgId:%d, create dbConn after 1000 ms", pContext->vgId);
|
||||
pObj->tmrId = taosTmrStart(cqProcessCreateTimer, 1000, pObj, pContext->tmrCtrl);
|
||||
return;
|
||||
}
|
||||
|
@ -262,7 +270,7 @@ static void cqCreateStream(SCqContext *pContext, SCqObj *pObj) {
|
|||
pObj->pStream = taos_open_stream(pContext->dbConn, pObj->sqlStr, cqProcessStreamRes, 0, pObj, NULL);
|
||||
if (pObj->pStream) {
|
||||
pContext->num++;
|
||||
cTrace("vgId:%d, id:%d CQ:%s is openned", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
cInfo("vgId:%d, id:%d CQ:%s is openned", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
} else {
|
||||
cError("vgId:%d, id:%d CQ:%s, failed to open", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
}
|
||||
|
@ -278,7 +286,7 @@ static void cqProcessStreamRes(void *param, TAOS_RES *tres, TAOS_ROW row) {
|
|||
STSchema *pSchema = pObj->pSchema;
|
||||
if (pObj->pStream == NULL) return;
|
||||
|
||||
cTrace("vgId:%d, id:%d CQ:%s stream result is ready", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
cDebug("vgId:%d, id:%d CQ:%s stream result is ready", pContext->vgId, pObj->tid, pObj->sqlStr);
|
||||
|
||||
int size = sizeof(SWalHead) + sizeof(SSubmitMsg) + sizeof(SSubmitBlk) + TD_DATA_ROW_HEAD_SIZE + pObj->rowSize;
|
||||
char *buffer = calloc(size, 1);
|
||||
|
|
|
@ -464,7 +464,30 @@ void dnodeUpdateMnodeEpSetForPeer(SRpcEpSet *pEpSet) {
|
|||
dInfo("mnode EP list for peer is changed, numOfEps:%d inUse:%d", pEpSet->numOfEps, pEpSet->inUse);
|
||||
for (int i = 0; i < pEpSet->numOfEps; ++i) {
|
||||
pEpSet->port[i] -= TSDB_PORT_DNODEDNODE;
|
||||
dInfo("mnode index:%d %s:%u", i, pEpSet->fqdn[i], pEpSet->port[i])
|
||||
dInfo("mnode index:%d %s:%u", i, pEpSet->fqdn[i], pEpSet->port[i]);
|
||||
|
||||
if (!mnodeIsRunning()) {
|
||||
if (strcmp(pEpSet->fqdn[i], tsLocalFqdn) == 0 && pEpSet->port[i] == tsServerPort) {
|
||||
dInfo("mnode index:%d %s:%u should work as mnode", i, pEpSet->fqdn[i], pEpSet->port[i]);
|
||||
bool find = false;
|
||||
for (int i = 0; i < tsDMnodeInfos.nodeNum; ++i) {
|
||||
if (tsDMnodeInfos.nodeInfos[i].nodeId == dnodeGetDnodeId()) {
|
||||
dInfo("localEp found in mnode infos");
|
||||
find = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!find) {
|
||||
dInfo("localEp not found in mnode infos, will set into mnode infos");
|
||||
tstrncpy(tsDMnodeInfos.nodeInfos[tsDMnodeInfos.nodeNum].nodeEp, tsLocalEp, TSDB_EP_LEN);
|
||||
tsDMnodeInfos.nodeInfos[tsDMnodeInfos.nodeNum].nodeId = dnodeGetDnodeId();
|
||||
tsDMnodeInfos.nodeNum++;
|
||||
}
|
||||
|
||||
dnodeStartMnode();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tsDMnodeEpSet = *pEpSet;
|
||||
|
|
|
@ -146,19 +146,16 @@ void dnodeProcessModuleStatus(uint32_t moduleStatus) {
|
|||
}
|
||||
}
|
||||
|
||||
bool dnodeCheckMnodeStarting() {
|
||||
if (tsModuleStatus & TSDB_MOD_MNODE) return false;
|
||||
|
||||
SDMMnodeInfos *mnodes = dnodeGetMnodeInfos();
|
||||
for (int32_t i = 0; i < mnodes->nodeNum; ++i) {
|
||||
SDMMnodeInfo *node = &mnodes->nodeInfos[i];
|
||||
if (node->nodeId == dnodeGetDnodeId()) {
|
||||
uint32_t moduleStatus = tsModuleStatus | (1 << TSDB_MOD_MNODE);;
|
||||
dInfo("start mnode module, module status:%d, new status:%d", tsModuleStatus, moduleStatus);
|
||||
dnodeProcessModuleStatus(moduleStatus);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool dnodeStartMnode() {
|
||||
if (tsModuleStatus & (1 << TSDB_MOD_MNODE)) {
|
||||
dDebug("mnode module is already started, module status:%d", tsModuleStatus);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t moduleStatus = tsModuleStatus | (1 << TSDB_MOD_MNODE);
|
||||
dInfo("start mnode module, module status:%d, new status:%d", tsModuleStatus, moduleStatus);
|
||||
dnodeProcessModuleStatus(moduleStatus);
|
||||
|
||||
sdbUpdateSync();
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -187,6 +187,7 @@ void dnodeSendRpcReadRsp(void *pVnode, SReadMsg *pRead, int32_t code) {
|
|||
}
|
||||
|
||||
void dnodeDispatchNonRspMsg(void *pVnode, SReadMsg *pRead, int32_t code) {
|
||||
rpcFreeCont(pRead->rpcMsg.pCont);
|
||||
vnodeRelease(pVnode);
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ void dnodeGetMnodeEpSetForPeer(void *epSet);
|
|||
void dnodeGetMnodeEpSetForShell(void *epSet);
|
||||
void * dnodeGetMnodeInfos();
|
||||
int32_t dnodeGetDnodeId();
|
||||
bool dnodeCheckMnodeStarting();
|
||||
bool dnodeStartMnode();
|
||||
|
||||
void dnodeAddClientRspHandle(uint8_t msgType, void (*fp)(SRpcMsg *rpcMsg));
|
||||
void dnodeSendMsgToDnode(SRpcEpSet *epSet, SRpcMsg *rpcMsg);
|
||||
|
|
|
@ -64,7 +64,7 @@ extern const int32_t TYPE_BYTES[11];
|
|||
// TODO: replace and remove code below
|
||||
#define CHAR_BYTES sizeof(char)
|
||||
#define SHORT_BYTES sizeof(int16_t)
|
||||
#define INT_BYTES sizeof(int)
|
||||
#define INT_BYTES sizeof(int32_t)
|
||||
#define LONG_BYTES sizeof(int64_t)
|
||||
#define FLOAT_BYTES sizeof(float)
|
||||
#define DOUBLE_BYTES sizeof(double)
|
||||
|
@ -73,7 +73,7 @@ extern const int32_t TYPE_BYTES[11];
|
|||
#define TSDB_DATA_BOOL_NULL 0x02
|
||||
#define TSDB_DATA_TINYINT_NULL 0x80
|
||||
#define TSDB_DATA_SMALLINT_NULL 0x8000
|
||||
#define TSDB_DATA_INT_NULL 0x80000000
|
||||
#define TSDB_DATA_INT_NULL 0x80000000L
|
||||
#define TSDB_DATA_BIGINT_NULL 0x8000000000000000L
|
||||
|
||||
#define TSDB_DATA_FLOAT_NULL 0x7FF00000 // it is an NAN
|
||||
|
@ -101,6 +101,7 @@ extern const int32_t TYPE_BYTES[11];
|
|||
#define TSDB_TIME_PRECISION_MILLI 0
|
||||
#define TSDB_TIME_PRECISION_MICRO 1
|
||||
#define TSDB_TIME_PRECISION_NANO 2
|
||||
#define TSDB_TICK_PER_SECOND(precision) ((precision)==TSDB_TIME_PRECISION_MILLI ? 1e3L : ((precision)==TSDB_TIME_PRECISION_MICRO ? 1e6L : 1e9L))
|
||||
|
||||
#define TSDB_TIME_PRECISION_MILLI_STR "ms"
|
||||
#define TSDB_TIME_PRECISION_MICRO_STR "us"
|
||||
|
@ -130,22 +131,31 @@ do { \
|
|||
#define GET_INT16_VAL(x) (*(int16_t *)(x))
|
||||
#define GET_INT32_VAL(x) (*(int32_t *)(x))
|
||||
#define GET_INT64_VAL(x) (*(int64_t *)(x))
|
||||
#ifdef _TD_ARM_32_
|
||||
#define GET_FLOAT_VAL(x) taos_align_get_float(x)
|
||||
#define GET_DOUBLE_VAL(x) taos_align_get_double(x)
|
||||
|
||||
float taos_align_get_float(const char* pBuf);
|
||||
double taos_align_get_double(const char* pBuf);
|
||||
#ifdef _TD_ARM_32
|
||||
|
||||
//#define __float_align_declear() float __underlyFloat = 0.0;
|
||||
//#define __float_align_declear()
|
||||
//#define GET_FLOAT_VAL_ALIGN(x) (*(int32_t*)&(__underlyFloat) = *(int32_t*)(x); __underlyFloat);
|
||||
// notes: src must be float or double type variable !!!
|
||||
#define SET_FLOAT_VAL_ALIGN(dst, src) (*(int32_t*) dst = *(int32_t*)src);
|
||||
#define SET_DOUBLE_VAL_ALIGN(dst, src) (*(int64_t*) dst = *(int64_t*)src);
|
||||
//#define SET_FLOAT_VAL_ALIGN(dst, src) (*(int32_t*) dst = *(int32_t*)src);
|
||||
//#define SET_DOUBLE_VAL_ALIGN(dst, src) (*(int64_t*) dst = *(int64_t*)src);
|
||||
|
||||
float taos_align_get_float(const char* pBuf);
|
||||
double taos_align_get_double(const char* pBuf);
|
||||
|
||||
#define GET_FLOAT_VAL(x) taos_align_get_float(x)
|
||||
#define GET_DOUBLE_VAL(x) taos_align_get_double(x)
|
||||
#define SET_FLOAT_VAL(x, y) { float z = (float)(y); (*(int32_t*) x = *(int32_t*)(&z)); }
|
||||
#define SET_DOUBLE_VAL(x, y) { double z = (double)(y); (*(int64_t*) x = *(int64_t*)(&z)); }
|
||||
#define SET_FLOAT_PTR(x, y) { (*(int32_t*) x = *(int32_t*)y); }
|
||||
#define SET_DOUBLE_PTR(x, y) { (*(int64_t*) x = *(int64_t*)y); }
|
||||
#else
|
||||
#define GET_FLOAT_VAL(x) (*(float *)(x))
|
||||
#define GET_DOUBLE_VAL(x) (*(double *)(x))
|
||||
#define SET_FLOAT_VAL(x, y) { (*(float *)(x)) = (float)(y); }
|
||||
#define SET_DOUBLE_VAL(x, y) { (*(double *)(x)) = (double)(y); }
|
||||
#define SET_FLOAT_PTR(x, y) { (*(float *)(x)) = (*(float *)(y)); }
|
||||
#define SET_DOUBLE_PTR(x, y) { (*(double *)(x)) = (*(double *)(y)); }
|
||||
#endif
|
||||
|
||||
typedef struct tDataTypeDescriptor {
|
||||
|
@ -198,7 +208,7 @@ void setNullN(char *val, int32_t type, int32_t bytes, int32_t numOfElems);
|
|||
void* getNullValue(int32_t type);
|
||||
|
||||
void assignVal(char *val, const char *src, int32_t len, int32_t type);
|
||||
void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
|
||||
void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size, void* buf);
|
||||
|
||||
// TODO: check if below is necessary
|
||||
#define TSDB_RELATION_INVALID 0
|
||||
|
@ -209,21 +219,24 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
|
|||
#define TSDB_RELATION_GREATER_EQUAL 5
|
||||
#define TSDB_RELATION_NOT_EQUAL 6
|
||||
#define TSDB_RELATION_LIKE 7
|
||||
#define TSDB_RELATION_IN 8
|
||||
#define TSDB_RELATION_ISNULL 8
|
||||
#define TSDB_RELATION_NOTNULL 9
|
||||
#define TSDB_RELATION_IN 10
|
||||
|
||||
#define TSDB_RELATION_AND 9
|
||||
#define TSDB_RELATION_OR 10
|
||||
#define TSDB_RELATION_NOT 11
|
||||
#define TSDB_RELATION_AND 11
|
||||
#define TSDB_RELATION_OR 12
|
||||
#define TSDB_RELATION_NOT 13
|
||||
|
||||
#define TSDB_BINARY_OP_ADD 12
|
||||
#define TSDB_BINARY_OP_SUBTRACT 13
|
||||
#define TSDB_BINARY_OP_MULTIPLY 14
|
||||
#define TSDB_BINARY_OP_DIVIDE 15
|
||||
#define TSDB_BINARY_OP_REMAINDER 16
|
||||
#define TSDB_BINARY_OP_ADD 30
|
||||
#define TSDB_BINARY_OP_SUBTRACT 31
|
||||
#define TSDB_BINARY_OP_MULTIPLY 32
|
||||
#define TSDB_BINARY_OP_DIVIDE 33
|
||||
#define TSDB_BINARY_OP_REMAINDER 34
|
||||
#define TS_PATH_DELIMITER_LEN 1
|
||||
|
||||
#define TSDB_UNI_LEN 24
|
||||
#define TSDB_USER_LEN TSDB_UNI_LEN
|
||||
|
||||
// ACCOUNT is a 32 bit positive integer
|
||||
// this is the length of its string representation
|
||||
// including the terminator zero
|
||||
|
@ -241,7 +254,7 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
|
|||
#define TSDB_MAX_SAVED_SQL_LEN TSDB_MAX_COLUMNS * 64
|
||||
#define TSDB_MAX_SQL_LEN TSDB_PAYLOAD_SIZE
|
||||
#define TSDB_MAX_SQL_SHOW_LEN 256
|
||||
#define TSDB_MAX_ALLOWED_SQL_LEN (8*1024*1024U) // sql length should be less than 8mb
|
||||
#define TSDB_MAX_ALLOWED_SQL_LEN (1*1024*1024U) // sql length should be less than 8mb
|
||||
|
||||
#define TSDB_MAX_BYTES_PER_ROW 16384
|
||||
#define TSDB_MAX_TAGS_LEN 16384
|
||||
|
@ -290,6 +303,8 @@ void tsDataSwap(void *pLeft, void *pRight, int32_t type, int32_t size);
|
|||
#define TSDB_CQ_SQL_SIZE 1024
|
||||
#define TSDB_MIN_VNODES 64
|
||||
#define TSDB_MAX_VNODES 2048
|
||||
#define TSDB_MIN_VNODES_PER_DB 2
|
||||
#define TSDB_MAX_VNODES_PER_DB 64
|
||||
|
||||
#define TSDB_DNODE_ROLE_ANY 0
|
||||
#define TSDB_DNODE_ROLE_MGMT 1
|
||||
|
|
|
@ -98,7 +98,9 @@ TAOS_DEFINE_ERROR(TSDB_CODE_TSC_ACTION_IN_PROGRESS, 0, 0x0212, "Action in
|
|||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DISCONNECTED, 0, 0x0213, "Disconnected from service")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_NO_WRITE_AUTH, 0, 0x0214, "No write permission")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_CONN_KILLED, 0, 0x0215, "Connection killed")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax errr in SQL")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_SQL_SYNTAX_ERROR, 0, 0x0216, "Syntax error in SQL")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_DB_NOT_SELECTED, 0, 0x0217, "Database not specified or available")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_TSC_INVALID_TABLE_NAME, 0, 0x0218, "Table does not exist")
|
||||
|
||||
// mnode
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_MND_MSG_NOT_PROCESSED, 0, 0x0300, "Message not processed")
|
||||
|
@ -246,6 +248,107 @@ TAOS_DEFINE_ERROR(TSDB_CODE_SYN_NOT_ENABLED, 0, 0x0901, "Sync modul
|
|||
|
||||
// wal
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_APP_ERROR, 0, 0x1000, "Unexpected generic error in wal")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_WAL_FILE_CORRUPTED, 0, 0x1001, "WAL file is corrupted")
|
||||
|
||||
// http
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_SERVER_OFFLINE, 0, 0x1100, "http server is not onlin")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_UNSUPPORT_URL, 0, 0x1101, "url is not support")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVLALID_URL, 0, 0x1102, "invalid url format")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_ENOUGH_MEMORY, 0, 0x1103, "no enough memory")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_REQUSET_TOO_BIG, 0, 0x1104, "request size is too big")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_AUTH_INFO, 0, 0x1105, "no auth info input")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_MSG_INPUT, 0, 0x1106, "request is empty")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_SQL_INPUT, 0, 0x1107, "no sql input")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_NO_EXEC_USEDB, 0, 0x1108, "no need to execute use db cmd")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_SESSION_FULL, 0, 0x1109, "session list was full")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GEN_TAOSD_TOKEN_ERR, 0, 0x110A, "generate taosd token error")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_MULTI_REQUEST, 0, 0x110B, "size of multi request is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_CREATE_GZIP_FAILED, 0, 0x110C, "failed to create gzip")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_FINISH_GZIP_FAILED, 0, 0x110D, "failed to finish gzip")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_LOGIN_FAILED, 0, 0x110E, "failed to login")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_VERSION, 0, 0x1120, "invalid http version")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_CONTENT_LENGTH, 0, 0x1121, "invalid content length")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_AUTH_TYPE, 0, 0x1122, "invalid type of Authorization")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_AUTH_FORMAT, 0, 0x1123, "invalid format of Authorization")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_BASIC_AUTH, 0, 0x1124, "invalid basic Authorization")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_INVALID_TAOSD_AUTH, 0, 0x1125, "invalid taosd Authorization")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_METHOD_FAILED, 0, 0x1126, "failed to parse method")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_TARGET_FAILED, 0, 0x1127, "failed to parse target")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_VERSION_FAILED, 0, 0x1128, "failed to parse http version")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_SP_FAILED, 0, 0x1129, "failed to parse sp")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_STATUS_FAILED, 0, 0x112A, "failed to parse status")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_PHRASE_FAILED, 0, 0x112B, "failed to parse phrase")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CRLF_FAILED, 0, 0x112C, "failed to parse crlf")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_FAILED, 0, 0x112D, "failed to parse header")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_KEY_FAILED, 0, 0x112E, "failed to parse header key")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_HEADER_VAL_FAILED, 0, 0x112F, "failed to parse header val")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CHUNK_SIZE_FAILED, 0, 0x1130, "failed to parse chunk size")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_CHUNK_FAILED, 0, 0x1131, "failed to parse chunk")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_END_FAILED, 0, 0x1132, "failed to parse end section")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_INVALID_STATE, 0, 0x1134, "invalid parse state")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_PARSE_ERROR_STATE, 0, 0x1135, "failed to parse error section")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_QUERY_NULL, 0, 0x1150, "query size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_QUERY_SIZE, 0, 0x1151, "query size can not more than 100")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_GC_REQ_PARSE_ERROR, 0, 0x1152, "parse grafana json error")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_DB_NOT_INPUT, 0, 0x1160, "database name can not be null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_DB_TOO_LONG, 0, 0x1161, "database name too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_INVALID_JSON, 0, 0x1162, "invalid telegraf json fromat")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRICS_NULL, 0, 0x1163, "metrics size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRICS_SIZE, 0, 0x1164, "metrics size can not more than 1K")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NULL, 0, 0x1165, "metric name not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_TYPE, 0, 0x1166, "metric name type should be string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NAME_NULL, 0, 0x1167, "metric name length is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_METRIC_NAME_LONG, 0, 0x1168, "metric name length too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_NULL, 0, 0x1169, "timestamp not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_TYPE, 0, 0x116A, "timestamp type should be integer")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TIMESTAMP_VAL_NULL, 0, 0x116B, "timestamp value smaller than 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_NULL, 0, 0x116C, "tags not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_SIZE_0, 0, 0x116D, "tags size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAGS_SIZE_LONG, 0, 0x116E, "tags size too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NULL, 0, 0x116F, "tag is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NAME_NULL, 0, 0x1170, "tag name is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_NAME_SIZE, 0, 0x1171, "tag name length too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_VALUE_TYPE, 0, 0x1172, "tag value type should be number or string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TAG_VALUE_NULL, 0, 0x1173, "tag value is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TABLE_NULL, 0, 0x1174, "table is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_TABLE_SIZE, 0, 0x1175, "table name length too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_NULL, 0, 0x1176, "fields not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_SIZE_0, 0, 0x1177, "fields size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELDS_SIZE_LONG, 0, 0x1178, "fields size too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NULL, 0, 0x1179, "field is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NAME_NULL, 0, 0x117A, "field name is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_NAME_SIZE, 0, 0x117B, "field name length too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_VALUE_TYPE, 0, 0x117C, "field value type should be number or string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_FIELD_VALUE_NULL, 0, 0x117D, "field value is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_HOST_NOT_STRING, 0, 0x117E, "host type should be string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_TG_STABLE_NOT_EXIST, 0, 0x117F, "stable not exist")
|
||||
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_DB_NOT_INPUT, 0, 0x1190, "database name can not be null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_DB_TOO_LONG, 0, 0x1191, "database name too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_INVALID_JSON, 0, 0x1192, "invalid opentsdb json fromat")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRICS_NULL, 0, 0x1193, "metrics size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRICS_SIZE, 0, 0x1194, "metrics size can not more than 10K")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NULL, 0, 0x1195, "metric name not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_TYPE, 0, 0x1196, "metric name type should be string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NAME_NULL, 0, 0x1197, "metric name length is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_METRIC_NAME_LONG, 0, 0x1198, "metric name length can not more than 22")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_NULL, 0, 0x1199, "timestamp not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_TYPE, 0, 0x119A, "timestamp type should be integer")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TIMESTAMP_VAL_NULL, 0, 0x119B, "timestamp value smaller than 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_NULL, 0, 0x119C, "tags not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_SIZE_0, 0, 0x119D, "tags size is 0")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAGS_SIZE_LONG, 0, 0x119E, "tags size too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NULL, 0, 0x119F, "tag is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NAME_NULL, 0, 0x11A0, "tag name is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_NAME_SIZE, 0, 0x11A1, "tag name length too long")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_TYPE, 0, 0x11A2, "tag value type should be boolean, number or string")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_NULL, 0, 0x11A3, "tag value is null")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_TAG_VALUE_TOO_LONG, 0, 0x11A4, "tag value can not more than 64")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_NULL, 0, 0x11A5, "value not find")
|
||||
TAOS_DEFINE_ERROR(TSDB_CODE_HTTP_OP_VALUE_TYPE, 0, 0x11A6, "value type should be boolean, number or string")
|
||||
|
||||
#ifdef TAOS_ERROR_C
|
||||
};
|
||||
|
|
|
@ -460,11 +460,7 @@ typedef struct {
|
|||
int16_t order;
|
||||
int16_t orderColId;
|
||||
int16_t numOfCols; // the number of columns will be load from vnode
|
||||
int64_t intervalTime; // time interval for aggregation, in million second
|
||||
int64_t intervalOffset; // start offset for interval query
|
||||
int64_t slidingTime; // value for sliding window
|
||||
char intervalTimeUnit;
|
||||
char slidingTimeUnit; // time interval type, for revisement of interval(1d)
|
||||
SInterval interval;
|
||||
uint16_t tagCondLen; // tag length in current query
|
||||
int16_t numOfGroupCols; // num of group by columns
|
||||
int16_t orderByIdx;
|
||||
|
@ -677,6 +673,7 @@ typedef struct {
|
|||
typedef struct STableMetaMsg {
|
||||
int32_t contLen;
|
||||
char tableId[TSDB_TABLE_FNAME_LEN]; // table id
|
||||
char sTableId[TSDB_TABLE_FNAME_LEN];
|
||||
uint8_t numOfTags;
|
||||
uint8_t precision;
|
||||
uint8_t tableType;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#ifndef TDENGINE_TTOKENDEF_H
|
||||
#define TDENGINE_TTOKENDEF_H
|
||||
|
||||
|
||||
#define TK_ID 1
|
||||
#define TK_BOOL 2
|
||||
#define TK_TINYINT 3
|
||||
|
@ -75,24 +76,24 @@
|
|||
#define TK_VNODES 57
|
||||
#define TK_IPTOKEN 58
|
||||
#define TK_DOT 59
|
||||
#define TK_TABLES 60
|
||||
#define TK_STABLES 61
|
||||
#define TK_VGROUPS 62
|
||||
#define TK_DROP 63
|
||||
#define TK_TABLE 64
|
||||
#define TK_DATABASE 65
|
||||
#define TK_DNODE 66
|
||||
#define TK_USER 67
|
||||
#define TK_ACCOUNT 68
|
||||
#define TK_USE 69
|
||||
#define TK_DESCRIBE 70
|
||||
#define TK_ALTER 71
|
||||
#define TK_PASS 72
|
||||
#define TK_PRIVILEGE 73
|
||||
#define TK_LOCAL 74
|
||||
#define TK_IF 75
|
||||
#define TK_EXISTS 76
|
||||
#define TK_CREATE 77
|
||||
#define TK_CREATE 60
|
||||
#define TK_TABLE 61
|
||||
#define TK_DATABASE 62
|
||||
#define TK_TABLES 63
|
||||
#define TK_STABLES 64
|
||||
#define TK_VGROUPS 65
|
||||
#define TK_DROP 66
|
||||
#define TK_DNODE 67
|
||||
#define TK_USER 68
|
||||
#define TK_ACCOUNT 69
|
||||
#define TK_USE 70
|
||||
#define TK_DESCRIBE 71
|
||||
#define TK_ALTER 72
|
||||
#define TK_PASS 73
|
||||
#define TK_PRIVILEGE 74
|
||||
#define TK_LOCAL 75
|
||||
#define TK_IF 76
|
||||
#define TK_EXISTS 77
|
||||
#define TK_PPS 78
|
||||
#define TK_TSERIES 79
|
||||
#define TK_DBS 80
|
||||
|
@ -222,7 +223,6 @@
|
|||
#define TK_INTO 204
|
||||
#define TK_VALUES 205
|
||||
|
||||
|
||||
#define TK_SPACE 300
|
||||
#define TK_COMMENT 301
|
||||
#define TK_ILLEGAL 302
|
||||
|
|
|
@ -44,6 +44,7 @@ typedef void* twalh; // WAL HANDLE
|
|||
typedef int (*FWalWrite)(void *ahandle, void *pHead, int type);
|
||||
|
||||
twalh walOpen(const char *path, const SWalCfg *pCfg);
|
||||
int walAlter(twalh pWal, const SWalCfg *pCfg);
|
||||
void walClose(twalh);
|
||||
int walRenew(twalh);
|
||||
int walWrite(twalh, SWalHead *);
|
||||
|
|
|
@ -419,16 +419,16 @@ static void dumpFieldToFile(FILE* fp, const char* val, TAOS_FIELD* field, int32_
|
|||
char buf[TSDB_MAX_BYTES_PER_ROW];
|
||||
switch (field->type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
fprintf(fp, "%d", ((((int)(*((char *)val))) == 1) ? 1 : 0));
|
||||
fprintf(fp, "%d", ((((int32_t)(*((char *)val))) == 1) ? 1 : 0));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
fprintf(fp, "%d", (int)(*((char *)val)));
|
||||
fprintf(fp, "%d", *((int8_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
fprintf(fp, "%d", (int)(*((short *)val)));
|
||||
fprintf(fp, "%d", *((int16_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
fprintf(fp, "%d", *((int *)val));
|
||||
fprintf(fp, "%d", *((int32_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
fprintf(fp, "%" PRId64, *((int64_t *)val));
|
||||
|
@ -559,16 +559,16 @@ static void printField(const char* val, TAOS_FIELD* field, int width, int32_t le
|
|||
char buf[TSDB_MAX_BYTES_PER_ROW];
|
||||
switch (field->type) {
|
||||
case TSDB_DATA_TYPE_BOOL:
|
||||
printf("%*s", width, ((((int)(*((char *)val))) == 1) ? "true" : "false"));
|
||||
printf("%*s", width, ((((int32_t)(*((char *)val))) == 1) ? "true" : "false"));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_TINYINT:
|
||||
printf("%*d", width, (int)(*((char *)val)));
|
||||
printf("%*d", width, *((int8_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_SMALLINT:
|
||||
printf("%*d", width, (int)(*((short *)val)));
|
||||
printf("%*d", width, *((int16_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_INT:
|
||||
printf("%*d", width, *((int *)val));
|
||||
printf("%*d", width, *((int32_t *)val));
|
||||
break;
|
||||
case TSDB_DATA_TYPE_BIGINT:
|
||||
printf("%*" PRId64, width, *((int64_t *)val));
|
||||
|
@ -765,7 +765,9 @@ void read_history() {
|
|||
FILE *f = fopen(f_history, "r");
|
||||
if (f == NULL) {
|
||||
#ifndef WINDOWS
|
||||
fprintf(stderr, "Failed to open file %s\n", f_history);
|
||||
if (errno != ENOENT) {
|
||||
fprintf(stderr, "Failed to open file %s, reason:%s\n", f_history, strerror(errno));
|
||||
}
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
@ -792,7 +794,7 @@ void write_history() {
|
|||
FILE *f = fopen(f_history, "w");
|
||||
if (f == NULL) {
|
||||
#ifndef WINDOWS
|
||||
fprintf(stderr, "Failed to open file %s for write\n", f_history);
|
||||
fprintf(stderr, "Failed to open file %s for write, reason:%s\n", f_history, strerror(errno));
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -69,7 +69,8 @@ typedef struct SDnodeObj {
|
|||
int16_t cpuAvgUsage; // calc from sys.cpu
|
||||
int16_t memoryAvgUsage; // calc from sys.mem
|
||||
int16_t bandwidthUsage; // calc from sys.band
|
||||
int8_t reserved2[2];
|
||||
int8_t offlineReason;
|
||||
int8_t reserved2[1];
|
||||
} SDnodeObj;
|
||||
|
||||
typedef struct SMnodeObj {
|
||||
|
|
|
@ -33,6 +33,28 @@ typedef enum {
|
|||
TAOS_DN_ALTERNATIVE_ROLE_VNODE
|
||||
} EDnodeAlternativeRole;
|
||||
|
||||
typedef enum EDnodeOfflineReason {
|
||||
TAOS_DN_OFF_ONLINE = 0,
|
||||
TAOS_DN_OFF_STATUS_MSG_TIMEOUT,
|
||||
TAOS_DN_OFF_STATUS_NOT_RECEIVED,
|
||||
TAOS_DN_OFF_RESET_BY_MNODE,
|
||||
TAOS_DN_OFF_VERSION_NOT_MATCH,
|
||||
TAOS_DN_OFF_DNODE_ID_NOT_MATCH,
|
||||
TAOS_DN_OFF_CLUSTER_ID_NOT_MATCH,
|
||||
TAOS_DN_OFF_NUM_OF_MNODES_NOT_MATCH,
|
||||
TAOS_DN_OFF_ENABLE_BALANCE_NOT_MATCH,
|
||||
TAOS_DN_OFF_MN_EQUAL_VN_NOT_MATCH,
|
||||
TAOS_DN_OFF_OFFLINE_THRESHOLD_NOT_MATCH,
|
||||
TAOS_DN_OFF_STATUS_INTERVAL_NOT_MATCH,
|
||||
TAOS_DN_OFF_MAX_TAB_PER_VN_NOT_MATCH,
|
||||
TAOS_DN_OFF_MAX_VG_PER_DB_NOT_MATCH,
|
||||
TAOS_DN_OFF_ARBITRATOR_NOT_MATCH,
|
||||
TAOS_DN_OFF_TIME_ZONE_NOT_MATCH,
|
||||
TAOS_DN_OFF_LOCALE_NOT_MATCH,
|
||||
TAOS_DN_OFF_CHARSET_NOT_MATCH,
|
||||
TAOS_DN_OFF_OTHERS
|
||||
} EDnodeOfflineReason;
|
||||
|
||||
int32_t mnodeInitDnodes();
|
||||
void mnodeCleanupDnodes();
|
||||
|
||||
|
|
|
@ -760,6 +760,8 @@ static int32_t mnodeRetrieveDbs(SShowObj *pShow, char *data, int32_t rows, void
|
|||
}
|
||||
|
||||
pShow->numOfReads += numOfRows;
|
||||
mnodeVacuumResult(data, cols, numOfRows, rows, pShow);
|
||||
|
||||
mnodeDecUserRef(pUser);
|
||||
return numOfRows;
|
||||
}
|
||||
|
@ -910,13 +912,13 @@ static SDbCfg mnodeGetAlterDbOption(SDbObj *pDb, SCMAlterDbMsg *pAlter) {
|
|||
}
|
||||
|
||||
if (walLevel > 0 && walLevel != pDb->cfg.walLevel) {
|
||||
mError("db:%s, can't alter walLevel option", pDb->name);
|
||||
terrno = TSDB_CODE_MND_INVALID_DB_OPTION;
|
||||
mDebug("db:%s, walLevel:%d change to %d", pDb->name, pDb->cfg.walLevel, walLevel);
|
||||
newCfg.walLevel = walLevel;
|
||||
}
|
||||
|
||||
if (fsyncPeriod >= 0 && fsyncPeriod != pDb->cfg.fsyncPeriod) {
|
||||
mError("db:%s, can't alter fsyncPeriod option", pDb->name);
|
||||
terrno = TSDB_CODE_MND_INVALID_DB_OPTION;
|
||||
mDebug("db:%s, fsyncPeriod:%d change to %d", pDb->name, pDb->cfg.fsyncPeriod, fsyncPeriod);
|
||||
newCfg.fsyncPeriod = fsyncPeriod;
|
||||
}
|
||||
|
||||
if (replications > 0 && replications != pDb->cfg.replications) {
|
||||
|
|
|
@ -60,6 +60,28 @@ static int32_t mnodeGetDnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC
|
|||
static int32_t mnodeRetrieveDnodes(SShowObj *pShow, char *data, int32_t rows, void *pConn);
|
||||
static char* mnodeGetDnodeAlternativeRoleStr(int32_t alternativeRole);
|
||||
|
||||
static char* offlineReason[] = {
|
||||
"",
|
||||
"status msg timeout",
|
||||
"status not received",
|
||||
"status reset by mnode",
|
||||
"version not match",
|
||||
"dnodeId not match",
|
||||
"clusterId not match",
|
||||
"numOfMnodes not match",
|
||||
"balance not match",
|
||||
"mnEqualVn not match",
|
||||
"offThreshold not match",
|
||||
"interval not match",
|
||||
"maxTabPerVn not match",
|
||||
"maxVgPerDb not match",
|
||||
"arbitrator not match",
|
||||
"timezone not match",
|
||||
"locale not match",
|
||||
"charset not match",
|
||||
"unknown",
|
||||
};
|
||||
|
||||
static int32_t mnodeDnodeActionDestroy(SSdbOper *pOper) {
|
||||
taosTFree(pOper->pObj);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
|
@ -70,6 +92,7 @@ static int32_t mnodeDnodeActionInsert(SSdbOper *pOper) {
|
|||
if (pDnode->status != TAOS_DN_STATUS_DROPPING) {
|
||||
pDnode->status = TAOS_DN_STATUS_OFFLINE;
|
||||
pDnode->lastAccess = tsAccessSquence;
|
||||
pDnode->offlineReason = TAOS_DN_OFF_STATUS_NOT_RECEIVED;
|
||||
}
|
||||
|
||||
mInfo("dnode:%d, fqdn:%s ep:%s port:%d, do insert action", pDnode->dnodeId, pDnode->dnodeFqdn, pDnode->dnodeEp, pDnode->dnodePort);
|
||||
|
@ -334,61 +357,69 @@ static void mnodeProcessCfgDnodeMsgRsp(SRpcMsg *rpcMsg) {
|
|||
mInfo("cfg dnode rsp is received");
|
||||
}
|
||||
|
||||
static bool mnodeCheckClusterCfgPara(const SClusterCfg *clusterCfg) {
|
||||
static int32_t mnodeCheckClusterCfgPara(const SClusterCfg *clusterCfg) {
|
||||
if (clusterCfg->numOfMnodes != htonl(tsNumOfMnodes)) {
|
||||
mError("\"numOfMnodes\"[%d - %d] cfg parameters inconsistent", clusterCfg->numOfMnodes, htonl(tsNumOfMnodes));
|
||||
return false;
|
||||
return TAOS_DN_OFF_NUM_OF_MNODES_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->enableBalance != htonl(tsEnableBalance)) {
|
||||
mError("\"balance\"[%d - %d] cfg parameters inconsistent", clusterCfg->enableBalance, htonl(tsEnableBalance));
|
||||
return false;
|
||||
return TAOS_DN_OFF_ENABLE_BALANCE_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->mnodeEqualVnodeNum != htonl(tsMnodeEqualVnodeNum)) {
|
||||
mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg parameters inconsistent", clusterCfg->mnodeEqualVnodeNum, htonl(tsMnodeEqualVnodeNum));
|
||||
return false;
|
||||
mError("\"mnodeEqualVnodeNum\"[%d - %d] cfg parameters inconsistent", clusterCfg->mnodeEqualVnodeNum,
|
||||
htonl(tsMnodeEqualVnodeNum));
|
||||
return TAOS_DN_OFF_MN_EQUAL_VN_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->offlineThreshold != htonl(tsOfflineThreshold)) {
|
||||
mError("\"offlineThreshold\"[%d - %d] cfg parameters inconsistent", clusterCfg->offlineThreshold, htonl(tsOfflineThreshold));
|
||||
return false;
|
||||
mError("\"offlineThreshold\"[%d - %d] cfg parameters inconsistent", clusterCfg->offlineThreshold,
|
||||
htonl(tsOfflineThreshold));
|
||||
return TAOS_DN_OFF_OFFLINE_THRESHOLD_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->statusInterval != htonl(tsStatusInterval)) {
|
||||
mError("\"statusInterval\"[%d - %d] cfg parameters inconsistent", clusterCfg->statusInterval, htonl(tsStatusInterval));
|
||||
return false;
|
||||
mError("\"statusInterval\"[%d - %d] cfg parameters inconsistent", clusterCfg->statusInterval,
|
||||
htonl(tsStatusInterval));
|
||||
return TAOS_DN_OFF_STATUS_INTERVAL_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->maxtablesPerVnode != htonl(tsMaxTablePerVnode)) {
|
||||
mError("\"maxTablesPerVnode\"[%d - %d] cfg parameters inconsistent", clusterCfg->maxtablesPerVnode, htonl(tsMaxTablePerVnode));
|
||||
return false;
|
||||
mError("\"maxTablesPerVnode\"[%d - %d] cfg parameters inconsistent", clusterCfg->maxtablesPerVnode,
|
||||
htonl(tsMaxTablePerVnode));
|
||||
return TAOS_DN_OFF_MAX_TAB_PER_VN_NOT_MATCH;
|
||||
}
|
||||
if (clusterCfg->maxVgroupsPerDb != htonl(tsMaxVgroupsPerDb)) {
|
||||
mError("\"maxVgroupsPerDb\"[%d - %d] cfg parameters inconsistent", clusterCfg->maxVgroupsPerDb, htonl(tsMaxVgroupsPerDb));
|
||||
return false;
|
||||
mError("\"maxVgroupsPerDb\"[%d - %d] cfg parameters inconsistent", clusterCfg->maxVgroupsPerDb,
|
||||
htonl(tsMaxVgroupsPerDb));
|
||||
return TAOS_DN_OFF_MAX_VG_PER_DB_NOT_MATCH;
|
||||
}
|
||||
if (0 != strncasecmp(clusterCfg->arbitrator, tsArbitrator, strlen(tsArbitrator))) {
|
||||
mError("\"arbitrator\"[%s - %s] cfg parameters inconsistent", clusterCfg->arbitrator, tsArbitrator);
|
||||
return false;
|
||||
return TAOS_DN_OFF_ARBITRATOR_NOT_MATCH;
|
||||
}
|
||||
|
||||
int64_t checkTime = 0;
|
||||
char timestr[32] = "1970-01-01 00:00:00.00";
|
||||
(void)taosParseTime(timestr, &checkTime, strlen(timestr), TSDB_TIME_PRECISION_MILLI, 0);
|
||||
if ((0 != strncasecmp(clusterCfg->timezone, tsTimezone, strlen(tsTimezone))) && (checkTime != clusterCfg->checkTime)) {
|
||||
mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64"] cfg parameters inconsistent", clusterCfg->timezone, tsTimezone, clusterCfg->checkTime, checkTime);
|
||||
return false;
|
||||
if ((0 != strncasecmp(clusterCfg->timezone, tsTimezone, strlen(tsTimezone))) &&
|
||||
(checkTime != clusterCfg->checkTime)) {
|
||||
mError("\"timezone\"[%s - %s] [%" PRId64 " - %" PRId64 "] cfg parameters inconsistent", clusterCfg->timezone,
|
||||
tsTimezone, clusterCfg->checkTime, checkTime);
|
||||
return TAOS_DN_OFF_TIME_ZONE_NOT_MATCH;
|
||||
}
|
||||
|
||||
if (0 != strncasecmp(clusterCfg->locale, tsLocale, strlen(tsLocale))) {
|
||||
mError("\"locale\"[%s - %s] cfg parameters inconsistent", clusterCfg->locale, tsLocale);
|
||||
return false;
|
||||
return TAOS_DN_OFF_LOCALE_NOT_MATCH;
|
||||
}
|
||||
if (0 != strncasecmp(clusterCfg->charset, tsCharset, strlen(tsCharset))) {
|
||||
mError("\"charset\"[%s - %s] cfg parameters inconsistent.", clusterCfg->charset, tsCharset);
|
||||
return false;
|
||||
return TAOS_DN_OFF_CHARSET_NOT_MATCH;
|
||||
}
|
||||
|
||||
return true;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
||||
SDnodeObj *pDnode = NULL;
|
||||
SDMStatusMsg *pStatus = pMsg->rpcMsg.pCont;
|
||||
pStatus->dnodeId = htonl(pStatus->dnodeId);
|
||||
pStatus->moduleStatus = htonl(pStatus->moduleStatus);
|
||||
|
@ -397,11 +428,14 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
|
||||
uint32_t version = htonl(pStatus->version);
|
||||
if (version != tsVersion) {
|
||||
mError("status msg version:%d not equal with mnode:%d", version, tsVersion);
|
||||
pDnode = mnodeGetDnodeByEp(pStatus->dnodeEp);
|
||||
if (pDnode != NULL && pDnode->status != TAOS_DN_STATUS_READY) {
|
||||
pDnode->offlineReason = TAOS_DN_OFF_VERSION_NOT_MATCH;
|
||||
}
|
||||
mError("dnode:%d, status msg version:%d not equal with cluster:%d", pStatus->dnodeId, version, tsVersion);
|
||||
return TSDB_CODE_MND_INVALID_MSG_VERSION;
|
||||
}
|
||||
|
||||
SDnodeObj *pDnode = NULL;
|
||||
if (pStatus->dnodeId == 0) {
|
||||
pDnode = mnodeGetDnodeByEp(pStatus->dnodeEp);
|
||||
if (pDnode == NULL) {
|
||||
|
@ -411,7 +445,11 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
} else {
|
||||
pDnode = mnodeGetDnode(pStatus->dnodeId);
|
||||
if (pDnode == NULL) {
|
||||
mError("dnode id:%d, %s not exist", pStatus->dnodeId, pStatus->dnodeEp);
|
||||
pDnode = mnodeGetDnodeByEp(pStatus->dnodeEp);
|
||||
if (pDnode != NULL && pDnode->status != TAOS_DN_STATUS_READY) {
|
||||
pDnode->offlineReason = TAOS_DN_OFF_DNODE_ID_NOT_MATCH;
|
||||
}
|
||||
mError("dnode:%d, %s not exist", pStatus->dnodeId, pStatus->dnodeEp);
|
||||
return TSDB_CODE_MND_DNODE_NOT_EXIST;
|
||||
}
|
||||
}
|
||||
|
@ -426,6 +464,9 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
mDebug("dnode:%d %s, first access, set clusterId %s", pDnode->dnodeId, pDnode->dnodeEp, mnodeGetClusterId());
|
||||
} else {
|
||||
if (strncmp(pStatus->clusterId, mnodeGetClusterId(), TSDB_CLUSTER_ID_LEN - 1) != 0) {
|
||||
if (pDnode != NULL && pDnode->status != TAOS_DN_STATUS_READY) {
|
||||
pDnode->offlineReason = TAOS_DN_OFF_CLUSTER_ID_NOT_MATCH;
|
||||
}
|
||||
mError("dnode:%d, input clusterId %s not match with exist %s", pDnode->dnodeId, pStatus->clusterId,
|
||||
mnodeGetClusterId());
|
||||
return TSDB_CODE_MND_INVALID_CLUSTER_ID;
|
||||
|
@ -469,16 +510,19 @@ static int32_t mnodeProcessDnodeStatusMsg(SMnodeMsg *pMsg) {
|
|||
|
||||
if (pDnode->status == TAOS_DN_STATUS_OFFLINE) {
|
||||
// Verify whether the cluster parameters are consistent when status change from offline to ready
|
||||
bool ret = mnodeCheckClusterCfgPara(&(pStatus->clusterCfg));
|
||||
if (false == ret) {
|
||||
int32_t ret = mnodeCheckClusterCfgPara(&(pStatus->clusterCfg));
|
||||
if (0 != ret) {
|
||||
pDnode->offlineReason = ret;
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
rpcFreeCont(pRsp);
|
||||
mError("dnode:%d, %s cluster cfg parameters inconsistent", pDnode->dnodeId, pStatus->dnodeEp);
|
||||
mError("dnode:%d, %s cluster cfg parameters inconsistent, reason:%s", pDnode->dnodeId, pStatus->dnodeEp,
|
||||
offlineReason[ret]);
|
||||
return TSDB_CODE_MND_CLUSTER_CFG_INCONSISTENT;
|
||||
}
|
||||
|
||||
mDebug("dnode:%d, from offline to online", pDnode->dnodeId);
|
||||
pDnode->status = TAOS_DN_STATUS_READY;
|
||||
pDnode->offlineReason = TAOS_DN_OFF_ONLINE;
|
||||
balanceSyncNotify();
|
||||
balanceAsyncNotify();
|
||||
}
|
||||
|
@ -529,6 +573,7 @@ static int32_t mnodeCreateDnode(char *ep, SMnodeMsg *pMsg) {
|
|||
pDnode = (SDnodeObj *) calloc(1, sizeof(SDnodeObj));
|
||||
pDnode->createdTime = taosGetTimestampMs();
|
||||
pDnode->status = TAOS_DN_STATUS_OFFLINE;
|
||||
pDnode->offlineReason = TAOS_DN_OFF_STATUS_NOT_RECEIVED;
|
||||
tstrncpy(pDnode->dnodeEp, ep, TSDB_EP_LEN);
|
||||
taosGetFqdnPortFromEp(ep, pDnode->dnodeFqdn, &pDnode->dnodePort);
|
||||
|
||||
|
@ -654,13 +699,13 @@ static int32_t mnodeGetDnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC
|
|||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pShow->bytes[cols] = 12 + VARSTR_HEADER_SIZE;
|
||||
pShow->bytes[cols] = 10 + VARSTR_HEADER_SIZE;
|
||||
pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
|
||||
strcpy(pSchema[cols].name, "status");
|
||||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pShow->bytes[cols] = 6 + VARSTR_HEADER_SIZE;
|
||||
pShow->bytes[cols] = 5 + VARSTR_HEADER_SIZE;
|
||||
pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
|
||||
strcpy(pSchema[cols].name, "role");
|
||||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
|
@ -672,6 +717,12 @@ static int32_t mnodeGetDnodeMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *pC
|
|||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pShow->bytes[cols] = 24 + VARSTR_HEADER_SIZE;
|
||||
pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
|
||||
strcpy(pSchema[cols].name, "offline reason");
|
||||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pMeta->numOfColumns = htons(cols);
|
||||
pShow->numOfColumns = cols;
|
||||
|
||||
|
@ -731,6 +782,9 @@ static int32_t mnodeRetrieveDnodes(SShowObj *pShow, char *data, int32_t rows, vo
|
|||
*(int64_t *)pWrite = pDnode->createdTime;
|
||||
cols++;
|
||||
|
||||
pWrite = data + pShow->offset[cols] * rows + pShow->bytes[cols] * numOfRows;
|
||||
STR_TO_VARSTR(pWrite, offlineReason[pDnode->offlineReason]);
|
||||
cols++;
|
||||
|
||||
numOfRows++;
|
||||
mnodeDecDnodeRef(pDnode);
|
||||
|
|
|
@ -39,6 +39,11 @@ void mnodeCreateMsg(SMnodeMsg *pMsg, SRpcMsg *rpcMsg) {
|
|||
}
|
||||
|
||||
int32_t mnodeInitMsg(SMnodeMsg *pMsg) {
|
||||
if (pMsg->pUser != NULL) {
|
||||
mDebug("app:%p:%p, user info already inited", pMsg->rpcMsg.ahandle, pMsg);
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
||||
pMsg->pUser = mnodeGetUserFromConn(pMsg->rpcMsg.handle);
|
||||
if (pMsg->pUser == NULL) {
|
||||
return TSDB_CODE_MND_INVALID_USER;
|
||||
|
|
|
@ -91,7 +91,6 @@ typedef struct {
|
|||
} SSdbWriteWorkerPool;
|
||||
|
||||
extern void * tsMnodeTmr;
|
||||
static void * tsUpdateSyncTmr;
|
||||
static SSdbObject tsSdbObj = {0};
|
||||
static taos_qset tsSdbWriteQset;
|
||||
static taos_qall tsSdbWriteQall;
|
||||
|
@ -185,7 +184,11 @@ static int32_t sdbInitWal() {
|
|||
}
|
||||
|
||||
sdbInfo("open sdb wal for restore");
|
||||
walRestore(tsSdbObj.wal, NULL, sdbWrite);
|
||||
int code = walRestore(tsSdbObj.wal, NULL, sdbWrite);
|
||||
if (code != TSDB_CODE_SUCCESS) {
|
||||
sdbError("failed to open wal for restore, reason:%s", tstrerror(code));
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -294,16 +297,12 @@ static void sdbConfirmForward(void *ahandle, void *param, int32_t code) {
|
|||
taosFreeQitem(pOper);
|
||||
}
|
||||
|
||||
static void sdbUpdateSyncTmrFp(void *param, void *tmrId) { sdbUpdateSync(); }
|
||||
|
||||
void sdbUpdateSync() {
|
||||
if (!mnodeIsRunning()) {
|
||||
mDebug("mnode not start yet, update sync info later");
|
||||
if (dnodeCheckMnodeStarting()) {
|
||||
taosTmrReset(sdbUpdateSyncTmrFp, 1000, NULL, tsMnodeTmr, &tsUpdateSyncTmr);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
mDebug("update sync info in sdb");
|
||||
|
||||
SSyncCfg syncCfg = {0};
|
||||
|
|
|
@ -65,7 +65,7 @@ int32_t mnodeInitShow() {
|
|||
mnodeAddReadMsgHandle(TSDB_MSG_TYPE_CM_CONNECT, mnodeProcessConnectMsg);
|
||||
mnodeAddReadMsgHandle(TSDB_MSG_TYPE_CM_USE_DB, mnodeProcessUseMsg);
|
||||
|
||||
tsMnodeShowCache = taosCacheInit(TSDB_DATA_TYPE_BIGINT, 5, false, mnodeFreeShowObj, "show");
|
||||
tsMnodeShowCache = taosCacheInit(TSDB_CACHE_PTR_KEY, 5, true, mnodeFreeShowObj, "show");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -378,8 +378,8 @@ static bool mnodeCheckShowFinished(SShowObj *pShow) {
|
|||
}
|
||||
|
||||
static bool mnodeAccquireShowObj(SShowObj *pShow) {
|
||||
uint64_t handleVal = (uint64_t)pShow;
|
||||
SShowObj **ppShow = taosCacheAcquireByKey(tsMnodeShowCache, &handleVal, sizeof(int64_t));
|
||||
TSDB_CACHE_PTR_TYPE handleVal = (TSDB_CACHE_PTR_TYPE)pShow;
|
||||
SShowObj **ppShow = taosCacheAcquireByKey(tsMnodeShowCache, &handleVal, sizeof(TSDB_CACHE_PTR_TYPE));
|
||||
if (ppShow) {
|
||||
mDebug("%p, show is accquired from cache, data:%p, index:%d", pShow, ppShow, pShow->index);
|
||||
return true;
|
||||
|
@ -389,10 +389,12 @@ static bool mnodeAccquireShowObj(SShowObj *pShow) {
|
|||
}
|
||||
|
||||
static void* mnodePutShowObj(SShowObj *pShow) {
|
||||
const int32_t DEFAULT_SHOWHANDLE_LIFE_SPAN = tsShellActivityTimer * 6 * 1000;
|
||||
|
||||
if (tsMnodeShowCache != NULL) {
|
||||
pShow->index = atomic_add_fetch_32(&tsShowObjIndex, 1);
|
||||
uint64_t handleVal = (uint64_t)pShow;
|
||||
SShowObj **ppShow = taosCachePut(tsMnodeShowCache, &handleVal, sizeof(int64_t), &pShow, sizeof(int64_t), 6000);
|
||||
TSDB_CACHE_PTR_TYPE handleVal = (TSDB_CACHE_PTR_TYPE)pShow;
|
||||
SShowObj **ppShow = taosCachePut(tsMnodeShowCache, &handleVal, sizeof(TSDB_CACHE_PTR_TYPE), &pShow, sizeof(TSDB_CACHE_PTR_TYPE), DEFAULT_SHOWHANDLE_LIFE_SPAN);
|
||||
pShow->ppShow = (void**)ppShow;
|
||||
mDebug("%p, show is put into cache, data:%p index:%d", pShow, ppShow, pShow->index);
|
||||
return pShow;
|
||||
|
|
|
@ -1384,6 +1384,9 @@ int32_t mnodeRetrieveShowSuperTables(SShowObj *pShow, char *data, int32_t rows,
|
|||
}
|
||||
|
||||
pShow->numOfReads += numOfRows;
|
||||
const int32_t NUM_OF_COLUMNS = 5;
|
||||
|
||||
mnodeVacuumResult(data, NUM_OF_COLUMNS, numOfRows, rows, pShow);
|
||||
mnodeDecDbRef(pDb);
|
||||
|
||||
return numOfRows;
|
||||
|
@ -2090,8 +2093,11 @@ static int32_t mnodeDoGetChildTableMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta) {
|
|||
pMeta->precision = pDb->cfg.precision;
|
||||
pMeta->tableType = pTable->info.type;
|
||||
tstrncpy(pMeta->tableId, pTable->info.tableId, TSDB_TABLE_FNAME_LEN);
|
||||
if (pTable->superTable != NULL) {
|
||||
tstrncpy(pMeta->sTableId, pTable->superTable->info.tableId, TSDB_TABLE_FNAME_LEN);
|
||||
}
|
||||
|
||||
if (pTable->info.type == TSDB_CHILD_TABLE) {
|
||||
if (pTable->info.type == TSDB_CHILD_TABLE && pTable->superTable != NULL) {
|
||||
pMeta->sversion = htons(pTable->superTable->sversion);
|
||||
pMeta->tversion = htons(pTable->superTable->tversion);
|
||||
pMeta->numOfTags = (int8_t)pTable->superTable->numOfTags;
|
||||
|
@ -2122,8 +2128,8 @@ static int32_t mnodeDoGetChildTableMeta(SMnodeMsg *pMsg, STableMetaMsg *pMeta) {
|
|||
}
|
||||
pMeta->vgroup.vgId = htonl(pMsg->pVgroup->vgId);
|
||||
|
||||
mDebug("app:%p:%p, table:%s, uid:%" PRIu64 " table meta is retrieved", pMsg->rpcMsg.ahandle, pMsg,
|
||||
pTable->info.tableId, pTable->uid);
|
||||
mDebug("app:%p:%p, table:%s, uid:%" PRIu64 " table meta is retrieved, vgId:%d sid:%d", pMsg->rpcMsg.ahandle, pMsg,
|
||||
pTable->info.tableId, pTable->uid, pTable->vgId, pTable->sid);
|
||||
|
||||
return TSDB_CODE_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -434,7 +434,8 @@ int32_t mnodeGetAvailableVgroup(SMnodeMsg *pMsg, SVgObj **ppVgroup, int32_t *pSi
|
|||
int maxVgroupsPerDb = tsMaxVgroupsPerDb;
|
||||
if (maxVgroupsPerDb <= 0) {
|
||||
maxVgroupsPerDb = mnodeGetOnlinDnodesCpuCoreNum();
|
||||
maxVgroupsPerDb = MAX(maxVgroupsPerDb, 2);
|
||||
maxVgroupsPerDb = MAX(maxVgroupsPerDb, TSDB_MIN_VNODES_PER_DB);
|
||||
maxVgroupsPerDb = MIN(maxVgroupsPerDb, TSDB_MAX_VNODES_PER_DB);
|
||||
}
|
||||
|
||||
int32_t code = TSDB_CODE_MND_NO_ENOUGH_DNODES;
|
||||
|
@ -660,13 +661,13 @@ static int32_t mnodeGetVgroupMeta(STableMetaMsg *pMeta, SShowObj *pShow, void *p
|
|||
for (int32_t i = 0; i < pShow->maxReplica; ++i) {
|
||||
pShow->bytes[cols] = 2;
|
||||
pSchema[cols].type = TSDB_DATA_TYPE_SMALLINT;
|
||||
strcpy(pSchema[cols].name, "dnode");
|
||||
snprintf(pSchema[cols].name, TSDB_COL_NAME_LEN, "dnode%d", i + 1);
|
||||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
|
||||
pShow->bytes[cols] = 9 + VARSTR_HEADER_SIZE;
|
||||
pSchema[cols].type = TSDB_DATA_TYPE_BINARY;
|
||||
strcpy(pSchema[cols].name, "vstatus");
|
||||
snprintf(pSchema[cols].name, TSDB_COL_NAME_LEN, "v%dstatus", i + 1);
|
||||
pSchema[cols].bytes = htons(pShow->bytes[cols]);
|
||||
cols++;
|
||||
}
|
||||
|
|
|
@ -24,10 +24,14 @@ extern "C" {
|
|||
#include "osDarwin.h"
|
||||
#endif
|
||||
|
||||
#ifdef _TD_ARM_64_
|
||||
#ifdef _TD_ARM_64
|
||||
#include "osArm64.h"
|
||||
#endif
|
||||
|
||||
#ifdef _TD_ARM_32
|
||||
#include "osArm32.h"
|
||||
#endif
|
||||
|
||||
#ifdef _TD_LINUX_64
|
||||
#include "osLinux64.h"
|
||||
#endif
|
||||
|
@ -40,7 +44,7 @@ extern "C" {
|
|||
#include "osAlpine.h"
|
||||
#endif
|
||||
|
||||
#ifdef _TD_NINGSI_60_
|
||||
#ifdef _TD_NINGSI_60
|
||||
#include "osNingsi.h"
|
||||
#endif
|
||||
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* 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 TDENGINE_OS_ARM32_H
|
||||
#define TDENGINE_OS_ARM32_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <argp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <endian.h>
|
||||
#include <errno.h>
|
||||
#include <float.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <libgen.h>
|
||||
#include <limits.h>
|
||||
#include <locale.h>
|
||||
#include <math.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <netinet/udp.h>
|
||||
#include <pthread.h>
|
||||
#include <pwd.h>
|
||||
#include <regex.h>
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <sys/epoll.h>
|
||||
#include <sys/eventfd.h>
|
||||
#include <sys/file.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/sendfile.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <sys/statvfs.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/uio.h>
|
||||
#include <sys/un.h>
|
||||
#include <syslog.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
#include <wchar.h>
|
||||
#include <wordexp.h>
|
||||
#include <wctype.h>
|
||||
#include <inttypes.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <sys/resource.h>
|
||||
#include <error.h>
|
||||
|
||||
#define TAOS_OS_FUNC_LZ4
|
||||
#define BUILDIN_CLZL(val) __builtin_clzll(val)
|
||||
#define BUILDIN_CTZL(val) __builtin_ctzll(val)
|
||||
#define BUILDIN_CLZ(val) __builtin_clz(val)
|
||||
#define BUILDIN_CTZ(val) __builtin_ctz(val)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -20,11 +20,14 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
// TAOS_OS_FUNC_DIR
|
||||
void taosRemoveDir(char *rootDir);
|
||||
int taosMkDir(const char *pathname, mode_t mode);
|
||||
void taosRename(char* oldName, char *newName);
|
||||
void taosRemoveOldLogFiles(char *rootDir, int32_t keepDays);
|
||||
int32_t taosCompressFile(char *srcFileName, char *destFileName);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -129,8 +129,6 @@ void* atomic_exchange_ptr_impl( void **ptr, void *val );
|
|||
#define atomic_fetch_xor_64(ptr, val) __sync_fetch_and_xor((ptr), (val))
|
||||
#define atomic_fetch_xor_ptr(ptr, val) __sync_fetch_and_xor((ptr), (val))
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -30,8 +30,6 @@ extern "C" {
|
|||
#define MILLISECOND_PER_HOUR (MILLISECOND_PER_MINUTE * 60)
|
||||
#define MILLISECOND_PER_DAY (MILLISECOND_PER_HOUR * 24)
|
||||
#define MILLISECOND_PER_WEEK (MILLISECOND_PER_DAY * 7)
|
||||
#define MILLISECOND_PER_MONTH (MILLISECOND_PER_DAY * 30)
|
||||
#define MILLISECOND_PER_YEAR (MILLISECOND_PER_DAY * 365)
|
||||
|
||||
//@return timestamp in second
|
||||
int32_t taosGetTimestampSec();
|
||||
|
@ -63,8 +61,23 @@ static FORCE_INLINE int64_t taosGetTimestamp(int32_t precision) {
|
|||
}
|
||||
}
|
||||
|
||||
int32_t getTimestampInUsFromStr(char* token, int32_t tokenlen, int64_t* ts);
|
||||
int32_t parseDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit);
|
||||
|
||||
typedef struct SInterval {
|
||||
int32_t tz; // query client timezone
|
||||
char intervalUnit;
|
||||
char slidingUnit;
|
||||
char offsetUnit;
|
||||
int64_t interval;
|
||||
int64_t sliding;
|
||||
int64_t offset;
|
||||
} SInterval;
|
||||
|
||||
int64_t taosTimeAdd(int64_t t, int64_t duration, char unit, int32_t precision);
|
||||
int64_t taosTimeTruncate(int64_t t, const SInterval* pInterval, int32_t precision);
|
||||
int32_t taosTimeCountInterval(int64_t skey, int64_t ekey, int64_t interval, char unit, int32_t precision);
|
||||
|
||||
int32_t parseAbsoluteDuration(char* token, int32_t tokenlen, int64_t* ts);
|
||||
int32_t parseNatualDuration(const char* token, int32_t tokenLen, int64_t* duration, char* unit);
|
||||
|
||||
int32_t taosParseTime(char* timestr, int64_t* time, int32_t len, int32_t timePrec, int8_t dayligth);
|
||||
void deltaToUtcInitOnce();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue