Merge from master
This commit is contained in:
commit
9d9d946073
124
.drone.yml
124
.drone.yml
|
@ -15,7 +15,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -26,7 +26,32 @@ steps:
|
||||||
- 2.0
|
- 2.0
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: test_arm64
|
name: test_arm64_bionic
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: arm64v8/ubuntu:bionic
|
||||||
|
commands:
|
||||||
|
- apt-get update
|
||||||
|
- apt-get install -y cmake build-essential
|
||||||
|
- mkdir debug
|
||||||
|
- cd debug
|
||||||
|
- cmake .. -DCPUTYPE=aarch64 > /dev/null
|
||||||
|
- make -j4
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
- 2.0
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: test_arm64_focal
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -34,14 +59,15 @@ platform:
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: build
|
- name: build
|
||||||
image: gcc
|
image: arm64v8/ubuntu:focal
|
||||||
commands:
|
commands:
|
||||||
|
- echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections
|
||||||
- apt-get update
|
- apt-get update
|
||||||
- apt-get install -y cmake build-essential
|
- apt-get install -y -qq cmake build-essential
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake .. -DCPUTYPE=aarch64 > /dev/null
|
- cmake .. -DCPUTYPE=aarch64 > /dev/null
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -52,7 +78,57 @@ steps:
|
||||||
- 2.0
|
- 2.0
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: test_arm
|
name: test_arm64_centos7
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: arm64v8/centos:7
|
||||||
|
commands:
|
||||||
|
- yum install -y gcc gcc-c++ make cmake git
|
||||||
|
- mkdir debug
|
||||||
|
- cd debug
|
||||||
|
- cmake .. -DCPUTYPE=aarch64 > /dev/null
|
||||||
|
- make -j4
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
- 2.0
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: test_arm64_centos8
|
||||||
|
|
||||||
|
platform:
|
||||||
|
os: linux
|
||||||
|
arch: arm64
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: build
|
||||||
|
image: arm64v8/centos:8
|
||||||
|
commands:
|
||||||
|
- dnf install -y gcc gcc-c++ make cmake epel-release git libarchive
|
||||||
|
- mkdir debug
|
||||||
|
- cd debug
|
||||||
|
- cmake .. -DCPUTYPE=aarch64 > /dev/null
|
||||||
|
- make -j4
|
||||||
|
trigger:
|
||||||
|
event:
|
||||||
|
- pull_request
|
||||||
|
when:
|
||||||
|
branch:
|
||||||
|
- develop
|
||||||
|
- master
|
||||||
|
- 2.0
|
||||||
|
---
|
||||||
|
kind: pipeline
|
||||||
|
name: test_arm_bionic
|
||||||
|
|
||||||
platform:
|
platform:
|
||||||
os: linux
|
os: linux
|
||||||
|
@ -67,7 +143,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake .. -DCPUTYPE=aarch32 > /dev/null
|
- cmake .. -DCPUTYPE=aarch32 > /dev/null
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -76,7 +152,6 @@ steps:
|
||||||
- develop
|
- develop
|
||||||
- master
|
- master
|
||||||
- 2.0
|
- 2.0
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: build_trusty
|
name: build_trusty
|
||||||
|
@ -95,7 +170,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -121,7 +196,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -130,7 +205,6 @@ steps:
|
||||||
- develop
|
- develop
|
||||||
- master
|
- master
|
||||||
- 2.0
|
- 2.0
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
name: build_bionic
|
name: build_bionic
|
||||||
|
@ -147,7 +221,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -171,7 +245,7 @@ steps:
|
||||||
- mkdir debug
|
- mkdir debug
|
||||||
- cd debug
|
- cd debug
|
||||||
- cmake ..
|
- cmake ..
|
||||||
- make
|
- make -j4
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- pull_request
|
- pull_request
|
||||||
|
@ -180,27 +254,3 @@ steps:
|
||||||
- develop
|
- develop
|
||||||
- master
|
- master
|
||||||
- 2.0
|
- 2.0
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
name: goodbye
|
|
||||||
|
|
||||||
platform:
|
|
||||||
os: linux
|
|
||||||
arch: amd64
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: 64-bit
|
|
||||||
image: alpine
|
|
||||||
commands:
|
|
||||||
- echo 64-bit is good.
|
|
||||||
when:
|
|
||||||
branch:
|
|
||||||
- develop
|
|
||||||
- master
|
|
||||||
- 2.0
|
|
||||||
|
|
||||||
|
|
||||||
depends_on:
|
|
||||||
- test_arm64
|
|
||||||
- test_amd64
|
|
|
@ -5,7 +5,7 @@ node {
|
||||||
git url: 'https://github.com/taosdata/TDengine.git'
|
git url: 'https://github.com/taosdata/TDengine.git'
|
||||||
}
|
}
|
||||||
|
|
||||||
def skipstage=0
|
def skipbuild=0
|
||||||
|
|
||||||
def abortPreviousBuilds() {
|
def abortPreviousBuilds() {
|
||||||
def currentJobName = env.JOB_NAME
|
def currentJobName = env.JOB_NAME
|
||||||
|
@ -33,8 +33,7 @@ def abort_previous(){
|
||||||
milestone(buildNumber)
|
milestone(buildNumber)
|
||||||
}
|
}
|
||||||
def pre_test(){
|
def pre_test(){
|
||||||
|
sh'hostname'
|
||||||
|
|
||||||
sh '''
|
sh '''
|
||||||
sudo rmtaos || echo "taosd has not installed"
|
sudo rmtaos || echo "taosd has not installed"
|
||||||
'''
|
'''
|
||||||
|
@ -107,19 +106,17 @@ def pre_test(){
|
||||||
make > /dev/null
|
make > /dev/null
|
||||||
make install > /dev/null
|
make install > /dev/null
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
pip3 install ${WKC}/src/connector/python
|
pip3 install ${WKC}/src/connector/python/
|
||||||
'''
|
'''
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
pipeline {
|
pipeline {
|
||||||
agent none
|
agent none
|
||||||
|
|
||||||
environment{
|
environment{
|
||||||
WK = '/var/lib/jenkins/workspace/TDinternal'
|
WK = '/var/lib/jenkins/workspace/TDinternal'
|
||||||
WKC= '/var/lib/jenkins/workspace/TDinternal/community'
|
WKC= '/var/lib/jenkins/workspace/TDinternal/community'
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
stage('pre_build'){
|
stage('pre_build'){
|
||||||
agent{label 'master'}
|
agent{label 'master'}
|
||||||
|
@ -135,19 +132,22 @@ pipeline {
|
||||||
rm -rf ${WORKSPACE}.tes
|
rm -rf ${WORKSPACE}.tes
|
||||||
cp -r ${WORKSPACE} ${WORKSPACE}.tes
|
cp -r ${WORKSPACE} ${WORKSPACE}.tes
|
||||||
cd ${WORKSPACE}.tes
|
cd ${WORKSPACE}.tes
|
||||||
|
git fetch
|
||||||
'''
|
'''
|
||||||
script {
|
script {
|
||||||
if (env.CHANGE_TARGET == 'master') {
|
if (env.CHANGE_TARGET == 'master') {
|
||||||
sh '''
|
sh '''
|
||||||
git checkout master
|
git checkout master
|
||||||
git pull origin master
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
else {
|
else if(env.CHANGE_TARGET == '2.0'){
|
||||||
|
sh '''
|
||||||
|
git checkout 2.0
|
||||||
|
'''
|
||||||
|
}
|
||||||
|
else{
|
||||||
sh '''
|
sh '''
|
||||||
git checkout develop
|
git checkout develop
|
||||||
git pull origin develop
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -157,30 +157,32 @@ pipeline {
|
||||||
'''
|
'''
|
||||||
|
|
||||||
script{
|
script{
|
||||||
env.skipstage=sh(script:"cd ${WORKSPACE}.tes && git --no-pager diff --name-only FETCH_HEAD ${env.CHANGE_TARGET}|grep -v -E '.*md|//src//connector|Jenkinsfile|test-all.sh' || echo 0 ",returnStdout:true)
|
skipbuild='2'
|
||||||
|
skipbuild=sh(script: "git log -2 --pretty=%B | fgrep -ie '[skip ci]' -e '[ci skip]' && echo 1 || echo 2", returnStdout:true)
|
||||||
|
println skipbuild
|
||||||
}
|
}
|
||||||
println env.skipstage
|
|
||||||
sh'''
|
sh'''
|
||||||
rm -rf ${WORKSPACE}.tes
|
rm -rf ${WORKSPACE}.tes
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('Parallel test stage') {
|
stage('Parallel test stage') {
|
||||||
//only build pr
|
//only build pr
|
||||||
when {
|
when {
|
||||||
|
allOf{
|
||||||
changeRequest()
|
changeRequest()
|
||||||
expression {
|
expression{
|
||||||
env.skipstage != 0
|
return skipbuild.trim() == '2'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
parallel {
|
parallel {
|
||||||
stage('python_1_s1') {
|
stage('python_1_s1') {
|
||||||
agent{label 'p1'}
|
agent{label " slave1 || slave11 "}
|
||||||
steps {
|
steps {
|
||||||
|
|
||||||
pre_test()
|
pre_test()
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
|
@ -191,11 +193,11 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('python_2_s5') {
|
stage('python_2_s5') {
|
||||||
agent{label 'p2'}
|
agent{label " slave5 || slave15 "}
|
||||||
steps {
|
steps {
|
||||||
|
|
||||||
pre_test()
|
pre_test()
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
|
@ -205,9 +207,9 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('python_3_s6') {
|
stage('python_3_s6') {
|
||||||
agent{label 'p3'}
|
agent{label " slave6 || slave16 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
|
@ -218,10 +220,30 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('test_b1_s2') {
|
stage('test_b1_s2') {
|
||||||
agent{label 'b1'}
|
agent{label " slave2 || slave12 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
|
sh '''
|
||||||
|
rm -rf /var/lib/taos/*
|
||||||
|
rm -rf /var/log/taos/*
|
||||||
|
nohup taosd >/dev/null &
|
||||||
|
sleep 10
|
||||||
|
'''
|
||||||
|
sh '''
|
||||||
|
cd ${WKC}/tests/examples/nodejs
|
||||||
|
npm install td2.0-connector > /dev/null 2>&1
|
||||||
|
node nodejsChecker.js host=localhost
|
||||||
|
'''
|
||||||
|
sh '''
|
||||||
|
cd ${WKC}/tests/examples/C#/taosdemo
|
||||||
|
mcs -out:taosdemo *.cs > /dev/null 2>&1
|
||||||
|
echo '' |./taosdemo
|
||||||
|
'''
|
||||||
|
sh '''
|
||||||
|
cd ${WKC}/tests/gotest
|
||||||
|
bash batchtest.sh
|
||||||
|
'''
|
||||||
sh '''
|
sh '''
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
./test-all.sh b1fq
|
./test-all.sh b1fq
|
||||||
|
@ -229,9 +251,8 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('test_crash_gen_s3') {
|
stage('test_crash_gen_s3') {
|
||||||
agent{label "b2"}
|
agent{label " slave3 || slave13 "}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
pre_test()
|
pre_test()
|
||||||
|
@ -257,7 +278,7 @@ pipeline {
|
||||||
./handle_taosd_val_log.sh
|
./handle_taosd_val_log.sh
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
|
@ -265,12 +286,10 @@ pipeline {
|
||||||
date
|
date
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
stage('test_valgrind_s4') {
|
stage('test_valgrind_s4') {
|
||||||
agent{label "b3"}
|
agent{label " slave4 || slave14 "}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
pre_test()
|
pre_test()
|
||||||
|
@ -281,7 +300,7 @@ pipeline {
|
||||||
./handle_val_log.sh
|
./handle_val_log.sh
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
cd ${WKC}/tests
|
cd ${WKC}/tests
|
||||||
|
@ -296,9 +315,9 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('test_b4_s7') {
|
stage('test_b4_s7') {
|
||||||
agent{label 'b4'}
|
agent{label " slave7 || slave17 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
|
@ -315,9 +334,9 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('test_b5_s8') {
|
stage('test_b5_s8') {
|
||||||
agent{label 'b5'}
|
agent{label " slave8 || slave18 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
|
@ -328,9 +347,9 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('test_b6_s9') {
|
stage('test_b6_s9') {
|
||||||
agent{label 'b6'}
|
agent{label " slave9 || slave19 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
|
@ -341,9 +360,9 @@ pipeline {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
stage('test_b7_s10') {
|
stage('test_b7_s10') {
|
||||||
agent{label 'b7'}
|
agent{label " slave10 || slave20 "}
|
||||||
steps {
|
steps {
|
||||||
timeout(time: 45, unit: 'MINUTES'){
|
timeout(time: 55, unit: 'MINUTES'){
|
||||||
pre_test()
|
pre_test()
|
||||||
sh '''
|
sh '''
|
||||||
date
|
date
|
||||||
|
@ -434,5 +453,4 @@ pipeline {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,7 +4,7 @@ PROJECT(TDengine)
|
||||||
IF (DEFINED VERNUMBER)
|
IF (DEFINED VERNUMBER)
|
||||||
SET(TD_VER_NUMBER ${VERNUMBER})
|
SET(TD_VER_NUMBER ${VERNUMBER})
|
||||||
ELSE ()
|
ELSE ()
|
||||||
SET(TD_VER_NUMBER "2.1.6.0")
|
SET(TD_VER_NUMBER "2.1.7.1")
|
||||||
ENDIF ()
|
ENDIF ()
|
||||||
|
|
||||||
IF (DEFINED VERCOMPATIBLE)
|
IF (DEFINED VERCOMPATIBLE)
|
||||||
|
|
|
@ -98,6 +98,7 @@ int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDef
|
||||||
char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) {
|
char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) {
|
||||||
int nBytes;
|
int nBytes;
|
||||||
char *pBuf;
|
char *pBuf;
|
||||||
|
char *pBuf1;
|
||||||
nBytes = 4 * ((int)lstrlen(string) + 1); /* Worst case for the size needed */
|
nBytes = 4 * ((int)lstrlen(string) + 1); /* Worst case for the size needed */
|
||||||
pBuf = (char *)malloc(nBytes);
|
pBuf = (char *)malloc(nBytes);
|
||||||
if (!pBuf) {
|
if (!pBuf) {
|
||||||
|
@ -110,8 +111,9 @@ char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefault
|
||||||
free(pBuf);
|
free(pBuf);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
pBuf = realloc(pBuf, nBytes+1);
|
pBuf1 = realloc(pBuf, nBytes+1);
|
||||||
return pBuf;
|
if(pBuf1 == NULL && pBuf != NULL) free(pBuf);
|
||||||
|
return pBuf1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int CountCharacters(const char *string, UINT cp) {
|
int CountCharacters(const char *string, UINT cp) {
|
||||||
|
|
|
@ -68,6 +68,7 @@ int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) {
|
||||||
int iString = FALSE; /* TRUE = string mode; FALSE = non-string mode */
|
int iString = FALSE; /* TRUE = string mode; FALSE = non-string mode */
|
||||||
int nBackslash = 0;
|
int nBackslash = 0;
|
||||||
char **ppszArg;
|
char **ppszArg;
|
||||||
|
char **ppszArg1;
|
||||||
int iArg = FALSE; /* TRUE = inside an argument; FALSE = between arguments */
|
int iArg = FALSE; /* TRUE = inside an argument; FALSE = between arguments */
|
||||||
|
|
||||||
ppszArg = (char **)malloc((argc+1)*sizeof(char *));
|
ppszArg = (char **)malloc((argc+1)*sizeof(char *));
|
||||||
|
@ -89,7 +90,10 @@ int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) {
|
||||||
if ((!iArg) && (c != ' ') && (c != '\t')) { /* Beginning of a new argument */
|
if ((!iArg) && (c != ' ') && (c != '\t')) { /* Beginning of a new argument */
|
||||||
iArg = TRUE;
|
iArg = TRUE;
|
||||||
ppszArg[argc++] = pszCopy+j;
|
ppszArg[argc++] = pszCopy+j;
|
||||||
ppszArg = (char **)realloc(ppszArg, (argc+1)*sizeof(char *));
|
ppszArg1 = (char **)realloc(ppszArg, (argc+1)*sizeof(char *));
|
||||||
|
if(ppszArg1 == NULL && ppszArg != NULL)
|
||||||
|
free(ppszArg);
|
||||||
|
ppszArg = ppszArg1;
|
||||||
if (!ppszArg) return -1;
|
if (!ppszArg) return -1;
|
||||||
pszCopy[j] = c0 = '\0';
|
pszCopy[j] = c0 = '\0';
|
||||||
}
|
}
|
||||||
|
@ -212,7 +216,7 @@ int _initU(void) {
|
||||||
fprintf(stderr, "Warning: Can't convert the argument line to UTF-8\n");
|
fprintf(stderr, "Warning: Can't convert the argument line to UTF-8\n");
|
||||||
_acmdln[0] = '\0';
|
_acmdln[0] = '\0';
|
||||||
}
|
}
|
||||||
realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */
|
//realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */
|
||||||
/* Should not fail since we make it smaller */
|
/* Should not fail since we make it smaller */
|
||||||
|
|
||||||
/* Record the console code page, to allow converting the output accordingly */
|
/* Record the console code page, to allow converting the output accordingly */
|
||||||
|
|
|
@ -196,6 +196,7 @@ not_compact_enough:
|
||||||
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
||||||
char *realpath(const char *path, char *outbuf) {
|
char *realpath(const char *path, char *outbuf) {
|
||||||
char *pOutbuf = outbuf;
|
char *pOutbuf = outbuf;
|
||||||
|
char *pOutbuf1 = NULL;
|
||||||
int iErr;
|
int iErr;
|
||||||
const char *pc;
|
const char *pc;
|
||||||
|
|
||||||
|
@ -242,8 +243,11 @@ realpath_failed:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
if (!outbuf) {
|
||||||
return pOutbuf;
|
pOutbuf1 = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
||||||
|
if(pOutbuf1 == NULL && pOutbuf) free(pOutbuf);
|
||||||
|
}
|
||||||
|
return pOutbuf1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -517,6 +521,7 @@ int ResolveLinksA(const char *path, char *buf, size_t bufsize) {
|
||||||
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
||||||
char *realpathU(const char *path, char *outbuf) {
|
char *realpathU(const char *path, char *outbuf) {
|
||||||
char *pOutbuf = outbuf;
|
char *pOutbuf = outbuf;
|
||||||
|
char *pOutbuf1 = NULL;
|
||||||
char *pPath1 = NULL;
|
char *pPath1 = NULL;
|
||||||
char *pPath2 = NULL;
|
char *pPath2 = NULL;
|
||||||
int iErr;
|
int iErr;
|
||||||
|
@ -590,10 +595,13 @@ realpathU_failed:
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG_LEAVE(("return 0x%p; // \"%s\"\n", pOutbuf, pOutbuf));
|
DEBUG_LEAVE(("return 0x%p; // \"%s\"\n", pOutbuf, pOutbuf));
|
||||||
if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
if (!outbuf) {
|
||||||
|
pOutbuf1 = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
||||||
|
if(pOutbuf1 == NULL && pOutbuf) free(pOutbuf);
|
||||||
|
}
|
||||||
free(pPath1);
|
free(pPath1);
|
||||||
free(pPath2);
|
free(pPath2);
|
||||||
return pOutbuf;
|
return pOutbuf1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* defined(_WIN32) */
|
#endif /* defined(_WIN32) */
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 0ca5b15a8eac40327dd737be52c926fa5675712c
|
Subproject commit ceda5bf9fcd7836509ac97dcc0056b3f1dd48cc5
|
|
@ -144,6 +144,9 @@ keepColumnName 1
|
||||||
# max length of an SQL
|
# max length of an SQL
|
||||||
# maxSQLLength 65480
|
# maxSQLLength 65480
|
||||||
|
|
||||||
|
# max length of WildCards
|
||||||
|
# maxWildCardsLength 100
|
||||||
|
|
||||||
# the maximum number of records allowed for super table time sorting
|
# the maximum number of records allowed for super table time sorting
|
||||||
# maxNumOfOrderedRes 100000
|
# maxNumOfOrderedRes 100000
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ fi
|
||||||
if [ "$pagMode" == "lite" ]; then
|
if [ "$pagMode" == "lite" ]; then
|
||||||
strip ${build_dir}/bin/taosd
|
strip ${build_dir}/bin/taosd
|
||||||
strip ${build_dir}/bin/taos
|
strip ${build_dir}/bin/taos
|
||||||
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${script_dir}/remove.sh"
|
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${script_dir}/remove.sh ${script_dir}/startPre.sh"
|
||||||
else
|
else
|
||||||
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdump ${build_dir}/bin/taosdemo ${build_dir}/bin/tarbitrator\
|
bin_files="${build_dir}/bin/taosd ${build_dir}/bin/taos ${build_dir}/bin/taosdump ${build_dir}/bin/taosdemo ${build_dir}/bin/tarbitrator\
|
||||||
${script_dir}/remove.sh ${script_dir}/set_core.sh ${script_dir}/startPre.sh ${script_dir}/taosd-dump-cfg.gdb"
|
${script_dir}/remove.sh ${script_dir}/set_core.sh ${script_dir}/startPre.sh ${script_dir}/taosd-dump-cfg.gdb"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: tdengine
|
name: tdengine
|
||||||
base: core18
|
base: core18
|
||||||
version: '2.1.6.0'
|
version: '2.1.7.1'
|
||||||
icon: snap/gui/t-dengine.svg
|
icon: snap/gui/t-dengine.svg
|
||||||
summary: an open-source big data platform designed and optimized for IoT.
|
summary: an open-source big data platform designed and optimized for IoT.
|
||||||
description: |
|
description: |
|
||||||
|
@ -72,7 +72,7 @@ parts:
|
||||||
- usr/bin/taosd
|
- usr/bin/taosd
|
||||||
- usr/bin/taos
|
- usr/bin/taos
|
||||||
- usr/bin/taosdemo
|
- usr/bin/taosdemo
|
||||||
- usr/lib/libtaos.so.2.1.6.0
|
- usr/lib/libtaos.so.2.1.7.1
|
||||||
- usr/lib/libtaos.so.1
|
- usr/lib/libtaos.so.1
|
||||||
- usr/lib/libtaos.so
|
- usr/lib/libtaos.so
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,17 @@ void bnCleanupDnodes() {
|
||||||
|
|
||||||
static void bnCheckDnodesSize(int32_t dnodesNum) {
|
static void bnCheckDnodesSize(int32_t dnodesNum) {
|
||||||
if (tsBnDnodes.maxSize <= dnodesNum) {
|
if (tsBnDnodes.maxSize <= dnodesNum) {
|
||||||
tsBnDnodes.maxSize = dnodesNum * 2;
|
int32_t maxSize = dnodesNum * 2;
|
||||||
tsBnDnodes.list = realloc(tsBnDnodes.list, tsBnDnodes.maxSize * sizeof(SDnodeObj *));
|
SDnodeObj** list1 = NULL;
|
||||||
|
int32_t retry = 0;
|
||||||
|
|
||||||
|
while(list1 == NULL && retry++ < 3) {
|
||||||
|
list1 = realloc(tsBnDnodes.list, maxSize * sizeof(SDnodeObj *));
|
||||||
|
}
|
||||||
|
if(list1) {
|
||||||
|
tsBnDnodes.list = list1;
|
||||||
|
tsBnDnodes.maxSize = maxSize;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,12 @@ void tscUnlockByThread(int64_t *lockedBy);
|
||||||
|
|
||||||
int tsInsertInitialCheck(SSqlObj *pSql);
|
int tsInsertInitialCheck(SSqlObj *pSql);
|
||||||
|
|
||||||
|
void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs);
|
||||||
|
|
||||||
|
void tscFreeRetrieveSup(SSqlObj *pSql);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -31,11 +31,12 @@ extern "C" {
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_SUPER_TABLE(metaInfo) \
|
#define UTIL_TABLE_IS_SUPER_TABLE(metaInfo) \
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_SUPER_TABLE))
|
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_SUPER_TABLE))
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_CHILD_TABLE(metaInfo) \
|
#define UTIL_TABLE_IS_CHILD_TABLE(metaInfo) \
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE))
|
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_CHILD_TABLE))
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo)\
|
#define UTIL_TABLE_IS_NORMAL_TABLE(metaInfo) \
|
||||||
(!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo)))
|
(!(UTIL_TABLE_IS_SUPER_TABLE(metaInfo) || UTIL_TABLE_IS_CHILD_TABLE(metaInfo) || UTIL_TABLE_IS_TMP_TABLE(metaInfo)))
|
||||||
|
|
||||||
#define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \
|
#define UTIL_TABLE_IS_TMP_TABLE(metaInfo) \
|
||||||
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE))
|
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE))
|
||||||
|
@ -142,6 +143,7 @@ bool tscIsSessionWindowQuery(SQueryInfo* pQueryInfo);
|
||||||
bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo);
|
bool tscIsSecondStageQuery(SQueryInfo* pQueryInfo);
|
||||||
bool tsIsArithmeticQueryOnAggResult(SQueryInfo* pQueryInfo);
|
bool tsIsArithmeticQueryOnAggResult(SQueryInfo* pQueryInfo);
|
||||||
bool tscGroupbyColumn(SQueryInfo* pQueryInfo);
|
bool tscGroupbyColumn(SQueryInfo* pQueryInfo);
|
||||||
|
int32_t tscGetTopBotQueryExprIndex(SQueryInfo* pQueryInfo);
|
||||||
bool tscIsTopBotQuery(SQueryInfo* pQueryInfo);
|
bool tscIsTopBotQuery(SQueryInfo* pQueryInfo);
|
||||||
bool hasTagValOutput(SQueryInfo* pQueryInfo);
|
bool hasTagValOutput(SQueryInfo* pQueryInfo);
|
||||||
bool timeWindowInterpoRequired(SQueryInfo *pQueryInfo);
|
bool timeWindowInterpoRequired(SQueryInfo *pQueryInfo);
|
||||||
|
|
|
@ -84,9 +84,14 @@ typedef struct SParamInfo {
|
||||||
} SParamInfo;
|
} SParamInfo;
|
||||||
|
|
||||||
typedef struct SBoundColumn {
|
typedef struct SBoundColumn {
|
||||||
bool hasVal; // denote if current column has bound or not
|
|
||||||
int32_t offset; // all column offset value
|
int32_t offset; // all column offset value
|
||||||
|
int32_t toffset; // first part offset for SDataRow TODO: get offset from STSchema on future
|
||||||
|
uint8_t valStat; // denote if current column bound or not(0 means has val, 1 means no val)
|
||||||
} SBoundColumn;
|
} SBoundColumn;
|
||||||
|
typedef enum {
|
||||||
|
VAL_STAT_HAS = 0x0, // 0 means has val
|
||||||
|
VAL_STAT_NONE = 0x01, // 1 means no val
|
||||||
|
} EValStat;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t schemaColIdx;
|
uint16_t schemaColIdx;
|
||||||
|
@ -99,32 +104,106 @@ typedef enum _COL_ORDER_STATUS {
|
||||||
ORDER_STATUS_ORDERED = 1,
|
ORDER_STATUS_ORDERED = 1,
|
||||||
ORDER_STATUS_DISORDERED = 2,
|
ORDER_STATUS_DISORDERED = 2,
|
||||||
} EOrderStatus;
|
} EOrderStatus;
|
||||||
|
|
||||||
typedef struct SParsedDataColInfo {
|
typedef struct SParsedDataColInfo {
|
||||||
int16_t numOfCols;
|
int16_t numOfCols;
|
||||||
int16_t numOfBound;
|
int16_t numOfBound;
|
||||||
int32_t * boundedColumns; // bounded column idx according to schema
|
uint16_t flen; // TODO: get from STSchema
|
||||||
|
uint16_t allNullLen; // TODO: get from STSchema
|
||||||
|
uint16_t extendedVarLen;
|
||||||
|
int32_t * boundedColumns; // bound column idx according to schema
|
||||||
SBoundColumn * cols;
|
SBoundColumn * cols;
|
||||||
SBoundIdxInfo *colIdxInfo;
|
SBoundIdxInfo *colIdxInfo;
|
||||||
int8_t orderStatus; // bounded columns:
|
int8_t orderStatus; // bound columns
|
||||||
} SParsedDataColInfo;
|
} SParsedDataColInfo;
|
||||||
|
|
||||||
#define IS_DATA_COL_ORDERED(s) ((s) == (int8_t)ORDER_STATUS_ORDERED)
|
#define IS_DATA_COL_ORDERED(spd) ((spd->orderStatus) == (int8_t)ORDER_STATUS_ORDERED)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
SSchema * pSchema;
|
int32_t dataLen; // len of SDataRow
|
||||||
int16_t sversion;
|
int32_t kvLen; // len of SKVRow
|
||||||
int32_t flen;
|
} SMemRowInfo;
|
||||||
uint16_t nCols;
|
typedef struct {
|
||||||
void * buf;
|
uint8_t memRowType;
|
||||||
void * pDataBlock;
|
uint8_t compareStat; // 0 unknown, 1 need compare, 2 no need
|
||||||
SSubmitBlk *pSubmitBlk;
|
TDRowTLenT dataRowInitLen;
|
||||||
|
TDRowTLenT kvRowInitLen;
|
||||||
|
SMemRowInfo *rowInfo;
|
||||||
} SMemRowBuilder;
|
} SMemRowBuilder;
|
||||||
|
|
||||||
typedef struct {
|
typedef enum {
|
||||||
TDRowLenT allNullLen;
|
ROW_COMPARE_UNKNOWN = 0,
|
||||||
} SMemRowHelper;
|
ROW_COMPARE_NEED = 1,
|
||||||
|
ROW_COMPARE_NO_NEED = 2,
|
||||||
|
} ERowCompareStat;
|
||||||
|
|
||||||
|
int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec);
|
||||||
|
|
||||||
|
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint32_t nCols, uint32_t nBoundCols,
|
||||||
|
int32_t allNullLen);
|
||||||
|
void destroyMemRowBuilder(SMemRowBuilder *pBuilder);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
*
|
||||||
|
* @param memRowType
|
||||||
|
* @param spd
|
||||||
|
* @param idx the absolute bound index of columns
|
||||||
|
* @return FORCE_INLINE
|
||||||
|
*/
|
||||||
|
static FORCE_INLINE void tscGetMemRowAppendInfo(SSchema *pSchema, uint8_t memRowType, SParsedDataColInfo *spd,
|
||||||
|
int32_t idx, int32_t *toffset, int16_t *colId) {
|
||||||
|
int32_t schemaIdx = 0;
|
||||||
|
if (IS_DATA_COL_ORDERED(spd)) {
|
||||||
|
schemaIdx = spd->boundedColumns[idx];
|
||||||
|
if (isDataRowT(memRowType)) {
|
||||||
|
*toffset = (spd->cols + schemaIdx)->toffset; // the offset of firstPart
|
||||||
|
} else {
|
||||||
|
*toffset = idx * sizeof(SColIdx); // the offset of SColIdx
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ASSERT(idx == (spd->colIdxInfo + idx)->boundIdx);
|
||||||
|
schemaIdx = (spd->colIdxInfo + idx)->schemaColIdx;
|
||||||
|
if (isDataRowT(memRowType)) {
|
||||||
|
*toffset = (spd->cols + schemaIdx)->toffset;
|
||||||
|
} else {
|
||||||
|
*toffset = ((spd->colIdxInfo + idx)->finalIdx) * sizeof(SColIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*colId = pSchema[schemaIdx].colId;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Applicable to consume by multi-columns
|
||||||
|
*
|
||||||
|
* @param row
|
||||||
|
* @param value
|
||||||
|
* @param isCopyVarData In some scenario, the varVal is copied to row directly before calling tdAppend***ColVal()
|
||||||
|
* @param colId
|
||||||
|
* @param colType
|
||||||
|
* @param idx index in SSchema
|
||||||
|
* @param pBuilder
|
||||||
|
* @param spd
|
||||||
|
* @return FORCE_INLINE
|
||||||
|
*/
|
||||||
|
static FORCE_INLINE void tscAppendMemRowColVal(SMemRow row, const void *value, bool isCopyVarData, int16_t colId,
|
||||||
|
int8_t colType, int32_t toffset, SMemRowBuilder *pBuilder,
|
||||||
|
int32_t rowNum) {
|
||||||
|
tdAppendMemRowColVal(row, value, isCopyVarData, colId, colType, toffset);
|
||||||
|
if (pBuilder->compareStat == ROW_COMPARE_NEED) {
|
||||||
|
SMemRowInfo *pRowInfo = pBuilder->rowInfo + rowNum;
|
||||||
|
tdGetColAppendDeltaLen(value, colType, &pRowInfo->dataLen, &pRowInfo->kvLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Applicable to consume by one row
|
||||||
|
static FORCE_INLINE void tscAppendMemRowColValEx(SMemRow row, const void *value, bool isCopyVarData, int16_t colId,
|
||||||
|
int8_t colType, int32_t toffset, int32_t *dataLen, int32_t *kvLen,
|
||||||
|
uint8_t compareStat) {
|
||||||
|
tdAppendMemRowColVal(row, value, isCopyVarData, colId, colType, toffset);
|
||||||
|
if (compareStat == ROW_COMPARE_NEED) {
|
||||||
|
tdGetColAppendDeltaLen(value, colType, dataLen, kvLen);
|
||||||
|
}
|
||||||
|
}
|
||||||
typedef struct STableDataBlocks {
|
typedef struct STableDataBlocks {
|
||||||
SName tableName;
|
SName tableName;
|
||||||
int8_t tsSource; // where does the UNIX timestamp come from, server or client
|
int8_t tsSource; // where does the UNIX timestamp come from, server or client
|
||||||
|
@ -146,7 +225,7 @@ typedef struct STableDataBlocks {
|
||||||
uint32_t numOfAllocedParams;
|
uint32_t numOfAllocedParams;
|
||||||
uint32_t numOfParams;
|
uint32_t numOfParams;
|
||||||
SParamInfo * params;
|
SParamInfo * params;
|
||||||
SMemRowHelper rowHelper;
|
SMemRowBuilder rowBuilder;
|
||||||
} STableDataBlocks;
|
} STableDataBlocks;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
@ -435,8 +514,398 @@ int16_t getNewResColId(SSqlCmd* pCmd);
|
||||||
|
|
||||||
int32_t schemaIdxCompar(const void *lhs, const void *rhs);
|
int32_t schemaIdxCompar(const void *lhs, const void *rhs);
|
||||||
int32_t boundIdxCompar(const void *lhs, const void *rhs);
|
int32_t boundIdxCompar(const void *lhs, const void *rhs);
|
||||||
int initSMemRowHelper(SMemRowHelper *pHelper, SSchema *pSSchema, uint16_t nCols, uint16_t allNullColsLen);
|
static FORCE_INLINE int32_t getExtendedRowSize(STableDataBlocks *pBlock) {
|
||||||
int32_t getExtendedRowSize(STableComInfo *tinfo);
|
ASSERT(pBlock->rowSize == pBlock->pTableMeta->tableInfo.rowSize);
|
||||||
|
return pBlock->rowSize + TD_MEM_ROW_DATA_HEAD_SIZE + pBlock->boundColumnInfo.extendedVarLen;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE void checkAndConvertMemRow(SMemRow row, int32_t dataLen, int32_t kvLen) {
|
||||||
|
if (isDataRow(row)) {
|
||||||
|
if (kvLen < (dataLen * KVRatioConvert)) {
|
||||||
|
memRowSetConvert(row);
|
||||||
|
}
|
||||||
|
} else if (kvLen > dataLen) {
|
||||||
|
memRowSetConvert(row);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE void initSMemRow(SMemRow row, uint8_t memRowType, STableDataBlocks *pBlock, int16_t nBoundCols) {
|
||||||
|
memRowSetType(row, memRowType);
|
||||||
|
if (isDataRowT(memRowType)) {
|
||||||
|
dataRowSetVersion(memRowDataBody(row), pBlock->pTableMeta->sversion);
|
||||||
|
dataRowSetLen(memRowDataBody(row), (TDRowLenT)(TD_DATA_ROW_HEAD_SIZE + pBlock->boundColumnInfo.flen));
|
||||||
|
} else {
|
||||||
|
ASSERT(nBoundCols > 0);
|
||||||
|
memRowSetKvVersion(row, pBlock->pTableMeta->sversion);
|
||||||
|
kvRowSetNCols(memRowKvBody(row), nBoundCols);
|
||||||
|
kvRowSetLen(memRowKvBody(row), (TDRowLenT)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nBoundCols));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* TODO: Move to tdataformat.h and refactor when STSchema available.
|
||||||
|
* - fetch flen and toffset from STSChema and remove param spd
|
||||||
|
*/
|
||||||
|
static FORCE_INLINE void convertToSDataRow(SMemRow dest, SMemRow src, SSchema *pSchema, int nCols,
|
||||||
|
SParsedDataColInfo *spd) {
|
||||||
|
ASSERT(isKvRow(src));
|
||||||
|
SKVRow kvRow = memRowKvBody(src);
|
||||||
|
SDataRow dataRow = memRowDataBody(dest);
|
||||||
|
|
||||||
|
memRowSetType(dest, SMEM_ROW_DATA);
|
||||||
|
dataRowSetVersion(dataRow, memRowKvVersion(src));
|
||||||
|
dataRowSetLen(dataRow, (TDRowLenT)(TD_DATA_ROW_HEAD_SIZE + spd->flen));
|
||||||
|
|
||||||
|
int32_t kvIdx = 0;
|
||||||
|
for (int i = 0; i < nCols; ++i) {
|
||||||
|
SSchema *schema = pSchema + i;
|
||||||
|
void * val = tdGetKVRowValOfColEx(kvRow, schema->colId, &kvIdx);
|
||||||
|
tdAppendDataColVal(dataRow, val != NULL ? val : getNullValue(schema->type), true, schema->type,
|
||||||
|
(spd->cols + i)->toffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move to tdataformat.h and refactor when STSchema available.
|
||||||
|
static FORCE_INLINE void convertToSKVRow(SMemRow dest, SMemRow src, SSchema *pSchema, int nCols, int nBoundCols,
|
||||||
|
SParsedDataColInfo *spd) {
|
||||||
|
ASSERT(isDataRow(src));
|
||||||
|
|
||||||
|
SDataRow dataRow = memRowDataBody(src);
|
||||||
|
SKVRow kvRow = memRowKvBody(dest);
|
||||||
|
|
||||||
|
memRowSetType(dest, SMEM_ROW_KV);
|
||||||
|
memRowSetKvVersion(kvRow, dataRowVersion(dataRow));
|
||||||
|
kvRowSetNCols(kvRow, nBoundCols);
|
||||||
|
kvRowSetLen(kvRow, (TDRowLenT)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nBoundCols));
|
||||||
|
|
||||||
|
int32_t toffset = 0, kvOffset = 0;
|
||||||
|
for (int i = 0; i < nCols; ++i) {
|
||||||
|
if ((spd->cols + i)->valStat == VAL_STAT_HAS) {
|
||||||
|
SSchema *schema = pSchema + i;
|
||||||
|
toffset = (spd->cols + i)->toffset;
|
||||||
|
void *val = tdGetRowDataOfCol(dataRow, schema->type, toffset + TD_DATA_ROW_HEAD_SIZE);
|
||||||
|
tdAppendKvColVal(kvRow, val, true, schema->colId, schema->type, kvOffset);
|
||||||
|
kvOffset += sizeof(SColIdx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Move to tdataformat.h and refactor when STSchema available.
|
||||||
|
static FORCE_INLINE void convertSMemRow(SMemRow dest, SMemRow src, STableDataBlocks *pBlock) {
|
||||||
|
STableMeta * pTableMeta = pBlock->pTableMeta;
|
||||||
|
STableComInfo tinfo = tscGetTableInfo(pTableMeta);
|
||||||
|
SSchema * pSchema = tscGetTableSchema(pTableMeta);
|
||||||
|
SParsedDataColInfo *spd = &pBlock->boundColumnInfo;
|
||||||
|
|
||||||
|
ASSERT(dest != src);
|
||||||
|
|
||||||
|
if (isDataRow(src)) {
|
||||||
|
// TODO: Can we use pBlock -> numOfParam directly?
|
||||||
|
ASSERT(spd->numOfBound > 0);
|
||||||
|
convertToSKVRow(dest, src, pSchema, tinfo.numOfColumns, spd->numOfBound, spd);
|
||||||
|
} else {
|
||||||
|
convertToSDataRow(dest, src, pSchema, tinfo.numOfColumns, spd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool isNullStr(SStrToken *pToken) {
|
||||||
|
return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) &&
|
||||||
|
(strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t tscToDouble(SStrToken *pToken, double *value, char **endPtr) {
|
||||||
|
errno = 0;
|
||||||
|
*value = strtold(pToken->z, endPtr);
|
||||||
|
|
||||||
|
// not a valid integer number, return error
|
||||||
|
if ((*endPtr - pToken->z) != pToken->n) {
|
||||||
|
return TK_ILLEGAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pToken->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
|
||||||
|
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
|
||||||
|
|
||||||
|
static FORCE_INLINE int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pToken, SMemRow row, char *msg, char **str,
|
||||||
|
bool primaryKey, int16_t timePrec, int32_t toffset, int16_t colId,
|
||||||
|
int32_t *dataLen, int32_t *kvLen, uint8_t compareStat) {
|
||||||
|
int64_t iv;
|
||||||
|
int32_t ret;
|
||||||
|
char * endptr = NULL;
|
||||||
|
|
||||||
|
if (IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid numeric data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (pSchema->type) {
|
||||||
|
case TSDB_DATA_TYPE_BOOL: { // bool
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
|
||||||
|
if (strncmp(pToken->z, "true", pToken->n) == 0) {
|
||||||
|
tscAppendMemRowColValEx(row, &TRUE_VALUE, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
} else if (strncmp(pToken->z, "false", pToken->n) == 0) {
|
||||||
|
tscAppendMemRowColValEx(row, &FALSE_VALUE, true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
return tscSQLSyntaxErrMsg(msg, "invalid bool data", pToken->z);
|
||||||
|
}
|
||||||
|
} else if (pToken->type == TK_INTEGER) {
|
||||||
|
iv = strtoll(pToken->z, NULL, 10);
|
||||||
|
tscAppendMemRowColValEx(row, ((iv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset,
|
||||||
|
dataLen, kvLen, compareStat);
|
||||||
|
} else if (pToken->type == TK_FLOAT) {
|
||||||
|
double dv = strtod(pToken->z, NULL);
|
||||||
|
tscAppendMemRowColValEx(row, ((dv == 0) ? &FALSE_VALUE : &TRUE_VALUE), true, colId, pSchema->type, toffset,
|
||||||
|
dataLen, kvLen, compareStat);
|
||||||
|
} else {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid bool data", pToken->z);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid tinyint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_TINYINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tmpVal = (uint8_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid unsigned tinyint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UTINYINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "unsigned tinyint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t tmpVal = (uint8_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid smallint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_SMALLINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "smallint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
int16_t tmpVal = (int16_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid unsigned smallint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_USMALLINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "unsigned smallint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t tmpVal = (uint16_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_INT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid int data", pToken->z);
|
||||||
|
} else if (!IS_VALID_INT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "int data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tmpVal = (int32_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid unsigned int data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "unsigned int data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t tmpVal = (uint32_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid bigint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_BIGINT(iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "bigint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
tscAppendMemRowColValEx(row, &iv, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
||||||
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid unsigned bigint data", pToken->z);
|
||||||
|
} else if (!IS_VALID_UBIGINT((uint64_t)iv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "unsigned bigint data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t tmpVal = (uint64_t)iv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
double dv;
|
||||||
|
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
|
||||||
|
isnan(dv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
float tmpVal = (float)dv;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
|
if (isNullStr(pToken)) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
double dv;
|
||||||
|
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
||||||
|
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
||||||
|
}
|
||||||
|
|
||||||
|
tscAppendMemRowColValEx(row, &dv, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
|
// binary data cannot be null-terminated char string, otherwise the last char of the string is lost
|
||||||
|
if (pToken->type == TK_NULL) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else { // too long values will return invalid sql, not be truncated automatically
|
||||||
|
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { // todo refactor
|
||||||
|
return tscInvalidOperationMsg(msg, "string data overflow", pToken->z);
|
||||||
|
}
|
||||||
|
// STR_WITH_SIZE_TO_VARSTR(payload, pToken->z, pToken->n);
|
||||||
|
char *rowEnd = memRowEnd(row);
|
||||||
|
STR_WITH_SIZE_TO_VARSTR(rowEnd, pToken->z, pToken->n);
|
||||||
|
tscAppendMemRowColValEx(row, rowEnd, false, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
|
if (pToken->type == TK_NULL) {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
} else {
|
||||||
|
// if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
|
||||||
|
int32_t output = 0;
|
||||||
|
char * rowEnd = memRowEnd(row);
|
||||||
|
if (!taosMbsToUcs4(pToken->z, pToken->n, (char *)varDataVal(rowEnd), pSchema->bytes - VARSTR_HEADER_SIZE,
|
||||||
|
&output)) {
|
||||||
|
char buf[512] = {0};
|
||||||
|
snprintf(buf, tListLen(buf), "%s", strerror(errno));
|
||||||
|
return tscInvalidOperationMsg(msg, buf, pToken->z);
|
||||||
|
}
|
||||||
|
varDataSetLen(rowEnd, output);
|
||||||
|
tscAppendMemRowColValEx(row, rowEnd, false, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
|
if (pToken->type == TK_NULL) {
|
||||||
|
if (primaryKey) {
|
||||||
|
// When building SKVRow primaryKey, we should not skip even with NULL value.
|
||||||
|
int64_t tmpVal = 0;
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
} else {
|
||||||
|
tscAppendMemRowColValEx(row, getNullValue(pSchema->type), true, colId, pSchema->type, toffset, dataLen, kvLen,
|
||||||
|
compareStat);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
int64_t tmpVal;
|
||||||
|
if (tsParseTime(pToken, &tmpVal, str, msg, timePrec) != TSDB_CODE_SUCCESS) {
|
||||||
|
return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z);
|
||||||
|
}
|
||||||
|
tscAppendMemRowColValEx(row, &tmpVal, true, colId, pSchema->type, toffset, dataLen, kvLen, compareStat);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,43 +38,60 @@ enum {
|
||||||
TSDB_USE_CLI_TS = 1,
|
TSDB_USE_CLI_TS = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint8_t TRUE_VALUE = (uint8_t)TSDB_TRUE;
|
|
||||||
static uint8_t FALSE_VALUE = (uint8_t)TSDB_FALSE;
|
|
||||||
|
|
||||||
static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t *numOfRows);
|
static int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t *numOfRows);
|
||||||
static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDataColInfo *pColInfo, SSchema *pSchema,
|
static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDataColInfo *pColInfo, SSchema *pSchema,
|
||||||
char *str, char **end);
|
char *str, char **end);
|
||||||
|
int initMemRowBuilder(SMemRowBuilder *pBuilder, uint32_t nRows, uint32_t nCols, uint32_t nBoundCols,
|
||||||
int32_t getExtendedRowSize(STableComInfo *tinfo) {
|
int32_t allNullLen) {
|
||||||
return tinfo->rowSize + PAYLOAD_HEADER_LEN + PAYLOAD_COL_HEAD_LEN * tinfo->numOfColumns;
|
ASSERT(nRows >= 0 && nCols > 0 && (nBoundCols <= nCols));
|
||||||
}
|
if (nRows > 0) {
|
||||||
int initSMemRowHelper(SMemRowHelper *pHelper, SSchema *pSSchema, uint16_t nCols, uint16_t allNullColsLen) {
|
// already init(bind multiple rows by single column)
|
||||||
pHelper->allNullLen = allNullColsLen; // TODO: get allNullColsLen when creating or altering table meta
|
if (pBuilder->compareStat == ROW_COMPARE_NEED && (pBuilder->rowInfo != NULL)) {
|
||||||
if (pHelper->allNullLen == 0) {
|
return TSDB_CODE_SUCCESS;
|
||||||
for (uint16_t i = 0; i < nCols; ++i) {
|
|
||||||
uint8_t type = pSSchema[i].type;
|
|
||||||
int32_t typeLen = TYPE_BYTES[type];
|
|
||||||
pHelper->allNullLen += typeLen;
|
|
||||||
if (TSDB_DATA_TYPE_BINARY == type) {
|
|
||||||
pHelper->allNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES);
|
|
||||||
} else if (TSDB_DATA_TYPE_NCHAR == type) {
|
|
||||||
int len = VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE;
|
|
||||||
pHelper->allNullLen += len;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static int32_t tscToDouble(SStrToken *pToken, double *value, char **endPtr) {
|
|
||||||
errno = 0;
|
|
||||||
*value = strtold(pToken->z, endPtr);
|
|
||||||
|
|
||||||
// not a valid integer number, return error
|
|
||||||
if ((*endPtr - pToken->z) != pToken->n) {
|
|
||||||
return TK_ILLEGAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return pToken->type;
|
if (nBoundCols == 0) { // file input
|
||||||
|
pBuilder->memRowType = SMEM_ROW_DATA;
|
||||||
|
pBuilder->compareStat = ROW_COMPARE_NO_NEED;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
} else {
|
||||||
|
float boundRatio = ((float)nBoundCols / (float)nCols);
|
||||||
|
|
||||||
|
if (boundRatio < KVRatioKV) {
|
||||||
|
pBuilder->memRowType = SMEM_ROW_KV;
|
||||||
|
pBuilder->compareStat = ROW_COMPARE_NO_NEED;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
} else if (boundRatio > KVRatioData) {
|
||||||
|
pBuilder->memRowType = SMEM_ROW_DATA;
|
||||||
|
pBuilder->compareStat = ROW_COMPARE_NO_NEED;
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
pBuilder->compareStat = ROW_COMPARE_NEED;
|
||||||
|
|
||||||
|
if (boundRatio < KVRatioPredict) {
|
||||||
|
pBuilder->memRowType = SMEM_ROW_KV;
|
||||||
|
} else {
|
||||||
|
pBuilder->memRowType = SMEM_ROW_DATA;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pBuilder->dataRowInitLen = TD_MEM_ROW_DATA_HEAD_SIZE + allNullLen;
|
||||||
|
pBuilder->kvRowInitLen = TD_MEM_ROW_KV_HEAD_SIZE + nBoundCols * sizeof(SColIdx);
|
||||||
|
|
||||||
|
if (nRows > 0) {
|
||||||
|
pBuilder->rowInfo = tcalloc(nRows, sizeof(SMemRowInfo));
|
||||||
|
if (pBuilder->rowInfo == NULL) {
|
||||||
|
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < nRows; ++i) {
|
||||||
|
(pBuilder->rowInfo + i)->dataLen = pBuilder->dataRowInitLen;
|
||||||
|
(pBuilder->rowInfo + i)->kvLen = pBuilder->kvRowInitLen;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec) {
|
int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int16_t timePrec) {
|
||||||
|
@ -146,10 +163,6 @@ int tsParseTime(SStrToken *pToken, int64_t *time, char **next, char *error, int1
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isNullStr(SStrToken* pToken) {
|
|
||||||
return (pToken->type == TK_NULL) || ((pToken->type == TK_STRING) && (pToken->n != 0) &&
|
|
||||||
(strncasecmp(TSDB_DATA_NULL_STR_L, pToken->z, pToken->n) == 0));
|
|
||||||
}
|
|
||||||
int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, char *msg, char **str, bool primaryKey,
|
int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, char *msg, char **str, bool primaryKey,
|
||||||
int16_t timePrec) {
|
int16_t timePrec) {
|
||||||
int64_t iv;
|
int64_t iv;
|
||||||
|
@ -400,342 +413,6 @@ int32_t tsParseOneColumn(SSchema *pSchema, SStrToken *pToken, char *payload, cha
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE TDRowLenT tsSetPayloadColValue(char *payloadStart, char *payload, int16_t columnId,
|
|
||||||
uint8_t columnType, const void *value, uint16_t valueLen, TDRowTLenT tOffset) {
|
|
||||||
payloadColSetId(payload, columnId);
|
|
||||||
payloadColSetType(payload, columnType);
|
|
||||||
memcpy(POINTER_SHIFT(payloadStart,tOffset), value, valueLen);
|
|
||||||
return valueLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int32_t tsParseOneColumnKV(SSchema *pSchema, SStrToken *pToken, char *payloadStart, char *primaryKeyStart,
|
|
||||||
char *payload, char *msg, char **str, bool primaryKey, int16_t timePrec,
|
|
||||||
TDRowTLenT tOffset, TDRowLenT *sizeAppend, TDRowLenT *dataRowColDeltaLen,
|
|
||||||
TDRowLenT *kvRowColLen) {
|
|
||||||
int64_t iv;
|
|
||||||
int32_t ret;
|
|
||||||
char * endptr = NULL;
|
|
||||||
|
|
||||||
if (IS_NUMERIC_TYPE(pSchema->type) && pToken->n == 0) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid numeric data", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (pSchema->type) {
|
|
||||||
case TSDB_DATA_TYPE_BOOL: { // bool
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_BOOL), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
|
||||||
} else {
|
|
||||||
if ((pToken->type == TK_BOOL || pToken->type == TK_STRING) && (pToken->n != 0)) {
|
|
||||||
if (strncmp(pToken->z, "true", pToken->n) == 0) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &TRUE_VALUE,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
|
||||||
} else if (strncmp(pToken->z, "false", pToken->n) == 0) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &FALSE_VALUE,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
|
||||||
} else {
|
|
||||||
return tscSQLSyntaxErrMsg(msg, "invalid bool data", pToken->z);
|
|
||||||
}
|
|
||||||
} else if (pToken->type == TK_INTEGER) {
|
|
||||||
iv = strtoll(pToken->z, NULL, 10);
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
((iv == 0) ? &FALSE_VALUE : &TRUE_VALUE), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
|
||||||
} else if (pToken->type == TK_FLOAT) {
|
|
||||||
double dv = strtod(pToken->z, NULL);
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
((dv == 0) ? &FALSE_VALUE : &TRUE_VALUE), TYPE_BYTES[TSDB_DATA_TYPE_BOOL], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BOOL]);
|
|
||||||
} else {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid bool data", pToken->z);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_TINYINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_TINYINT), TYPE_BYTES[TSDB_DATA_TYPE_TINYINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid tinyint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_TINYINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tmpVal = (uint8_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_TINYINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TINYINT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_UTINYINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_UTINYINT), TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid unsigned tinyint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_UTINYINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "unsigned tinyint data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t tmpVal = (uint8_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UTINYINT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_SMALLINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_SMALLINT), TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid smallint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_SMALLINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "smallint data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
int16_t tmpVal = (int16_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_SMALLINT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_USMALLINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend =
|
|
||||||
tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_USMALLINT), TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid unsigned smallint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_USMALLINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "unsigned smallint data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint16_t tmpVal = (uint16_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_USMALLINT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_INT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_INT), TYPE_BYTES[TSDB_DATA_TYPE_INT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid int data", pToken->z);
|
|
||||||
} else if (!IS_VALID_INT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "int data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t tmpVal = (int32_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_INT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_INT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_UINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_UINT), TYPE_BYTES[TSDB_DATA_TYPE_UINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid unsigned int data", pToken->z);
|
|
||||||
} else if (!IS_VALID_UINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "unsigned int data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t tmpVal = (uint32_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_UINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UINT]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_BIGINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_BIGINT), TYPE_BYTES[TSDB_DATA_TYPE_BIGINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, true);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid bigint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_BIGINT(iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "bigint data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &iv,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_BIGINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_BIGINT]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_UBIGINT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_UBIGINT), TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT], tOffset);
|
|
||||||
} else {
|
|
||||||
ret = tStrToInteger(pToken->z, pToken->type, pToken->n, &iv, false);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid unsigned bigint data", pToken->z);
|
|
||||||
} else if (!IS_VALID_UBIGINT((uint64_t)iv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "unsigned bigint data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t tmpVal = (uint64_t)iv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_UBIGINT]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_FLOAT:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_FLOAT), TYPE_BYTES[TSDB_DATA_TYPE_FLOAT], tOffset);
|
|
||||||
} else {
|
|
||||||
double dv;
|
|
||||||
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || dv > FLT_MAX || dv < -FLT_MAX || isinf(dv) ||
|
|
||||||
isnan(dv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "illegal float data", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
float tmpVal = (float)dv;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_FLOAT], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_FLOAT]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_DOUBLE:
|
|
||||||
if (isNullStr(pToken)) {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_DOUBLE), TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE], tOffset);
|
|
||||||
} else {
|
|
||||||
double dv;
|
|
||||||
if (TK_ILLEGAL == tscToDouble(pToken, &dv, &endptr)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((dv == HUGE_VAL || dv == -HUGE_VAL) && errno == ERANGE) || isinf(dv) || isnan(dv)) {
|
|
||||||
return tscInvalidOperationMsg(msg, "illegal double data", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type, &dv,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_DOUBLE]);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_BINARY:
|
|
||||||
// binary data cannot be null-terminated char string, otherwise the last char of the string is lost
|
|
||||||
if (pToken->type == TK_NULL) {
|
|
||||||
payloadColSetId(payload, pSchema->colId);
|
|
||||||
payloadColSetType(payload, pSchema->type);
|
|
||||||
memcpy(POINTER_SHIFT(payloadStart, tOffset), getNullValue(TSDB_DATA_TYPE_BINARY), VARSTR_HEADER_SIZE + CHAR_BYTES);
|
|
||||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + CHAR_BYTES);
|
|
||||||
} else { // too long values will return invalid sql, not be truncated automatically
|
|
||||||
if (pToken->n + VARSTR_HEADER_SIZE > pSchema->bytes) { // todo refactor
|
|
||||||
return tscInvalidOperationMsg(msg, "string data overflow", pToken->z);
|
|
||||||
}
|
|
||||||
// STR_WITH_SIZE_TO_VARSTR(payload, pToken->z, pToken->n);
|
|
||||||
|
|
||||||
payloadColSetId(payload, pSchema->colId);
|
|
||||||
payloadColSetType(payload, pSchema->type);
|
|
||||||
varDataSetLen(POINTER_SHIFT(payloadStart,tOffset), pToken->n);
|
|
||||||
memcpy(varDataVal(POINTER_SHIFT(payloadStart,tOffset)), pToken->z, pToken->n);
|
|
||||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + pToken->n);
|
|
||||||
*dataRowColDeltaLen += (TDRowLenT)(pToken->n - CHAR_BYTES);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + VARSTR_HEADER_SIZE + pToken->n);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_NCHAR:
|
|
||||||
if (pToken->type == TK_NULL) {
|
|
||||||
payloadColSetId(payload, pSchema->colId);
|
|
||||||
payloadColSetType(payload, pSchema->type);
|
|
||||||
memcpy(POINTER_SHIFT(payloadStart,tOffset), getNullValue(TSDB_DATA_TYPE_NCHAR), VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
|
|
||||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
|
|
||||||
} else {
|
|
||||||
// if the converted output len is over than pColumnModel->bytes, return error: 'Argument list too long'
|
|
||||||
int32_t output = 0;
|
|
||||||
payloadColSetId(payload, pSchema->colId);
|
|
||||||
payloadColSetType(payload, pSchema->type);
|
|
||||||
if (!taosMbsToUcs4(pToken->z, pToken->n, varDataVal(POINTER_SHIFT(payloadStart,tOffset)),
|
|
||||||
pSchema->bytes - VARSTR_HEADER_SIZE, &output)) {
|
|
||||||
char buf[512] = {0};
|
|
||||||
snprintf(buf, tListLen(buf), "%s", strerror(errno));
|
|
||||||
return tscInvalidOperationMsg(msg, buf, pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
varDataSetLen(POINTER_SHIFT(payloadStart,tOffset), output);
|
|
||||||
|
|
||||||
*sizeAppend = (TDRowLenT)(VARSTR_HEADER_SIZE + output);
|
|
||||||
*dataRowColDeltaLen += (TDRowLenT)(output - sizeof(uint32_t));
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + VARSTR_HEADER_SIZE + output);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
|
||||||
if (pToken->type == TK_NULL) {
|
|
||||||
if (primaryKey) {
|
|
||||||
// When building SKVRow primaryKey, we should not skip even with NULL value.
|
|
||||||
int64_t tmpVal = 0;
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, primaryKeyStart, pSchema->colId, pSchema->type, &tmpVal,
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP]);
|
|
||||||
} else {
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, payload, pSchema->colId, pSchema->type,
|
|
||||||
getNullValue(TSDB_DATA_TYPE_TIMESTAMP),
|
|
||||||
TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
int64_t tmpVal;
|
|
||||||
if (tsParseTime(pToken, &tmpVal, str, msg, timePrec) != TSDB_CODE_SUCCESS) {
|
|
||||||
return tscInvalidOperationMsg(msg, "invalid timestamp", pToken->z);
|
|
||||||
}
|
|
||||||
|
|
||||||
*sizeAppend = tsSetPayloadColValue(payloadStart, primaryKey ? primaryKeyStart : payload, pSchema->colId,
|
|
||||||
pSchema->type, &tmpVal, TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP], tOffset);
|
|
||||||
*kvRowColLen += (TDRowLenT)(sizeof(SColIdx) + TYPE_BYTES[TSDB_DATA_TYPE_TIMESTAMP]);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The server time/client time should not be mixed up in one sql string
|
* The server time/client time should not be mixed up in one sql string
|
||||||
* Do not employ sort operation is not involved if server time is used.
|
* Do not employ sort operation is not involved if server time is used.
|
||||||
|
@ -777,31 +454,24 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
|
||||||
int32_t index = 0;
|
int32_t index = 0;
|
||||||
SStrToken sToken = {0};
|
SStrToken sToken = {0};
|
||||||
|
|
||||||
SMemRowHelper *pHelper = &pDataBlocks->rowHelper;
|
char *row = pDataBlocks->pData + pDataBlocks->size; // skip the SSubmitBlk header
|
||||||
char * payload = pDataBlocks->pData + pDataBlocks->size;
|
|
||||||
|
|
||||||
SParsedDataColInfo *spd = &pDataBlocks->boundColumnInfo;
|
SParsedDataColInfo *spd = &pDataBlocks->boundColumnInfo;
|
||||||
SSchema * schema = tscGetTableSchema(pDataBlocks->pTableMeta);
|
STableMeta * pTableMeta = pDataBlocks->pTableMeta;
|
||||||
|
SSchema * schema = tscGetTableSchema(pTableMeta);
|
||||||
|
SMemRowBuilder * pBuilder = &pDataBlocks->rowBuilder;
|
||||||
|
int32_t dataLen = pBuilder->dataRowInitLen;
|
||||||
|
int32_t kvLen = pBuilder->kvRowInitLen;
|
||||||
|
bool isParseBindParam = false;
|
||||||
|
|
||||||
TDRowTLenT dataRowLen = pHelper->allNullLen;
|
initSMemRow(row, pBuilder->memRowType, pDataBlocks, spd->numOfBound);
|
||||||
TDRowTLenT kvRowLen = TD_MEM_ROW_KV_VER_SIZE;
|
|
||||||
TDRowTLenT payloadValOffset = 0;
|
|
||||||
TDRowLenT colValOffset = 0;
|
|
||||||
ASSERT(dataRowLen > 0);
|
|
||||||
|
|
||||||
payloadSetNCols(payload, spd->numOfBound);
|
|
||||||
payloadValOffset = payloadValuesOffset(payload); // rely on payloadNCols
|
|
||||||
// payloadSetTLen(payload, payloadValOffset);
|
|
||||||
|
|
||||||
char *kvPrimaryKeyStart = payload + PAYLOAD_HEADER_LEN; // primaryKey in 1st column tuple
|
|
||||||
char *kvStart = kvPrimaryKeyStart + PAYLOAD_COL_HEAD_LEN; // the column tuple behind the primaryKey
|
|
||||||
|
|
||||||
// 1. set the parsed value from sql string
|
// 1. set the parsed value from sql string
|
||||||
for (int i = 0; i < spd->numOfBound; ++i) {
|
for (int i = 0; i < spd->numOfBound; ++i) {
|
||||||
// the start position in data block buffer of current value in sql
|
// the start position in data block buffer of current value in sql
|
||||||
int32_t colIndex = spd->boundedColumns[i];
|
int32_t colIndex = spd->boundedColumns[i];
|
||||||
|
|
||||||
char *start = payload + spd->cols[colIndex].offset;
|
char *start = row + spd->cols[colIndex].offset;
|
||||||
|
|
||||||
SSchema *pSchema = &schema[colIndex]; // get colId here
|
SSchema *pSchema = &schema[colIndex]; // get colId here
|
||||||
|
|
||||||
|
@ -810,6 +480,9 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
|
||||||
*str += index;
|
*str += index;
|
||||||
|
|
||||||
if (sToken.type == TK_QUESTION) {
|
if (sToken.type == TK_QUESTION) {
|
||||||
|
if (!isParseBindParam) {
|
||||||
|
isParseBindParam = true;
|
||||||
|
}
|
||||||
if (pInsertParam->insertType != TSDB_QUERY_TYPE_STMT_INSERT) {
|
if (pInsertParam->insertType != TSDB_QUERY_TYPE_STMT_INSERT) {
|
||||||
return tscSQLSyntaxErrMsg(pInsertParam->msg, "? only allowed in binding insertion", *str);
|
return tscSQLSyntaxErrMsg(pInsertParam->msg, "? only allowed in binding insertion", *str);
|
||||||
}
|
}
|
||||||
|
@ -861,52 +534,43 @@ int tsParseOneRow(char **str, STableDataBlocks *pDataBlocks, int16_t timePrec, i
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
bool isPrimaryKey = (colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX);
|
||||||
TDRowLenT dataRowDeltaColLen = 0; // When combine the data as SDataRow, the delta len between all NULL columns.
|
int32_t toffset = -1;
|
||||||
TDRowLenT kvRowColLen = 0;
|
int16_t colId = -1;
|
||||||
TDRowLenT colValAppended = 0;
|
tscGetMemRowAppendInfo(schema, pBuilder->memRowType, spd, i, &toffset, &colId);
|
||||||
|
|
||||||
if (!IS_DATA_COL_ORDERED(spd->orderStatus)) {
|
int32_t ret = tsParseOneColumnKV(pSchema, &sToken, row, pInsertParam->msg, str, isPrimaryKey, timePrec, toffset,
|
||||||
ASSERT(spd->colIdxInfo != NULL);
|
colId, &dataLen, &kvLen, pBuilder->compareStat);
|
||||||
if(!isPrimaryKey) {
|
|
||||||
kvStart = POINTER_SHIFT(kvPrimaryKeyStart, spd->colIdxInfo[i].finalIdx * PAYLOAD_COL_HEAD_LEN);
|
|
||||||
} else {
|
|
||||||
ASSERT(spd->colIdxInfo[i].finalIdx == 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// the primary key locates in 1st column
|
|
||||||
int32_t ret = tsParseOneColumnKV(pSchema, &sToken, payload, kvPrimaryKeyStart, kvStart, pInsertParam->msg, str,
|
|
||||||
isPrimaryKey, timePrec, payloadValOffset + colValOffset, &colValAppended,
|
|
||||||
&dataRowDeltaColLen, &kvRowColLen);
|
|
||||||
if (ret != TSDB_CODE_SUCCESS) {
|
if (ret != TSDB_CODE_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isPrimaryKey) {
|
if (isPrimaryKey) {
|
||||||
if (tsCheckTimestamp(pDataBlocks, payloadValues(payload)) != TSDB_CODE_SUCCESS) {
|
TSKEY tsKey = memRowKey(row);
|
||||||
|
if (tsCheckTimestamp(pDataBlocks, (const char *)&tsKey) != TSDB_CODE_SUCCESS) {
|
||||||
tscInvalidOperationMsg(pInsertParam->msg, "client time/server time can not be mixed up", sToken.z);
|
tscInvalidOperationMsg(pInsertParam->msg, "client time/server time can not be mixed up", sToken.z);
|
||||||
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
|
return TSDB_CODE_TSC_INVALID_TIME_STAMP;
|
||||||
}
|
}
|
||||||
payloadColSetOffset(kvPrimaryKeyStart, colValOffset);
|
|
||||||
} else {
|
|
||||||
payloadColSetOffset(kvStart, colValOffset);
|
|
||||||
if (IS_DATA_COL_ORDERED(spd->orderStatus)) {
|
|
||||||
kvStart += PAYLOAD_COL_HEAD_LEN; // move to next column
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
colValOffset += colValAppended;
|
if (!isParseBindParam) {
|
||||||
kvRowLen += kvRowColLen;
|
// 2. check and set convert flag
|
||||||
dataRowLen += dataRowDeltaColLen;
|
if (pBuilder->compareStat == ROW_COMPARE_NEED) {
|
||||||
|
checkAndConvertMemRow(row, dataLen, kvLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (kvRowLen < dataRowLen) {
|
// 3. set the null value for the columns that do not assign values
|
||||||
payloadSetType(payload, SMEM_ROW_KV);
|
if ((spd->numOfBound < spd->numOfCols) && isDataRow(row) && !isNeedConvertRow(row)) {
|
||||||
} else {
|
SDataRow dataRow = memRowDataBody(row);
|
||||||
payloadSetType(payload, SMEM_ROW_DATA);
|
for (int32_t i = 0; i < spd->numOfCols; ++i) {
|
||||||
|
if (spd->cols[i].valStat == VAL_STAT_NONE) {
|
||||||
|
tdAppendDataColVal(dataRow, getNullValue(schema[i].type), true, schema[i].type, spd->cols[i].toffset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*len = (int32_t)(payloadValOffset + colValOffset);
|
*len = getExtendedRowSize(pDataBlocks);
|
||||||
payloadSetTLen(payload, *len);
|
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -957,11 +621,13 @@ int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SIn
|
||||||
|
|
||||||
int32_t precision = tinfo.precision;
|
int32_t precision = tinfo.precision;
|
||||||
|
|
||||||
int32_t extendedRowSize = getExtendedRowSize(&tinfo);
|
int32_t extendedRowSize = getExtendedRowSize(pDataBlock);
|
||||||
|
|
||||||
initSMemRowHelper(&pDataBlock->rowHelper, tscGetTableSchema(pDataBlock->pTableMeta),
|
|
||||||
tscGetNumOfColumns(pDataBlock->pTableMeta), 0);
|
|
||||||
|
|
||||||
|
if (TSDB_CODE_SUCCESS !=
|
||||||
|
(code = initMemRowBuilder(&pDataBlock->rowBuilder, 0, tinfo.numOfColumns, pDataBlock->boundColumnInfo.numOfBound,
|
||||||
|
pDataBlock->boundColumnInfo.allNullLen))) {
|
||||||
|
return code;
|
||||||
|
}
|
||||||
while (1) {
|
while (1) {
|
||||||
index = 0;
|
index = 0;
|
||||||
sToken = tStrGetToken(*str, &index, false);
|
sToken = tStrGetToken(*str, &index, false);
|
||||||
|
@ -1010,19 +676,37 @@ int32_t tsParseValues(char **str, STableDataBlocks *pDataBlock, int maxRows, SIn
|
||||||
void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols) {
|
void tscSetBoundColumnInfo(SParsedDataColInfo *pColInfo, SSchema *pSchema, int32_t numOfCols) {
|
||||||
pColInfo->numOfCols = numOfCols;
|
pColInfo->numOfCols = numOfCols;
|
||||||
pColInfo->numOfBound = numOfCols;
|
pColInfo->numOfBound = numOfCols;
|
||||||
pColInfo->orderStatus = ORDER_STATUS_ORDERED;
|
pColInfo->orderStatus = ORDER_STATUS_ORDERED; // default is ORDERED for non-bound mode
|
||||||
pColInfo->boundedColumns = calloc(pColInfo->numOfCols, sizeof(int32_t));
|
pColInfo->boundedColumns = calloc(pColInfo->numOfCols, sizeof(int32_t));
|
||||||
pColInfo->cols = calloc(pColInfo->numOfCols, sizeof(SBoundColumn));
|
pColInfo->cols = calloc(pColInfo->numOfCols, sizeof(SBoundColumn));
|
||||||
pColInfo->colIdxInfo = NULL;
|
pColInfo->colIdxInfo = NULL;
|
||||||
|
pColInfo->flen = 0;
|
||||||
|
pColInfo->allNullLen = 0;
|
||||||
|
|
||||||
|
int32_t nVar = 0;
|
||||||
for (int32_t i = 0; i < pColInfo->numOfCols; ++i) {
|
for (int32_t i = 0; i < pColInfo->numOfCols; ++i) {
|
||||||
|
uint8_t type = pSchema[i].type;
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
pColInfo->cols[i].offset = pSchema[i - 1].bytes + pColInfo->cols[i - 1].offset;
|
pColInfo->cols[i].offset = pSchema[i - 1].bytes + pColInfo->cols[i - 1].offset;
|
||||||
|
pColInfo->cols[i].toffset = pColInfo->flen;
|
||||||
|
}
|
||||||
|
pColInfo->flen += TYPE_BYTES[type];
|
||||||
|
switch (type) {
|
||||||
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
|
pColInfo->allNullLen += (VARSTR_HEADER_SIZE + CHAR_BYTES);
|
||||||
|
++nVar;
|
||||||
|
break;
|
||||||
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
|
pColInfo->allNullLen += (VARSTR_HEADER_SIZE + TSDB_NCHAR_SIZE);
|
||||||
|
++nVar;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pColInfo->cols[i].hasVal = true;
|
|
||||||
pColInfo->boundedColumns[i] = i;
|
pColInfo->boundedColumns[i] = i;
|
||||||
}
|
}
|
||||||
|
pColInfo->allNullLen += pColInfo->flen;
|
||||||
|
pColInfo->extendedVarLen = (uint16_t)(nVar * sizeof(VarDataOffsetT));
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t * numOfRows) {
|
int32_t tscAllocateMemIfNeed(STableDataBlocks *pDataBlock, int32_t rowSize, int32_t * numOfRows) {
|
||||||
|
@ -1135,22 +819,16 @@ int tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf, SBlockKeyInfo *pBlk
|
||||||
}
|
}
|
||||||
memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc);
|
memset(pBlkKeyInfo->pKeyTuple, 0, nAlloc);
|
||||||
|
|
||||||
|
int32_t extendedRowSize = getExtendedRowSize(dataBuf);
|
||||||
SBlockKeyTuple *pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
|
SBlockKeyTuple *pBlkKeyTuple = pBlkKeyInfo->pKeyTuple;
|
||||||
char * pBlockData = pBlocks->data;
|
char * pBlockData = pBlocks->data;
|
||||||
TDRowTLenT totolPayloadTLen = 0;
|
|
||||||
TDRowTLenT payloadTLen = 0;
|
|
||||||
int n = 0;
|
int n = 0;
|
||||||
while (n < nRows) {
|
while (n < nRows) {
|
||||||
pBlkKeyTuple->skey = payloadTSKey(pBlockData);
|
pBlkKeyTuple->skey = memRowKey(pBlockData);
|
||||||
pBlkKeyTuple->payloadAddr = pBlockData;
|
pBlkKeyTuple->payloadAddr = pBlockData;
|
||||||
payloadTLen = payloadTLen(pBlockData);
|
|
||||||
#if 0
|
|
||||||
ASSERT(payloadNCols(pBlockData) <= 4096);
|
|
||||||
ASSERT(payloadTLen(pBlockData) < 65536);
|
|
||||||
#endif
|
|
||||||
totolPayloadTLen += payloadTLen;
|
|
||||||
// next loop
|
// next loop
|
||||||
pBlockData += payloadTLen;
|
pBlockData += extendedRowSize;
|
||||||
++pBlkKeyTuple;
|
++pBlkKeyTuple;
|
||||||
++n;
|
++n;
|
||||||
}
|
}
|
||||||
|
@ -1167,7 +845,6 @@ int tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf, SBlockKeyInfo *pBlk
|
||||||
TSKEY tj = (pBlkKeyTuple + j)->skey;
|
TSKEY tj = (pBlkKeyTuple + j)->skey;
|
||||||
|
|
||||||
if (ti == tj) {
|
if (ti == tj) {
|
||||||
totolPayloadTLen -= payloadTLen(pBlkKeyTuple + j);
|
|
||||||
++j;
|
++j;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1183,17 +860,15 @@ int tscSortRemoveDataBlockDupRows(STableDataBlocks *dataBuf, SBlockKeyInfo *pBlk
|
||||||
pBlocks->numOfRows = i + 1;
|
pBlocks->numOfRows = i + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
dataBuf->size = sizeof(SSubmitBlk) + totolPayloadTLen;
|
dataBuf->size = sizeof(SSubmitBlk) + pBlocks->numOfRows * extendedRowSize;
|
||||||
dataBuf->prevTS = INT64_MIN;
|
dataBuf->prevTS = INT64_MIN;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t doParseInsertStatement(SInsertStatementParam *pInsertParam, char **str, STableDataBlocks* dataBuf, int32_t *totalNum) {
|
static int32_t doParseInsertStatement(SInsertStatementParam *pInsertParam, char **str, STableDataBlocks* dataBuf, int32_t *totalNum) {
|
||||||
STableComInfo tinfo = tscGetTableInfo(dataBuf->pTableMeta);
|
|
||||||
|
|
||||||
int32_t maxNumOfRows;
|
int32_t maxNumOfRows;
|
||||||
int32_t code = tscAllocateMemIfNeed(dataBuf, getExtendedRowSize(&tinfo), &maxNumOfRows);
|
int32_t code = tscAllocateMemIfNeed(dataBuf, getExtendedRowSize(dataBuf), &maxNumOfRows);
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
return TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
|
@ -1531,7 +1206,7 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
||||||
pColInfo->numOfBound = 0;
|
pColInfo->numOfBound = 0;
|
||||||
memset(pColInfo->boundedColumns, 0, sizeof(int32_t) * nCols);
|
memset(pColInfo->boundedColumns, 0, sizeof(int32_t) * nCols);
|
||||||
for (int32_t i = 0; i < nCols; ++i) {
|
for (int32_t i = 0; i < nCols; ++i) {
|
||||||
pColInfo->cols[i].hasVal = false;
|
pColInfo->cols[i].valStat = VAL_STAT_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
@ -1570,12 +1245,12 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
||||||
int32_t nScanned = 0, t = lastColIdx + 1;
|
int32_t nScanned = 0, t = lastColIdx + 1;
|
||||||
while (t < nCols) {
|
while (t < nCols) {
|
||||||
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
||||||
if (pColInfo->cols[t].hasVal == true) {
|
if (pColInfo->cols[t].valStat == VAL_STAT_HAS) {
|
||||||
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
||||||
goto _clean;
|
goto _clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
pColInfo->cols[t].hasVal = true;
|
pColInfo->cols[t].valStat = VAL_STAT_HAS;
|
||||||
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
||||||
++pColInfo->numOfBound;
|
++pColInfo->numOfBound;
|
||||||
findColumnIndex = true;
|
findColumnIndex = true;
|
||||||
|
@ -1593,12 +1268,12 @@ static int32_t parseBoundColumns(SInsertStatementParam *pInsertParam, SParsedDat
|
||||||
int32_t nRemain = nCols - nScanned;
|
int32_t nRemain = nCols - nScanned;
|
||||||
while (t < nRemain) {
|
while (t < nRemain) {
|
||||||
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
if (strncmp(sToken.z, pSchema[t].name, sToken.n) == 0 && strlen(pSchema[t].name) == sToken.n) {
|
||||||
if (pColInfo->cols[t].hasVal == true) {
|
if (pColInfo->cols[t].valStat == VAL_STAT_HAS) {
|
||||||
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
code = tscInvalidOperationMsg(pInsertParam->msg, "duplicated column name", sToken.z);
|
||||||
goto _clean;
|
goto _clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
pColInfo->cols[t].hasVal = true;
|
pColInfo->cols[t].valStat = VAL_STAT_HAS;
|
||||||
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
pColInfo->boundedColumns[pColInfo->numOfBound] = t;
|
||||||
++pColInfo->numOfBound;
|
++pColInfo->numOfBound;
|
||||||
findColumnIndex = true;
|
findColumnIndex = true;
|
||||||
|
@ -1833,7 +1508,7 @@ int tsParseInsertSql(SSqlObj *pSql) {
|
||||||
goto _clean;
|
goto _clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dataBuf->boundColumnInfo.cols[0].hasVal == false) {
|
if (dataBuf->boundColumnInfo.cols[0].valStat == VAL_STAT_NONE) {
|
||||||
code = tscInvalidOperationMsg(pInsertParam->msg, "primary timestamp column can not be null", NULL);
|
code = tscInvalidOperationMsg(pInsertParam->msg, "primary timestamp column can not be null", NULL);
|
||||||
goto _clean;
|
goto _clean;
|
||||||
}
|
}
|
||||||
|
@ -2044,15 +1719,18 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int32_t numOfRow
|
||||||
goto _error;
|
goto _error;
|
||||||
}
|
}
|
||||||
|
|
||||||
tscAllocateMemIfNeed(pTableDataBlock, getExtendedRowSize(&tinfo), &maxRows);
|
tscAllocateMemIfNeed(pTableDataBlock, getExtendedRowSize(pTableDataBlock), &maxRows);
|
||||||
tokenBuf = calloc(1, TSDB_MAX_BYTES_PER_ROW);
|
tokenBuf = calloc(1, TSDB_MAX_BYTES_PER_ROW);
|
||||||
if (tokenBuf == NULL) {
|
if (tokenBuf == NULL) {
|
||||||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
goto _error;
|
goto _error;
|
||||||
}
|
}
|
||||||
|
|
||||||
initSMemRowHelper(&pTableDataBlock->rowHelper, tscGetTableSchema(pTableDataBlock->pTableMeta),
|
if (TSDB_CODE_SUCCESS !=
|
||||||
tscGetNumOfColumns(pTableDataBlock->pTableMeta), 0);
|
(ret = initMemRowBuilder(&pTableDataBlock->rowBuilder, 0, tinfo.numOfColumns, pTableDataBlock->numOfParams,
|
||||||
|
pTableDataBlock->boundColumnInfo.allNullLen))) {
|
||||||
|
goto _error;
|
||||||
|
}
|
||||||
|
|
||||||
while ((readLen = tgetline(&line, &n, fp)) != -1) {
|
while ((readLen = tgetline(&line, &n, fp)) != -1) {
|
||||||
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
|
if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) {
|
||||||
|
|
|
@ -299,7 +299,7 @@ static int fillColumnsNull(STableDataBlocks* pBlock, int32_t rowNum) {
|
||||||
SSchema *schema = (SSchema*)pBlock->pTableMeta->schema;
|
SSchema *schema = (SSchema*)pBlock->pTableMeta->schema;
|
||||||
|
|
||||||
for (int32_t i = 0; i < spd->numOfCols; ++i) {
|
for (int32_t i = 0; i < spd->numOfCols; ++i) {
|
||||||
if (!spd->cols[i].hasVal) { // current column do not have any value to insert, set it to null
|
if (spd->cols[i].valStat == VAL_STAT_NONE) { // current column do not have any value to insert, set it to null
|
||||||
for (int32_t n = 0; n < rowNum; ++n) {
|
for (int32_t n = 0; n < rowNum; ++n) {
|
||||||
char *ptr = pBlock->pData + sizeof(SSubmitBlk) + pBlock->rowSize * n + offset;
|
char *ptr = pBlock->pData + sizeof(SSubmitBlk) + pBlock->rowSize * n + offset;
|
||||||
|
|
||||||
|
@ -1527,8 +1527,9 @@ int taos_stmt_prepare(TAOS_STMT* stmt, const char* sql, unsigned long length) {
|
||||||
pCmd->insertParam.insertType = TSDB_QUERY_TYPE_STMT_INSERT;
|
pCmd->insertParam.insertType = TSDB_QUERY_TYPE_STMT_INSERT;
|
||||||
pCmd->insertParam.objectId = pSql->self;
|
pCmd->insertParam.objectId = pSql->self;
|
||||||
|
|
||||||
pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
|
char* sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
|
||||||
|
if(sqlstr == NULL && pSql->sqlstr) free(pSql->sqlstr);
|
||||||
|
pSql->sqlstr = sqlstr;
|
||||||
if (pSql->sqlstr == NULL) {
|
if (pSql->sqlstr == NULL) {
|
||||||
tscError("%p failed to malloc sql string buffer", pSql);
|
tscError("%p failed to malloc sql string buffer", pSql);
|
||||||
STMT_RET(TSDB_CODE_TSC_OUT_OF_MEMORY);
|
STMT_RET(TSDB_CODE_TSC_OUT_OF_MEMORY);
|
||||||
|
|
|
@ -1940,20 +1940,6 @@ static void addPrimaryTsColIntoResult(SQueryInfo* pQueryInfo, SSqlCmd* pCmd) {
|
||||||
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
|
pQueryInfo->type |= TSDB_QUERY_TYPE_PROJECTION_QUERY;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isValidDistinctSql(SQueryInfo* pQueryInfo) {
|
|
||||||
if (pQueryInfo == NULL) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ((pQueryInfo->type & TSDB_QUERY_TYPE_STABLE_QUERY) != TSDB_QUERY_TYPE_STABLE_QUERY
|
|
||||||
&& (pQueryInfo->type & TSDB_QUERY_TYPE_TABLE_QUERY) != TSDB_QUERY_TYPE_TABLE_QUERY) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (tscNumOfExprs(pQueryInfo) == 1){
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool hasNoneUserDefineExpr(SQueryInfo* pQueryInfo) {
|
static bool hasNoneUserDefineExpr(SQueryInfo* pQueryInfo) {
|
||||||
size_t numOfExprs = taosArrayGetSize(pQueryInfo->exprList);
|
size_t numOfExprs = taosArrayGetSize(pQueryInfo->exprList);
|
||||||
for (int32_t i = 0; i < numOfExprs; ++i) {
|
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||||
|
@ -2043,8 +2029,11 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
||||||
const char* msg1 = "too many items in selection clause";
|
const char* msg1 = "too many items in selection clause";
|
||||||
const char* msg2 = "functions or others can not be mixed up";
|
const char* msg2 = "functions or others can not be mixed up";
|
||||||
const char* msg3 = "not support query expression";
|
const char* msg3 = "not support query expression";
|
||||||
const char* msg4 = "only support distinct one column or tag";
|
const char* msg4 = "not support distinct mixed with proj/agg func";
|
||||||
const char* msg5 = "invalid function name";
|
const char* msg5 = "invalid function name";
|
||||||
|
const char* msg6 = "not support distinct mixed with join";
|
||||||
|
const char* msg7 = "not support distinct mixed with groupby";
|
||||||
|
const char* msg8 = "not support distinct in nest query";
|
||||||
|
|
||||||
// too many result columns not support order by in query
|
// too many result columns not support order by in query
|
||||||
if (taosArrayGetSize(pSelNodeList) > TSDB_MAX_COLUMNS) {
|
if (taosArrayGetSize(pSelNodeList) > TSDB_MAX_COLUMNS) {
|
||||||
|
@ -2055,19 +2044,31 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
||||||
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
|
pQueryInfo->colList = taosArrayInit(4, POINTER_BYTES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool hasDistinct = false;
|
bool hasDistinct = false;
|
||||||
|
bool hasAgg = false;
|
||||||
size_t numOfExpr = taosArrayGetSize(pSelNodeList);
|
size_t numOfExpr = taosArrayGetSize(pSelNodeList);
|
||||||
|
int32_t distIdx = -1;
|
||||||
for (int32_t i = 0; i < numOfExpr; ++i) {
|
for (int32_t i = 0; i < numOfExpr; ++i) {
|
||||||
int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo);
|
int32_t outputIndex = (int32_t)tscNumOfExprs(pQueryInfo);
|
||||||
tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i);
|
tSqlExprItem* pItem = taosArrayGet(pSelNodeList, i);
|
||||||
|
|
||||||
if (hasDistinct == false) {
|
if (hasDistinct == false) {
|
||||||
hasDistinct = (pItem->distinct == true);
|
hasDistinct = (pItem->distinct == true);
|
||||||
|
distIdx = hasDistinct ? i : -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t type = pItem->pNode->type;
|
int32_t type = pItem->pNode->type;
|
||||||
if (type == SQL_NODE_SQLFUNCTION) {
|
if (type == SQL_NODE_SQLFUNCTION) {
|
||||||
|
hasAgg = true;
|
||||||
|
if (hasDistinct) break;
|
||||||
|
|
||||||
pItem->pNode->functionId = isValidFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
pItem->pNode->functionId = isValidFunction(pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||||
|
|
||||||
|
if (pItem->pNode->functionId == TSDB_FUNC_BLKINFO && taosArrayGetSize(pQueryInfo->pUpstream) > 0) {
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||||
|
}
|
||||||
|
|
||||||
SUdfInfo* pUdfInfo = NULL;
|
SUdfInfo* pUdfInfo = NULL;
|
||||||
if (pItem->pNode->functionId < 0) {
|
if (pItem->pNode->functionId < 0) {
|
||||||
pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
pUdfInfo = isValidUdf(pQueryInfo->pUdfInfo, pItem->pNode->Expr.operand.z, pItem->pNode->Expr.operand.n);
|
||||||
|
@ -2102,10 +2103,22 @@ int32_t validateSelectNodeList(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SArray* pS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//TODO(dengyihao), refactor as function
|
||||||
|
//handle distinct func mixed with other func
|
||||||
if (hasDistinct == true) {
|
if (hasDistinct == true) {
|
||||||
if (!isValidDistinctSql(pQueryInfo) ) {
|
if (distIdx != 0 || hasAgg) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg4);
|
||||||
}
|
}
|
||||||
|
if (joinQuery) {
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||||
|
}
|
||||||
|
if (pQueryInfo->groupbyExpr.numOfGroupCols != 0) {
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg7);
|
||||||
|
}
|
||||||
|
if (pQueryInfo->pDownstream != NULL) {
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg8);
|
||||||
|
}
|
||||||
|
|
||||||
pQueryInfo->distinct = true;
|
pQueryInfo->distinct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2664,8 +2677,8 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
assert(ids.num == 1);
|
assert(ids.num == 1);
|
||||||
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
|
tscColumnListInsert(pQueryInfo->colList, ids.ids[0].columnIndex, pExpr->base.uid, pSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid);
|
tscInsertPrimaryTsSourceColumn(pQueryInfo, pExpr->base.uid);
|
||||||
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3047,7 +3060,6 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col
|
||||||
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, &s);
|
tscColumnListInsert(pQueryInfo->colList, index.columnIndex, uid, &s);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
|
tscInsertPrimaryTsSourceColumn(pQueryInfo, pTableMetaInfo->pTableMeta->id.uid);
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -3218,7 +3230,7 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||||
pCmd->command = TSDB_SQL_SHOW;
|
pCmd->command = TSDB_SQL_SHOW;
|
||||||
|
|
||||||
const char* msg1 = "invalid name";
|
const char* msg1 = "invalid name";
|
||||||
const char* msg2 = "pattern filter string too long";
|
const char* msg2 = "wildcard string should be less than %d characters";
|
||||||
const char* msg3 = "database name too long";
|
const char* msg3 = "database name too long";
|
||||||
const char* msg4 = "invalid ip address";
|
const char* msg4 = "invalid ip address";
|
||||||
const char* msg5 = "database name is empty";
|
const char* msg5 = "database name is empty";
|
||||||
|
@ -3262,8 +3274,10 @@ int32_t setShowInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tscValidateTableNameLength(pCmd->payloadLen)) {
|
if (pPattern->n > tsMaxWildCardsLen){
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
char tmp[64] = {0};
|
||||||
|
sprintf(tmp, msg2, tsMaxWildCardsLen);
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), tmp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (showType == TSDB_MGMT_TABLE_VNODES) {
|
} else if (showType == TSDB_MGMT_TABLE_VNODES) {
|
||||||
|
@ -4258,6 +4272,10 @@ static bool isValidExpr(tSqlExpr* pLeft, tSqlExpr* pRight, int32_t optr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pLeft->tokenId >= TK_BOOL && pLeft->tokenId <= TK_BINARY && (optr == TK_NOTNULL || optr == TK_ISNULL)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4390,15 +4408,17 @@ static int32_t validateNullExpr(tSqlExpr* pExpr, char* msgBuf) {
|
||||||
|
|
||||||
// check for like expression
|
// check for like expression
|
||||||
static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) {
|
static int32_t validateLikeExpr(tSqlExpr* pExpr, STableMeta* pTableMeta, int32_t index, char* msgBuf) {
|
||||||
const char* msg1 = "wildcard string should be less than 20 characters";
|
const char* msg1 = "wildcard string should be less than %d characters";
|
||||||
const char* msg2 = "illegal column name";
|
const char* msg2 = "illegal column name";
|
||||||
|
|
||||||
tSqlExpr* pLeft = pExpr->pLeft;
|
tSqlExpr* pLeft = pExpr->pLeft;
|
||||||
tSqlExpr* pRight = pExpr->pRight;
|
tSqlExpr* pRight = pExpr->pRight;
|
||||||
|
|
||||||
if (pExpr->tokenId == TK_LIKE) {
|
if (pExpr->tokenId == TK_LIKE) {
|
||||||
if (pRight->value.nLen > TSDB_PATTERN_STRING_MAX_LEN) {
|
if (pRight->value.nLen > tsMaxWildCardsLen) {
|
||||||
return invalidOperationMsg(msgBuf, msg1);
|
char tmp[64] = {0};
|
||||||
|
sprintf(tmp, msg1, tsMaxWildCardsLen);
|
||||||
|
return invalidOperationMsg(msgBuf, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
SSchema* pSchema = tscGetTableSchema(pTableMeta);
|
SSchema* pSchema = tscGetTableSchema(pTableMeta);
|
||||||
|
@ -4504,7 +4524,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
|
||||||
*/
|
*/
|
||||||
tSqlExprDestroy(*pExpr);
|
tSqlExprDestroy(*pExpr);
|
||||||
} else {
|
} else {
|
||||||
ret = setExprToCond(&pCondExpr->pTimewindow, *pExpr, msg3, parentOptr, pQueryInfo->msg);
|
ret = setExprToCond(&pCondExpr->pTimewindow, *pExpr, msg3, parentOptr, pCmd->payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
*pExpr = NULL; // remove this expression
|
*pExpr = NULL; // remove this expression
|
||||||
|
@ -4542,7 +4562,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
|
||||||
}
|
}
|
||||||
|
|
||||||
pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY;
|
pQueryInfo->type |= TSDB_QUERY_TYPE_JOIN_QUERY;
|
||||||
ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pQueryInfo->msg);
|
ret = setExprToCond(&pCondExpr->pJoinExpr, *pExpr, NULL, parentOptr, pCmd->payload);
|
||||||
*pExpr = NULL;
|
*pExpr = NULL;
|
||||||
} else {
|
} else {
|
||||||
// do nothing
|
// do nothing
|
||||||
|
@ -4560,7 +4580,7 @@ static int32_t handleExprInQueryCond(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, tSql
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = setExprToCond(&pCondExpr->pColumnCond, *pExpr, NULL, parentOptr, pQueryInfo->msg);
|
ret = setExprToCond(&pCondExpr->pColumnCond, *pExpr, NULL, parentOptr, pCmd->payload);
|
||||||
*pExpr = NULL; // remove it from expr tree
|
*pExpr = NULL; // remove it from expr tree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5362,6 +5382,7 @@ int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNo
|
||||||
const char* msg3 = "top/bottom not support fill";
|
const char* msg3 = "top/bottom not support fill";
|
||||||
const char* msg4 = "illegal value or data overflow";
|
const char* msg4 = "illegal value or data overflow";
|
||||||
const char* msg5 = "fill only available for interval query";
|
const char* msg5 = "fill only available for interval query";
|
||||||
|
const char* msg6 = "not supported function now";
|
||||||
|
|
||||||
if ((!isTimeWindowQuery(pQueryInfo)) && (!tscIsPointInterpQuery(pQueryInfo))) {
|
if ((!isTimeWindowQuery(pQueryInfo)) && (!tscIsPointInterpQuery(pQueryInfo))) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg5);
|
||||||
|
@ -5400,6 +5421,9 @@ int32_t validateFillNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNo
|
||||||
}
|
}
|
||||||
} else if (strncasecmp(pItem->pVar.pz, "prev", 4) == 0 && pItem->pVar.nLen == 4) {
|
} else if (strncasecmp(pItem->pVar.pz, "prev", 4) == 0 && pItem->pVar.nLen == 4) {
|
||||||
pQueryInfo->fillType = TSDB_FILL_PREV;
|
pQueryInfo->fillType = TSDB_FILL_PREV;
|
||||||
|
if (tscIsPointInterpQuery(pQueryInfo) && pQueryInfo->order.order == TSDB_ORDER_DESC) {
|
||||||
|
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg6);
|
||||||
|
}
|
||||||
} else if (strncasecmp(pItem->pVar.pz, "next", 4) == 0 && pItem->pVar.nLen == 4) {
|
} else if (strncasecmp(pItem->pVar.pz, "next", 4) == 0 && pItem->pVar.nLen == 4) {
|
||||||
pQueryInfo->fillType = TSDB_FILL_NEXT;
|
pQueryInfo->fillType = TSDB_FILL_NEXT;
|
||||||
} else if (strncasecmp(pItem->pVar.pz, "linear", 6) == 0 && pItem->pVar.nLen == 6) {
|
} else if (strncasecmp(pItem->pVar.pz, "linear", 6) == 0 && pItem->pVar.nLen == 6) {
|
||||||
|
@ -5478,14 +5502,19 @@ static void setDefaultOrderInfo(SQueryInfo* pQueryInfo) {
|
||||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||||
if (isTopBottomQuery(pQueryInfo)) {
|
if (isTopBottomQuery(pQueryInfo)) {
|
||||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||||
} else { // in case of select tbname from super_table, the defualt order column can not be the primary ts column
|
} else { // in case of select tbname from super_table, the default order column can not be the primary ts column
|
||||||
pQueryInfo->order.orderColId = INT32_MIN;
|
pQueryInfo->order.orderColId = INT32_MIN; // todo define a macro
|
||||||
}
|
}
|
||||||
|
|
||||||
/* for super table query, set default ascending order for group output */
|
/* for super table query, set default ascending order for group output */
|
||||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) {
|
||||||
pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC;
|
pQueryInfo->groupbyExpr.orderType = TSDB_ORDER_ASC;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pQueryInfo->distinct) {
|
||||||
|
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
||||||
|
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) {
|
int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSqlNode, SSchema* pSchema) {
|
||||||
|
@ -5493,21 +5522,17 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
const char* msg1 = "invalid column name";
|
const char* msg1 = "invalid column name";
|
||||||
const char* msg2 = "order by primary timestamp, first tag or groupby column in groupby clause allowed";
|
const char* msg2 = "order by primary timestamp, first tag or groupby column in groupby clause allowed";
|
||||||
const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed";
|
const char* msg3 = "invalid column in order by clause, only primary timestamp or first tag in groupby clause allowed";
|
||||||
|
const char* msg4 = "orderby column must projected in subquery";
|
||||||
|
|
||||||
setDefaultOrderInfo(pQueryInfo);
|
setDefaultOrderInfo(pQueryInfo);
|
||||||
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||||
|
|
||||||
|
if (pQueryInfo->distinct || pSqlNode->pSortOrder == NULL) {
|
||||||
if (pQueryInfo->distinct == true) {
|
|
||||||
pQueryInfo->order.order = TSDB_ORDER_ASC;
|
|
||||||
pQueryInfo->order.orderColId = 0;
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
if (pSqlNode->pSortOrder == NULL) {
|
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
SArray* pSortorder = pSqlNode->pSortOrder;
|
char* pMsgBuf = tscGetErrorMsgPayload(pCmd);
|
||||||
|
SArray* pSortOrder = pSqlNode->pSortOrder;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* for table query, there is only one or none order option is allowed, which is the
|
* for table query, there is only one or none order option is allowed, which is the
|
||||||
|
@ -5515,19 +5540,19 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
*
|
*
|
||||||
* for super table query, the order option must be less than 3.
|
* for super table query, the order option must be less than 3.
|
||||||
*/
|
*/
|
||||||
size_t size = taosArrayGetSize(pSortorder);
|
size_t size = taosArrayGetSize(pSortOrder);
|
||||||
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo)) {
|
if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo)) {
|
||||||
if (size > 1) {
|
if (size > 1) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg0);
|
return invalidOperationMsg(pMsgBuf, msg0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (size > 2) {
|
if (size > 2) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
return invalidOperationMsg(pMsgBuf, msg3);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// handle the first part of order by
|
// handle the first part of order by
|
||||||
tVariant* pVar = taosArrayGet(pSortorder, 0);
|
tVariant* pVar = taosArrayGet(pSortOrder, 0);
|
||||||
|
|
||||||
// e.g., order by 1 asc, return directly with out further check.
|
// e.g., order by 1 asc, return directly with out further check.
|
||||||
if (pVar->nType >= TSDB_DATA_TYPE_TINYINT && pVar->nType <= TSDB_DATA_TYPE_BIGINT) {
|
if (pVar->nType >= TSDB_DATA_TYPE_TINYINT && pVar->nType <= TSDB_DATA_TYPE_BIGINT) {
|
||||||
|
@ -5539,7 +5564,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
|
|
||||||
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query
|
if (UTIL_TABLE_IS_SUPER_TABLE(pTableMetaInfo)) { // super table query
|
||||||
if (getColumnIndexByName(&columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
if (getColumnIndexByName(&columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
return invalidOperationMsg(pMsgBuf, msg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool orderByTags = false;
|
bool orderByTags = false;
|
||||||
|
@ -5551,7 +5576,7 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
|
|
||||||
// it is a tag column
|
// it is a tag column
|
||||||
if (pQueryInfo->groupbyExpr.columnInfo == NULL) {
|
if (pQueryInfo->groupbyExpr.columnInfo == NULL) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
}
|
}
|
||||||
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0);
|
SColIndex* pColIndex = taosArrayGet(pQueryInfo->groupbyExpr.columnInfo, 0);
|
||||||
if (relTagIndex == pColIndex->colIndex) {
|
if (relTagIndex == pColIndex->colIndex) {
|
||||||
|
@ -5572,13 +5597,14 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
orderByGroupbyCol = true;
|
orderByGroupbyCol = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(orderByTags || orderByTS || orderByGroupbyCol) && !isTopBottomQuery(pQueryInfo)) {
|
if (!(orderByTags || orderByTS || orderByGroupbyCol) && !isTopBottomQuery(pQueryInfo)) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg3);
|
return invalidOperationMsg(pMsgBuf, msg3);
|
||||||
} else { // order by top/bottom result value column is not supported in case of interval query.
|
} else { // order by top/bottom result value column is not supported in case of interval query.
|
||||||
assert(!(orderByTags && orderByTS && orderByGroupbyCol));
|
assert(!(orderByTags && orderByTS && orderByGroupbyCol));
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t s = taosArrayGetSize(pSortorder);
|
size_t s = taosArrayGetSize(pSortOrder);
|
||||||
if (s == 1) {
|
if (s == 1) {
|
||||||
if (orderByTags) {
|
if (orderByTags) {
|
||||||
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||||
|
@ -5591,13 +5617,15 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
|
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
|
||||||
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
||||||
} else if (isTopBottomQuery(pQueryInfo)) {
|
} else if (isTopBottomQuery(pQueryInfo)) {
|
||||||
|
int32_t topBotIndex = tscGetTopBotQueryExprIndex(pQueryInfo);
|
||||||
|
assert(topBotIndex >= 1);
|
||||||
/* order of top/bottom query in interval is not valid */
|
/* order of top/bottom query in interval is not valid */
|
||||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, 0);
|
SExprInfo* pExpr = tscExprGet(pQueryInfo, topBotIndex-1);
|
||||||
assert(pExpr->base.functionId == TSDB_FUNC_TS);
|
assert(pExpr->base.functionId == TSDB_FUNC_TS);
|
||||||
|
|
||||||
pExpr = tscExprGet(pQueryInfo, 1);
|
pExpr = tscExprGet(pQueryInfo, topBotIndex);
|
||||||
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
|
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
|
@ -5612,12 +5640,21 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
|
|
||||||
// orderby ts query on super table
|
// orderby ts query on super table
|
||||||
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
|
if (tscOrderedProjectionQueryOnSTable(pQueryInfo, 0)) {
|
||||||
|
bool found = false;
|
||||||
|
for (int32_t i = 0; i < tscNumOfExprs(pQueryInfo); ++i) {
|
||||||
|
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||||
|
if (pExpr->base.functionId == TSDB_FUNC_PRJ && pExpr->base.colInfo.colId == PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||||
|
found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!found && pQueryInfo->pDownstream) {
|
||||||
|
return invalidOperationMsg(pMsgBuf, msg4);
|
||||||
|
}
|
||||||
addPrimaryTsColIntoResult(pQueryInfo, pCmd);
|
addPrimaryTsColIntoResult(pQueryInfo, pCmd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
|
|
||||||
if (s == 2) {
|
|
||||||
tVariantListItem *pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
tVariantListItem *pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
if (orderByTags) {
|
if (orderByTags) {
|
||||||
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
pQueryInfo->groupbyExpr.orderIndex = index.columnIndex - tscGetNumOfColumns(pTableMetaInfo->pTableMeta);
|
||||||
|
@ -5634,22 +5671,23 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
tVariant* pVar2 = &pItem->pVar;
|
tVariant* pVar2 = &pItem->pVar;
|
||||||
SStrToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz};
|
SStrToken cname = {pVar2->nLen, pVar2->nType, pVar2->pz};
|
||||||
if (getColumnIndexByName(&cname, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
if (getColumnIndexByName(&cname, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
return invalidOperationMsg(pMsgBuf, msg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
} else {
|
} else {
|
||||||
tVariantListItem* p1 = taosArrayGet(pSortorder, 1);
|
tVariantListItem* p1 = taosArrayGet(pSortOrder, 1);
|
||||||
pQueryInfo->order.order = p1->sortOrder;
|
pQueryInfo->order.order = p1->sortOrder;
|
||||||
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
pQueryInfo->order.orderColId = PRIMARYKEY_TIMESTAMP_COL_INDEX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else { // meter query
|
} else if (UTIL_TABLE_IS_NORMAL_TABLE(pTableMetaInfo) || UTIL_TABLE_IS_CHILD_TABLE(pTableMetaInfo)) { // check order by clause for normal table & temp table
|
||||||
if (getColumnIndexByName(&columnName, pQueryInfo, &index, tscGetErrorMsgPayload(pCmd)) != TSDB_CODE_SUCCESS) {
|
if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg1);
|
return invalidOperationMsg(pMsgBuf, msg1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) {
|
if (index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX && !isTopBottomQuery(pQueryInfo)) {
|
||||||
bool validOrder = false;
|
bool validOrder = false;
|
||||||
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
|
SArray *columnInfo = pQueryInfo->groupbyExpr.columnInfo;
|
||||||
|
@ -5657,13 +5695,14 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
|
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
|
||||||
validOrder = (pColIndex->colIndex == index.columnIndex);
|
validOrder = (pColIndex->colIndex == index.columnIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validOrder) {
|
if (!validOrder) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
|
tVariantListItem* p1 = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
pQueryInfo->groupbyExpr.orderIndex = pSchema[index.columnIndex].colId;
|
pQueryInfo->groupbyExpr.orderIndex = pSchema[index.columnIndex].colId;
|
||||||
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
|
pQueryInfo->groupbyExpr.orderType = p1->sortOrder;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isTopBottomQuery(pQueryInfo)) {
|
if (isTopBottomQuery(pQueryInfo)) {
|
||||||
|
@ -5673,19 +5712,22 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
|
SColIndex* pColIndex = taosArrayGet(columnInfo, 0);
|
||||||
validOrder = (pColIndex->colIndex == index.columnIndex);
|
validOrder = (pColIndex->colIndex == index.columnIndex);
|
||||||
} else {
|
} else {
|
||||||
|
int32_t topBotIndex = tscGetTopBotQueryExprIndex(pQueryInfo);
|
||||||
|
assert(topBotIndex >= 1);
|
||||||
/* order of top/bottom query in interval is not valid */
|
/* order of top/bottom query in interval is not valid */
|
||||||
SExprInfo* pExpr = tscExprGet(pQueryInfo, 0);
|
SExprInfo* pExpr = tscExprGet(pQueryInfo, topBotIndex-1);
|
||||||
assert(pExpr->base.functionId == TSDB_FUNC_TS);
|
assert(pExpr->base.functionId == TSDB_FUNC_TS);
|
||||||
|
|
||||||
pExpr = tscExprGet(pQueryInfo, 1);
|
pExpr = tscExprGet(pQueryInfo, topBotIndex);
|
||||||
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
if (pExpr->base.colInfo.colIndex != index.columnIndex && index.columnIndex != PRIMARYKEY_TIMESTAMP_COL_INDEX) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
validOrder = true;
|
validOrder = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!validOrder) {
|
if (!validOrder) {
|
||||||
return invalidOperationMsg(tscGetErrorMsgPayload(pCmd), msg2);
|
return invalidOperationMsg(pMsgBuf, msg2);
|
||||||
}
|
}
|
||||||
|
|
||||||
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
|
@ -5695,6 +5737,18 @@ int32_t validateOrderbyNode(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SSqlNode* pSq
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
|
pQueryInfo->order.order = pItem->sortOrder;
|
||||||
|
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
||||||
|
} else {
|
||||||
|
// handle the temp table order by clause. You can order by any single column in case of the temp table, created by
|
||||||
|
// inner subquery.
|
||||||
|
assert(UTIL_TABLE_IS_TMP_TABLE(pTableMetaInfo) && taosArrayGetSize(pSqlNode->pSortOrder) == 1);
|
||||||
|
|
||||||
|
if (getColumnIndexByName(&columnName, pQueryInfo, &index, pMsgBuf) != TSDB_CODE_SUCCESS) {
|
||||||
|
return invalidOperationMsg(pMsgBuf, msg1);
|
||||||
|
}
|
||||||
|
|
||||||
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
tVariantListItem* pItem = taosArrayGet(pSqlNode->pSortOrder, 0);
|
||||||
pQueryInfo->order.order = pItem->sortOrder;
|
pQueryInfo->order.order = pItem->sortOrder;
|
||||||
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
pQueryInfo->order.orderColId = pSchema[index.columnIndex].colId;
|
||||||
|
@ -5884,6 +5938,10 @@ int32_t setAlterTableInfo(SSqlObj* pSql, struct SSqlInfo* pInfo) {
|
||||||
|
|
||||||
tVariantListItem* pItem = taosArrayGet(pVarList, 1);
|
tVariantListItem* pItem = taosArrayGet(pVarList, 1);
|
||||||
SSchema* pTagsSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex.columnIndex);
|
SSchema* pTagsSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, columnIndex.columnIndex);
|
||||||
|
|
||||||
|
if (IS_VAR_DATA_TYPE(pTagsSchema->type) && (pItem->pVar.nLen > pTagsSchema->bytes * TSDB_NCHAR_SIZE)) {
|
||||||
|
return invalidOperationMsg(pMsg, msg14);
|
||||||
|
}
|
||||||
pAlterSQL->tagData.data = calloc(1, pTagsSchema->bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE);
|
pAlterSQL->tagData.data = calloc(1, pTagsSchema->bytes * TSDB_NCHAR_SIZE + VARSTR_HEADER_SIZE);
|
||||||
|
|
||||||
if (tVariantDump(&pItem->pVar, pAlterSQL->tagData.data, pTagsSchema->type, true) != TSDB_CODE_SUCCESS) {
|
if (tVariantDump(&pItem->pVar, pAlterSQL->tagData.data, pTagsSchema->type, true) != TSDB_CODE_SUCCESS) {
|
||||||
|
@ -8367,7 +8425,7 @@ static STableMeta* extractTempTableMetaFromSubquery(SQueryInfo* pUpstream) {
|
||||||
|
|
||||||
n += 1;
|
n += 1;
|
||||||
}
|
}
|
||||||
|
info->numOfColumns = n;
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8390,13 +8448,12 @@ static int32_t doValidateSubquery(SSqlNode* pSqlNode, int32_t index, SSqlObj* pS
|
||||||
pSub->pUdfInfo = pUdfInfo;
|
pSub->pUdfInfo = pUdfInfo;
|
||||||
pSub->udfCopy = true;
|
pSub->udfCopy = true;
|
||||||
|
|
||||||
|
pSub->pDownstream = pQueryInfo;
|
||||||
int32_t code = validateSqlNode(pSql, p, pSub);
|
int32_t code = validateSqlNode(pSql, p, pSub);
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
return code;
|
return code;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSub->pDownstream = pQueryInfo;
|
|
||||||
|
|
||||||
// create dummy table meta info
|
// create dummy table meta info
|
||||||
STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo));
|
STableMetaInfo* pTableMetaInfo1 = calloc(1, sizeof(STableMetaInfo));
|
||||||
if (pTableMetaInfo1 == NULL) {
|
if (pTableMetaInfo1 == NULL) {
|
||||||
|
@ -8455,7 +8512,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
||||||
const char* msg9 = "not support 3 level select";
|
const char* msg9 = "not support 3 level select";
|
||||||
|
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
|
|
||||||
SSqlCmd* pCmd = &pSql->cmd;
|
SSqlCmd* pCmd = &pSql->cmd;
|
||||||
|
|
||||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||||
|
@ -8750,8 +8806,6 @@ int32_t validateSqlNode(SSqlObj* pSql, SSqlNode* pSqlNode, SQueryInfo* pQueryInf
|
||||||
pQueryInfo->simpleAgg = isSimpleAggregateRv(pQueryInfo);
|
pQueryInfo->simpleAgg = isSimpleAggregateRv(pQueryInfo);
|
||||||
pQueryInfo->onlyTagQuery = onlyTagPrjFunction(pQueryInfo);
|
pQueryInfo->onlyTagQuery = onlyTagPrjFunction(pQueryInfo);
|
||||||
pQueryInfo->groupbyColumn = tscGroupbyColumn(pQueryInfo);
|
pQueryInfo->groupbyColumn = tscGroupbyColumn(pQueryInfo);
|
||||||
//pQueryInfo->globalMerge = tscIsTwoStageSTableQuery(pQueryInfo, 0);
|
|
||||||
|
|
||||||
pQueryInfo->arithmeticOnAgg = tsIsArithmeticQueryOnAggResult(pQueryInfo);
|
pQueryInfo->arithmeticOnAgg = tsIsArithmeticQueryOnAggResult(pQueryInfo);
|
||||||
pQueryInfo->orderProjectQuery = tscOrderedProjectionQueryOnSTable(pQueryInfo, 0);
|
pQueryInfo->orderProjectQuery = tscOrderedProjectionQueryOnSTable(pQueryInfo, 0);
|
||||||
|
|
||||||
|
|
|
@ -409,7 +409,7 @@ static void doProcessMsgFromServer(SSchedMsg* pSchedMsg) {
|
||||||
if ((TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY |
|
if ((TSDB_QUERY_HAS_TYPE(pQueryInfo->type, (TSDB_QUERY_TYPE_STABLE_SUBQUERY | TSDB_QUERY_TYPE_SUBQUERY |
|
||||||
TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) &&
|
TSDB_QUERY_TYPE_TAG_FILTER_QUERY)) &&
|
||||||
!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) ||
|
!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_PROJECTION_QUERY)) ||
|
||||||
(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY))) {
|
(TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_NEST_SUBQUERY)) || (TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_STABLE_SUBQUERY) && pQueryInfo->distinct)) {
|
||||||
// do nothing in case of super table subquery
|
// do nothing in case of super table subquery
|
||||||
} else {
|
} else {
|
||||||
pSql->retry += 1;
|
pSql->retry += 1;
|
||||||
|
@ -880,16 +880,16 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd);
|
SQueryInfo *pQueryInfo = tscGetQueryInfo(pCmd);
|
||||||
|
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
||||||
|
STableMeta * pTableMeta = pTableMetaInfo->pTableMeta;
|
||||||
|
|
||||||
SQueryAttr query = {{0}};
|
SQueryAttr query = {{0}};
|
||||||
tscCreateQueryFromQueryInfo(pQueryInfo, &query, pSql);
|
tscCreateQueryFromQueryInfo(pQueryInfo, &query, pSql);
|
||||||
|
query.vgId = pTableMeta->vgId;
|
||||||
|
|
||||||
SArray* tableScanOperator = createTableScanPlan(&query);
|
SArray* tableScanOperator = createTableScanPlan(&query);
|
||||||
SArray* queryOperator = createExecOperatorPlan(&query);
|
SArray* queryOperator = createExecOperatorPlan(&query);
|
||||||
|
|
||||||
STableMetaInfo *pTableMetaInfo = tscGetMetaInfo(pQueryInfo, 0);
|
|
||||||
STableMeta * pTableMeta = pTableMetaInfo->pTableMeta;
|
|
||||||
|
|
||||||
SQueryTableMsg *pQueryMsg = (SQueryTableMsg *)pCmd->payload;
|
SQueryTableMsg *pQueryMsg = (SQueryTableMsg *)pCmd->payload;
|
||||||
tstrncpy(pQueryMsg->version, version, tListLen(pQueryMsg->version));
|
tstrncpy(pQueryMsg->version, version, tListLen(pQueryMsg->version));
|
||||||
|
|
||||||
|
|
|
@ -887,7 +887,9 @@ int taos_validate_sql(TAOS *taos, const char *sql) {
|
||||||
return TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
|
return TSDB_CODE_TSC_EXCEED_SQL_LIMIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
pSql->sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
|
char* sqlstr = realloc(pSql->sqlstr, sqlLen + 1);
|
||||||
|
if(sqlstr == NULL && pSql->sqlstr) free(pSql->sqlstr);
|
||||||
|
pSql->sqlstr = sqlstr;
|
||||||
if (pSql->sqlstr == NULL) {
|
if (pSql->sqlstr == NULL) {
|
||||||
tscError("0x%"PRIx64" failed to malloc sql string buffer", pSql->self);
|
tscError("0x%"PRIx64" failed to malloc sql string buffer", pSql->self);
|
||||||
tfree(pSql);
|
tfree(pSql);
|
||||||
|
|
|
@ -2034,17 +2034,14 @@ void tscHandleMasterJoinQuery(SSqlObj* pSql) {
|
||||||
tscAsyncResultOnError(pSql);
|
tscAsyncResultOnError(pSql);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs) {
|
void doCleanupSubqueries(SSqlObj *pSql, int32_t numOfSubs) {
|
||||||
assert(numOfSubs <= pSql->subState.numOfSub && numOfSubs >= 0);
|
assert(numOfSubs <= pSql->subState.numOfSub && numOfSubs >= 0);
|
||||||
|
|
||||||
for(int32_t i = 0; i < numOfSubs; ++i) {
|
for(int32_t i = 0; i < numOfSubs; ++i) {
|
||||||
SSqlObj* pSub = pSql->pSubs[i];
|
SSqlObj* pSub = pSql->pSubs[i];
|
||||||
assert(pSub != NULL);
|
assert(pSub != NULL);
|
||||||
|
|
||||||
SRetrieveSupport* pSupport = pSub->param;
|
tscFreeRetrieveSup(pSub);
|
||||||
|
|
||||||
tfree(pSupport->localBuffer);
|
|
||||||
tfree(pSupport);
|
|
||||||
|
|
||||||
taos_free_result(pSub);
|
taos_free_result(pSub);
|
||||||
}
|
}
|
||||||
|
@ -2395,8 +2392,12 @@ int32_t tscHandleFirstRoundStableQuery(SSqlObj *pSql) {
|
||||||
SColumn* x = taosArrayGetP(pNewQueryInfo->colList, index1);
|
SColumn* x = taosArrayGetP(pNewQueryInfo->colList, index1);
|
||||||
tscColumnCopy(x, pCol);
|
tscColumnCopy(x, pCol);
|
||||||
} else {
|
} else {
|
||||||
SColumn *p = tscColumnClone(pCol);
|
SSchema ss = {.type = (uint8_t)pCol->info.type, .bytes = pCol->info.bytes, .colId = (int16_t)pCol->columnIndex};
|
||||||
taosArrayPush(pNewQueryInfo->colList, &p);
|
tscColumnListInsert(pNewQueryInfo->colList, pCol->columnIndex, pCol->tableUid, &ss);
|
||||||
|
int32_t ti = tscColumnExists(pNewQueryInfo->colList, pCol->columnIndex, pCol->tableUid);
|
||||||
|
assert(ti >= 0);
|
||||||
|
SColumn* x = taosArrayGetP(pNewQueryInfo->colList, ti);
|
||||||
|
tscColumnCopy(x, pCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2558,7 +2559,7 @@ int32_t tscHandleMasterSTableQuery(SSqlObj *pSql) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tscFreeRetrieveSup(SSqlObj *pSql) {
|
void tscFreeRetrieveSup(SSqlObj *pSql) {
|
||||||
SRetrieveSupport *trsupport = pSql->param;
|
SRetrieveSupport *trsupport = pSql->param;
|
||||||
|
|
||||||
void* p = atomic_val_compare_exchange_ptr(&pSql->param, trsupport, 0);
|
void* p = atomic_val_compare_exchange_ptr(&pSql->param, trsupport, 0);
|
||||||
|
@ -2716,33 +2717,43 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO
|
||||||
if (!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
|
if (!TSDB_QUERY_HAS_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_JOIN_SEC_STAGE)) {
|
||||||
|
|
||||||
int32_t code = pParentSql->res.code;
|
int32_t code = pParentSql->res.code;
|
||||||
if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry) {
|
SSqlObj *userSql = NULL;
|
||||||
// remove the cached tableMeta and vgroup id list, and then parse the sql again
|
if (pParentSql->param) {
|
||||||
SSqlCmd* pParentCmd = &pParentSql->cmd;
|
userSql = ((SRetrieveSupport*)pParentSql->param)->pParentSql;
|
||||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pParentCmd, 0);
|
}
|
||||||
tscRemoveTableMetaBuf(pTableMetaInfo, pParentSql->self);
|
|
||||||
|
|
||||||
pParentCmd->pTableMetaMap = tscCleanupTableMetaMap(pParentCmd->pTableMetaMap);
|
if (userSql == NULL) {
|
||||||
pParentCmd->pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
userSql = pParentSql;
|
||||||
|
}
|
||||||
|
|
||||||
pParentSql->res.code = TSDB_CODE_SUCCESS;
|
if ((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && userSql->retry < userSql->maxRetry) {
|
||||||
pParentSql->retry++;
|
if (userSql != pParentSql) {
|
||||||
|
tscFreeRetrieveSup(pParentSql);
|
||||||
|
}
|
||||||
|
|
||||||
tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self,
|
tscFreeSubobj(userSql);
|
||||||
tstrerror(code), pParentSql->retry);
|
tfree(userSql->pSubs);
|
||||||
|
|
||||||
code = tsParseSql(pParentSql, true);
|
userSql->res.code = TSDB_CODE_SUCCESS;
|
||||||
|
userSql->retry++;
|
||||||
|
|
||||||
|
tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", userSql->self,
|
||||||
|
tstrerror(code), userSql->retry);
|
||||||
|
|
||||||
|
tscResetSqlCmd(&userSql->cmd, true);
|
||||||
|
code = tsParseSql(userSql, true);
|
||||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code != TSDB_CODE_SUCCESS) {
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
pParentSql->res.code = code;
|
userSql->res.code = code;
|
||||||
tscAsyncResultOnError(pParentSql);
|
tscAsyncResultOnError(userSql);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
executeQuery(pParentSql, pQueryInfo);
|
pQueryInfo = tscGetQueryInfo(&userSql->cmd);
|
||||||
|
executeQuery(userSql, pQueryInfo);
|
||||||
} else {
|
} else {
|
||||||
(*pParentSql->fp)(pParentSql->param, pParentSql, pParentSql->res.code);
|
(*pParentSql->fp)(pParentSql->param, pParentSql, pParentSql->res.code);
|
||||||
}
|
}
|
||||||
|
@ -2812,7 +2823,6 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p
|
||||||
pParentSql->self, pState->numOfSub, pState->numOfRetrievedRows);
|
pParentSql->self, pState->numOfSub, pState->numOfRetrievedRows);
|
||||||
|
|
||||||
SQueryInfo *pPQueryInfo = tscGetQueryInfo(&pParentSql->cmd);
|
SQueryInfo *pPQueryInfo = tscGetQueryInfo(&pParentSql->cmd);
|
||||||
tscClearInterpInfo(pPQueryInfo);
|
|
||||||
|
|
||||||
code = tscCreateGlobalMerger(trsupport->pExtMemBuffer, pState->numOfSub, pDesc, pPQueryInfo, &pParentSql->res.pMerger, pParentSql->self);
|
code = tscCreateGlobalMerger(trsupport->pExtMemBuffer, pState->numOfSub, pDesc, pPQueryInfo, &pParentSql->res.pMerger, pParentSql->self);
|
||||||
pParentSql->res.code = code;
|
pParentSql->res.code = code;
|
||||||
|
|
|
@ -369,6 +369,27 @@ bool tscGroupbyColumn(SQueryInfo* pQueryInfo) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t tscGetTopBotQueryExprIndex(SQueryInfo* pQueryInfo) {
|
||||||
|
size_t numOfExprs = tscNumOfExprs(pQueryInfo);
|
||||||
|
|
||||||
|
for (int32_t i = 0; i < numOfExprs; ++i) {
|
||||||
|
SExprInfo* pExpr = tscExprGet(pQueryInfo, i);
|
||||||
|
if (pExpr == NULL) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pExpr->base.functionId == TSDB_FUNC_TS) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pExpr->base.functionId == TSDB_FUNC_TOP || pExpr->base.functionId == TSDB_FUNC_BOTTOM) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool tscIsTopBotQuery(SQueryInfo* pQueryInfo) {
|
bool tscIsTopBotQuery(SQueryInfo* pQueryInfo) {
|
||||||
size_t numOfExprs = tscNumOfExprs(pQueryInfo);
|
size_t numOfExprs = tscNumOfExprs(pQueryInfo);
|
||||||
|
|
||||||
|
@ -625,8 +646,10 @@ static void setResRawPtrImpl(SSqlRes* pRes, SInternalField* pInfo, int32_t i, bo
|
||||||
|
|
||||||
} else if (convertNchar && pInfo->field.type == TSDB_DATA_TYPE_NCHAR) {
|
} else if (convertNchar && pInfo->field.type == TSDB_DATA_TYPE_NCHAR) {
|
||||||
// convert unicode to native code in a temporary buffer extra one byte for terminated symbol
|
// convert unicode to native code in a temporary buffer extra one byte for terminated symbol
|
||||||
pRes->buffer[i] = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows);
|
char* buffer = realloc(pRes->buffer[i], pInfo->field.bytes * pRes->numOfRows);
|
||||||
|
if(buffer == NULL)
|
||||||
|
return ;
|
||||||
|
pRes->buffer[i] = buffer;
|
||||||
// string terminated char for binary data
|
// string terminated char for binary data
|
||||||
memset(pRes->buffer[i], 0, pInfo->field.bytes * pRes->numOfRows);
|
memset(pRes->buffer[i], 0, pInfo->field.bytes * pRes->numOfRows);
|
||||||
|
|
||||||
|
@ -1206,7 +1229,6 @@ void handleDownstreamOperator(SSqlObj** pSqlObjList, int32_t numOfUpstream, SQue
|
||||||
createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo);
|
createInputDataFilterInfo(px, numOfCol1, &numOfFilterCols, &pFilterInfo);
|
||||||
|
|
||||||
SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilterInfo, numOfFilterCols);
|
SOperatorInfo* pSourceOperator = createDummyInputOperator(pSqlObjList[0], pSchema, numOfCol1, pFilterInfo, numOfFilterCols);
|
||||||
|
|
||||||
pOutput->precision = pSqlObjList[0]->res.precision;
|
pOutput->precision = pSqlObjList[0]->res.precision;
|
||||||
|
|
||||||
SSchema* schema = NULL;
|
SSchema* schema = NULL;
|
||||||
|
@ -1502,7 +1524,6 @@ void tscFreeSqlObj(SSqlObj* pSql) {
|
||||||
tscFreeSqlResult(pSql);
|
tscFreeSqlResult(pSql);
|
||||||
tscResetSqlCmd(pCmd, false);
|
tscResetSqlCmd(pCmd, false);
|
||||||
|
|
||||||
memset(pCmd->payload, 0, (size_t)pCmd->allocSize);
|
|
||||||
tfree(pCmd->payload);
|
tfree(pCmd->payload);
|
||||||
pCmd->allocSize = 0;
|
pCmd->allocSize = 0;
|
||||||
|
|
||||||
|
@ -1776,101 +1797,6 @@ int32_t tscGetDataBlockFromList(SHashObj* pHashList, int64_t id, int32_t size, i
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static SMemRow tdGenMemRowFromBuilder(SMemRowBuilder* pBuilder) {
|
|
||||||
SSchema* pSchema = pBuilder->pSchema;
|
|
||||||
char* p = (char*)pBuilder->buf;
|
|
||||||
int toffset = 0;
|
|
||||||
uint16_t nCols = pBuilder->nCols;
|
|
||||||
|
|
||||||
uint8_t memRowType = payloadType(p);
|
|
||||||
uint16_t nColsBound = payloadNCols(p);
|
|
||||||
if (pBuilder->nCols <= 0 || nColsBound <= 0) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
char* pVals = POINTER_SHIFT(p, payloadValuesOffset(p));
|
|
||||||
SMemRow* memRow = (SMemRow)pBuilder->pDataBlock;
|
|
||||||
memRowSetType(memRow, memRowType);
|
|
||||||
|
|
||||||
// ----------------- Raw payload structure for row:
|
|
||||||
/* |<------------ Head ------------->|<----------- body of column data tuple ------------------->|
|
|
||||||
* | |<----------------- flen ------------->|<--- value part --->|
|
|
||||||
* |SMemRowType| dataTLen | nCols | colId | colType | offset | ... | value |...|...|... |
|
|
||||||
* +-----------+----------+----------+--------------------------------------|--------------------|
|
|
||||||
* | uint8_t | uint32_t | uint16_t | int16_t | uint8_t | uint16_t | ... |.......|...|...|... |
|
|
||||||
* +-----------+----------+----------+--------------------------------------+--------------------|
|
|
||||||
* 1. offset in column data tuple starts from the value part in case of uint16_t overflow.
|
|
||||||
* 2. dataTLen: total length including the header and body.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (memRowType == SMEM_ROW_DATA) {
|
|
||||||
SDataRow trow = (SDataRow)memRowDataBody(memRow);
|
|
||||||
dataRowSetLen(trow, (TDRowLenT)(TD_DATA_ROW_HEAD_SIZE + pBuilder->flen));
|
|
||||||
dataRowSetVersion(trow, pBuilder->sversion);
|
|
||||||
|
|
||||||
p = (char*)payloadBody(pBuilder->buf);
|
|
||||||
uint16_t i = 0, j = 0;
|
|
||||||
while (j < nCols) {
|
|
||||||
if (i >= nColsBound) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
int16_t colId = payloadColId(p);
|
|
||||||
if (colId == pSchema[j].colId) {
|
|
||||||
// ASSERT(payloadColType(p) == pSchema[j].type);
|
|
||||||
tdAppendColVal(trow, POINTER_SHIFT(pVals, payloadColOffset(p)), pSchema[j].type, toffset);
|
|
||||||
toffset += TYPE_BYTES[pSchema[j].type];
|
|
||||||
p = payloadNextCol(p);
|
|
||||||
++i;
|
|
||||||
++j;
|
|
||||||
} else if (colId < pSchema[j].colId) {
|
|
||||||
p = payloadNextCol(p);
|
|
||||||
++i;
|
|
||||||
} else {
|
|
||||||
tdAppendColVal(trow, getNullValue(pSchema[j].type), pSchema[j].type, toffset);
|
|
||||||
toffset += TYPE_BYTES[pSchema[j].type];
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while (j < nCols) {
|
|
||||||
tdAppendColVal(trow, getNullValue(pSchema[j].type), pSchema[j].type, toffset);
|
|
||||||
toffset += TYPE_BYTES[pSchema[j].type];
|
|
||||||
++j;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if 0 // no need anymore
|
|
||||||
while (i < nColsBound) {
|
|
||||||
p = payloadNextCol(p);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} else if (memRowType == SMEM_ROW_KV) {
|
|
||||||
SKVRow kvRow = (SKVRow)memRowKvBody(memRow);
|
|
||||||
kvRowSetLen(kvRow, (TDRowLenT)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nColsBound));
|
|
||||||
kvRowSetNCols(kvRow, nColsBound);
|
|
||||||
memRowSetKvVersion(memRow, pBuilder->sversion);
|
|
||||||
|
|
||||||
p = (char*)payloadBody(pBuilder->buf);
|
|
||||||
int i = 0;
|
|
||||||
while (i < nColsBound) {
|
|
||||||
int16_t colId = payloadColId(p);
|
|
||||||
uint8_t colType = payloadColType(p);
|
|
||||||
tdAppendKvColVal(kvRow, POINTER_SHIFT(pVals,payloadColOffset(p)), colId, colType, &toffset);
|
|
||||||
//toffset += sizeof(SColIdx);
|
|
||||||
p = payloadNextCol(p);
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ASSERT(0);
|
|
||||||
}
|
|
||||||
int32_t rowTLen = memRowTLen(memRow);
|
|
||||||
pBuilder->pDataBlock = (char*)pBuilder->pDataBlock + rowTLen; // next row
|
|
||||||
pBuilder->pSubmitBlk->dataLen += rowTLen;
|
|
||||||
|
|
||||||
return memRow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Erase the empty space reserved for binary data
|
// Erase the empty space reserved for binary data
|
||||||
static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SInsertStatementParam* insertParam,
|
static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SInsertStatementParam* insertParam,
|
||||||
SBlockKeyTuple* blkKeyTuple) {
|
SBlockKeyTuple* blkKeyTuple) {
|
||||||
|
@ -1902,10 +1828,11 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SI
|
||||||
int32_t schemaSize = sizeof(STColumn) * numOfCols;
|
int32_t schemaSize = sizeof(STColumn) * numOfCols;
|
||||||
pBlock->schemaLen = schemaSize;
|
pBlock->schemaLen = schemaSize;
|
||||||
} else {
|
} else {
|
||||||
|
if (IS_RAW_PAYLOAD(insertParam->payloadType)) {
|
||||||
for (int32_t j = 0; j < tinfo.numOfColumns; ++j) {
|
for (int32_t j = 0; j < tinfo.numOfColumns; ++j) {
|
||||||
flen += TYPE_BYTES[pSchema[j].type];
|
flen += TYPE_BYTES[pSchema[j].type];
|
||||||
}
|
}
|
||||||
|
}
|
||||||
pBlock->schemaLen = 0;
|
pBlock->schemaLen = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1932,18 +1859,19 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, SI
|
||||||
pBlock->dataLen += memRowTLen(memRow);
|
pBlock->dataLen += memRowTLen(memRow);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SMemRowBuilder rowBuilder;
|
|
||||||
rowBuilder.pSchema = pSchema;
|
|
||||||
rowBuilder.sversion = pTableMeta->sversion;
|
|
||||||
rowBuilder.flen = flen;
|
|
||||||
rowBuilder.nCols = tinfo.numOfColumns;
|
|
||||||
rowBuilder.pDataBlock = pDataBlock;
|
|
||||||
rowBuilder.pSubmitBlk = pBlock;
|
|
||||||
rowBuilder.buf = p;
|
|
||||||
|
|
||||||
for (int32_t i = 0; i < numOfRows; ++i) {
|
for (int32_t i = 0; i < numOfRows; ++i) {
|
||||||
rowBuilder.buf = (blkKeyTuple + i)->payloadAddr;
|
char* payload = (blkKeyTuple + i)->payloadAddr;
|
||||||
tdGenMemRowFromBuilder(&rowBuilder);
|
if (isNeedConvertRow(payload)) {
|
||||||
|
convertSMemRow(pDataBlock, payload, pTableDataBlock);
|
||||||
|
TDRowTLenT rowTLen = memRowTLen(pDataBlock);
|
||||||
|
pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen);
|
||||||
|
pBlock->dataLen += rowTLen;
|
||||||
|
} else {
|
||||||
|
TDRowTLenT rowTLen = memRowTLen(payload);
|
||||||
|
memcpy(pDataBlock, payload, rowTLen);
|
||||||
|
pDataBlock = POINTER_SHIFT(pDataBlock, rowTLen);
|
||||||
|
pBlock->dataLen += rowTLen;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1958,7 +1886,7 @@ static int32_t getRowExpandSize(STableMeta* pTableMeta) {
|
||||||
int32_t result = TD_MEM_ROW_DATA_HEAD_SIZE;
|
int32_t result = TD_MEM_ROW_DATA_HEAD_SIZE;
|
||||||
int32_t columns = tscGetNumOfColumns(pTableMeta);
|
int32_t columns = tscGetNumOfColumns(pTableMeta);
|
||||||
SSchema* pSchema = tscGetTableSchema(pTableMeta);
|
SSchema* pSchema = tscGetTableSchema(pTableMeta);
|
||||||
for(int32_t i = 0; i < columns; i++) {
|
for (int32_t i = 0; i < columns; i++) {
|
||||||
if (IS_VAR_DATA_TYPE((pSchema + i)->type)) {
|
if (IS_VAR_DATA_TYPE((pSchema + i)->type)) {
|
||||||
result += TYPE_BYTES[TSDB_DATA_TYPE_BINARY];
|
result += TYPE_BYTES[TSDB_DATA_TYPE_BINARY];
|
||||||
}
|
}
|
||||||
|
@ -2004,7 +1932,7 @@ int32_t tscMergeTableDataBlocks(SInsertStatementParam *pInsertParam, bool freeBl
|
||||||
SSubmitBlk* pBlocks = (SSubmitBlk*) pOneTableBlock->pData;
|
SSubmitBlk* pBlocks = (SSubmitBlk*) pOneTableBlock->pData;
|
||||||
if (pBlocks->numOfRows > 0) {
|
if (pBlocks->numOfRows > 0) {
|
||||||
// the maximum expanded size in byte when a row-wise data is converted to SDataRow format
|
// the maximum expanded size in byte when a row-wise data is converted to SDataRow format
|
||||||
int32_t expandSize = getRowExpandSize(pOneTableBlock->pTableMeta);
|
int32_t expandSize = isRawPayload ? getRowExpandSize(pOneTableBlock->pTableMeta) : 0;
|
||||||
STableDataBlocks* dataBuf = NULL;
|
STableDataBlocks* dataBuf = NULL;
|
||||||
|
|
||||||
int32_t ret = tscGetDataBlockFromList(pVnodeDataBlockHashList, pOneTableBlock->vgId, TSDB_PAYLOAD_SIZE,
|
int32_t ret = tscGetDataBlockFromList(pVnodeDataBlockHashList, pOneTableBlock->vgId, TSDB_PAYLOAD_SIZE,
|
||||||
|
@ -2017,7 +1945,8 @@ int32_t tscMergeTableDataBlocks(SInsertStatementParam *pInsertParam, bool freeBl
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t destSize = dataBuf->size + pOneTableBlock->size + pBlocks->numOfRows * expandSize + sizeof(STColumn) * tscGetNumOfColumns(pOneTableBlock->pTableMeta);
|
int64_t destSize = dataBuf->size + pOneTableBlock->size + pBlocks->numOfRows * expandSize +
|
||||||
|
sizeof(STColumn) * tscGetNumOfColumns(pOneTableBlock->pTableMeta);
|
||||||
|
|
||||||
if (dataBuf->nAllocSize < destSize) {
|
if (dataBuf->nAllocSize < destSize) {
|
||||||
dataBuf->nAllocSize = (uint32_t)(destSize * 1.5);
|
dataBuf->nAllocSize = (uint32_t)(destSize * 1.5);
|
||||||
|
@ -2061,7 +1990,9 @@ int32_t tscMergeTableDataBlocks(SInsertStatementParam *pInsertParam, bool freeBl
|
||||||
pBlocks->numOfRows, pBlocks->sversion, blkKeyInfo.pKeyTuple->skey, pLastKeyTuple->skey);
|
pBlocks->numOfRows, pBlocks->sversion, blkKeyInfo.pKeyTuple->skey, pLastKeyTuple->skey);
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t len = pBlocks->numOfRows * (pOneTableBlock->rowSize + expandSize) + sizeof(STColumn) * tscGetNumOfColumns(pOneTableBlock->pTableMeta);
|
int32_t len = pBlocks->numOfRows *
|
||||||
|
(isRawPayload ? (pOneTableBlock->rowSize + expandSize) : getExtendedRowSize(pOneTableBlock)) +
|
||||||
|
sizeof(STColumn) * tscGetNumOfColumns(pOneTableBlock->pTableMeta);
|
||||||
|
|
||||||
pBlocks->tid = htonl(pBlocks->tid);
|
pBlocks->tid = htonl(pBlocks->tid);
|
||||||
pBlocks->uid = htobe64(pBlocks->uid);
|
pBlocks->uid = htobe64(pBlocks->uid);
|
||||||
|
@ -3622,8 +3553,10 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, __async_cb_func_t
|
||||||
pNewQueryInfo->numOfTables = 0;
|
pNewQueryInfo->numOfTables = 0;
|
||||||
pNewQueryInfo->pTableMetaInfo = NULL;
|
pNewQueryInfo->pTableMetaInfo = NULL;
|
||||||
pNewQueryInfo->bufLen = pQueryInfo->bufLen;
|
pNewQueryInfo->bufLen = pQueryInfo->bufLen;
|
||||||
|
|
||||||
pNewQueryInfo->buf = malloc(pQueryInfo->bufLen);
|
pNewQueryInfo->buf = malloc(pQueryInfo->bufLen);
|
||||||
|
|
||||||
|
|
||||||
|
pNewQueryInfo->distinct = pQueryInfo->distinct;
|
||||||
if (pNewQueryInfo->buf == NULL) {
|
if (pNewQueryInfo->buf == NULL) {
|
||||||
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
goto _error;
|
goto _error;
|
||||||
|
@ -3834,8 +3767,7 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) {
|
||||||
int32_t index = ps->subqueryIndex;
|
int32_t index = ps->subqueryIndex;
|
||||||
bool ret = subAndCheckDone(pSql, pParentSql, index);
|
bool ret = subAndCheckDone(pSql, pParentSql, index);
|
||||||
|
|
||||||
tfree(ps);
|
tscFreeRetrieveSup(pSql);
|
||||||
pSql->param = NULL;
|
|
||||||
|
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
tscDebug("0x%"PRIx64" sub:0x%"PRIx64" orderOfSub:%d completed, not all subquery finished", pParentSql->self, pSql->self, index);
|
tscDebug("0x%"PRIx64" sub:0x%"PRIx64" orderOfSub:%d completed, not all subquery finished", pParentSql->self, pSql->self, index);
|
||||||
|
@ -3845,12 +3777,13 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) {
|
||||||
// todo refactor
|
// todo refactor
|
||||||
tscDebug("0x%"PRIx64" all subquery response received, retry", pParentSql->self);
|
tscDebug("0x%"PRIx64" all subquery response received, retry", pParentSql->self);
|
||||||
|
|
||||||
SSqlCmd* pParentCmd = &pParentSql->cmd;
|
if (code && !((code == TSDB_CODE_TDB_INVALID_TABLE_ID || code == TSDB_CODE_VND_INVALID_VGROUP_ID) && pParentSql->retry < pParentSql->maxRetry)) {
|
||||||
STableMetaInfo* pTableMetaInfo = tscGetTableMetaInfoFromCmd(pParentCmd, 0);
|
tscAsyncResultOnError(pParentSql);
|
||||||
tscRemoveTableMetaBuf(pTableMetaInfo, pParentSql->self);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
pParentCmd->pTableMetaMap = tscCleanupTableMetaMap(pParentCmd->pTableMetaMap);
|
tscFreeSubobj(pParentSql);
|
||||||
pParentCmd->pTableMetaMap = taosHashInit(4, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
tfree(pParentSql->pSubs);
|
||||||
|
|
||||||
pParentSql->res.code = TSDB_CODE_SUCCESS;
|
pParentSql->res.code = TSDB_CODE_SUCCESS;
|
||||||
pParentSql->retry++;
|
pParentSql->retry++;
|
||||||
|
@ -3858,6 +3791,9 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) {
|
||||||
tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self,
|
tscDebug("0x%"PRIx64" retry parse sql and send query, prev error: %s, retry:%d", pParentSql->self,
|
||||||
tstrerror(code), pParentSql->retry);
|
tstrerror(code), pParentSql->retry);
|
||||||
|
|
||||||
|
|
||||||
|
tscResetSqlCmd(&pParentSql->cmd, true);
|
||||||
|
|
||||||
code = tsParseSql(pParentSql, true);
|
code = tsParseSql(pParentSql, true);
|
||||||
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
if (code == TSDB_CODE_TSC_ACTION_IN_PROGRESS) {
|
||||||
return;
|
return;
|
||||||
|
@ -3869,7 +3805,8 @@ static void tscSubqueryCompleteCallback(void* param, TAOS_RES* tres, int code) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SQueryInfo *pQueryInfo = tscGetQueryInfo(pParentCmd);
|
SQueryInfo *pQueryInfo = tscGetQueryInfo(&pParentSql->cmd);
|
||||||
|
|
||||||
executeQuery(pParentSql, pQueryInfo);
|
executeQuery(pParentSql, pQueryInfo);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -3892,9 +3829,11 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (taosArrayGetSize(pQueryInfo->pUpstream) > 0) { // nest query. do execute it firstly
|
if (taosArrayGetSize(pQueryInfo->pUpstream) > 0) { // nest query. do execute it firstly
|
||||||
|
assert(pSql->subState.numOfSub == 0);
|
||||||
pSql->subState.numOfSub = (int32_t) taosArrayGetSize(pQueryInfo->pUpstream);
|
pSql->subState.numOfSub = (int32_t) taosArrayGetSize(pQueryInfo->pUpstream);
|
||||||
|
assert(pSql->pSubs == NULL);
|
||||||
pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES);
|
pSql->pSubs = calloc(pSql->subState.numOfSub, POINTER_BYTES);
|
||||||
|
assert(pSql->subState.states == NULL);
|
||||||
pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t));
|
pSql->subState.states = calloc(pSql->subState.numOfSub, sizeof(int8_t));
|
||||||
code = pthread_mutex_init(&pSql->subState.mutex, NULL);
|
code = pthread_mutex_init(&pSql->subState.mutex, NULL);
|
||||||
|
|
||||||
|
@ -3920,6 +3859,9 @@ void executeQuery(SSqlObj* pSql, SQueryInfo* pQueryInfo) {
|
||||||
pNew->sqlstr = strdup(pSql->sqlstr);
|
pNew->sqlstr = strdup(pSql->sqlstr);
|
||||||
pNew->fp = tscSubqueryCompleteCallback;
|
pNew->fp = tscSubqueryCompleteCallback;
|
||||||
pNew->maxRetry = pSql->maxRetry;
|
pNew->maxRetry = pSql->maxRetry;
|
||||||
|
|
||||||
|
pNew->cmd.resColumnId = TSDB_RES_COL_ID;
|
||||||
|
|
||||||
tsem_init(&pNew->rspSem, 0, 0);
|
tsem_init(&pNew->rspSem, 0, 0);
|
||||||
|
|
||||||
SRetrieveSupport* ps = calloc(1, sizeof(SRetrieveSupport)); // todo use object id
|
SRetrieveSupport* ps = calloc(1, sizeof(SRetrieveSupport)); // todo use object id
|
||||||
|
@ -4454,6 +4396,7 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta** ppChild, const char* name,
|
||||||
STableMeta* p = NULL;
|
STableMeta* p = NULL;
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
STableMeta* pChild = *ppChild;
|
STableMeta* pChild = *ppChild;
|
||||||
|
STableMeta* pChild1;
|
||||||
|
|
||||||
taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz);
|
taosHashGetCloneExt(tscTableMetaMap, pChild->sTableName, strnlen(pChild->sTableName, TSDB_TABLE_FNAME_LEN), NULL, (void **)&p, &sz);
|
||||||
|
|
||||||
|
@ -4464,7 +4407,10 @@ int32_t tscCreateTableMetaFromSTableMeta(STableMeta** ppChild, const char* name,
|
||||||
int32_t totalBytes = (p->tableInfo.numOfColumns + p->tableInfo.numOfTags) * sizeof(SSchema);
|
int32_t totalBytes = (p->tableInfo.numOfColumns + p->tableInfo.numOfTags) * sizeof(SSchema);
|
||||||
int32_t tableMetaSize = sizeof(STableMeta) + totalBytes;
|
int32_t tableMetaSize = sizeof(STableMeta) + totalBytes;
|
||||||
if (*tableMetaCapacity < tableMetaSize) {
|
if (*tableMetaCapacity < tableMetaSize) {
|
||||||
pChild = realloc(pChild, tableMetaSize);
|
pChild1 = realloc(pChild, tableMetaSize);
|
||||||
|
if(pChild1 == NULL)
|
||||||
|
return -1;
|
||||||
|
pChild = pChild1;
|
||||||
*tableMetaCapacity = (size_t)tableMetaSize;
|
*tableMetaCapacity = (size_t)tableMetaSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,7 @@ typedef void *SDataRow;
|
||||||
#define TD_DATA_ROW_HEAD_SIZE (sizeof(uint16_t) + sizeof(int16_t))
|
#define TD_DATA_ROW_HEAD_SIZE (sizeof(uint16_t) + sizeof(int16_t))
|
||||||
|
|
||||||
#define dataRowLen(r) (*(TDRowLenT *)(r)) // 0~65535
|
#define dataRowLen(r) (*(TDRowLenT *)(r)) // 0~65535
|
||||||
|
#define dataRowEnd(r) POINTER_SHIFT(r, dataRowLen(r))
|
||||||
#define dataRowVersion(r) (*(int16_t *)POINTER_SHIFT(r, sizeof(int16_t)))
|
#define dataRowVersion(r) (*(int16_t *)POINTER_SHIFT(r, sizeof(int16_t)))
|
||||||
#define dataRowTuple(r) POINTER_SHIFT(r, TD_DATA_ROW_HEAD_SIZE)
|
#define dataRowTuple(r) POINTER_SHIFT(r, TD_DATA_ROW_HEAD_SIZE)
|
||||||
#define dataRowTKey(r) (*(TKEY *)(dataRowTuple(r)))
|
#define dataRowTKey(r) (*(TKEY *)(dataRowTuple(r)))
|
||||||
|
@ -201,14 +202,18 @@ void tdFreeDataRow(SDataRow row);
|
||||||
void tdInitDataRow(SDataRow row, STSchema *pSchema);
|
void tdInitDataRow(SDataRow row, STSchema *pSchema);
|
||||||
SDataRow tdDataRowDup(SDataRow row);
|
SDataRow tdDataRowDup(SDataRow row);
|
||||||
|
|
||||||
|
|
||||||
// offset here not include dataRow header length
|
// offset here not include dataRow header length
|
||||||
static FORCE_INLINE int tdAppendColVal(SDataRow row, const void *value, int8_t type, int32_t offset) {
|
static FORCE_INLINE int tdAppendDataColVal(SDataRow row, const void *value, bool isCopyVarData, int8_t type,
|
||||||
|
int32_t offset) {
|
||||||
ASSERT(value != NULL);
|
ASSERT(value != NULL);
|
||||||
int32_t toffset = offset + TD_DATA_ROW_HEAD_SIZE;
|
int32_t toffset = offset + TD_DATA_ROW_HEAD_SIZE;
|
||||||
|
|
||||||
if (IS_VAR_DATA_TYPE(type)) {
|
if (IS_VAR_DATA_TYPE(type)) {
|
||||||
*(VarDataOffsetT *)POINTER_SHIFT(row, toffset) = dataRowLen(row);
|
*(VarDataOffsetT *)POINTER_SHIFT(row, toffset) = dataRowLen(row);
|
||||||
|
if (isCopyVarData) {
|
||||||
memcpy(POINTER_SHIFT(row, dataRowLen(row)), value, varDataTLen(value));
|
memcpy(POINTER_SHIFT(row, dataRowLen(row)), value, varDataTLen(value));
|
||||||
|
}
|
||||||
dataRowLen(row) += varDataTLen(value);
|
dataRowLen(row) += varDataTLen(value);
|
||||||
} else {
|
} else {
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
|
@ -223,6 +228,12 @@ static FORCE_INLINE int tdAppendColVal(SDataRow row, const void *value, int8_t t
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// offset here not include dataRow header length
|
||||||
|
static FORCE_INLINE int tdAppendColVal(SDataRow row, const void *value, int8_t type, int32_t offset) {
|
||||||
|
return tdAppendDataColVal(row, value, true, type, offset);
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE: offset here including the header size
|
// NOTE: offset here including the header size
|
||||||
static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t offset) {
|
static FORCE_INLINE void *tdGetRowDataOfCol(SDataRow row, int8_t type, int32_t offset) {
|
||||||
if (IS_VAR_DATA_TYPE(type)) {
|
if (IS_VAR_DATA_TYPE(type)) {
|
||||||
|
@ -328,11 +339,10 @@ static FORCE_INLINE void dataColReset(SDataCol *pDataCol) { pDataCol->len = 0; }
|
||||||
int tdAllocMemForCol(SDataCol *pCol, int maxPoints);
|
int tdAllocMemForCol(SDataCol *pCol, int maxPoints);
|
||||||
|
|
||||||
void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints);
|
void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints);
|
||||||
void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints);
|
int dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints);
|
||||||
void dataColSetOffset(SDataCol *pCol, int nEle);
|
void dataColSetOffset(SDataCol *pCol, int nEle);
|
||||||
|
|
||||||
bool isNEleNull(SDataCol *pCol, int nEle);
|
bool isNEleNull(SDataCol *pCol, int nEle);
|
||||||
void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints);
|
|
||||||
|
|
||||||
// Get the data pointer from a column-wised data
|
// Get the data pointer from a column-wised data
|
||||||
static FORCE_INLINE const void *tdGetColDataOfRow(SDataCol *pCol, int row) {
|
static FORCE_INLINE const void *tdGetColDataOfRow(SDataCol *pCol, int row) {
|
||||||
|
@ -357,10 +367,8 @@ static FORCE_INLINE int32_t dataColGetNEleLen(SDataCol *pDataCol, int rows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int maxRowSize;
|
|
||||||
int maxCols; // max number of columns
|
int maxCols; // max number of columns
|
||||||
int maxPoints; // max number of points
|
int maxPoints; // max number of points
|
||||||
|
|
||||||
int numOfRows;
|
int numOfRows;
|
||||||
int numOfCols; // Total number of cols
|
int numOfCols; // Total number of cols
|
||||||
int sversion; // TODO: set sversion
|
int sversion; // TODO: set sversion
|
||||||
|
@ -407,7 +415,7 @@ static FORCE_INLINE TSKEY dataColsKeyLast(SDataCols *pCols) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows);
|
SDataCols *tdNewDataCols(int maxCols, int maxRows);
|
||||||
void tdResetDataCols(SDataCols *pCols);
|
void tdResetDataCols(SDataCols *pCols);
|
||||||
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
|
int tdInitDataCols(SDataCols *pCols, STSchema *pSchema);
|
||||||
SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
|
SDataCols *tdDupDataCols(SDataCols *pCols, bool keepData);
|
||||||
|
@ -475,9 +483,10 @@ static FORCE_INLINE void *tdGetKVRowIdxOfCol(SKVRow row, int16_t colId) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// offset here not include kvRow header length
|
// offset here not include kvRow header length
|
||||||
static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t colId, int8_t type, int32_t *offset) {
|
static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, bool isCopyValData, int16_t colId, int8_t type,
|
||||||
|
int32_t offset) {
|
||||||
ASSERT(value != NULL);
|
ASSERT(value != NULL);
|
||||||
int32_t toffset = *offset + TD_KV_ROW_HEAD_SIZE;
|
int32_t toffset = offset + TD_KV_ROW_HEAD_SIZE;
|
||||||
SColIdx *pColIdx = (SColIdx *)POINTER_SHIFT(row, toffset);
|
SColIdx *pColIdx = (SColIdx *)POINTER_SHIFT(row, toffset);
|
||||||
char * ptr = (char *)POINTER_SHIFT(row, kvRowLen(row));
|
char * ptr = (char *)POINTER_SHIFT(row, kvRowLen(row));
|
||||||
|
|
||||||
|
@ -485,10 +494,12 @@ static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t
|
||||||
pColIdx->offset = kvRowLen(row); // offset of pColIdx including the TD_KV_ROW_HEAD_SIZE
|
pColIdx->offset = kvRowLen(row); // offset of pColIdx including the TD_KV_ROW_HEAD_SIZE
|
||||||
|
|
||||||
if (IS_VAR_DATA_TYPE(type)) {
|
if (IS_VAR_DATA_TYPE(type)) {
|
||||||
|
if (isCopyValData) {
|
||||||
memcpy(ptr, value, varDataTLen(value));
|
memcpy(ptr, value, varDataTLen(value));
|
||||||
|
}
|
||||||
kvRowLen(row) += varDataTLen(value);
|
kvRowLen(row) += varDataTLen(value);
|
||||||
} else {
|
} else {
|
||||||
if (*offset == 0) {
|
if (offset == 0) {
|
||||||
ASSERT(type == TSDB_DATA_TYPE_TIMESTAMP);
|
ASSERT(type == TSDB_DATA_TYPE_TIMESTAMP);
|
||||||
TKEY tvalue = tdGetTKEY(*(TSKEY *)value);
|
TKEY tvalue = tdGetTKEY(*(TSKEY *)value);
|
||||||
memcpy(ptr, (void *)(&tvalue), TYPE_BYTES[type]);
|
memcpy(ptr, (void *)(&tvalue), TYPE_BYTES[type]);
|
||||||
|
@ -497,7 +508,6 @@ static FORCE_INLINE int tdAppendKvColVal(SKVRow row, const void *value, int16_t
|
||||||
}
|
}
|
||||||
kvRowLen(row) += TYPE_BYTES[type];
|
kvRowLen(row) += TYPE_BYTES[type];
|
||||||
}
|
}
|
||||||
*offset += sizeof(SColIdx);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -537,8 +547,9 @@ SKVRow tdGetKVRowFromBuilder(SKVRowBuilder *pBuilder);
|
||||||
static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId, int8_t type, void *value) {
|
static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId, int8_t type, void *value) {
|
||||||
if (pBuilder->nCols >= pBuilder->tCols) {
|
if (pBuilder->nCols >= pBuilder->tCols) {
|
||||||
pBuilder->tCols *= 2;
|
pBuilder->tCols *= 2;
|
||||||
pBuilder->pColIdx = (SColIdx *)realloc((void *)(pBuilder->pColIdx), sizeof(SColIdx) * pBuilder->tCols);
|
SColIdx* pColIdx = (SColIdx *)realloc((void *)(pBuilder->pColIdx), sizeof(SColIdx) * pBuilder->tCols);
|
||||||
if (pBuilder->pColIdx == NULL) return -1;
|
if (pColIdx == NULL) return -1;
|
||||||
|
pBuilder->pColIdx = pColIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
pBuilder->pColIdx[pBuilder->nCols].colId = colId;
|
pBuilder->pColIdx[pBuilder->nCols].colId = colId;
|
||||||
|
@ -551,8 +562,9 @@ static FORCE_INLINE int tdAddColToKVRow(SKVRowBuilder *pBuilder, int16_t colId,
|
||||||
while (tlen > pBuilder->alloc - pBuilder->size) {
|
while (tlen > pBuilder->alloc - pBuilder->size) {
|
||||||
pBuilder->alloc *= 2;
|
pBuilder->alloc *= 2;
|
||||||
}
|
}
|
||||||
pBuilder->buf = realloc(pBuilder->buf, pBuilder->alloc);
|
void* buf = realloc(pBuilder->buf, pBuilder->alloc);
|
||||||
if (pBuilder->buf == NULL) return -1;
|
if (buf == NULL) return -1;
|
||||||
|
pBuilder->buf = buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(POINTER_SHIFT(pBuilder->buf, pBuilder->size), value, tlen);
|
memcpy(POINTER_SHIFT(pBuilder->buf, pBuilder->size), value, tlen);
|
||||||
|
@ -592,12 +604,24 @@ typedef void *SMemRow;
|
||||||
#define TD_MEM_ROW_DATA_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_DATA_ROW_HEAD_SIZE)
|
#define TD_MEM_ROW_DATA_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_DATA_ROW_HEAD_SIZE)
|
||||||
#define TD_MEM_ROW_KV_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_MEM_ROW_KV_VER_SIZE + TD_KV_ROW_HEAD_SIZE)
|
#define TD_MEM_ROW_KV_HEAD_SIZE (TD_MEM_ROW_TYPE_SIZE + TD_MEM_ROW_KV_VER_SIZE + TD_KV_ROW_HEAD_SIZE)
|
||||||
|
|
||||||
#define SMEM_ROW_DATA 0U // SDataRow
|
#define SMEM_ROW_DATA 0x0U // SDataRow
|
||||||
#define SMEM_ROW_KV 1U // SKVRow
|
#define SMEM_ROW_KV 0x01U // SKVRow
|
||||||
|
#define SMEM_ROW_CONVERT 0x80U // SMemRow convert flag
|
||||||
|
|
||||||
#define memRowType(r) (*(uint8_t *)(r))
|
#define KVRatioKV (0.2f) // all bool
|
||||||
|
#define KVRatioPredict (0.4f)
|
||||||
|
#define KVRatioData (0.75f) // all bigint
|
||||||
|
#define KVRatioConvert (0.9f)
|
||||||
|
|
||||||
|
#define memRowType(r) ((*(uint8_t *)(r)) & 0x01)
|
||||||
|
|
||||||
|
#define memRowSetType(r, t) ((*(uint8_t *)(r)) = (t)) // set the total byte in case of dirty memory
|
||||||
|
#define memRowSetConvert(r) ((*(uint8_t *)(r)) = (((*(uint8_t *)(r)) & 0x7F) | SMEM_ROW_CONVERT)) // highest bit
|
||||||
|
#define isDataRowT(t) (SMEM_ROW_DATA == (((uint8_t)(t)) & 0x01))
|
||||||
#define isDataRow(r) (SMEM_ROW_DATA == memRowType(r))
|
#define isDataRow(r) (SMEM_ROW_DATA == memRowType(r))
|
||||||
|
#define isKvRowT(t) (SMEM_ROW_KV == (((uint8_t)(t)) & 0x01))
|
||||||
#define isKvRow(r) (SMEM_ROW_KV == memRowType(r))
|
#define isKvRow(r) (SMEM_ROW_KV == memRowType(r))
|
||||||
|
#define isNeedConvertRow(r) (((*(uint8_t *)(r)) & 0x80) == SMEM_ROW_CONVERT)
|
||||||
|
|
||||||
#define memRowDataBody(r) POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE) // section after flag
|
#define memRowDataBody(r) POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE) // section after flag
|
||||||
#define memRowKvBody(r) \
|
#define memRowKvBody(r) \
|
||||||
|
@ -614,6 +638,14 @@ typedef void *SMemRow;
|
||||||
#define memRowLen(r) (isDataRow(r) ? memRowDataLen(r) : memRowKvLen(r))
|
#define memRowLen(r) (isDataRow(r) ? memRowDataLen(r) : memRowKvLen(r))
|
||||||
#define memRowTLen(r) (isDataRow(r) ? memRowDataTLen(r) : memRowKvTLen(r)) // using uint32_t/int32_t to store the TLen
|
#define memRowTLen(r) (isDataRow(r) ? memRowDataTLen(r) : memRowKvTLen(r)) // using uint32_t/int32_t to store the TLen
|
||||||
|
|
||||||
|
static FORCE_INLINE char *memRowEnd(SMemRow row) {
|
||||||
|
if (isDataRow(row)) {
|
||||||
|
return (char *)dataRowEnd(memRowDataBody(row));
|
||||||
|
} else {
|
||||||
|
return (char *)kvRowEnd(memRowKvBody(row));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#define memRowDataVersion(r) dataRowVersion(memRowDataBody(r))
|
#define memRowDataVersion(r) dataRowVersion(memRowDataBody(r))
|
||||||
#define memRowKvVersion(r) (*(int16_t *)POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE))
|
#define memRowKvVersion(r) (*(int16_t *)POINTER_SHIFT(r, TD_MEM_ROW_TYPE_SIZE))
|
||||||
#define memRowVersion(r) (isDataRow(r) ? memRowDataVersion(r) : memRowKvVersion(r)) // schema version
|
#define memRowVersion(r) (isDataRow(r) ? memRowDataVersion(r) : memRowKvVersion(r)) // schema version
|
||||||
|
@ -631,7 +663,6 @@ typedef void *SMemRow;
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define memRowSetType(r, t) (memRowType(r) = (t))
|
|
||||||
#define memRowSetLen(r, l) (isDataRow(r) ? memRowDataLen(r) = (l) : memRowKvLen(r) = (l))
|
#define memRowSetLen(r, l) (isDataRow(r) ? memRowDataLen(r) = (l) : memRowKvLen(r) = (l))
|
||||||
#define memRowSetVersion(r, v) (isDataRow(r) ? dataRowSetVersion(memRowDataBody(r), v) : memRowSetKvVersion(r, v))
|
#define memRowSetVersion(r, v) (isDataRow(r) ? dataRowSetVersion(memRowDataBody(r), v) : memRowSetKvVersion(r, v))
|
||||||
#define memRowCpy(dst, r) memcpy((dst), (r), memRowTLen(r))
|
#define memRowCpy(dst, r) memcpy((dst), (r), memRowTLen(r))
|
||||||
|
@ -664,12 +695,12 @@ static FORCE_INLINE void *tdGetMemRowDataOfColEx(void *row, int16_t colId, int8_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static FORCE_INLINE int tdAppendMemColVal(SMemRow row, const void *value, int16_t colId, int8_t type, int32_t offset,
|
static FORCE_INLINE int tdAppendMemRowColVal(SMemRow row, const void *value, bool isCopyVarData, int16_t colId,
|
||||||
int32_t *kvOffset) {
|
int8_t type, int32_t offset) {
|
||||||
if (isDataRow(row)) {
|
if (isDataRow(row)) {
|
||||||
tdAppendColVal(memRowDataBody(row), value, type, offset);
|
tdAppendDataColVal(memRowDataBody(row), value, isCopyVarData, type, offset);
|
||||||
} else {
|
} else {
|
||||||
tdAppendKvColVal(memRowKvBody(row), value, colId, type, kvOffset);
|
tdAppendKvColVal(memRowKvBody(row), value, isCopyVarData, colId, type, offset);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -691,6 +722,30 @@ static FORCE_INLINE int32_t tdGetColAppendLen(uint8_t rowType, const void *value
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. calculate the delta of AllNullLen for SDataRow.
|
||||||
|
* 2. calculate the real len for SKVRow.
|
||||||
|
*/
|
||||||
|
static FORCE_INLINE void tdGetColAppendDeltaLen(const void *value, int8_t colType, int32_t *dataLen, int32_t *kvLen) {
|
||||||
|
switch (colType) {
|
||||||
|
case TSDB_DATA_TYPE_BINARY: {
|
||||||
|
int32_t varLen = varDataLen(value);
|
||||||
|
*dataLen += (varLen - CHAR_BYTES);
|
||||||
|
*kvLen += (varLen + sizeof(SColIdx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_DATA_TYPE_NCHAR: {
|
||||||
|
int32_t varLen = varDataLen(value);
|
||||||
|
*dataLen += (varLen - TSDB_NCHAR_SIZE);
|
||||||
|
*kvLen += (varLen + sizeof(SColIdx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
*kvLen += (TYPE_BYTES[colType] + sizeof(SColIdx));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int16_t colId;
|
int16_t colId;
|
||||||
|
@ -706,7 +761,7 @@ static FORCE_INLINE void setSColInfo(SColInfo* colInfo, int16_t colId, uint8_t c
|
||||||
|
|
||||||
SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2);
|
SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSchema1, STSchema *pSchema2);
|
||||||
|
|
||||||
|
#if 0
|
||||||
// ----------------- Raw payload structure for row:
|
// ----------------- Raw payload structure for row:
|
||||||
/* |<------------ Head ------------->|<----------- body of column data tuple ------------------->|
|
/* |<------------ Head ------------->|<----------- body of column data tuple ------------------->|
|
||||||
* | |<----------------- flen ------------->|<--- value part --->|
|
* | |<----------------- flen ------------->|<--- value part --->|
|
||||||
|
@ -752,6 +807,8 @@ SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSch
|
||||||
|
|
||||||
static FORCE_INLINE char *payloadNextCol(char *pCol) { return (char *)POINTER_SHIFT(pCol, PAYLOAD_COL_HEAD_LEN); }
|
static FORCE_INLINE char *payloadNextCol(char *pCol) { return (char *)POINTER_SHIFT(pCol, PAYLOAD_COL_HEAD_LEN); }
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -59,6 +59,7 @@ extern char tsLocale[];
|
||||||
extern char tsCharset[]; // default encode string
|
extern char tsCharset[]; // default encode string
|
||||||
extern int8_t tsEnableCoreFile;
|
extern int8_t tsEnableCoreFile;
|
||||||
extern int32_t tsCompressMsgSize;
|
extern int32_t tsCompressMsgSize;
|
||||||
|
extern int32_t tsMaxNumOfDistinctResults;
|
||||||
extern char tsTempDir[];
|
extern char tsTempDir[];
|
||||||
|
|
||||||
//query buffer management
|
//query buffer management
|
||||||
|
@ -70,6 +71,7 @@ extern int8_t tsKeepOriginalColumnName;
|
||||||
|
|
||||||
// client
|
// client
|
||||||
extern int32_t tsMaxSQLStringLen;
|
extern int32_t tsMaxSQLStringLen;
|
||||||
|
extern int32_t tsMaxWildCardsLen;
|
||||||
extern int8_t tsTscEnableRecordSql;
|
extern int8_t tsTscEnableRecordSql;
|
||||||
extern int32_t tsMaxNumOfOrderedResults;
|
extern int32_t tsMaxNumOfOrderedResults;
|
||||||
extern int32_t tsMinSlidingTime;
|
extern int32_t tsMinSlidingTime;
|
||||||
|
|
|
@ -19,10 +19,10 @@
|
||||||
#include "wchar.h"
|
#include "wchar.h"
|
||||||
#include "tarray.h"
|
#include "tarray.h"
|
||||||
|
|
||||||
|
static void dataColSetNEleNull(SDataCol *pCol, int nEle);
|
||||||
static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
|
static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, int limit1, SDataCols *src2, int *iter2,
|
||||||
int limit2, int tRows, bool forceSetNull);
|
int limit2, int tRows, bool forceSetNull);
|
||||||
|
|
||||||
//TODO: change caller to use return val
|
|
||||||
int tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
|
int tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
|
||||||
int spaceNeeded = pCol->bytes * maxPoints;
|
int spaceNeeded = pCol->bytes * maxPoints;
|
||||||
if(IS_VAR_DATA_TYPE(pCol->type)) {
|
if(IS_VAR_DATA_TYPE(pCol->type)) {
|
||||||
|
@ -31,7 +31,7 @@ int tdAllocMemForCol(SDataCol *pCol, int maxPoints) {
|
||||||
if(pCol->spaceSize < spaceNeeded) {
|
if(pCol->spaceSize < spaceNeeded) {
|
||||||
void* ptr = realloc(pCol->pData, spaceNeeded);
|
void* ptr = realloc(pCol->pData, spaceNeeded);
|
||||||
if(ptr == NULL) {
|
if(ptr == NULL) {
|
||||||
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)pCol->spaceSize,
|
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)spaceNeeded,
|
||||||
strerror(errno));
|
strerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
} else {
|
} else {
|
||||||
|
@ -138,8 +138,9 @@ int tdAddColToSchema(STSchemaBuilder *pBuilder, int8_t type, int16_t colId, int1
|
||||||
|
|
||||||
if (pBuilder->nCols >= pBuilder->tCols) {
|
if (pBuilder->nCols >= pBuilder->tCols) {
|
||||||
pBuilder->tCols *= 2;
|
pBuilder->tCols *= 2;
|
||||||
pBuilder->columns = (STColumn *)realloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols);
|
STColumn* columns = (STColumn *)realloc(pBuilder->columns, sizeof(STColumn) * pBuilder->tCols);
|
||||||
if (pBuilder->columns == NULL) return -1;
|
if (columns == NULL) return -1;
|
||||||
|
pBuilder->columns = columns;
|
||||||
}
|
}
|
||||||
|
|
||||||
STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]);
|
STColumn *pCol = &(pBuilder->columns[pBuilder->nCols]);
|
||||||
|
@ -239,20 +240,19 @@ void dataColInit(SDataCol *pDataCol, STColumn *pCol, int maxPoints) {
|
||||||
pDataCol->len = 0;
|
pDataCol->len = 0;
|
||||||
}
|
}
|
||||||
// value from timestamp should be TKEY here instead of TSKEY
|
// value from timestamp should be TKEY here instead of TSKEY
|
||||||
void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints) {
|
int dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxPoints) {
|
||||||
ASSERT(pCol != NULL && value != NULL);
|
ASSERT(pCol != NULL && value != NULL);
|
||||||
|
|
||||||
if (isAllRowsNull(pCol)) {
|
if (isAllRowsNull(pCol)) {
|
||||||
if (isNull(value, pCol->type)) {
|
if (isNull(value, pCol->type)) {
|
||||||
// all null value yet, just return
|
// all null value yet, just return
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(tdAllocMemForCol(pCol, maxPoints) < 0) return -1;
|
||||||
if (numOfRows > 0) {
|
if (numOfRows > 0) {
|
||||||
// Find the first not null value, fill all previouse values as NULL
|
// Find the first not null value, fill all previouse values as NULL
|
||||||
dataColSetNEleNull(pCol, numOfRows, maxPoints);
|
dataColSetNEleNull(pCol, numOfRows);
|
||||||
} else {
|
|
||||||
tdAllocMemForCol(pCol, maxPoints);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,12 +268,21 @@ void dataColAppendVal(SDataCol *pCol, const void *value, int numOfRows, int maxP
|
||||||
memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes);
|
memcpy(POINTER_SHIFT(pCol->pData, pCol->len), value, pCol->bytes);
|
||||||
pCol->len += pCol->bytes;
|
pCol->len += pCol->bytes;
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FORCE_INLINE const void *tdGetColDataOfRowUnsafe(SDataCol *pCol, int row) {
|
||||||
|
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
||||||
|
return POINTER_SHIFT(pCol->pData, pCol->dataOff[row]);
|
||||||
|
} else {
|
||||||
|
return POINTER_SHIFT(pCol->pData, TYPE_BYTES[pCol->type] * row);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isNEleNull(SDataCol *pCol, int nEle) {
|
bool isNEleNull(SDataCol *pCol, int nEle) {
|
||||||
if(isAllRowsNull(pCol)) return true;
|
if(isAllRowsNull(pCol)) return true;
|
||||||
for (int i = 0; i < nEle; i++) {
|
for (int i = 0; i < nEle; i++) {
|
||||||
if (!isNull(tdGetColDataOfRow(pCol, i), pCol->type)) return false;
|
if (!isNull(tdGetColDataOfRowUnsafe(pCol, i), pCol->type)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -290,9 +299,7 @@ static FORCE_INLINE void dataColSetNullAt(SDataCol *pCol, int index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dataColSetNEleNull(SDataCol *pCol, int nEle, int maxPoints) {
|
static void dataColSetNEleNull(SDataCol *pCol, int nEle) {
|
||||||
tdAllocMemForCol(pCol, maxPoints);
|
|
||||||
|
|
||||||
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
if (IS_VAR_DATA_TYPE(pCol->type)) {
|
||||||
pCol->len = 0;
|
pCol->len = 0;
|
||||||
for (int i = 0; i < nEle; i++) {
|
for (int i = 0; i < nEle; i++) {
|
||||||
|
@ -318,7 +325,7 @@ void dataColSetOffset(SDataCol *pCol, int nEle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) {
|
SDataCols *tdNewDataCols(int maxCols, int maxRows) {
|
||||||
SDataCols *pCols = (SDataCols *)calloc(1, sizeof(SDataCols));
|
SDataCols *pCols = (SDataCols *)calloc(1, sizeof(SDataCols));
|
||||||
if (pCols == NULL) {
|
if (pCols == NULL) {
|
||||||
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
|
uDebug("malloc failure, size:%" PRId64 " failed, reason:%s", (int64_t)sizeof(SDataCols), strerror(errno));
|
||||||
|
@ -326,6 +333,9 @@ SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pCols->maxPoints = maxRows;
|
pCols->maxPoints = maxRows;
|
||||||
|
pCols->maxCols = maxCols;
|
||||||
|
pCols->numOfRows = 0;
|
||||||
|
pCols->numOfCols = 0;
|
||||||
|
|
||||||
if (maxCols > 0) {
|
if (maxCols > 0) {
|
||||||
pCols->cols = (SDataCol *)calloc(maxCols, sizeof(SDataCol));
|
pCols->cols = (SDataCol *)calloc(maxCols, sizeof(SDataCol));
|
||||||
|
@ -342,13 +352,8 @@ SDataCols *tdNewDataCols(int maxRowSize, int maxCols, int maxRows) {
|
||||||
pCols->cols[i].pData = NULL;
|
pCols->cols[i].pData = NULL;
|
||||||
pCols->cols[i].dataOff = NULL;
|
pCols->cols[i].dataOff = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCols->maxCols = maxCols;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pCols->maxRowSize = maxRowSize;
|
|
||||||
|
|
||||||
|
|
||||||
return pCols;
|
return pCols;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,8 +362,9 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
|
||||||
int oldMaxCols = pCols->maxCols;
|
int oldMaxCols = pCols->maxCols;
|
||||||
if (schemaNCols(pSchema) > oldMaxCols) {
|
if (schemaNCols(pSchema) > oldMaxCols) {
|
||||||
pCols->maxCols = schemaNCols(pSchema);
|
pCols->maxCols = schemaNCols(pSchema);
|
||||||
pCols->cols = (SDataCol *)realloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols);
|
void* ptr = (SDataCol *)realloc(pCols->cols, sizeof(SDataCol) * pCols->maxCols);
|
||||||
if (pCols->cols == NULL) return -1;
|
if (ptr == NULL) return -1;
|
||||||
|
pCols->cols = ptr;
|
||||||
for(i = oldMaxCols; i < pCols->maxCols; i++) {
|
for(i = oldMaxCols; i < pCols->maxCols; i++) {
|
||||||
pCols->cols[i].pData = NULL;
|
pCols->cols[i].pData = NULL;
|
||||||
pCols->cols[i].dataOff = NULL;
|
pCols->cols[i].dataOff = NULL;
|
||||||
|
@ -366,10 +372,6 @@ int tdInitDataCols(SDataCols *pCols, STSchema *pSchema) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (schemaTLen(pSchema) > pCols->maxRowSize) {
|
|
||||||
pCols->maxRowSize = schemaTLen(pSchema);
|
|
||||||
}
|
|
||||||
|
|
||||||
tdResetDataCols(pCols);
|
tdResetDataCols(pCols);
|
||||||
pCols->numOfCols = schemaNCols(pSchema);
|
pCols->numOfCols = schemaNCols(pSchema);
|
||||||
|
|
||||||
|
@ -398,7 +400,7 @@ SDataCols *tdFreeDataCols(SDataCols *pCols) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
|
SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
|
||||||
SDataCols *pRet = tdNewDataCols(pDataCols->maxRowSize, pDataCols->maxCols, pDataCols->maxPoints);
|
SDataCols *pRet = tdNewDataCols(pDataCols->maxCols, pDataCols->maxPoints);
|
||||||
if (pRet == NULL) return NULL;
|
if (pRet == NULL) return NULL;
|
||||||
|
|
||||||
pRet->numOfCols = pDataCols->numOfCols;
|
pRet->numOfCols = pDataCols->numOfCols;
|
||||||
|
@ -413,7 +415,10 @@ SDataCols *tdDupDataCols(SDataCols *pDataCols, bool keepData) {
|
||||||
|
|
||||||
if (keepData) {
|
if (keepData) {
|
||||||
if (pDataCols->cols[i].len > 0) {
|
if (pDataCols->cols[i].len > 0) {
|
||||||
tdAllocMemForCol(&pRet->cols[i], pRet->maxPoints);
|
if(tdAllocMemForCol(&pRet->cols[i], pRet->maxPoints) < 0) {
|
||||||
|
tdFreeDataCols(pRet);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
pRet->cols[i].len = pDataCols->cols[i].len;
|
pRet->cols[i].len = pDataCols->cols[i].len;
|
||||||
memcpy(pRet->cols[i].pData, pDataCols->cols[i].pData, pDataCols->cols[i].len);
|
memcpy(pRet->cols[i].pData, pDataCols->cols[i].pData, pDataCols->cols[i].len);
|
||||||
if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) {
|
if (IS_VAR_DATA_TYPE(pRet->cols[i].type)) {
|
||||||
|
@ -584,9 +589,12 @@ static void tdMergeTwoDataCols(SDataCols *target, SDataCols *src1, int *iter1, i
|
||||||
if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) {
|
if ((key1 > key2) || (key1 == key2 && !TKEY_IS_DELETED(tkey2))) {
|
||||||
for (int i = 0; i < src2->numOfCols; i++) {
|
for (int i = 0; i < src2->numOfCols; i++) {
|
||||||
ASSERT(target->cols[i].type == src2->cols[i].type);
|
ASSERT(target->cols[i].type == src2->cols[i].type);
|
||||||
if (src2->cols[i].len > 0 && (forceSetNull || (!forceSetNull && !isNull(src2->cols[i].pData, src2->cols[i].type)))) {
|
if (src2->cols[i].len > 0 && !isNull(src2->cols[i].pData, src2->cols[i].type)) {
|
||||||
dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
|
dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src2->cols + i, *iter2), target->numOfRows,
|
||||||
target->maxPoints);
|
target->maxPoints);
|
||||||
|
} else if(!forceSetNull && key1 == key2 && src1->cols[i].len > 0) {
|
||||||
|
dataColAppendVal(&(target->cols[i]), tdGetColDataOfRow(src1->cols + i, *iter1), target->numOfRows,
|
||||||
|
target->maxPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
target->numOfRows++;
|
target->numOfRows++;
|
||||||
|
@ -844,7 +852,8 @@ SMemRow mergeTwoMemRows(void *buffer, SMemRow row1, SMemRow row2, STSchema *pSch
|
||||||
int16_t k;
|
int16_t k;
|
||||||
for (k = 0; k < nKvNCols; ++k) {
|
for (k = 0; k < nKvNCols; ++k) {
|
||||||
SColInfo *pColInfo = taosArrayGet(stashRow, k);
|
SColInfo *pColInfo = taosArrayGet(stashRow, k);
|
||||||
tdAppendKvColVal(kvRow, pColInfo->colVal, pColInfo->colId, pColInfo->colType, &toffset);
|
tdAppendKvColVal(kvRow, pColInfo->colVal, true, pColInfo->colId, pColInfo->colType, toffset);
|
||||||
|
toffset += sizeof(SColIdx);
|
||||||
}
|
}
|
||||||
ASSERT(kvLen == memRowTLen(tRow));
|
ASSERT(kvLen == memRowTLen(tRow));
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,10 @@
|
||||||
#include "tutil.h"
|
#include "tutil.h"
|
||||||
#include "tlocale.h"
|
#include "tlocale.h"
|
||||||
#include "ttimezone.h"
|
#include "ttimezone.h"
|
||||||
|
#include "tcompare.h"
|
||||||
|
|
||||||
|
// TSDB
|
||||||
|
bool tsdbForceKeepFile = false;
|
||||||
|
|
||||||
// cluster
|
// cluster
|
||||||
char tsFirst[TSDB_EP_LEN] = {0};
|
char tsFirst[TSDB_EP_LEN] = {0};
|
||||||
|
@ -75,6 +79,7 @@ int32_t tsCompressMsgSize = -1;
|
||||||
|
|
||||||
// client
|
// client
|
||||||
int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN;
|
int32_t tsMaxSQLStringLen = TSDB_MAX_ALLOWED_SQL_LEN;
|
||||||
|
int32_t tsMaxWildCardsLen = TSDB_PATTERN_STRING_DEFAULT_LEN;
|
||||||
int8_t tsTscEnableRecordSql = 0;
|
int8_t tsTscEnableRecordSql = 0;
|
||||||
|
|
||||||
// the maximum number of results for projection query on super table that are returned from
|
// the maximum number of results for projection query on super table that are returned from
|
||||||
|
@ -84,6 +89,9 @@ int32_t tsMaxNumOfOrderedResults = 100000;
|
||||||
// 10 ms for sliding time, the value will changed in case of time precision changed
|
// 10 ms for sliding time, the value will changed in case of time precision changed
|
||||||
int32_t tsMinSlidingTime = 10;
|
int32_t tsMinSlidingTime = 10;
|
||||||
|
|
||||||
|
// the maxinum number of distict query result
|
||||||
|
int32_t tsMaxNumOfDistinctResults = 1000 * 10000;
|
||||||
|
|
||||||
// 1 us for interval time range, changed accordingly
|
// 1 us for interval time range, changed accordingly
|
||||||
int32_t tsMinIntervalTime = 1;
|
int32_t tsMinIntervalTime = 1;
|
||||||
|
|
||||||
|
@ -541,6 +549,16 @@ static void doInitGlobalConfig(void) {
|
||||||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||||
taosInitConfigOption(cfg);
|
taosInitConfigOption(cfg);
|
||||||
|
|
||||||
|
cfg.option = "maxNumOfDistinctRes";
|
||||||
|
cfg.ptr = &tsMaxNumOfDistinctResults;
|
||||||
|
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||||
|
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_SHOW | TSDB_CFG_CTYPE_B_CLIENT;
|
||||||
|
cfg.minValue = 10*10000;
|
||||||
|
cfg.maxValue = 10000*10000;
|
||||||
|
cfg.ptrLength = 0;
|
||||||
|
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||||
|
taosInitConfigOption(cfg);
|
||||||
|
|
||||||
cfg.option = "numOfMnodes";
|
cfg.option = "numOfMnodes";
|
||||||
cfg.ptr = &tsNumOfMnodes;
|
cfg.ptr = &tsNumOfMnodes;
|
||||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||||
|
@ -984,6 +1002,16 @@ static void doInitGlobalConfig(void) {
|
||||||
cfg.unitType = TAOS_CFG_UTYPE_BYTE;
|
cfg.unitType = TAOS_CFG_UTYPE_BYTE;
|
||||||
taosInitConfigOption(cfg);
|
taosInitConfigOption(cfg);
|
||||||
|
|
||||||
|
cfg.option = "maxWildCardsLength";
|
||||||
|
cfg.ptr = &tsMaxWildCardsLen;
|
||||||
|
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||||
|
cfg.cfgType = TSDB_CFG_CTYPE_B_CONFIG | TSDB_CFG_CTYPE_B_CLIENT | TSDB_CFG_CTYPE_B_SHOW;
|
||||||
|
cfg.minValue = 0;
|
||||||
|
cfg.maxValue = TSDB_MAX_FIELD_LEN;
|
||||||
|
cfg.ptrLength = 0;
|
||||||
|
cfg.unitType = TAOS_CFG_UTYPE_BYTE;
|
||||||
|
taosInitConfigOption(cfg);
|
||||||
|
|
||||||
cfg.option = "maxNumOfOrderedRes";
|
cfg.option = "maxNumOfOrderedRes";
|
||||||
cfg.ptr = &tsMaxNumOfOrderedResults;
|
cfg.ptr = &tsMaxNumOfOrderedResults;
|
||||||
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
cfg.valType = TAOS_CFG_VTYPE_INT32;
|
||||||
|
@ -1531,6 +1559,7 @@ static void doInitGlobalConfig(void) {
|
||||||
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
cfg.unitType = TAOS_CFG_UTYPE_NONE;
|
||||||
taosInitConfigOption(cfg);
|
taosInitConfigOption(cfg);
|
||||||
|
|
||||||
|
assert(tsGlobalConfigNum <= TSDB_CFG_MAX_NUM);
|
||||||
#ifdef TD_TSZ
|
#ifdef TD_TSZ
|
||||||
// lossy compress
|
// lossy compress
|
||||||
cfg.option = "lossyColumns";
|
cfg.option = "lossyColumns";
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit b8f76da4a708d158ec3cc4b844571dc4414e36b4
|
Subproject commit 050667e5b4d0eafa5387e4283e713559b421203f
|
|
@ -1 +1 @@
|
||||||
Subproject commit 4a4d79099b076b8ff12d5b4fdbcba54049a6866d
|
Subproject commit 32e2c97a4cf7bedaa99f5d6dd8cb036e7f4470df
|
|
@ -1 +1 @@
|
||||||
Subproject commit ce5201014136503d34fecbd56494b67b4961056c
|
Subproject commit b62a26ecc164a310104df57691691b237e091c89
|
|
@ -113,7 +113,6 @@
|
||||||
</includes>
|
</includes>
|
||||||
<excludes>
|
<excludes>
|
||||||
<exclude>**/AppMemoryLeakTest.java</exclude>
|
<exclude>**/AppMemoryLeakTest.java</exclude>
|
||||||
<exclude>**/AuthenticationTest.java</exclude>
|
|
||||||
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
|
<exclude>**/ConnectMultiTaosdByRestfulWithDifferentTokenTest.java</exclude>
|
||||||
<exclude>**/DatetimeBefore1970Test.java</exclude>
|
<exclude>**/DatetimeBefore1970Test.java</exclude>
|
||||||
<exclude>**/FailOverTest.java</exclude>
|
<exclude>**/FailOverTest.java</exclude>
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
package com.taosdata.jdbc;
|
package com.taosdata.jdbc;
|
||||||
|
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -127,6 +129,11 @@ public class TSDBDriver extends AbstractDriver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER))
|
||||||
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED);
|
||||||
|
if (!props.containsKey(TSDBDriver.PROPERTY_KEY_PASSWORD))
|
||||||
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
TSDBJNIConnector.init((String) props.get(PROPERTY_KEY_CONFIG_DIR), (String) props.get(PROPERTY_KEY_LOCALE),
|
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));
|
(String) props.get(PROPERTY_KEY_CHARSET), (String) props.get(PROPERTY_KEY_TIME_ZONE));
|
||||||
|
|
|
@ -33,6 +33,8 @@ public class TSDBError {
|
||||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_NUMERIC_VALUE_OUT_OF_RANGE, "numeric value out of range");
|
||||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE, "unknown taos type in tdengine");
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TAOS_TYPE, "unknown taos type in tdengine");
|
||||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision");
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN_TIMESTAMP_PRECISION, "unknown timestamp precision");
|
||||||
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, "user is required");
|
||||||
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, "password is required");
|
||||||
|
|
||||||
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
TSDBErrorMap.put(TSDBErrorNumbers.ERROR_UNKNOWN, "unknown error");
|
||||||
|
|
||||||
|
|
|
@ -29,6 +29,9 @@ public class TSDBErrorNumbers {
|
||||||
public static final int ERROR_UNKNOWN_TIMESTAMP_PRECISION = 0x2316; // unknown timestamp precision
|
public static final int ERROR_UNKNOWN_TIMESTAMP_PRECISION = 0x2316; // unknown timestamp precision
|
||||||
public static final int ERROR_RESTFul_Client_Protocol_Exception = 0x2317;
|
public static final int ERROR_RESTFul_Client_Protocol_Exception = 0x2317;
|
||||||
public static final int ERROR_RESTFul_Client_IOException = 0x2318;
|
public static final int ERROR_RESTFul_Client_IOException = 0x2318;
|
||||||
|
public static final int ERROR_USER_IS_REQUIRED = 0x2319; // user is required
|
||||||
|
public static final int ERROR_PASSWORD_IS_REQUIRED = 0x231a; // password is required
|
||||||
|
|
||||||
|
|
||||||
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
|
public static final int ERROR_UNKNOWN = 0x2350; //unknown error
|
||||||
|
|
||||||
|
@ -67,6 +70,8 @@ public class TSDBErrorNumbers {
|
||||||
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE);
|
errorNumbers.add(ERROR_UNKNOWN_TAOS_TYPE);
|
||||||
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
errorNumbers.add(ERROR_UNKNOWN_TIMESTAMP_PRECISION);
|
||||||
errorNumbers.add(ERROR_RESTFul_Client_IOException);
|
errorNumbers.add(ERROR_RESTFul_Client_IOException);
|
||||||
|
errorNumbers.add(ERROR_USER_IS_REQUIRED);
|
||||||
|
errorNumbers.add(ERROR_PASSWORD_IS_REQUIRED);
|
||||||
|
|
||||||
errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception);
|
errorNumbers.add(ERROR_RESTFul_Client_Protocol_Exception);
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,6 @@ public class TSDBJNIConnector {
|
||||||
|
|
||||||
static {
|
static {
|
||||||
System.loadLibrary("taos");
|
System.loadLibrary("taos");
|
||||||
System.out.println("java.library.path:" + System.getProperty("java.library.path"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isClosed() {
|
public boolean isClosed() {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.taosdata.jdbc.utils.HttpClientPoolUtil;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
@ -40,8 +41,13 @@ public class RestfulDriver extends AbstractDriver {
|
||||||
|
|
||||||
String loginUrl = "http://" + host + ":" + port + "/rest/login/" + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + "/" + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD) + "";
|
String loginUrl = "http://" + host + ":" + port + "/rest/login/" + props.getProperty(TSDBDriver.PROPERTY_KEY_USER) + "/" + props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD) + "";
|
||||||
try {
|
try {
|
||||||
String user = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_USER), "UTF-8");
|
if (!props.containsKey(TSDBDriver.PROPERTY_KEY_USER))
|
||||||
String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), "UTF-8");
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED);
|
||||||
|
if (!props.containsKey(TSDBDriver.PROPERTY_KEY_PASSWORD))
|
||||||
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED);
|
||||||
|
|
||||||
|
String user = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_USER), StandardCharsets.UTF_8.displayName());
|
||||||
|
String password = URLEncoder.encode(props.getProperty(TSDBDriver.PROPERTY_KEY_PASSWORD), StandardCharsets.UTF_8.displayName());
|
||||||
loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + "";
|
loginUrl = "http://" + props.getProperty(TSDBDriver.PROPERTY_KEY_HOST) + ":" + props.getProperty(TSDBDriver.PROPERTY_KEY_PORT) + "/rest/login/" + user + "/" + password + "";
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
|
|
@ -7,6 +7,7 @@ import com.taosdata.jdbc.AbstractStatement;
|
||||||
import com.taosdata.jdbc.TSDBDriver;
|
import com.taosdata.jdbc.TSDBDriver;
|
||||||
import com.taosdata.jdbc.TSDBError;
|
import com.taosdata.jdbc.TSDBError;
|
||||||
import com.taosdata.jdbc.TSDBErrorNumbers;
|
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||||
|
import com.taosdata.jdbc.enums.TimestampFormat;
|
||||||
import com.taosdata.jdbc.utils.HttpClientPoolUtil;
|
import com.taosdata.jdbc.utils.HttpClientPoolUtil;
|
||||||
import com.taosdata.jdbc.utils.SqlSyntaxValidator;
|
import com.taosdata.jdbc.utils.SqlSyntaxValidator;
|
||||||
|
|
||||||
|
@ -45,9 +46,7 @@ public class RestfulStatement extends AbstractStatement {
|
||||||
if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql))
|
if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql))
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql);
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql);
|
||||||
|
|
||||||
final String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
return executeOneUpdate(sql);
|
||||||
|
|
||||||
return executeOneUpdate(url, sql);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -62,34 +61,25 @@ public class RestfulStatement extends AbstractStatement {
|
||||||
public boolean execute(String sql) throws SQLException {
|
public boolean execute(String sql) throws SQLException {
|
||||||
if (isClosed())
|
if (isClosed())
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_STATEMENT_CLOSED);
|
||||||
if (!SqlSyntaxValidator.isValidForExecute(sql))
|
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE, "not a valid sql for execute: " + sql);
|
|
||||||
|
|
||||||
//如果执行了use操作应该将当前Statement的catalog设置为新的database
|
//如果执行了use操作应该将当前Statement的catalog设置为新的database
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
|
||||||
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("TIMESTAMP")) {
|
|
||||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
|
|
||||||
}
|
|
||||||
if (conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).equals("UTC")) {
|
|
||||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (SqlSyntaxValidator.isUseSql(sql)) {
|
if (SqlSyntaxValidator.isUseSql(sql)) {
|
||||||
HttpClientPoolUtil.execute(url, sql, this.conn.getToken());
|
HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken());
|
||||||
this.database = sql.trim().replace("use", "").trim();
|
this.database = sql.trim().replace("use", "").trim();
|
||||||
this.conn.setCatalog(this.database);
|
this.conn.setCatalog(this.database);
|
||||||
result = false;
|
result = false;
|
||||||
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
|
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedQuery(sql)) {
|
||||||
executeOneQuery(sql);
|
executeOneQuery(sql);
|
||||||
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
|
} else if (SqlSyntaxValidator.isDatabaseUnspecifiedUpdate(sql)) {
|
||||||
executeOneUpdate(url, sql);
|
executeOneUpdate(sql);
|
||||||
result = false;
|
result = false;
|
||||||
} else {
|
} else {
|
||||||
if (SqlSyntaxValidator.isValidForExecuteQuery(sql)) {
|
if (SqlSyntaxValidator.isValidForExecuteQuery(sql)) {
|
||||||
executeQuery(sql);
|
executeOneQuery(sql);
|
||||||
} else {
|
} else {
|
||||||
executeUpdate(sql);
|
executeOneUpdate(sql);
|
||||||
result = false;
|
result = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -97,19 +87,25 @@ public class RestfulStatement extends AbstractStatement {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ResultSet executeOneQuery(String sql) throws SQLException {
|
private String getUrl() throws SQLException {
|
||||||
if (!SqlSyntaxValidator.isValidForExecuteQuery(sql))
|
TimestampFormat timestampFormat = TimestampFormat.valueOf(conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT).trim().toUpperCase());
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_QUERY, "not a valid sql for executeQuery: " + sql);
|
String url;
|
||||||
|
switch (timestampFormat) {
|
||||||
// row data
|
case TIMESTAMP:
|
||||||
String url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
|
||||||
String timestampFormat = conn.getClientInfo(TSDBDriver.PROPERTY_KEY_TIMESTAMP_FORMAT);
|
|
||||||
if ("TIMESTAMP".equalsIgnoreCase(timestampFormat))
|
|
||||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
|
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlt";
|
||||||
if ("UTC".equalsIgnoreCase(timestampFormat))
|
break;
|
||||||
|
case UTC:
|
||||||
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
|
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sqlutc";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
url = "http://" + conn.getHost() + ":" + conn.getPort() + "/rest/sql";
|
||||||
|
}
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
String result = HttpClientPoolUtil.execute(url, sql, this.conn.getToken());
|
private ResultSet executeOneQuery(String sql) throws SQLException {
|
||||||
|
// row data
|
||||||
|
String result = HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken());
|
||||||
JSONObject resultJson = JSON.parseObject(result);
|
JSONObject resultJson = JSON.parseObject(result);
|
||||||
if (resultJson.getString("status").equals("error")) {
|
if (resultJson.getString("status").equals("error")) {
|
||||||
throw TSDBError.createSQLException(resultJson.getInteger("code"), resultJson.getString("desc"));
|
throw TSDBError.createSQLException(resultJson.getInteger("code"), resultJson.getString("desc"));
|
||||||
|
@ -119,11 +115,8 @@ public class RestfulStatement extends AbstractStatement {
|
||||||
return resultSet;
|
return resultSet;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int executeOneUpdate(String url, String sql) throws SQLException {
|
private int executeOneUpdate(String sql) throws SQLException {
|
||||||
if (!SqlSyntaxValidator.isValidForExecuteUpdate(sql))
|
String result = HttpClientPoolUtil.execute(getUrl(), sql, this.conn.getToken());
|
||||||
throw TSDBError.createSQLException(TSDBErrorNumbers.ERROR_INVALID_FOR_EXECUTE_UPDATE, "not a valid sql for executeUpdate: " + sql);
|
|
||||||
|
|
||||||
String result = HttpClientPoolUtil.execute(url, sql, this.conn.getToken());
|
|
||||||
JSONObject jsonObject = JSON.parseObject(result);
|
JSONObject jsonObject = JSON.parseObject(result);
|
||||||
if (jsonObject.getString("status").equals("error")) {
|
if (jsonObject.getString("status").equals("error")) {
|
||||||
throw TSDBError.createSQLException(jsonObject.getInteger("code"), jsonObject.getString("desc"));
|
throw TSDBError.createSQLException(jsonObject.getInteger("code"), jsonObject.getString("desc"));
|
||||||
|
@ -134,7 +127,7 @@ public class RestfulStatement extends AbstractStatement {
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getAffectedRows(JSONObject jsonObject) throws SQLException {
|
private int getAffectedRows(JSONObject jsonObject) throws SQLException {
|
||||||
// create ... SQLs should return 0 , and Restful result is this:
|
// create ... SQLs should return 0 , and Restful result like this:
|
||||||
// {"status": "succ", "head": ["affected_rows"], "data": [[0]], "rows": 1}
|
// {"status": "succ", "head": ["affected_rows"], "data": [[0]], "rows": 1}
|
||||||
JSONArray head = jsonObject.getJSONArray("head");
|
JSONArray head = jsonObject.getJSONArray("head");
|
||||||
if (head.size() != 1 || !"affected_rows".equals(head.getString(0)))
|
if (head.size() != 1 || !"affected_rows".equals(head.getString(0)))
|
||||||
|
|
|
@ -16,8 +16,7 @@ package com.taosdata.jdbc.utils;
|
||||||
|
|
||||||
public class SqlSyntaxValidator {
|
public class SqlSyntaxValidator {
|
||||||
|
|
||||||
private static final String[] SQL = {"select", "insert", "import", "create", "use", "alter", "drop", "set", "show", "describe", "reset"};
|
private static final String[] updateSQL = {"insert", "import", "create", "use", "alter", "drop", "set", "reset"};
|
||||||
private static final String[] updateSQL = {"insert", "import", "create", "use", "alter", "drop", "set"};
|
|
||||||
private static final String[] querySQL = {"select", "show", "describe"};
|
private static final String[] querySQL = {"select", "show", "describe"};
|
||||||
|
|
||||||
private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"};
|
private static final String[] databaseUnspecifiedShow = {"databases", "dnodes", "mnodes", "variables"};
|
||||||
|
@ -38,14 +37,6 @@ public class SqlSyntaxValidator {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isValidForExecute(String sql) {
|
|
||||||
for (String prefix : SQL) {
|
|
||||||
if (sql.trim().toLowerCase().startsWith(prefix))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isDatabaseUnspecifiedQuery(String sql) {
|
public static boolean isDatabaseUnspecifiedQuery(String sql) {
|
||||||
for (String databaseObj : databaseUnspecifiedShow) {
|
for (String databaseObj : databaseUnspecifiedShow) {
|
||||||
if (sql.trim().toLowerCase().matches("show\\s+" + databaseObj + ".*"))
|
if (sql.trim().toLowerCase().matches("show\\s+" + databaseObj + ".*"))
|
||||||
|
@ -63,9 +54,5 @@ public class SqlSyntaxValidator {
|
||||||
return sql.trim().toLowerCase().startsWith("use");
|
return sql.trim().toLowerCase().startsWith("use");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isSelectSql(String sql) {
|
|
||||||
return sql.trim().toLowerCase().startsWith("select");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,8 @@ public class SubscribeTest {
|
||||||
@Before
|
@Before
|
||||||
public void createDatabase() throws SQLException {
|
public void createDatabase() throws SQLException {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
package com.taosdata.jdbc.cases;
|
package com.taosdata.jdbc.cases;
|
||||||
|
|
||||||
|
import com.taosdata.jdbc.TSDBErrorNumbers;
|
||||||
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
|
@ -12,6 +15,47 @@ public class AuthenticationTest {
|
||||||
private static final String password = "taos?data";
|
private static final String password = "taos?data";
|
||||||
private Connection conn;
|
private Connection conn;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connectWithoutUserByJni() {
|
||||||
|
try {
|
||||||
|
DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Assert.assertEquals(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, e.getErrorCode());
|
||||||
|
Assert.assertEquals("ERROR (2319): user is required", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connectWithoutUserByRestful() {
|
||||||
|
try {
|
||||||
|
DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Assert.assertEquals(TSDBErrorNumbers.ERROR_USER_IS_REQUIRED, e.getErrorCode());
|
||||||
|
Assert.assertEquals("ERROR (2319): user is required", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connectWithoutPasswordByJni() {
|
||||||
|
try {
|
||||||
|
DriverManager.getConnection("jdbc:TAOS://" + host + ":0/?user=root");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Assert.assertEquals(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, e.getErrorCode());
|
||||||
|
Assert.assertEquals("ERROR (231a): password is required", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void connectWithoutPasswordByRestful() {
|
||||||
|
try {
|
||||||
|
DriverManager.getConnection("jdbc:TAOS-RS://" + host + ":6041/?user=root");
|
||||||
|
} catch (SQLException e) {
|
||||||
|
Assert.assertEquals(TSDBErrorNumbers.ERROR_PASSWORD_IS_REQUIRED, e.getErrorCode());
|
||||||
|
Assert.assertEquals("ERROR (231a): password is required", e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
||||||
// change password
|
// change password
|
||||||
|
|
|
@ -29,6 +29,8 @@ public class BatchInsertTest {
|
||||||
public void before() {
|
public void before() {
|
||||||
try {
|
try {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -21,6 +21,8 @@ public class ImportTest {
|
||||||
public static void before() {
|
public static void before() {
|
||||||
try {
|
try {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -270,6 +270,41 @@ public class InsertSpecialCharacterJniTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Ignore
|
||||||
|
@Test
|
||||||
|
public void testSingleQuotaEscape() throws SQLException {
|
||||||
|
final long now = System.currentTimeMillis();
|
||||||
|
final String sql = "insert into t? using ? tags(?) values(?, ?, ?) t? using " + tbname2 + " tags(?) values(?,?,?) ";
|
||||||
|
try (PreparedStatement pstmt = conn.prepareStatement(sql)) {
|
||||||
|
// t1
|
||||||
|
pstmt.setInt(1, 1);
|
||||||
|
pstmt.setString(2, tbname2);
|
||||||
|
pstmt.setString(3, special_character_str_5);
|
||||||
|
pstmt.setTimestamp(4, new Timestamp(now));
|
||||||
|
pstmt.setBytes(5, special_character_str_5.getBytes());
|
||||||
|
// t2
|
||||||
|
pstmt.setInt(7, 2);
|
||||||
|
pstmt.setString(8, special_character_str_5);
|
||||||
|
pstmt.setTimestamp(9, new Timestamp(now));
|
||||||
|
pstmt.setString(11, special_character_str_5);
|
||||||
|
|
||||||
|
int ret = pstmt.executeUpdate();
|
||||||
|
Assert.assertEquals(2, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
String query = "select * from ?.t? where ? < ? and ts >= ? and f1 is not null";
|
||||||
|
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||||
|
pstmt.setString(1, dbName);
|
||||||
|
pstmt.setInt(2, 1);
|
||||||
|
pstmt.setString(3, "ts");
|
||||||
|
pstmt.setTimestamp(4, new Timestamp(System.currentTimeMillis()));
|
||||||
|
pstmt.setTimestamp(5, new Timestamp(0));
|
||||||
|
|
||||||
|
ResultSet rs = pstmt.executeQuery();
|
||||||
|
Assert.assertNotNull(rs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCase10() throws SQLException {
|
public void testCase10() throws SQLException {
|
||||||
final long now = System.currentTimeMillis();
|
final long now = System.currentTimeMillis();
|
||||||
|
@ -293,13 +328,12 @@ public class InsertSpecialCharacterJniTest {
|
||||||
Assert.assertEquals(2, ret);
|
Assert.assertEquals(2, ret);
|
||||||
}
|
}
|
||||||
//query t1
|
//query t1
|
||||||
String query = "select * from ?.t? where ts < ? and ts >= ? and ? is not null";
|
String query = "select * from ?.t? where ts < ? and ts >= ? and f1 is not null";
|
||||||
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||||
pstmt.setString(1, dbName);
|
pstmt.setString(1, dbName);
|
||||||
pstmt.setInt(2, 1);
|
pstmt.setInt(2, 1);
|
||||||
pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
|
pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
|
||||||
pstmt.setTimestamp(4, new Timestamp(0));
|
pstmt.setTimestamp(4, new Timestamp(0));
|
||||||
pstmt.setString(5, "f1");
|
|
||||||
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
ResultSet rs = pstmt.executeQuery();
|
||||||
rs.next();
|
rs.next();
|
||||||
|
@ -311,12 +345,11 @@ public class InsertSpecialCharacterJniTest {
|
||||||
Assert.assertNull(f2);
|
Assert.assertNull(f2);
|
||||||
}
|
}
|
||||||
// query t2
|
// query t2
|
||||||
query = "select * from t? where ts < ? and ts >= ? and ? is not null";
|
query = "select * from t? where ts < ? and ts >= ? and f2 is not null";
|
||||||
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||||
pstmt.setInt(1, 2);
|
pstmt.setInt(1, 2);
|
||||||
pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
|
pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
|
||||||
pstmt.setTimestamp(3, new Timestamp(0));
|
pstmt.setTimestamp(3, new Timestamp(0));
|
||||||
pstmt.setString(4, "f2");
|
|
||||||
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
ResultSet rs = pstmt.executeQuery();
|
||||||
rs.next();
|
rs.next();
|
||||||
|
|
|
@ -293,13 +293,12 @@ public class InsertSpecialCharacterRestfulTest {
|
||||||
Assert.assertEquals(2, ret);
|
Assert.assertEquals(2, ret);
|
||||||
}
|
}
|
||||||
//query t1
|
//query t1
|
||||||
String query = "select * from ?.t? where ts < ? and ts >= ? and ? is not null";
|
String query = "select * from ?.t? where ts < ? and ts >= ? and f1 is not null";
|
||||||
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||||
pstmt.setString(1, dbName);
|
pstmt.setString(1, dbName);
|
||||||
pstmt.setInt(2, 1);
|
pstmt.setInt(2, 1);
|
||||||
pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
|
pstmt.setTimestamp(3, new Timestamp(System.currentTimeMillis()));
|
||||||
pstmt.setTimestamp(4, new Timestamp(0));
|
pstmt.setTimestamp(4, new Timestamp(0));
|
||||||
pstmt.setString(5, "f1");
|
|
||||||
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
ResultSet rs = pstmt.executeQuery();
|
||||||
rs.next();
|
rs.next();
|
||||||
|
@ -311,12 +310,11 @@ public class InsertSpecialCharacterRestfulTest {
|
||||||
Assert.assertNull(f2);
|
Assert.assertNull(f2);
|
||||||
}
|
}
|
||||||
// query t2
|
// query t2
|
||||||
query = "select * from t? where ts < ? and ts >= ? and ? is not null";
|
query = "select * from t? where ts < ? and ts >= ? and f2 is not null";
|
||||||
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
try (PreparedStatement pstmt = conn.prepareStatement(query)) {
|
||||||
pstmt.setInt(1, 2);
|
pstmt.setInt(1, 2);
|
||||||
pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
|
pstmt.setTimestamp(2, new Timestamp(System.currentTimeMillis()));
|
||||||
pstmt.setTimestamp(3, new Timestamp(0));
|
pstmt.setTimestamp(3, new Timestamp(0));
|
||||||
pstmt.setString(4, "f2");
|
|
||||||
|
|
||||||
ResultSet rs = pstmt.executeQuery();
|
ResultSet rs = pstmt.executeQuery();
|
||||||
rs.next();
|
rs.next();
|
||||||
|
|
|
@ -22,6 +22,8 @@ public class QueryDataTest {
|
||||||
public void createDatabase() {
|
public void createDatabase() {
|
||||||
try {
|
try {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -1,51 +1,49 @@
|
||||||
package com.taosdata.jdbc.cases;
|
package com.taosdata.jdbc.cases;
|
||||||
|
|
||||||
import com.taosdata.jdbc.TSDBDriver;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import java.sql.*;
|
import java.sql.Connection;
|
||||||
import java.util.Properties;
|
import java.sql.DriverManager;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
|
||||||
public class ResetQueryCacheTest {
|
public class ResetQueryCacheTest {
|
||||||
|
|
||||||
static Connection connection;
|
@Test
|
||||||
static Statement statement;
|
public void jni() throws SQLException {
|
||||||
static String host = "127.0.0.1";
|
// given
|
||||||
|
Connection connection = DriverManager.getConnection("jdbc:TAOS://127.0.0.1:0/?user=root&password=taosdata&timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8");
|
||||||
|
Statement statement = connection.createStatement();
|
||||||
|
|
||||||
@Before
|
// when
|
||||||
public void init() {
|
boolean execute = statement.execute("reset query cache");
|
||||||
try {
|
|
||||||
Properties properties = new Properties();
|
// then
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
assertFalse(execute);
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
assertEquals(0, statement.getUpdateCount());
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
|
||||||
connection = DriverManager.getConnection("jdbc:TAOS://" + host + ":0/", properties);
|
statement.close();
|
||||||
statement = connection.createStatement();
|
connection.close();
|
||||||
} catch (SQLException e) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResetQueryCache() throws SQLException {
|
public void restful() throws SQLException {
|
||||||
String resetSql = "reset query cache";
|
// given
|
||||||
statement.execute(resetSql);
|
Connection connection = DriverManager.getConnection("jdbc:TAOS-RS://127.0.0.1:6041/?user=root&password=taosdata&timezone=UTC-8&charset=UTF-8&locale=en_US.UTF-8");
|
||||||
}
|
Statement statement = connection.createStatement();
|
||||||
|
|
||||||
|
// when
|
||||||
|
boolean execute = statement.execute("reset query cache");
|
||||||
|
|
||||||
|
// then
|
||||||
|
assertFalse(execute);
|
||||||
|
assertEquals(0, statement.getUpdateCount());
|
||||||
|
|
||||||
@After
|
|
||||||
public void close() {
|
|
||||||
try {
|
|
||||||
if (statement != null)
|
|
||||||
statement.close();
|
statement.close();
|
||||||
if (connection != null)
|
|
||||||
connection.close();
|
connection.close();
|
||||||
} catch (SQLException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -20,6 +20,8 @@ public class SelectTest {
|
||||||
public void createDatabaseAndTable() {
|
public void createDatabaseAndTable() {
|
||||||
try {
|
try {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -24,6 +24,8 @@ public class StableTest {
|
||||||
public static void createDatabase() {
|
public static void createDatabase() {
|
||||||
try {
|
try {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_USER, "root");
|
||||||
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_PASSWORD, "taosdata");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_CHARSET, "UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_LOCALE, "en_US.UTF-8");
|
||||||
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
properties.setProperty(TSDBDriver.PROPERTY_KEY_TIME_ZONE, "UTC-8");
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
package com.taosdata.jdbc.utils;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class SqlSyntaxValidatorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isSelectSQL() {
|
|
||||||
Assert.assertTrue(SqlSyntaxValidator.isSelectSql("select * from test.weather"));
|
|
||||||
Assert.assertTrue(SqlSyntaxValidator.isSelectSql(" select * from test.weather"));
|
|
||||||
Assert.assertTrue(SqlSyntaxValidator.isSelectSql(" select * from test.weather "));
|
|
||||||
Assert.assertFalse(SqlSyntaxValidator.isSelectSql("insert into test.weather values(now, 1.1, 2)"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void isUseSQL() {
|
|
||||||
Assert.assertTrue(SqlSyntaxValidator.isUseSql("use database test"));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -109,6 +109,24 @@ function convertDouble(data, num_of_rows, nbytes = 0, offset = 0, precision = 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function convertBinary(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) {
|
||||||
|
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
|
||||||
|
let res = [];
|
||||||
|
|
||||||
|
let currOffset = 0;
|
||||||
|
while (currOffset < data.length) {
|
||||||
|
let len = data.readIntLE(currOffset, 2);
|
||||||
|
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
|
||||||
|
if (dataEntry[0] == 255) {
|
||||||
|
res.push(null)
|
||||||
|
} else {
|
||||||
|
res.push(dataEntry.toString("utf-8"));
|
||||||
|
}
|
||||||
|
currOffset += nbytes;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) {
|
function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0) {
|
||||||
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
|
data = ref.reinterpret(data.deref(), nbytes * num_of_rows, offset);
|
||||||
let res = [];
|
let res = [];
|
||||||
|
@ -117,7 +135,11 @@ function convertNchar(data, num_of_rows, nbytes = 0, offset = 0, precision = 0)
|
||||||
while (currOffset < data.length) {
|
while (currOffset < data.length) {
|
||||||
let len = data.readIntLE(currOffset, 2);
|
let len = data.readIntLE(currOffset, 2);
|
||||||
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
|
let dataEntry = data.slice(currOffset + 2, currOffset + len + 2); //one entry in a row under a column;
|
||||||
|
if (dataEntry[0] == 255 && dataEntry[1] == 255) {
|
||||||
|
res.push(null)
|
||||||
|
} else {
|
||||||
res.push(dataEntry.toString("utf-8"));
|
res.push(dataEntry.toString("utf-8"));
|
||||||
|
}
|
||||||
currOffset += nbytes;
|
currOffset += nbytes;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
@ -132,7 +154,7 @@ let convertFunctions = {
|
||||||
[FieldTypes.C_BIGINT]: convertBigint,
|
[FieldTypes.C_BIGINT]: convertBigint,
|
||||||
[FieldTypes.C_FLOAT]: convertFloat,
|
[FieldTypes.C_FLOAT]: convertFloat,
|
||||||
[FieldTypes.C_DOUBLE]: convertDouble,
|
[FieldTypes.C_DOUBLE]: convertDouble,
|
||||||
[FieldTypes.C_BINARY]: convertNchar,
|
[FieldTypes.C_BINARY]: convertBinary,
|
||||||
[FieldTypes.C_TIMESTAMP]: convertTimestamp,
|
[FieldTypes.C_TIMESTAMP]: convertTimestamp,
|
||||||
[FieldTypes.C_NCHAR]: convertNchar
|
[FieldTypes.C_NCHAR]: convertNchar
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,7 +47,8 @@ class TaosTimestamp extends Date {
|
||||||
super(Math.floor(date / 1000));
|
super(Math.floor(date / 1000));
|
||||||
this.precisionExtras = date % 1000;
|
this.precisionExtras = date % 1000;
|
||||||
} else if (precision === 2) {
|
} else if (precision === 2) {
|
||||||
super(parseInt(date / 1000000));
|
// use BigInt to fix: 1623254400999999999 / 1000000 = 1623254401000 which not expected
|
||||||
|
super(parseInt(BigInt(date) / 1000000n));
|
||||||
// use BigInt to fix: 1625801548423914405 % 1000000 = 914496 which not expected (914405)
|
// use BigInt to fix: 1625801548423914405 % 1000000 = 914496 which not expected (914405)
|
||||||
this.precisionExtras = parseInt(BigInt(date) % 1000000n);
|
this.precisionExtras = parseInt(BigInt(date) % 1000000n);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "td2.0-connector",
|
"name": "td2.0-connector",
|
||||||
"version": "2.0.9",
|
"version": "2.0.10",
|
||||||
"description": "A Node.js connector for TDengine.",
|
"description": "A Node.js connector for TDengine.",
|
||||||
"main": "tdengine.js",
|
"main": "tdengine.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
const taos = require('../tdengine');
|
||||||
|
var conn = taos.connect({ host: "localhost" });
|
||||||
|
var c1 = conn.cursor();
|
||||||
|
|
||||||
|
|
||||||
|
function checkData(data, row, col, expect) {
|
||||||
|
let checkdata = data[row][col];
|
||||||
|
if (checkdata == expect) {
|
||||||
|
// console.log('check pass')
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.log('check failed, expect ' + expect + ', but is ' + checkdata)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
c1.execute('drop database if exists testnodejsnchar')
|
||||||
|
c1.execute('create database testnodejsnchar')
|
||||||
|
c1.execute('use testnodejsnchar');
|
||||||
|
c1.execute('create table tb (ts timestamp, value float, text binary(200))')
|
||||||
|
c1.execute("insert into tb values('2021-06-10 00:00:00', 24.7, '中文10000000000000000000000');") -
|
||||||
|
c1.execute('insert into tb values(1623254400150, 24.7, NULL);')
|
||||||
|
c1.execute('import into tb values(1623254400300, 24.7, "中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000");')
|
||||||
|
sql = 'select * from tb;'
|
||||||
|
|
||||||
|
console.log('*******************************************')
|
||||||
|
|
||||||
|
c1.execute(sql);
|
||||||
|
data = c1.fetchall();
|
||||||
|
console.log(data)
|
||||||
|
//check data about insert data
|
||||||
|
checkData(data, 0, 2, '中文10000000000000000000000')
|
||||||
|
checkData(data, 1, 2, null)
|
||||||
|
checkData(data, 2, 2, '中文3中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000中文10000000000000000000000')
|
|
@ -166,7 +166,6 @@ int32_t dnodeInitSystem() {
|
||||||
taosInitGlobalCfg();
|
taosInitGlobalCfg();
|
||||||
taosReadGlobalLogCfg();
|
taosReadGlobalLogCfg();
|
||||||
taosSetCoreDump();
|
taosSetCoreDump();
|
||||||
taosInitNotes();
|
|
||||||
dnodeInitTmr();
|
dnodeInitTmr();
|
||||||
|
|
||||||
if (dnodeCreateDir(tsLogDir) < 0) {
|
if (dnodeCreateDir(tsLogDir) < 0) {
|
||||||
|
@ -188,6 +187,8 @@ int32_t dnodeInitSystem() {
|
||||||
|
|
||||||
dInfo("start to initialize TDengine");
|
dInfo("start to initialize TDengine");
|
||||||
|
|
||||||
|
taosInitNotes();
|
||||||
|
|
||||||
if (dnodeInitComponents() != 0) {
|
if (dnodeInitComponents() != 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,6 +42,8 @@ int32_t main(int32_t argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
} else if (strcmp(argv[i], "-C") == 0) {
|
} else if (strcmp(argv[i], "-C") == 0) {
|
||||||
dump_config = 1;
|
dump_config = 1;
|
||||||
|
} else if (strcmp(argv[i], "--force-keep-file") == 0) {
|
||||||
|
tsdbForceKeepFile = true;
|
||||||
} else if (strcmp(argv[i], "--compact-mnode-wal") == 0) {
|
} else if (strcmp(argv[i], "--compact-mnode-wal") == 0) {
|
||||||
tsCompactMnodeWal = 1;
|
tsCompactMnodeWal = 1;
|
||||||
} else if (strcmp(argv[i], "-V") == 0) {
|
} else if (strcmp(argv[i], "-V") == 0) {
|
||||||
|
|
|
@ -32,7 +32,7 @@ typedef enum {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
int8_t msgType;
|
int8_t msgType;
|
||||||
int8_t sver;
|
int8_t sver; // sver 2 for WAL SDataRow/SMemRow compatibility
|
||||||
int8_t reserved[2];
|
int8_t reserved[2];
|
||||||
int32_t len;
|
int32_t len;
|
||||||
uint64_t version;
|
uint64_t version;
|
||||||
|
|
|
@ -72,12 +72,13 @@ static int32_t shellShowTables(TAOS *con, char *db) {
|
||||||
int32_t tbIndex = tbNum++;
|
int32_t tbIndex = tbNum++;
|
||||||
if (tbMallocNum < tbNum) {
|
if (tbMallocNum < tbNum) {
|
||||||
tbMallocNum = (tbMallocNum * 2 + 1);
|
tbMallocNum = (tbMallocNum * 2 + 1);
|
||||||
tbNames = realloc(tbNames, tbMallocNum * sizeof(char *));
|
char** tbNames1 = realloc(tbNames, tbMallocNum * sizeof(char *));
|
||||||
if (tbNames == NULL) {
|
if (tbNames1 == NULL) {
|
||||||
fprintf(stdout, "failed to malloc tablenames, num:%d\n", tbMallocNum);
|
fprintf(stdout, "failed to malloc tablenames, num:%d\n", tbMallocNum);
|
||||||
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
code = TSDB_CODE_TSC_OUT_OF_MEMORY;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
tbNames = tbNames1;
|
||||||
}
|
}
|
||||||
|
|
||||||
tbNames[tbIndex] = malloc(TSDB_TABLE_NAME_LEN);
|
tbNames[tbIndex] = malloc(TSDB_TABLE_NAME_LEN);
|
||||||
|
|
|
@ -64,6 +64,10 @@ void printHelp() {
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char DARWINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
|
||||||
|
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
|
||||||
|
char g_password[MAX_PASSWORD_SIZE];
|
||||||
|
|
||||||
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
wordexp_t full_path;
|
wordexp_t full_path;
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
|
@ -77,8 +81,19 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for password
|
// for password
|
||||||
else if (strcmp(argv[i], "-p") == 0) {
|
else if (strncmp(argv[i], "-p", 2) == 0) {
|
||||||
arguments->is_use_passwd = true;
|
strcpy(tsOsName, "Darwin");
|
||||||
|
printf(DARWINCLIENT_VERSION, tsOsName, taos_get_client_info());
|
||||||
|
if (strlen(argv[i]) == 2) {
|
||||||
|
printf("Enter password: ");
|
||||||
|
if (scanf("%s", g_password) > 1) {
|
||||||
|
fprintf(stderr, "password read error\n");
|
||||||
|
}
|
||||||
|
getchar();
|
||||||
|
} else {
|
||||||
|
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
|
||||||
|
}
|
||||||
|
arguments->password = g_password;
|
||||||
}
|
}
|
||||||
// for management port
|
// for management port
|
||||||
else if (strcmp(argv[i], "-P") == 0) {
|
else if (strcmp(argv[i], "-P") == 0) {
|
||||||
|
|
|
@ -65,7 +65,15 @@ extern TAOS *taos_connect_auth(const char *ip, const char *user, const char *aut
|
||||||
*/
|
*/
|
||||||
TAOS *shellInit(SShellArguments *_args) {
|
TAOS *shellInit(SShellArguments *_args) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
if (!_args->is_use_passwd) {
|
||||||
|
#ifdef TD_WINDOWS
|
||||||
|
strcpy(tsOsName, "Windows");
|
||||||
|
#elif defined(TD_DARWIN)
|
||||||
|
strcpy(tsOsName, "Darwin");
|
||||||
|
#endif
|
||||||
printf(CLIENT_VERSION, tsOsName, taos_get_client_info());
|
printf(CLIENT_VERSION, tsOsName, taos_get_client_info());
|
||||||
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
|
||||||
// set options before initializing
|
// set options before initializing
|
||||||
|
@ -73,9 +81,7 @@ TAOS *shellInit(SShellArguments *_args) {
|
||||||
taos_options(TSDB_OPTION_TIMEZONE, _args->timezone);
|
taos_options(TSDB_OPTION_TIMEZONE, _args->timezone);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_args->is_use_passwd) {
|
if (!_args->is_use_passwd) {
|
||||||
if (_args->password == NULL) _args->password = getpass("Enter password: ");
|
|
||||||
} else {
|
|
||||||
_args->password = TSDB_DEFAULT_PASS;
|
_args->password = TSDB_DEFAULT_PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,7 @@ static char doc[] = "";
|
||||||
static char args_doc[] = "";
|
static char args_doc[] = "";
|
||||||
static struct argp_option options[] = {
|
static struct argp_option options[] = {
|
||||||
{"host", 'h', "HOST", 0, "TDengine server FQDN to connect. The default host is localhost."},
|
{"host", 'h', "HOST", 0, "TDengine server FQDN to connect. The default host is localhost."},
|
||||||
{"password", 'p', "PASSWORD", OPTION_ARG_OPTIONAL, "The password to use when connecting to the server."},
|
{"password", 'p', 0, 0, "The password to use when connecting to the server."},
|
||||||
{"port", 'P', "PORT", 0, "The TCP/IP port number to use for the connection."},
|
{"port", 'P', "PORT", 0, "The TCP/IP port number to use for the connection."},
|
||||||
{"user", 'u', "USER", 0, "The user name to use when connecting to the server."},
|
{"user", 'u', "USER", 0, "The user name to use when connecting to the server."},
|
||||||
{"auth", 'A', "Auth", 0, "The auth string to use when connecting to the server."},
|
{"auth", 'A', "Auth", 0, "The auth string to use when connecting to the server."},
|
||||||
|
@ -63,8 +63,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||||
arguments->host = arg;
|
arguments->host = arg;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
arguments->is_use_passwd = true;
|
|
||||||
if (arg) arguments->password = arg;
|
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
if (arg) {
|
if (arg) {
|
||||||
|
@ -160,12 +158,41 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||||
/* Our argp parser. */
|
/* Our argp parser. */
|
||||||
static struct argp argp = {options, parse_opt, args_doc, doc};
|
static struct argp argp = {options, parse_opt, args_doc, doc};
|
||||||
|
|
||||||
|
char LINUXCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
|
||||||
|
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
|
||||||
|
char g_password[MAX_PASSWORD_SIZE];
|
||||||
|
|
||||||
|
static void parse_password(
|
||||||
|
int argc, char *argv[], SShellArguments *arguments) {
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strncmp(argv[i], "-p", 2) == 0) {
|
||||||
|
strcpy(tsOsName, "Linux");
|
||||||
|
printf(LINUXCLIENT_VERSION, tsOsName, taos_get_client_info());
|
||||||
|
if (strlen(argv[i]) == 2) {
|
||||||
|
printf("Enter password: ");
|
||||||
|
if (scanf("%20s", g_password) > 1) {
|
||||||
|
fprintf(stderr, "password reading error\n");
|
||||||
|
}
|
||||||
|
getchar();
|
||||||
|
} else {
|
||||||
|
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
|
||||||
|
}
|
||||||
|
arguments->password = g_password;
|
||||||
|
arguments->is_use_passwd = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
static char verType[32] = {0};
|
static char verType[32] = {0};
|
||||||
sprintf(verType, "version: %s\n", version);
|
sprintf(verType, "version: %s\n", version);
|
||||||
|
|
||||||
argp_program_version = verType;
|
argp_program_version = verType;
|
||||||
|
|
||||||
|
if (argc > 1) {
|
||||||
|
parse_password(argc, argv, arguments);
|
||||||
|
}
|
||||||
|
|
||||||
argp_parse(&argp, argc, argv, 0, 0, arguments);
|
argp_parse(&argp, argc, argv, 0, 0, arguments);
|
||||||
if (arguments->abort) {
|
if (arguments->abort) {
|
||||||
#ifndef _ALPINE
|
#ifndef _ALPINE
|
||||||
|
|
|
@ -71,7 +71,9 @@ int checkVersion() {
|
||||||
// Global configurations
|
// Global configurations
|
||||||
SShellArguments args = {
|
SShellArguments args = {
|
||||||
.host = NULL,
|
.host = NULL,
|
||||||
|
#ifndef TD_WINDOWS
|
||||||
.password = NULL,
|
.password = NULL,
|
||||||
|
#endif
|
||||||
.user = NULL,
|
.user = NULL,
|
||||||
.database = NULL,
|
.database = NULL,
|
||||||
.timezone = NULL,
|
.timezone = NULL,
|
||||||
|
|
|
@ -19,6 +19,9 @@
|
||||||
|
|
||||||
extern char configDir[];
|
extern char configDir[];
|
||||||
|
|
||||||
|
char WINCLIENT_VERSION[] = "Welcome to the TDengine shell from %s, Client Version:%s\n"
|
||||||
|
"Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.\n\n";
|
||||||
|
|
||||||
void printVersion() {
|
void printVersion() {
|
||||||
printf("version: %s\n", version);
|
printf("version: %s\n", version);
|
||||||
}
|
}
|
||||||
|
@ -61,6 +64,8 @@ void printHelp() {
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char g_password[MAX_PASSWORD_SIZE];
|
||||||
|
|
||||||
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
// for host
|
// for host
|
||||||
|
@ -73,11 +78,20 @@ void shellParseArgument(int argc, char *argv[], SShellArguments *arguments) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for password
|
// for password
|
||||||
else if (strcmp(argv[i], "-p") == 0) {
|
else if (strncmp(argv[i], "-p", 2) == 0) {
|
||||||
arguments->is_use_passwd = true;
|
arguments->is_use_passwd = true;
|
||||||
if (i < argc - 1 && argv[i + 1][0] != '-') {
|
strcpy(tsOsName, "Windows");
|
||||||
arguments->password = argv[++i];
|
printf(WINCLIENT_VERSION, tsOsName, taos_get_client_info());
|
||||||
|
if (strlen(argv[i]) == 2) {
|
||||||
|
printf("Enter password: ");
|
||||||
|
if (scanf("%s", g_password) > 1) {
|
||||||
|
fprintf(stderr, "password read error!\n");
|
||||||
}
|
}
|
||||||
|
getchar();
|
||||||
|
} else {
|
||||||
|
tstrncpy(g_password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
|
||||||
|
}
|
||||||
|
arguments->password = g_password;
|
||||||
}
|
}
|
||||||
// for management port
|
// for management port
|
||||||
else if (strcmp(argv[i], "-P") == 0) {
|
else if (strcmp(argv[i], "-P") == 0) {
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -206,9 +206,9 @@ static struct argp_option options[] = {
|
||||||
{"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0},
|
{"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0},
|
||||||
{"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0},
|
{"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0},
|
||||||
#ifdef _TD_POWER_
|
#ifdef _TD_POWER_
|
||||||
{"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is powerdb.", 0},
|
{"password", 'p', 0, 0, "User password to connect to server. Default is powerdb.", 0},
|
||||||
#else
|
#else
|
||||||
{"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is taosdata.", 0},
|
{"password", 'p', 0, 0, "User password to connect to server. Default is taosdata.", 0},
|
||||||
#endif
|
#endif
|
||||||
{"port", 'P', "PORT", 0, "Port to connect", 0},
|
{"port", 'P', "PORT", 0, "Port to connect", 0},
|
||||||
{"cversion", 'v', "CVERION", 0, "client version", 0},
|
{"cversion", 'v', "CVERION", 0, "client version", 0},
|
||||||
|
@ -248,12 +248,14 @@ static struct argp_option options[] = {
|
||||||
{0}
|
{0}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define MAX_PASSWORD_SIZE 20
|
||||||
|
|
||||||
/* Used by main to communicate with parse_opt. */
|
/* Used by main to communicate with parse_opt. */
|
||||||
typedef struct arguments {
|
typedef struct arguments {
|
||||||
// connection option
|
// connection option
|
||||||
char *host;
|
char *host;
|
||||||
char *user;
|
char *user;
|
||||||
char *password;
|
char password[MAX_PASSWORD_SIZE];
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
char cversion[12];
|
char cversion[12];
|
||||||
uint16_t mysqlFlag;
|
uint16_t mysqlFlag;
|
||||||
|
@ -376,7 +378,6 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
|
||||||
g_args.user = arg;
|
g_args.user = arg;
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
g_args.password = arg;
|
|
||||||
break;
|
break;
|
||||||
case 'P':
|
case 'P':
|
||||||
g_args.port = atoi(arg);
|
g_args.port = atoi(arg);
|
||||||
|
@ -554,6 +555,25 @@ static void parse_precision_first(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void parse_password(
|
||||||
|
int argc, char *argv[], SArguments *arguments) {
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
if (strncmp(argv[i], "-p", 2) == 0) {
|
||||||
|
if (strlen(argv[i]) == 2) {
|
||||||
|
printf("Enter password: ");
|
||||||
|
taosSetConsoleEcho(false);
|
||||||
|
if(scanf("%20s", arguments->password) > 1) {
|
||||||
|
errorPrint("%s() LN%d, password read error!\n", __func__, __LINE__);
|
||||||
|
}
|
||||||
|
taosSetConsoleEcho(true);
|
||||||
|
} else {
|
||||||
|
tstrncpy(arguments->password, (char *)(argv[i] + 2), MAX_PASSWORD_SIZE);
|
||||||
|
}
|
||||||
|
argv[i] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void parse_timestamp(
|
static void parse_timestamp(
|
||||||
int argc, char *argv[], SArguments *arguments) {
|
int argc, char *argv[], SArguments *arguments) {
|
||||||
for (int i = 1; i < argc; i++) {
|
for (int i = 1; i < argc; i++) {
|
||||||
|
@ -616,9 +636,10 @@ int main(int argc, char *argv[]) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
/* Parse our arguments; every option seen by parse_opt will be
|
/* Parse our arguments; every option seen by parse_opt will be
|
||||||
reflected in arguments. */
|
reflected in arguments. */
|
||||||
if (argc > 2) {
|
if (argc > 1) {
|
||||||
parse_precision_first(argc, argv, &g_args);
|
parse_precision_first(argc, argv, &g_args);
|
||||||
parse_timestamp(argc, argv, &g_args);
|
parse_timestamp(argc, argv, &g_args);
|
||||||
|
parse_password(argc, argv, &g_args);
|
||||||
}
|
}
|
||||||
|
|
||||||
argp_parse(&argp, argc, argv, 0, 0, &g_args);
|
argp_parse(&argp, argc, argv, 0, 0, &g_args);
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
|
||||||
#if defined(WINDOWS)
|
#if defined(WINDOWS)
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
printf("welcome to use taospack tools v1.3 for windows.\n");
|
printf("welcome to use taospack tools v1.3 for windows.\n");
|
||||||
|
@ -148,7 +149,10 @@ float* read_float(const char* inFile, int* pcount){
|
||||||
//printf(" buff=%s float=%.50f \n ", buf, floats[fi]);
|
//printf(" buff=%s float=%.50f \n ", buf, floats[fi]);
|
||||||
if ( ++fi == malloc_cnt ) {
|
if ( ++fi == malloc_cnt ) {
|
||||||
malloc_cnt += 100000;
|
malloc_cnt += 100000;
|
||||||
floats = realloc(floats, malloc_cnt*sizeof(float));
|
float* floats1 = realloc(floats, malloc_cnt*sizeof(float));
|
||||||
|
if(floats1 == NULL)
|
||||||
|
break;
|
||||||
|
floats = floats1;
|
||||||
}
|
}
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
}
|
}
|
||||||
|
@ -601,7 +605,6 @@ void test_threadsafe_double(int thread_count){
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void unitTestFloat() {
|
void unitTestFloat() {
|
||||||
|
|
||||||
float ft1 [] = {1.11, 2.22, 3.333};
|
float ft1 [] = {1.11, 2.22, 3.333};
|
||||||
|
@ -662,7 +665,50 @@ void unitTestFloat() {
|
||||||
free(ft2);
|
free(ft2);
|
||||||
free(buff);
|
free(buff);
|
||||||
free(output);
|
free(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void leakFloat() {
|
||||||
|
|
||||||
|
int cnt = sizeof(g_ft1)/sizeof(float);
|
||||||
|
float* floats = g_ft1;
|
||||||
|
int algorithm = 2;
|
||||||
|
|
||||||
|
// compress
|
||||||
|
const char* input = (const char*)floats;
|
||||||
|
int input_len = cnt * sizeof(float);
|
||||||
|
int output_len = input_len + 1024;
|
||||||
|
char* output = (char*) malloc(output_len);
|
||||||
|
char* buff = (char*) malloc(input_len);
|
||||||
|
int buff_len = input_len;
|
||||||
|
|
||||||
|
int ret_len = 0;
|
||||||
|
ret_len = tsCompressFloatLossy(input, input_len, cnt, output, output_len, algorithm, buff, buff_len);
|
||||||
|
|
||||||
|
if(ret_len == 0) {
|
||||||
|
printf(" compress float error.\n");
|
||||||
|
free(buff);
|
||||||
|
free(output);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
float* ft2 = (float*)malloc(input_len);
|
||||||
|
ret_len = tsDecompressFloatLossy(output, ret_len, cnt, (char*)ft2, input_len, algorithm, buff, buff_len);
|
||||||
|
if(ret_len == 0) {
|
||||||
|
printf(" decompress float error.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
free(ft2);
|
||||||
|
free(buff);
|
||||||
|
free(output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void leakTest(){
|
||||||
|
for(int i=0; i< 90000000000000; i++){
|
||||||
|
if(i%10000==0)
|
||||||
|
printf(" ---------- %d ---------------- \n", i);
|
||||||
|
leakFloat();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define DB_CNT 500
|
#define DB_CNT 500
|
||||||
|
@ -689,7 +735,7 @@ extern char Compressor [];
|
||||||
// ----------------- main ----------------------
|
// ----------------- main ----------------------
|
||||||
//
|
//
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
printf("welcome to use taospack tools v1.3\n");
|
printf("welcome to use taospack tools v1.6\n");
|
||||||
|
|
||||||
//printf(" sizeof(int)=%d\n", (int)sizeof(int));
|
//printf(" sizeof(int)=%d\n", (int)sizeof(int));
|
||||||
//printf(" sizeof(long)=%d\n", (int)sizeof(long));
|
//printf(" sizeof(long)=%d\n", (int)sizeof(long));
|
||||||
|
@ -753,6 +799,9 @@ int main(int argc, char *argv[]) {
|
||||||
if(strcmp(argv[1], "-mem") == 0) {
|
if(strcmp(argv[1], "-mem") == 0) {
|
||||||
memTest();
|
memTest();
|
||||||
}
|
}
|
||||||
|
else if(strcmp(argv[1], "-leak") == 0) {
|
||||||
|
leakTest();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
unitTestFloat();
|
unitTestFloat();
|
||||||
|
|
|
@ -2921,10 +2921,11 @@ static SMultiTableMeta* ensureMsgBufferSpace(SMultiTableMeta *pMultiMeta, SArray
|
||||||
(*totalMallocLen) *= 2;
|
(*totalMallocLen) *= 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
pMultiMeta = realloc(pMultiMeta, *totalMallocLen);
|
SMultiTableMeta* pMultiMeta1 = realloc(pMultiMeta, *totalMallocLen);
|
||||||
if (pMultiMeta == NULL) {
|
if (pMultiMeta1 == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
pMultiMeta = pMultiMeta1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pMultiMeta;
|
return pMultiMeta;
|
||||||
|
|
|
@ -24,6 +24,8 @@ void* taosLoadDll(const char *filename);
|
||||||
void* taosLoadSym(void* handle, char* name);
|
void* taosLoadSym(void* handle, char* name);
|
||||||
void taosCloseDll(void *handle);
|
void taosCloseDll(void *handle);
|
||||||
|
|
||||||
|
int taosSetConsoleEcho(bool on);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -29,4 +29,30 @@ void* taosLoadSym(void* handle, char* name) {
|
||||||
void taosCloseDll(void *handle) {
|
void taosCloseDll(void *handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int taosSetConsoleEcho(bool on)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
|
||||||
|
int err;
|
||||||
|
struct termios term;
|
||||||
|
|
||||||
|
if (tcgetattr(STDIN_FILENO, &term) == -1) {
|
||||||
|
perror("Cannot get the attribution of the terminal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on)
|
||||||
|
term.c_lflag|=ECHOFLAGS;
|
||||||
|
else
|
||||||
|
term.c_lflag &=~ECHOFLAGS;
|
||||||
|
|
||||||
|
err = tcsetattr(STDIN_FILENO,TCSAFLUSH,&term);
|
||||||
|
if (err == -1 && err == EINTR) {
|
||||||
|
perror("Cannot set the attribution of the terminal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -504,8 +504,9 @@ void * taosTRealloc(void *ptr, size_t size) {
|
||||||
|
|
||||||
void * tptr = (void *)((char *)ptr - sizeof(size_t));
|
void * tptr = (void *)((char *)ptr - sizeof(size_t));
|
||||||
size_t tsize = size + sizeof(size_t);
|
size_t tsize = size + sizeof(size_t);
|
||||||
tptr = realloc(tptr, tsize);
|
void* tptr1 = realloc(tptr, tsize);
|
||||||
if (tptr == NULL) return NULL;
|
if (tptr1 == NULL) return NULL;
|
||||||
|
tptr = tptr1;
|
||||||
|
|
||||||
*(size_t *)tptr = size;
|
*(size_t *)tptr = size;
|
||||||
|
|
||||||
|
|
|
@ -51,4 +51,28 @@ void taosCloseDll(void *handle) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int taosSetConsoleEcho(bool on)
|
||||||
|
{
|
||||||
|
#define ECHOFLAGS (ECHO | ECHOE | ECHOK | ECHONL)
|
||||||
|
int err;
|
||||||
|
struct termios term;
|
||||||
|
|
||||||
|
if (tcgetattr(STDIN_FILENO, &term) == -1) {
|
||||||
|
perror("Cannot get the attribution of the terminal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (on)
|
||||||
|
term.c_lflag|=ECHOFLAGS;
|
||||||
|
else
|
||||||
|
term.c_lflag &=~ECHOFLAGS;
|
||||||
|
|
||||||
|
err = tcsetattr(STDIN_FILENO,TCSAFLUSH,&term);
|
||||||
|
if (err == -1 && err == EINTR) {
|
||||||
|
perror("Cannot set the attribution of the terminal");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -81,11 +81,13 @@ int32_t getstr(char **lineptr, size_t *n, FILE *stream, char terminator, int32_t
|
||||||
*n += MIN_CHUNK;
|
*n += MIN_CHUNK;
|
||||||
|
|
||||||
nchars_avail = (int32_t)(*n + *lineptr - read_pos);
|
nchars_avail = (int32_t)(*n + *lineptr - read_pos);
|
||||||
*lineptr = realloc(*lineptr, *n);
|
char* lineptr1 = realloc(*lineptr, *n);
|
||||||
if (!*lineptr) {
|
if (!lineptr1) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*lineptr = lineptr1;
|
||||||
|
|
||||||
read_pos = *n - nchars_avail + *lineptr;
|
read_pos = *n - nchars_avail + *lineptr;
|
||||||
assert((*lineptr + *n) == (read_pos + nchars_avail));
|
assert((*lineptr + *n) == (read_pos + nchars_avail));
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,3 +30,17 @@ void taosCloseDll(void *handle) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int taosSetConsoleEcho(bool on)
|
||||||
|
{
|
||||||
|
HANDLE hStdin = GetStdHandle(STD_INPUT_HANDLE);
|
||||||
|
DWORD mode = 0;
|
||||||
|
GetConsoleMode(hStdin, &mode );
|
||||||
|
if (on) {
|
||||||
|
mode |= ENABLE_ECHO_INPUT;
|
||||||
|
} else {
|
||||||
|
mode &= ~ENABLE_ECHO_INPUT;
|
||||||
|
}
|
||||||
|
SetConsoleMode(hStdin, mode);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -101,13 +101,17 @@ char *httpGetStatusDesc(int32_t statusCode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void httpCleanupString(HttpString *str) {
|
static void httpCleanupString(HttpString *str) {
|
||||||
|
if (str->str) {
|
||||||
free(str->str);
|
free(str->str);
|
||||||
str->str = NULL;
|
str->str = NULL;
|
||||||
str->pos = 0;
|
str->pos = 0;
|
||||||
str->size = 0;
|
str->size = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t httpAppendString(HttpString *str, const char *s, int32_t len) {
|
static int32_t httpAppendString(HttpString *str, const char *s, int32_t len) {
|
||||||
|
char *new_str = NULL;
|
||||||
|
|
||||||
if (str->size == 0) {
|
if (str->size == 0) {
|
||||||
str->pos = 0;
|
str->pos = 0;
|
||||||
str->size = len + 1;
|
str->size = len + 1;
|
||||||
|
@ -115,7 +119,16 @@ static int32_t httpAppendString(HttpString *str, const char *s, int32_t len) {
|
||||||
} else if (str->pos + len + 1 >= str->size) {
|
} else if (str->pos + len + 1 >= str->size) {
|
||||||
str->size += len;
|
str->size += len;
|
||||||
str->size *= 4;
|
str->size *= 4;
|
||||||
str->str = realloc(str->str, str->size);
|
|
||||||
|
new_str = realloc(str->str, str->size);
|
||||||
|
if (new_str == NULL && str->str) {
|
||||||
|
// if str->str was not NULL originally,
|
||||||
|
// the old allocated memory was left unchanged,
|
||||||
|
// see man 3 realloc
|
||||||
|
free(str->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
str->str = new_str;
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,7 +330,7 @@ static int32_t httpOnParseHeaderField(HttpParser *parser, const char *key, const
|
||||||
|
|
||||||
static int32_t httpOnBody(HttpParser *parser, const char *chunk, int32_t len) {
|
static int32_t httpOnBody(HttpParser *parser, const char *chunk, int32_t len) {
|
||||||
HttpContext *pContext = parser->pContext;
|
HttpContext *pContext = parser->pContext;
|
||||||
HttpString * buf = &parser->body;
|
HttpString *buf = &parser->body;
|
||||||
if (parser->parseCode != TSDB_CODE_SUCCESS) return -1;
|
if (parser->parseCode != TSDB_CODE_SUCCESS) return -1;
|
||||||
|
|
||||||
if (buf->size <= 0) {
|
if (buf->size <= 0) {
|
||||||
|
@ -326,6 +339,7 @@ static int32_t httpOnBody(HttpParser *parser, const char *chunk, int32_t len) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t newSize = buf->pos + len + 1;
|
int32_t newSize = buf->pos + len + 1;
|
||||||
|
char *newStr = NULL;
|
||||||
if (newSize >= buf->size) {
|
if (newSize >= buf->size) {
|
||||||
if (buf->size >= HTTP_BUFFER_SIZE) {
|
if (buf->size >= HTTP_BUFFER_SIZE) {
|
||||||
httpError("context:%p, fd:%d, failed parse body, exceeding buffer size %d", pContext, pContext->fd, buf->size);
|
httpError("context:%p, fd:%d, failed parse body, exceeding buffer size %d", pContext, pContext->fd, buf->size);
|
||||||
|
@ -336,7 +350,12 @@ static int32_t httpOnBody(HttpParser *parser, const char *chunk, int32_t len) {
|
||||||
newSize = MAX(newSize, HTTP_BUFFER_INIT);
|
newSize = MAX(newSize, HTTP_BUFFER_INIT);
|
||||||
newSize *= 4;
|
newSize *= 4;
|
||||||
newSize = MIN(newSize, HTTP_BUFFER_SIZE);
|
newSize = MIN(newSize, HTTP_BUFFER_SIZE);
|
||||||
buf->str = realloc(buf->str, newSize);
|
newStr = realloc(buf->str, newSize);
|
||||||
|
if (newStr == NULL && buf->str) {
|
||||||
|
free(buf->str);
|
||||||
|
}
|
||||||
|
|
||||||
|
buf->str = newStr;
|
||||||
buf->size = newSize;
|
buf->size = newSize;
|
||||||
|
|
||||||
if (buf->str == NULL) {
|
if (buf->str == NULL) {
|
||||||
|
@ -374,13 +393,20 @@ static HTTP_PARSER_STATE httpTopStack(HttpParser *parser) {
|
||||||
|
|
||||||
static int32_t httpPushStack(HttpParser *parser, HTTP_PARSER_STATE state) {
|
static int32_t httpPushStack(HttpParser *parser, HTTP_PARSER_STATE state) {
|
||||||
HttpStack *stack = &parser->stacks;
|
HttpStack *stack = &parser->stacks;
|
||||||
|
int8_t *newStacks = NULL;
|
||||||
if (stack->size == 0) {
|
if (stack->size == 0) {
|
||||||
stack->pos = 0;
|
stack->pos = 0;
|
||||||
stack->size = 32;
|
stack->size = 32;
|
||||||
stack->stacks = malloc(stack->size * sizeof(int8_t));
|
stack->stacks = malloc(stack->size * sizeof(int8_t));
|
||||||
} else if (stack->pos + 1 > stack->size) {
|
} else if (stack->pos + 1 > stack->size) {
|
||||||
stack->size *= 2;
|
stack->size *= 2;
|
||||||
stack->stacks = realloc(stack->stacks, stack->size * sizeof(int8_t));
|
|
||||||
|
newStacks = realloc(stack->stacks, stack->size * sizeof(int8_t));
|
||||||
|
if (newStacks == NULL && stack->stacks) {
|
||||||
|
free(stack->stacks);
|
||||||
|
}
|
||||||
|
|
||||||
|
stack->stacks = newStacks;
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -188,13 +188,17 @@ bool httpMallocMultiCmds(HttpContext *pContext, int32_t cmdSize, int32_t bufferS
|
||||||
bool httpReMallocMultiCmdsSize(HttpContext *pContext, int32_t cmdSize) {
|
bool httpReMallocMultiCmdsSize(HttpContext *pContext, int32_t cmdSize) {
|
||||||
HttpSqlCmds *multiCmds = pContext->multiCmds;
|
HttpSqlCmds *multiCmds = pContext->multiCmds;
|
||||||
|
|
||||||
if (cmdSize > HTTP_MAX_CMD_SIZE) {
|
if (cmdSize <= 0 || cmdSize > HTTP_MAX_CMD_SIZE) {
|
||||||
httpError("context:%p, fd:%d, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, pContext->user,
|
httpError("context:%p, fd:%d, user:%s, mulitcmd size:%d large then %d", pContext, pContext->fd, pContext->user,
|
||||||
cmdSize, HTTP_MAX_CMD_SIZE);
|
cmdSize, HTTP_MAX_CMD_SIZE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
multiCmds->cmds = (HttpSqlCmd *)realloc(multiCmds->cmds, (size_t)cmdSize * sizeof(HttpSqlCmd));
|
HttpSqlCmd *new_cmds = (HttpSqlCmd *)realloc(multiCmds->cmds, (size_t)cmdSize * sizeof(HttpSqlCmd));
|
||||||
|
if (new_cmds == NULL && multiCmds->cmds) {
|
||||||
|
free(multiCmds->cmds);
|
||||||
|
}
|
||||||
|
multiCmds->cmds = new_cmds;
|
||||||
if (multiCmds->cmds == NULL) {
|
if (multiCmds->cmds == NULL) {
|
||||||
httpError("context:%p, fd:%d, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->user, cmdSize);
|
httpError("context:%p, fd:%d, user:%s, malloc cmds:%d error", pContext, pContext->fd, pContext->user, cmdSize);
|
||||||
return false;
|
return false;
|
||||||
|
@ -208,13 +212,17 @@ bool httpReMallocMultiCmdsSize(HttpContext *pContext, int32_t cmdSize) {
|
||||||
bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int32_t bufferSize) {
|
bool httpReMallocMultiCmdsBuffer(HttpContext *pContext, int32_t bufferSize) {
|
||||||
HttpSqlCmds *multiCmds = pContext->multiCmds;
|
HttpSqlCmds *multiCmds = pContext->multiCmds;
|
||||||
|
|
||||||
if (bufferSize > HTTP_MAX_BUFFER_SIZE) {
|
if (bufferSize <= 0 || bufferSize > HTTP_MAX_BUFFER_SIZE) {
|
||||||
httpError("context:%p, fd:%d, user:%s, mulitcmd buffer size:%d large then %d", pContext, pContext->fd,
|
httpError("context:%p, fd:%d, user:%s, mulitcmd buffer size:%d large then %d", pContext, pContext->fd,
|
||||||
pContext->user, bufferSize, HTTP_MAX_BUFFER_SIZE);
|
pContext->user, bufferSize, HTTP_MAX_BUFFER_SIZE);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
multiCmds->buffer = (char *)realloc(multiCmds->buffer, (size_t)bufferSize);
|
char *new_buffer = (char *)realloc(multiCmds->buffer, (size_t)bufferSize);
|
||||||
|
if (new_buffer == NULL && multiCmds->buffer) {
|
||||||
|
free(multiCmds->buffer);
|
||||||
|
}
|
||||||
|
multiCmds->buffer = new_buffer;
|
||||||
if (multiCmds->buffer == NULL) {
|
if (multiCmds->buffer == NULL) {
|
||||||
httpError("context:%p, fd:%d, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->user, bufferSize);
|
httpError("context:%p, fd:%d, user:%s, malloc buffer:%d error", pContext, pContext->fd, pContext->user, bufferSize);
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -333,6 +333,7 @@ enum OPERATOR_TYPE_E {
|
||||||
OP_StateWindow = 22,
|
OP_StateWindow = 22,
|
||||||
OP_AllTimeWindow = 23,
|
OP_AllTimeWindow = 23,
|
||||||
OP_AllMultiTableTimeInterval = 24,
|
OP_AllMultiTableTimeInterval = 24,
|
||||||
|
OP_Order = 25,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct SOperatorInfo {
|
typedef struct SOperatorInfo {
|
||||||
|
@ -417,7 +418,6 @@ typedef struct STableScanInfo {
|
||||||
int32_t *rowCellInfoOffset;
|
int32_t *rowCellInfoOffset;
|
||||||
SExprInfo *pExpr;
|
SExprInfo *pExpr;
|
||||||
SSDataBlock block;
|
SSDataBlock block;
|
||||||
bool loadExternalRows; // load external rows (prev & next rows)
|
|
||||||
int32_t numOfOutput;
|
int32_t numOfOutput;
|
||||||
int64_t elapsedTime;
|
int64_t elapsedTime;
|
||||||
|
|
||||||
|
@ -510,13 +510,21 @@ typedef struct SStateWindowOperatorInfo {
|
||||||
bool reptScan;
|
bool reptScan;
|
||||||
} SStateWindowOperatorInfo ;
|
} SStateWindowOperatorInfo ;
|
||||||
|
|
||||||
|
typedef struct SDistinctDataInfo {
|
||||||
|
int32_t index;
|
||||||
|
int32_t type;
|
||||||
|
int32_t bytes;
|
||||||
|
} SDistinctDataInfo;
|
||||||
|
|
||||||
typedef struct SDistinctOperatorInfo {
|
typedef struct SDistinctOperatorInfo {
|
||||||
SHashObj *pSet;
|
SHashObj *pSet;
|
||||||
SSDataBlock *pRes;
|
SSDataBlock *pRes;
|
||||||
bool recordNullVal; //has already record the null value, no need to try again
|
bool recordNullVal; //has already record the null value, no need to try again
|
||||||
int64_t threshold;
|
int64_t threshold;
|
||||||
int64_t outputCapacity;
|
int64_t outputCapacity;
|
||||||
int32_t colIndex;
|
int32_t totalBytes;
|
||||||
|
char* buf;
|
||||||
|
SArray* pDistinctDataInfo;
|
||||||
} SDistinctOperatorInfo;
|
} SDistinctOperatorInfo;
|
||||||
|
|
||||||
struct SGlobalMerger;
|
struct SGlobalMerger;
|
||||||
|
@ -541,6 +549,13 @@ typedef struct SMultiwayMergeInfo {
|
||||||
SArray *udfInfo;
|
SArray *udfInfo;
|
||||||
} SMultiwayMergeInfo;
|
} SMultiwayMergeInfo;
|
||||||
|
|
||||||
|
// todo support the disk-based sort
|
||||||
|
typedef struct SOrderOperatorInfo {
|
||||||
|
int32_t colIndex;
|
||||||
|
int32_t order;
|
||||||
|
SSDataBlock *pDataBlock;
|
||||||
|
} SOrderOperatorInfo;
|
||||||
|
|
||||||
void appendUpstream(SOperatorInfo* p, SOperatorInfo* pUpstream);
|
void appendUpstream(SOperatorInfo* p, SOperatorInfo* pUpstream);
|
||||||
|
|
||||||
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime);
|
SOperatorInfo* createDataBlocksOptScanInfo(void* pTsdbQueryHandle, SQueryRuntimeEnv* pRuntimeEnv, int32_t repeatTime, int32_t reverseTime);
|
||||||
|
@ -570,6 +585,7 @@ SOperatorInfo* createFilterOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperator
|
||||||
int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter);
|
int32_t numOfOutput, SColumnInfo* pCols, int32_t numOfFilter);
|
||||||
|
|
||||||
SOperatorInfo* createJoinOperatorInfo(SOperatorInfo** pUpstream, int32_t numOfUpstream, SSchema* pSchema, int32_t numOfOutput);
|
SOperatorInfo* createJoinOperatorInfo(SOperatorInfo** pUpstream, int32_t numOfUpstream, SSchema* pSchema, int32_t numOfOutput);
|
||||||
|
SOperatorInfo* createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, SOrderVal* pOrderVal);
|
||||||
|
|
||||||
SSDataBlock* doGlobalAggregate(void* param, bool* newgroup);
|
SSDataBlock* doGlobalAggregate(void* param, bool* newgroup);
|
||||||
SSDataBlock* doMultiwayMergeSort(void* param, bool* newgroup);
|
SSDataBlock* doMultiwayMergeSort(void* param, bool* newgroup);
|
||||||
|
|
|
@ -220,6 +220,8 @@ tOrderDescriptor *tOrderDesCreate(const int32_t *orderColIdx, int32_t numOfOrder
|
||||||
|
|
||||||
void tOrderDescDestroy(tOrderDescriptor *pDesc);
|
void tOrderDescDestroy(tOrderDescriptor *pDesc);
|
||||||
|
|
||||||
|
void taoscQSort(void** pCols, SSchema* pSchema, int32_t numOfCols, int32_t numOfRows, int32_t index, __compar_fn_t compareFn);
|
||||||
|
|
||||||
void tColModelAppend(SColumnModel *dstModel, tFilePage *dstPage, void *srcData, int32_t srcStartRows,
|
void tColModelAppend(SColumnModel *dstModel, tFilePage *dstPage, void *srcData, int32_t srcStartRows,
|
||||||
int32_t numOfRowsToWrite, int32_t srcCapacity);
|
int32_t numOfRowsToWrite, int32_t srcCapacity);
|
||||||
|
|
||||||
|
|
|
@ -39,7 +39,6 @@
|
||||||
#define GET_QID(_r) (((SQInfo*)((_r)->qinfo))->qId)
|
#define GET_QID(_r) (((SQInfo*)((_r)->qinfo))->qId)
|
||||||
|
|
||||||
#define curTimeWindowIndex(_winres) ((_winres)->curIndex)
|
#define curTimeWindowIndex(_winres) ((_winres)->curIndex)
|
||||||
#define GET_ROW_PARAM_FOR_MULTIOUTPUT(_q, tbq, sq) (((tbq) && (!(sq)))? (_q)->pExpr1[1].base.param[0].i64:1)
|
|
||||||
|
|
||||||
int32_t getOutputInterResultBufSize(SQueryAttr* pQueryAttr);
|
int32_t getOutputInterResultBufSize(SQueryAttr* pQueryAttr);
|
||||||
|
|
||||||
|
@ -60,6 +59,7 @@ SResultRowCellInfo* getResultCell(const SResultRow* pRow, int32_t index, int32_t
|
||||||
|
|
||||||
void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr);
|
void* destroyQueryFuncExpr(SExprInfo* pExprInfo, int32_t numOfExpr);
|
||||||
void* freeColumnInfo(SColumnInfo* pColumnInfo, int32_t numOfCols);
|
void* freeColumnInfo(SColumnInfo* pColumnInfo, int32_t numOfCols);
|
||||||
|
int32_t getRowNumForMultioutput(SQueryAttr* pQueryAttr, bool topBottomQuery, bool stable);
|
||||||
|
|
||||||
static FORCE_INLINE SResultRow *getResultRow(SResultRowInfo *pResultRowInfo, int32_t slot) {
|
static FORCE_INLINE SResultRow *getResultRow(SResultRowInfo *pResultRowInfo, int32_t slot) {
|
||||||
assert(pResultRowInfo != NULL && slot >= 0 && slot < pResultRowInfo->size);
|
assert(pResultRowInfo != NULL && slot >= 0 && slot < pResultRowInfo->size);
|
||||||
|
@ -70,7 +70,7 @@ static FORCE_INLINE char* getPosInResultPage(SQueryAttr* pQueryAttr, tFilePage*
|
||||||
int32_t offset) {
|
int32_t offset) {
|
||||||
assert(rowOffset >= 0 && pQueryAttr != NULL);
|
assert(rowOffset >= 0 && pQueryAttr != NULL);
|
||||||
|
|
||||||
int32_t numOfRows = (int32_t)GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery);
|
int32_t numOfRows = (int32_t)getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery);
|
||||||
return ((char *)page->data) + rowOffset + offset * numOfRows;
|
return ((char *)page->data) + rowOffset + offset * numOfRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3670,6 +3670,8 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ascQuery = (pCtx->order == TSDB_ORDER_ASC);
|
||||||
|
|
||||||
if (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) {
|
if (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) {
|
||||||
*(TSKEY *)pCtx->pOutput = pCtx->startTs;
|
*(TSKEY *)pCtx->pOutput = pCtx->startTs;
|
||||||
} else if (type == TSDB_FILL_NULL) {
|
} else if (type == TSDB_FILL_NULL) {
|
||||||
|
@ -3677,7 +3679,7 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
} else if (type == TSDB_FILL_SET_VALUE) {
|
} else if (type == TSDB_FILL_SET_VALUE) {
|
||||||
tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true);
|
tVariantDump(&pCtx->param[1], pCtx->pOutput, pCtx->inputType, true);
|
||||||
} else {
|
} else {
|
||||||
if (pCtx->start.key != INT64_MIN && pCtx->start.key < pCtx->startTs && pCtx->end.key > pCtx->startTs) {
|
if (pCtx->start.key != INT64_MIN && ((ascQuery && pCtx->start.key <= pCtx->startTs && pCtx->end.key >= pCtx->startTs) || ((!ascQuery) && pCtx->start.key >= pCtx->startTs && pCtx->end.key <= pCtx->startTs))) {
|
||||||
if (type == TSDB_FILL_PREV) {
|
if (type == TSDB_FILL_PREV) {
|
||||||
if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) {
|
if (IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL) {
|
||||||
SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val);
|
SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, pCtx->start.val);
|
||||||
|
@ -3716,13 +3718,14 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
TSKEY skey = GET_TS_DATA(pCtx, 0);
|
TSKEY skey = GET_TS_DATA(pCtx, 0);
|
||||||
|
|
||||||
if (type == TSDB_FILL_PREV) {
|
if (type == TSDB_FILL_PREV) {
|
||||||
if (skey > pCtx->startTs) {
|
if ((ascQuery && skey > pCtx->startTs) || ((!ascQuery) && skey < pCtx->startTs)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pCtx->size > 1) {
|
if (pCtx->size > 1) {
|
||||||
TSKEY ekey = GET_TS_DATA(pCtx, 1);
|
TSKEY ekey = GET_TS_DATA(pCtx, 1);
|
||||||
if (ekey > skey && ekey <= pCtx->startTs) {
|
if ((ascQuery && ekey > skey && ekey <= pCtx->startTs) ||
|
||||||
|
((!ascQuery) && ekey < skey && ekey >= pCtx->startTs)){
|
||||||
skey = ekey;
|
skey = ekey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3731,10 +3734,10 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
TSKEY ekey = skey;
|
TSKEY ekey = skey;
|
||||||
char* val = NULL;
|
char* val = NULL;
|
||||||
|
|
||||||
if (ekey < pCtx->startTs) {
|
if ((ascQuery && ekey < pCtx->startTs) || ((!ascQuery) && ekey > pCtx->startTs)) {
|
||||||
if (pCtx->size > 1) {
|
if (pCtx->size > 1) {
|
||||||
ekey = GET_TS_DATA(pCtx, 1);
|
ekey = GET_TS_DATA(pCtx, 1);
|
||||||
if (ekey < pCtx->startTs) {
|
if ((ascQuery && ekey < pCtx->startTs) || ((!ascQuery) && ekey > pCtx->startTs)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3755,12 +3758,11 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
TSKEY ekey = GET_TS_DATA(pCtx, 1);
|
TSKEY ekey = GET_TS_DATA(pCtx, 1);
|
||||||
|
|
||||||
// no data generated yet
|
// no data generated yet
|
||||||
if (!(skey < pCtx->startTs && ekey > pCtx->startTs)) {
|
if ((ascQuery && !(skey <= pCtx->startTs && ekey >= pCtx->startTs))
|
||||||
|
|| ((!ascQuery) && !(skey >= pCtx->startTs && ekey <= pCtx->startTs))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(pCtx->start.key == INT64_MIN && skey < pCtx->startTs && ekey > pCtx->startTs);
|
|
||||||
|
|
||||||
char *start = GET_INPUT_DATA(pCtx, 0);
|
char *start = GET_INPUT_DATA(pCtx, 0);
|
||||||
char *end = GET_INPUT_DATA(pCtx, 1);
|
char *end = GET_INPUT_DATA(pCtx, 1);
|
||||||
|
|
||||||
|
@ -3788,11 +3790,37 @@ static void interp_function_impl(SQLFunctionCtx *pCtx) {
|
||||||
static void interp_function(SQLFunctionCtx *pCtx) {
|
static void interp_function(SQLFunctionCtx *pCtx) {
|
||||||
// at this point, the value is existed, return directly
|
// at this point, the value is existed, return directly
|
||||||
if (pCtx->size > 0) {
|
if (pCtx->size > 0) {
|
||||||
// impose the timestamp check
|
bool ascQuery = (pCtx->order == TSDB_ORDER_ASC);
|
||||||
TSKEY key = GET_TS_DATA(pCtx, 0);
|
TSKEY key;
|
||||||
|
char *pData;
|
||||||
|
int32_t typedData = 0;
|
||||||
|
|
||||||
|
if (ascQuery) {
|
||||||
|
key = GET_TS_DATA(pCtx, 0);
|
||||||
|
pData = GET_INPUT_DATA(pCtx, 0);
|
||||||
|
} else {
|
||||||
|
key = pCtx->start.key;
|
||||||
|
if (key == INT64_MIN) {
|
||||||
|
key = GET_TS_DATA(pCtx, 0);
|
||||||
|
pData = GET_INPUT_DATA(pCtx, 0);
|
||||||
|
} else {
|
||||||
|
if (!(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL)) {
|
||||||
|
pData = pCtx->start.ptr;
|
||||||
|
} else {
|
||||||
|
typedData = 1;
|
||||||
|
pData = (char *)&pCtx->start.val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if (key == pCtx->startTs && (ascQuery || !(IS_NUMERIC_TYPE(pCtx->inputType) || pCtx->inputType == TSDB_DATA_TYPE_BOOL))) {
|
||||||
if (key == pCtx->startTs) {
|
if (key == pCtx->startTs) {
|
||||||
char *pData = GET_INPUT_DATA(pCtx, 0);
|
if (typedData) {
|
||||||
|
SET_TYPED_DATA(pCtx->pOutput, pCtx->inputType, *(double *)pData);
|
||||||
|
} else {
|
||||||
assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType);
|
assignVal(pCtx->pOutput, pData, pCtx->inputBytes, pCtx->inputType);
|
||||||
|
}
|
||||||
|
|
||||||
SET_VAL(pCtx, 1, 1);
|
SET_VAL(pCtx, 1, 1);
|
||||||
} else {
|
} else {
|
||||||
interp_function_impl(pCtx);
|
interp_function_impl(pCtx);
|
||||||
|
@ -4062,12 +4090,15 @@ static void mergeTableBlockDist(SResultRowCellInfo* pResInfo, const STableBlockD
|
||||||
pDist->maxRows = pSrc->maxRows;
|
pDist->maxRows = pSrc->maxRows;
|
||||||
pDist->minRows = pSrc->minRows;
|
pDist->minRows = pSrc->minRows;
|
||||||
|
|
||||||
int32_t numSteps = tsMaxRowsInFileBlock/TSDB_BLOCK_DIST_STEP_ROWS;
|
int32_t maxSteps = TSDB_MAX_MAX_ROW_FBLOCK/TSDB_BLOCK_DIST_STEP_ROWS;
|
||||||
pDist->dataBlockInfos = taosArrayInit(numSteps, sizeof(SFileBlockInfo));
|
if (TSDB_MAX_MAX_ROW_FBLOCK % TSDB_BLOCK_DIST_STEP_ROWS != 0) {
|
||||||
taosArraySetSize(pDist->dataBlockInfos, numSteps);
|
++maxSteps;
|
||||||
|
}
|
||||||
|
pDist->dataBlockInfos = taosArrayInit(maxSteps, sizeof(SFileBlockInfo));
|
||||||
|
taosArraySetSize(pDist->dataBlockInfos, maxSteps);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t steps = taosArrayGetSize(pDist->dataBlockInfos);
|
size_t steps = taosArrayGetSize(pSrc->dataBlockInfos);
|
||||||
for (int32_t i = 0; i < steps; ++i) {
|
for (int32_t i = 0; i < steps; ++i) {
|
||||||
int32_t srcNumBlocks = ((SFileBlockInfo*)taosArrayGet(pSrc->dataBlockInfos, i))->numBlocksOfStep;
|
int32_t srcNumBlocks = ((SFileBlockInfo*)taosArrayGet(pSrc->dataBlockInfos, i))->numBlocksOfStep;
|
||||||
SFileBlockInfo* blockInfo = (SFileBlockInfo*)taosArrayGet(pDist->dataBlockInfos, i);
|
SFileBlockInfo* blockInfo = (SFileBlockInfo*)taosArrayGet(pDist->dataBlockInfos, i);
|
||||||
|
|
|
@ -44,6 +44,10 @@
|
||||||
|
|
||||||
#define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0}
|
#define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0}
|
||||||
|
|
||||||
|
#define MULTI_KEY_DELIM "-"
|
||||||
|
|
||||||
|
#define HASH_CAPACITY_LIMIT 10000000
|
||||||
|
|
||||||
#define TIME_WINDOW_COPY(_dst, _src) do {\
|
#define TIME_WINDOW_COPY(_dst, _src) do {\
|
||||||
(_dst).skey = (_src).skey;\
|
(_dst).skey = (_src).skey;\
|
||||||
(_dst).ekey = (_src).ekey;\
|
(_dst).ekey = (_src).ekey;\
|
||||||
|
@ -224,6 +228,7 @@ static void destroySFillOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroyGroupbyOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroyProjectOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
|
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroySWindowOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroySWindowOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroyStateWindowOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
static void destroyAggOperatorInfo(void* param, int32_t numOfOutput);
|
static void destroyAggOperatorInfo(void* param, int32_t numOfOutput);
|
||||||
|
@ -1326,6 +1331,16 @@ void doTimeWindowInterpolation(SOperatorInfo* pOperator, SOptrBasicInfo* pInfo,
|
||||||
|
|
||||||
pCtx[k].end.key = curTs;
|
pCtx[k].end.key = curTs;
|
||||||
pCtx[k].end.val = v2;
|
pCtx[k].end.val = v2;
|
||||||
|
|
||||||
|
if (pColInfo->info.type == TSDB_DATA_TYPE_BINARY || pColInfo->info.type == TSDB_DATA_TYPE_NCHAR) {
|
||||||
|
if (prevRowIndex == -1) {
|
||||||
|
pCtx[k].start.ptr = (char *)pRuntimeEnv->prevRow[index];
|
||||||
|
} else {
|
||||||
|
pCtx[k].start.ptr = (char *)pColInfo->pData + prevRowIndex * pColInfo->info.bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
pCtx[k].end.ptr = (char *)pColInfo->pData + curRowIndex * pColInfo->info.bytes;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (functionId == TSDB_FUNC_TWA) {
|
} else if (functionId == TSDB_FUNC_TWA) {
|
||||||
SPoint point1 = (SPoint){.key = prevTs, .val = &v1};
|
SPoint point1 = (SPoint){.key = prevTs, .val = &v1};
|
||||||
|
@ -1595,6 +1610,7 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe
|
||||||
SResultRow* pResult = NULL;
|
SResultRow* pResult = NULL;
|
||||||
int32_t forwardStep = 0;
|
int32_t forwardStep = 0;
|
||||||
int32_t ret = 0;
|
int32_t ret = 0;
|
||||||
|
STimeWindow preWin = win;
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
// null data, failed to allocate more memory buffer
|
// null data, failed to allocate more memory buffer
|
||||||
|
@ -1609,12 +1625,13 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe
|
||||||
|
|
||||||
// window start(end) key interpolation
|
// window start(end) key interpolation
|
||||||
doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
|
doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
|
||||||
doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
|
doApplyFunctions(pRuntimeEnv, pInfo->pCtx, ascQuery ? &win : &preWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
|
||||||
|
preWin = win;
|
||||||
|
|
||||||
int32_t prevEndPos = (forwardStep - 1) * step + startPos;
|
int32_t prevEndPos = (forwardStep - 1) * step + startPos;
|
||||||
startPos = getNextQualifiedWindow(pQueryAttr, &win, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
|
startPos = getNextQualifiedWindow(pQueryAttr, &win, &pSDataBlock->info, tsCols, binarySearchForKey, prevEndPos);
|
||||||
if (startPos < 0) {
|
if (startPos < 0) {
|
||||||
if (win.skey <= pQueryAttr->window.ekey) {
|
if ((ascQuery && win.skey <= pQueryAttr->window.ekey) || ((!ascQuery) && win.ekey >= pQueryAttr->window.ekey)) {
|
||||||
int32_t code = setResultOutputBufByKey(pRuntimeEnv, pResultRowInfo, pSDataBlock->info.tid, &win, masterScan, &pResult, tableGroupId,
|
int32_t code = setResultOutputBufByKey(pRuntimeEnv, pResultRowInfo, pSDataBlock->info.tid, &win, masterScan, &pResult, tableGroupId,
|
||||||
pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
|
pInfo->pCtx, numOfOutput, pInfo->rowCellInfoOffset);
|
||||||
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
|
if (code != TSDB_CODE_SUCCESS || pResult == NULL) {
|
||||||
|
@ -1625,7 +1642,7 @@ static void hashAllIntervalAgg(SOperatorInfo* pOperatorInfo, SResultRowInfo* pRe
|
||||||
|
|
||||||
// window start(end) key interpolation
|
// window start(end) key interpolation
|
||||||
doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
|
doWindowBorderInterpolation(pOperatorInfo, pSDataBlock, pInfo->pCtx, pResult, &win, startPos, forwardStep);
|
||||||
doApplyFunctions(pRuntimeEnv, pInfo->pCtx, &win, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
|
doApplyFunctions(pRuntimeEnv, pInfo->pCtx, ascQuery ? &win : &preWin, startPos, forwardStep, tsCols, pSDataBlock->info.rows, numOfOutput);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -2213,6 +2230,7 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OP_StateWindow: {
|
case OP_StateWindow: {
|
||||||
pRuntimeEnv->proot = createStatewindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
|
pRuntimeEnv->proot = createStatewindowOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput);
|
||||||
int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType;
|
int32_t opType = pRuntimeEnv->proot->upstream[0]->operatorType;
|
||||||
|
@ -2229,10 +2247,6 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
||||||
|
|
||||||
case OP_Filter: { // todo refactor
|
case OP_Filter: { // todo refactor
|
||||||
int32_t numOfFilterCols = 0;
|
int32_t numOfFilterCols = 0;
|
||||||
// if (pQueryAttr->numOfFilterCols > 0) {
|
|
||||||
// pRuntimeEnv->proot = createFilterOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1,
|
|
||||||
// pQueryAttr->numOfOutput, pQueryAttr->tableCols, pQueryAttr->numOfFilterCols);
|
|
||||||
// } else {
|
|
||||||
if (pQueryAttr->stableQuery) {
|
if (pQueryAttr->stableQuery) {
|
||||||
SColumnInfo* pColInfo =
|
SColumnInfo* pColInfo =
|
||||||
extractColumnFilterInfo(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3, &numOfFilterCols);
|
extractColumnFilterInfo(pQueryAttr->pExpr3, pQueryAttr->numOfExpr3, &numOfFilterCols);
|
||||||
|
@ -2246,7 +2260,7 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
||||||
pQueryAttr->numOfOutput, pColInfo, numOfFilterCols);
|
pQueryAttr->numOfOutput, pColInfo, numOfFilterCols);
|
||||||
freeColumnInfo(pColInfo, pQueryAttr->numOfOutput);
|
freeColumnInfo(pColInfo, pQueryAttr->numOfOutput);
|
||||||
}
|
}
|
||||||
// }
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2258,9 +2272,10 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
||||||
|
|
||||||
case OP_MultiwayMergeSort: {
|
case OP_MultiwayMergeSort: {
|
||||||
bool groupMix = true;
|
bool groupMix = true;
|
||||||
if(pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) {
|
if (pQueryAttr->slimit.offset != 0 || pQueryAttr->slimit.limit != -1) {
|
||||||
groupMix = false;
|
groupMix = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput,
|
pRuntimeEnv->proot = createMultiwaySortOperatorInfo(pRuntimeEnv, pQueryAttr->pExpr1, pQueryAttr->numOfOutput,
|
||||||
4096, merger, groupMix); // TODO hack it
|
4096, merger, groupMix); // TODO hack it
|
||||||
break;
|
break;
|
||||||
|
@ -2283,6 +2298,11 @@ static int32_t setupQueryRuntimeEnv(SQueryRuntimeEnv *pRuntimeEnv, int32_t numOf
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case OP_Order: {
|
||||||
|
pRuntimeEnv->proot = createOrderOperatorInfo(pRuntimeEnv, pRuntimeEnv->proot, pQueryAttr->pExpr1, pQueryAttr->numOfOutput, &pQueryAttr->order);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
@ -2706,7 +2726,7 @@ static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, i
|
||||||
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
|
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
|
||||||
int32_t MIN_ROWS_PER_PAGE = 4;
|
int32_t MIN_ROWS_PER_PAGE = 4;
|
||||||
|
|
||||||
*rowsize = (int32_t)(pQueryAttr->resultRowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
|
*rowsize = (int32_t)(pQueryAttr->resultRowSize * getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
|
||||||
int32_t overhead = sizeof(tFilePage);
|
int32_t overhead = sizeof(tFilePage);
|
||||||
|
|
||||||
// one page contains at least two rows
|
// one page contains at least two rows
|
||||||
|
@ -3575,6 +3595,7 @@ void setDefaultOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, SOptrBasicInfo *pInfo, i
|
||||||
SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
|
SResultRowInfo* pResultRowInfo = &pInfo->resultRowInfo;
|
||||||
|
|
||||||
int64_t tid = 0;
|
int64_t tid = 0;
|
||||||
|
pRuntimeEnv->keyBuf = realloc(pRuntimeEnv->keyBuf, sizeof(tid) + sizeof(int64_t) + POINTER_BYTES);
|
||||||
SResultRow* pRow = doSetResultOutBufByKey(pRuntimeEnv, pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid);
|
SResultRow* pRow = doSetResultOutBufByKey(pRuntimeEnv, pResultRowInfo, tid, (char *)&tid, sizeof(tid), true, uid);
|
||||||
|
|
||||||
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
|
for (int32_t i = 0; i < pDataBlock->info.numOfCols; ++i) {
|
||||||
|
@ -3630,7 +3651,7 @@ void updateOutputBuf(SOptrBasicInfo* pBInfo, int32_t *bufCapacity, int32_t numOf
|
||||||
// re-estabilish output buffer pointer.
|
// re-estabilish output buffer pointer.
|
||||||
int32_t functionId = pBInfo->pCtx[i].functionId;
|
int32_t functionId = pBInfo->pCtx[i].functionId;
|
||||||
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) {
|
if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM || functionId == TSDB_FUNC_DIFF || functionId == TSDB_FUNC_DERIVATIVE) {
|
||||||
pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[0].pOutput;
|
pBInfo->pCtx[i].ptsOutputBuf = pBInfo->pCtx[i-1].pOutput;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5024,6 +5045,9 @@ static SSDataBlock* doBlockInfoScan(void* param, bool* newgroup) {
|
||||||
tableBlockDist.numOfTables = (int32_t)pOperator->pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
|
tableBlockDist.numOfTables = (int32_t)pOperator->pRuntimeEnv->tableqinfoGroupInfo.numOfTables;
|
||||||
|
|
||||||
int32_t numRowSteps = tsMaxRowsInFileBlock / TSDB_BLOCK_DIST_STEP_ROWS;
|
int32_t numRowSteps = tsMaxRowsInFileBlock / TSDB_BLOCK_DIST_STEP_ROWS;
|
||||||
|
if (tsMaxRowsInFileBlock % TSDB_BLOCK_DIST_STEP_ROWS != 0) {
|
||||||
|
++numRowSteps;
|
||||||
|
}
|
||||||
tableBlockDist.dataBlockInfos = taosArrayInit(numRowSteps, sizeof(SFileBlockInfo));
|
tableBlockDist.dataBlockInfos = taosArrayInit(numRowSteps, sizeof(SFileBlockInfo));
|
||||||
taosArraySetSize(tableBlockDist.dataBlockInfos, numRowSteps);
|
taosArraySetSize(tableBlockDist.dataBlockInfos, numRowSteps);
|
||||||
tableBlockDist.maxRows = INT_MIN;
|
tableBlockDist.maxRows = INT_MIN;
|
||||||
|
@ -5298,7 +5322,7 @@ SOperatorInfo* createGlobalAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv,
|
||||||
SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));
|
SMultiwayMergeInfo* pInfo = calloc(1, sizeof(SMultiwayMergeInfo));
|
||||||
|
|
||||||
pInfo->resultRowFactor =
|
pInfo->resultRowFactor =
|
||||||
(int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery, false));
|
(int32_t)(getRowNumForMultioutput(pRuntimeEnv->pQueryAttr, pRuntimeEnv->pQueryAttr->topBotQuery, false));
|
||||||
|
|
||||||
pRuntimeEnv->scanFlag = MERGE_STAGE; // TODO init when creating pCtx
|
pRuntimeEnv->scanFlag = MERGE_STAGE; // TODO init when creating pCtx
|
||||||
|
|
||||||
|
@ -5404,6 +5428,114 @@ SOperatorInfo *createMultiwaySortOperatorInfo(SQueryRuntimeEnv *pRuntimeEnv, SEx
|
||||||
return pOperator;
|
return pOperator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int32_t doMergeSDatablock(SSDataBlock* pDest, SSDataBlock* pSrc) {
|
||||||
|
assert(pSrc != NULL && pDest != NULL && pDest->info.numOfCols == pSrc->info.numOfCols);
|
||||||
|
|
||||||
|
int32_t numOfCols = pSrc->info.numOfCols;
|
||||||
|
for(int32_t i = 0; i < numOfCols; ++i) {
|
||||||
|
SColumnInfoData* pCol2 = taosArrayGet(pDest->pDataBlock, i);
|
||||||
|
SColumnInfoData* pCol1 = taosArrayGet(pSrc->pDataBlock, i);
|
||||||
|
|
||||||
|
int32_t newSize = (pDest->info.rows + pSrc->info.rows) * pCol2->info.bytes;
|
||||||
|
char* tmp = realloc(pCol2->pData, newSize);
|
||||||
|
if (tmp != NULL) {
|
||||||
|
pCol2->pData = tmp;
|
||||||
|
int32_t offset = pCol2->info.bytes * pDest->info.rows;
|
||||||
|
memcpy(pCol2->pData + offset, pCol1->pData, pSrc->info.rows * pCol2->info.bytes);
|
||||||
|
} else {
|
||||||
|
return TSDB_CODE_VND_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pDest->info.rows += pSrc->info.rows;
|
||||||
|
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SSDataBlock* doSort(void* param, bool* newgroup) {
|
||||||
|
SOperatorInfo* pOperator = (SOperatorInfo*) param;
|
||||||
|
if (pOperator->status == OP_EXEC_DONE) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOrderOperatorInfo* pInfo = pOperator->info;
|
||||||
|
|
||||||
|
SSDataBlock* pBlock = NULL;
|
||||||
|
while(1) {
|
||||||
|
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_BEFORE_OPERATOR_EXEC);
|
||||||
|
pBlock = pOperator->upstream[0]->exec(pOperator->upstream[0], newgroup);
|
||||||
|
publishOperatorProfEvent(pOperator->upstream[0], QUERY_PROF_AFTER_OPERATOR_EXEC);
|
||||||
|
|
||||||
|
// start to flush data into disk and try do multiway merge sort
|
||||||
|
if (pBlock == NULL) {
|
||||||
|
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||||
|
pOperator->status = OP_EXEC_DONE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t code = doMergeSDatablock(pInfo->pDataBlock, pBlock);
|
||||||
|
if (code != TSDB_CODE_SUCCESS) {
|
||||||
|
// todo handle error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t numOfCols = pInfo->pDataBlock->info.numOfCols;
|
||||||
|
void** pCols = calloc(numOfCols, POINTER_BYTES);
|
||||||
|
SSchema* pSchema = calloc(numOfCols, sizeof(SSchema));
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < numOfCols; ++i) {
|
||||||
|
SColumnInfoData* p1 = taosArrayGet(pInfo->pDataBlock->pDataBlock, i);
|
||||||
|
pCols[i] = p1->pData;
|
||||||
|
pSchema[i].colId = p1->info.colId;
|
||||||
|
pSchema[i].bytes = p1->info.bytes;
|
||||||
|
pSchema[i].type = (uint8_t) p1->info.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
__compar_fn_t comp = getKeyComparFunc(pSchema[pInfo->colIndex].type, pInfo->order);
|
||||||
|
taoscQSort(pCols, pSchema, numOfCols, pInfo->pDataBlock->info.rows, pInfo->colIndex, comp);
|
||||||
|
|
||||||
|
tfree(pCols);
|
||||||
|
tfree(pSchema);
|
||||||
|
return (pInfo->pDataBlock->info.rows > 0)? pInfo->pDataBlock:NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOperatorInfo *createOrderOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput, SOrderVal* pOrderVal) {
|
||||||
|
SOrderOperatorInfo* pInfo = calloc(1, sizeof(SOrderOperatorInfo));
|
||||||
|
|
||||||
|
{
|
||||||
|
SSDataBlock* pDataBlock = calloc(1, sizeof(SSDataBlock));
|
||||||
|
pDataBlock->pDataBlock = taosArrayInit(numOfOutput, sizeof(SColumnInfoData));
|
||||||
|
for(int32_t i = 0; i < numOfOutput; ++i) {
|
||||||
|
SColumnInfoData col = {{0}};
|
||||||
|
col.info.colId = pExpr[i].base.colInfo.colId;
|
||||||
|
col.info.bytes = pExpr[i].base.colBytes;
|
||||||
|
col.info.type = pExpr[i].base.colType;
|
||||||
|
taosArrayPush(pDataBlock->pDataBlock, &col);
|
||||||
|
|
||||||
|
if (col.info.colId == pOrderVal->orderColId) {
|
||||||
|
pInfo->colIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pDataBlock->info.numOfCols = numOfOutput;
|
||||||
|
pInfo->order = pOrderVal->order;
|
||||||
|
pInfo->pDataBlock = pDataBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
|
pOperator->name = "InMemoryOrder";
|
||||||
|
pOperator->operatorType = OP_Order;
|
||||||
|
pOperator->blockingOptr = true;
|
||||||
|
pOperator->status = OP_IN_EXECUTING;
|
||||||
|
pOperator->info = pInfo;
|
||||||
|
pOperator->exec = doSort;
|
||||||
|
pOperator->cleanup = destroyOrderOperatorInfo;
|
||||||
|
pOperator->pRuntimeEnv = pRuntimeEnv;
|
||||||
|
|
||||||
|
appendUpstream(pOperator, upstream);
|
||||||
|
return pOperator;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
|
static int32_t getTableScanOrder(STableScanInfo* pTableScanInfo) {
|
||||||
return pTableScanInfo->order;
|
return pTableScanInfo->order;
|
||||||
}
|
}
|
||||||
|
@ -6327,7 +6459,7 @@ SOperatorInfo* createAggregateOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOpera
|
||||||
SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));
|
SAggOperatorInfo* pInfo = calloc(1, sizeof(SAggOperatorInfo));
|
||||||
|
|
||||||
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
|
SQueryAttr* pQueryAttr = pRuntimeEnv->pQueryAttr;
|
||||||
int32_t numOfRows = (int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
|
int32_t numOfRows = (int32_t)(getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery));
|
||||||
|
|
||||||
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
|
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, numOfRows);
|
||||||
pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
|
pInfo->binfo.pCtx = createSQLFunctionCtx(pRuntimeEnv, pExpr, numOfOutput, &pInfo->binfo.rowCellInfoOffset);
|
||||||
|
@ -6404,6 +6536,11 @@ static void destroyTagScanOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
|
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void destroyOrderOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
|
SOrderOperatorInfo* pInfo = (SOrderOperatorInfo*) param;
|
||||||
|
pInfo->pDataBlock = destroyOutputBuf(pInfo->pDataBlock);
|
||||||
|
}
|
||||||
|
|
||||||
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
|
static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
SFilterOperatorInfo* pInfo = (SFilterOperatorInfo*) param;
|
SFilterOperatorInfo* pInfo = (SFilterOperatorInfo*) param;
|
||||||
doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
|
doDestroyFilterInfo(pInfo->pFilterInfo, pInfo->numOfFilterCols);
|
||||||
|
@ -6412,6 +6549,8 @@ static void destroyConditionOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) {
|
static void destroyDistinctOperatorInfo(void* param, int32_t numOfOutput) {
|
||||||
SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param;
|
SDistinctOperatorInfo* pInfo = (SDistinctOperatorInfo*) param;
|
||||||
taosHashCleanup(pInfo->pSet);
|
taosHashCleanup(pInfo->pSet);
|
||||||
|
tfree(pInfo->buf);
|
||||||
|
taosArrayDestroy(pInfo->pDistinctDataInfo);
|
||||||
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
|
pInfo->pRes = destroyOutputBuf(pInfo->pRes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6701,7 +6840,7 @@ SOperatorInfo* createGroupbyOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperato
|
||||||
SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
|
SQueryAttr *pQueryAttr = pRuntimeEnv->pQueryAttr;
|
||||||
|
|
||||||
pQueryAttr->resultRowSize = (pQueryAttr->resultRowSize *
|
pQueryAttr->resultRowSize = (pQueryAttr->resultRowSize *
|
||||||
(int32_t)(GET_ROW_PARAM_FOR_MULTIOUTPUT(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery)));
|
(int32_t)(getRowNumForMultioutput(pQueryAttr, pQueryAttr->topBotQuery, pQueryAttr->stableQuery)));
|
||||||
|
|
||||||
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
|
pInfo->binfo.pRes = createOutputBuf(pExpr, numOfOutput, pRuntimeEnv->resultInfo.capacity);
|
||||||
initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
|
initResultRowInfo(&pInfo->binfo.resultRowInfo, 8, TSDB_DATA_TYPE_INT);
|
||||||
|
@ -6752,7 +6891,6 @@ SOperatorInfo* createFillOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorIn
|
||||||
pOperator->numOfOutput = numOfOutput;
|
pOperator->numOfOutput = numOfOutput;
|
||||||
pOperator->info = pInfo;
|
pOperator->info = pInfo;
|
||||||
pOperator->pRuntimeEnv = pRuntimeEnv;
|
pOperator->pRuntimeEnv = pRuntimeEnv;
|
||||||
|
|
||||||
pOperator->exec = doFill;
|
pOperator->exec = doFill;
|
||||||
pOperator->cleanup = destroySFillOperatorInfo;
|
pOperator->cleanup = destroySFillOperatorInfo;
|
||||||
|
|
||||||
|
@ -6954,6 +7092,52 @@ SOperatorInfo* createTagScanOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SExprInf
|
||||||
|
|
||||||
return pOperator;
|
return pOperator;
|
||||||
}
|
}
|
||||||
|
static bool initMultiDistinctInfo(SDistinctOperatorInfo *pInfo, SOperatorInfo* pOperator, SSDataBlock *pBlock) {
|
||||||
|
if (taosArrayGetSize(pInfo->pDistinctDataInfo) == pOperator->numOfOutput) {
|
||||||
|
// distinct info already inited
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < pOperator->numOfOutput; i++) {
|
||||||
|
pInfo->totalBytes += pOperator->pExpr[i].base.colBytes;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < pOperator->numOfOutput; i++) {
|
||||||
|
int numOfBlock = (int)taosArrayGetSize(pBlock->pDataBlock);
|
||||||
|
assert(i < numOfBlock);
|
||||||
|
for (int j = 0; j < numOfBlock; j++) {
|
||||||
|
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, j);
|
||||||
|
if (pColDataInfo->info.colId == pOperator->pExpr[i].base.resColId) {
|
||||||
|
SDistinctDataInfo item = {.index = j, .type = pColDataInfo->info.type, .bytes = pColDataInfo->info.bytes};
|
||||||
|
taosArrayInsert(pInfo->pDistinctDataInfo, i, &item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pInfo->totalBytes += (int32_t)strlen(MULTI_KEY_DELIM) * (pOperator->numOfOutput);
|
||||||
|
pInfo->buf = calloc(1, pInfo->totalBytes);
|
||||||
|
return taosArrayGetSize(pInfo->pDistinctDataInfo) == pOperator->numOfOutput ? true : false;
|
||||||
|
}
|
||||||
|
static void buildMultiDistinctKey(SDistinctOperatorInfo *pInfo, SSDataBlock *pBlock, int32_t rowId) {
|
||||||
|
char *p = pInfo->buf;
|
||||||
|
memset(p, 0, pInfo->totalBytes);
|
||||||
|
|
||||||
|
for (int i = 0; i < taosArrayGetSize(pInfo->pDistinctDataInfo); i++) {
|
||||||
|
SDistinctDataInfo* pDistDataInfo = (SDistinctDataInfo *)taosArrayGet(pInfo->pDistinctDataInfo, i);
|
||||||
|
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, pDistDataInfo->index);
|
||||||
|
char *val = ((char *)pColDataInfo->pData) + pColDataInfo->info.bytes * rowId;
|
||||||
|
if (isNull(val, pDistDataInfo->type)) {
|
||||||
|
p += pDistDataInfo->bytes;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (IS_VAR_DATA_TYPE(pDistDataInfo->type)) {
|
||||||
|
memcpy(p, varDataVal(val), varDataLen(val));
|
||||||
|
p += varDataLen(val);
|
||||||
|
} else {
|
||||||
|
memcpy(p, val, pDistDataInfo->bytes);
|
||||||
|
p += pDistDataInfo->bytes;
|
||||||
|
}
|
||||||
|
memcpy(p, MULTI_KEY_DELIM, strlen(MULTI_KEY_DELIM));
|
||||||
|
p += strlen(MULTI_KEY_DELIM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
||||||
SOperatorInfo* pOperator = (SOperatorInfo*) param;
|
SOperatorInfo* pOperator = (SOperatorInfo*) param;
|
||||||
|
@ -6961,11 +7145,9 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SDistinctOperatorInfo* pInfo = pOperator->info;
|
SDistinctOperatorInfo* pInfo = pOperator->info;
|
||||||
SSDataBlock* pRes = pInfo->pRes;
|
SSDataBlock* pRes = pInfo->pRes;
|
||||||
|
|
||||||
|
|
||||||
pRes->info.rows = 0;
|
pRes->info.rows = 0;
|
||||||
SSDataBlock* pBlock = NULL;
|
SSDataBlock* pBlock = NULL;
|
||||||
while(1) {
|
while(1) {
|
||||||
|
@ -6978,59 +7160,40 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
||||||
pOperator->status = OP_EXEC_DONE;
|
pOperator->status = OP_EXEC_DONE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (pInfo->colIndex == -1) {
|
if (!initMultiDistinctInfo(pInfo, pOperator, pBlock)) {
|
||||||
for (int i = 0; i < taosArrayGetSize(pBlock->pDataBlock); i++) {
|
|
||||||
SColumnInfoData* pColDataInfo = taosArrayGet(pBlock->pDataBlock, i);
|
|
||||||
if (pColDataInfo->info.colId == pOperator->pExpr[0].base.resColId) {
|
|
||||||
pInfo->colIndex = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (pInfo->colIndex == -1) {
|
|
||||||
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
setQueryStatus(pOperator->pRuntimeEnv, QUERY_COMPLETED);
|
||||||
pOperator->status = OP_EXEC_DONE;
|
pOperator->status = OP_EXEC_DONE;
|
||||||
return NULL;
|
break;
|
||||||
}
|
}
|
||||||
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pInfo->colIndex);
|
|
||||||
|
|
||||||
int16_t bytes = pColInfoData->info.bytes;
|
// ensure result output buf
|
||||||
int16_t type = pColInfoData->info.type;
|
|
||||||
|
|
||||||
// ensure the output buffer size
|
|
||||||
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, 0);
|
|
||||||
if (pRes->info.rows + pBlock->info.rows > pInfo->outputCapacity) {
|
if (pRes->info.rows + pBlock->info.rows > pInfo->outputCapacity) {
|
||||||
int32_t newSize = pRes->info.rows + pBlock->info.rows;
|
int32_t newSize = pRes->info.rows + pBlock->info.rows;
|
||||||
char* tmp = realloc(pResultColInfoData->pData, newSize * bytes);
|
for (int i = 0; i < taosArrayGetSize(pRes->pDataBlock); i++) {
|
||||||
|
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, i);
|
||||||
|
SDistinctDataInfo* pDistDataInfo = taosArrayGet(pInfo->pDistinctDataInfo, i);
|
||||||
|
char* tmp = realloc(pResultColInfoData->pData, newSize * pDistDataInfo->bytes);
|
||||||
if (tmp == NULL) {
|
if (tmp == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
} else {
|
} else {
|
||||||
pResultColInfoData->pData = tmp;
|
pResultColInfoData->pData = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
pInfo->outputCapacity = newSize;
|
pInfo->outputCapacity = newSize;
|
||||||
}
|
}
|
||||||
|
for (int32_t i = 0; i < pBlock->info.rows; i++) {
|
||||||
|
buildMultiDistinctKey(pInfo, pBlock, i);
|
||||||
|
if (taosHashGet(pInfo->pSet, pInfo->buf, pInfo->totalBytes) == NULL) {
|
||||||
|
int32_t dummy;
|
||||||
|
taosHashPut(pInfo->pSet, pInfo->buf, pInfo->totalBytes, &dummy, sizeof(dummy));
|
||||||
|
for (int j = 0; j < taosArrayGetSize(pRes->pDataBlock); j++) {
|
||||||
|
SDistinctDataInfo* pDistDataInfo = taosArrayGet(pInfo->pDistinctDataInfo, j); // distinct meta info
|
||||||
|
SColumnInfoData* pColInfoData = taosArrayGet(pBlock->pDataBlock, pDistDataInfo->index); //src
|
||||||
|
SColumnInfoData* pResultColInfoData = taosArrayGet(pRes->pDataBlock, j); // dist
|
||||||
|
char* val = ((char*)pColInfoData->pData) + pDistDataInfo->bytes * i;
|
||||||
|
char *start = pResultColInfoData->pData + pDistDataInfo->bytes * pInfo->pRes->info.rows;
|
||||||
|
memcpy(start, val, pDistDataInfo->bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int32_t i = 0; i < pBlock->info.rows; ++i) {
|
|
||||||
char* val = ((char*)pColInfoData->pData) + bytes * i;
|
|
||||||
if (isNull(val, type)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
char* p = val;
|
|
||||||
size_t keyLen = 0;
|
|
||||||
if (IS_VAR_DATA_TYPE(pOperator->pExpr->base.colType)) {
|
|
||||||
tstr* var = (tstr*)(val);
|
|
||||||
p = var->data;
|
|
||||||
keyLen = varDataLen(var);
|
|
||||||
} else {
|
|
||||||
keyLen = bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
int dummy;
|
|
||||||
void* res = taosHashGet(pInfo->pSet, p, keyLen);
|
|
||||||
if (res == NULL) {
|
|
||||||
taosHashPut(pInfo->pSet, p, keyLen, &dummy, sizeof(dummy));
|
|
||||||
char* start = pResultColInfoData->pData + bytes * pInfo->pRes->info.rows;
|
|
||||||
memcpy(start, val, bytes);
|
|
||||||
pRes->info.rows += 1;
|
pRes->info.rows += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7039,16 +7202,18 @@ static SSDataBlock* hashDistinct(void* param, bool* newgroup) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
|
return (pInfo->pRes->info.rows > 0)? pInfo->pRes:NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
SOperatorInfo* createDistinctOperatorInfo(SQueryRuntimeEnv* pRuntimeEnv, SOperatorInfo* upstream, SExprInfo* pExpr, int32_t numOfOutput) {
|
||||||
SDistinctOperatorInfo* pInfo = calloc(1, sizeof(SDistinctOperatorInfo));
|
SDistinctOperatorInfo* pInfo = calloc(1, sizeof(SDistinctOperatorInfo));
|
||||||
pInfo->colIndex = -1;
|
|
||||||
pInfo->threshold = 10000000; // distinct result threshold
|
pInfo->totalBytes = 0;
|
||||||
|
pInfo->buf = NULL;
|
||||||
|
pInfo->threshold = tsMaxNumOfDistinctResults; // distinct result threshold
|
||||||
pInfo->outputCapacity = 4096;
|
pInfo->outputCapacity = 4096;
|
||||||
pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(pExpr->base.colType), false, HASH_NO_LOCK);
|
pInfo->pDistinctDataInfo = taosArrayInit(numOfOutput, sizeof(SDistinctDataInfo));
|
||||||
|
pInfo->pSet = taosHashInit(64, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), false, HASH_NO_LOCK);
|
||||||
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity);
|
pInfo->pRes = createOutputBuf(pExpr, numOfOutput, (int32_t) pInfo->outputCapacity);
|
||||||
|
|
||||||
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
SOperatorInfo* pOperator = calloc(1, sizeof(SOperatorInfo));
|
||||||
|
|
|
@ -1102,3 +1102,57 @@ void tOrderDescDestroy(tOrderDescriptor *pDesc) {
|
||||||
destroyColumnModel(pDesc->pColumnModel);
|
destroyColumnModel(pDesc->pColumnModel);
|
||||||
tfree(pDesc);
|
tfree(pDesc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void taoscQSort(void** pCols, SSchema* pSchema, int32_t numOfCols, int32_t numOfRows, int32_t index, __compar_fn_t compareFn) {
|
||||||
|
assert(numOfRows > 0 && numOfCols > 0 && index >= 0 && index < numOfCols);
|
||||||
|
|
||||||
|
int32_t bytes = pSchema[index].bytes;
|
||||||
|
int32_t size = bytes + sizeof(int32_t);
|
||||||
|
|
||||||
|
char* buf = calloc(1, size * numOfRows);
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < numOfRows; ++i) {
|
||||||
|
char* dest = buf + size * i;
|
||||||
|
memcpy(dest, ((char*) pCols[index]) + bytes * i, bytes);
|
||||||
|
*(int32_t*)(dest+bytes) = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
qsort(buf, numOfRows, size, compareFn);
|
||||||
|
|
||||||
|
int32_t prevLength = 0;
|
||||||
|
char* p = NULL;
|
||||||
|
|
||||||
|
for(int32_t i = 0; i < numOfCols; ++i) {
|
||||||
|
int32_t bytes1 = pSchema[i].bytes;
|
||||||
|
|
||||||
|
if (i == index) {
|
||||||
|
for(int32_t j = 0; j < numOfRows; ++j){
|
||||||
|
char* src = buf + (j * size);
|
||||||
|
char* dest = ((char*)pCols[i]) + (j * bytes1);
|
||||||
|
memcpy(dest, src, bytes1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// make sure memory buffer is enough
|
||||||
|
if (prevLength < bytes1) {
|
||||||
|
char *tmp = realloc(p, bytes1 * numOfRows);
|
||||||
|
assert(tmp);
|
||||||
|
|
||||||
|
p = tmp;
|
||||||
|
prevLength = bytes1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(p, pCols[i], bytes1 * numOfRows);
|
||||||
|
|
||||||
|
for(int32_t j = 0; j < numOfRows; ++j){
|
||||||
|
char* dest = ((char*)pCols[i]) + bytes1 * j;
|
||||||
|
|
||||||
|
int32_t newPos = *(int32_t*)(buf + (j * size) + bytes);
|
||||||
|
char* src = p + (newPos * bytes1);
|
||||||
|
memcpy(dest, src, bytes1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tfree(buf);
|
||||||
|
tfree(p);
|
||||||
|
}
|
|
@ -206,6 +206,12 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, void** data, int32_t outputR
|
||||||
} else {
|
} else {
|
||||||
assert(pFillInfo->currentKey == ts);
|
assert(pFillInfo->currentKey == ts);
|
||||||
initBeforeAfterDataBuf(pFillInfo, prev);
|
initBeforeAfterDataBuf(pFillInfo, prev);
|
||||||
|
if (pFillInfo->type == TSDB_FILL_NEXT && (pFillInfo->index + 1) < pFillInfo->numOfRows) {
|
||||||
|
initBeforeAfterDataBuf(pFillInfo, next);
|
||||||
|
++pFillInfo->index;
|
||||||
|
copyCurrentRowIntoBuf(pFillInfo, srcData, *next);
|
||||||
|
--pFillInfo->index;
|
||||||
|
}
|
||||||
|
|
||||||
// assign rows to dst buffer
|
// assign rows to dst buffer
|
||||||
for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
|
for (int32_t i = 0; i < pFillInfo->numOfCols; ++i) {
|
||||||
|
@ -227,6 +233,12 @@ static int32_t fillResultImpl(SFillInfo* pFillInfo, void** data, int32_t outputR
|
||||||
} else if (pFillInfo->type == TSDB_FILL_LINEAR) {
|
} else if (pFillInfo->type == TSDB_FILL_LINEAR) {
|
||||||
assignVal(output, src, pCol->col.bytes, pCol->col.type);
|
assignVal(output, src, pCol->col.bytes, pCol->col.type);
|
||||||
memcpy(*prev + pCol->col.offset, src, pCol->col.bytes);
|
memcpy(*prev + pCol->col.offset, src, pCol->col.bytes);
|
||||||
|
} else if (pFillInfo->type == TSDB_FILL_NEXT) {
|
||||||
|
if (*next) {
|
||||||
|
assignVal(output, *next + pCol->col.offset, pCol->col.bytes, pCol->col.type);
|
||||||
|
} else {
|
||||||
|
setNull(output, pCol->col.type, pCol->col.bytes);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assignVal(output, (char*)&pCol->fillVal.i, pCol->col.bytes, pCol->col.type);
|
assignVal(output, (char*)&pCol->fillVal.i, pCol->col.bytes, pCol->col.type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -237,7 +237,7 @@ tMemBucket *tMemBucketCreate(int16_t nElemSize, int16_t dataType, double minval,
|
||||||
}
|
}
|
||||||
|
|
||||||
pBucket->elemPerPage = (pBucket->bufPageSize - sizeof(tFilePage))/pBucket->bytes;
|
pBucket->elemPerPage = (pBucket->bufPageSize - sizeof(tFilePage))/pBucket->bytes;
|
||||||
pBucket->comparFn = getKeyComparFunc(pBucket->type);
|
pBucket->comparFn = getKeyComparFunc(pBucket->type, TSDB_ORDER_ASC);
|
||||||
|
|
||||||
pBucket->hashFunc = getHashFunc(pBucket->type);
|
pBucket->hashFunc = getHashFunc(pBucket->type);
|
||||||
if (pBucket->hashFunc == NULL) {
|
if (pBucket->hashFunc == NULL) {
|
||||||
|
|
|
@ -557,10 +557,9 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
||||||
int32_t op = 0;
|
int32_t op = 0;
|
||||||
|
|
||||||
if (onlyQueryTags(pQueryAttr)) { // do nothing for tags query
|
if (onlyQueryTags(pQueryAttr)) { // do nothing for tags query
|
||||||
if (onlyQueryTags(pQueryAttr)) {
|
|
||||||
op = OP_TagScan;
|
op = OP_TagScan;
|
||||||
taosArrayPush(plan, &op);
|
taosArrayPush(plan, &op);
|
||||||
}
|
|
||||||
if (pQueryAttr->distinct) {
|
if (pQueryAttr->distinct) {
|
||||||
op = OP_Distinct;
|
op = OP_Distinct;
|
||||||
taosArrayPush(plan, &op);
|
taosArrayPush(plan, &op);
|
||||||
|
@ -651,8 +650,14 @@ SArray* createExecOperatorPlan(SQueryAttr* pQueryAttr) {
|
||||||
taosArrayPush(plan, &op);
|
taosArrayPush(plan, &op);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
// outer query order by support
|
||||||
|
int32_t orderColId = pQueryAttr->order.orderColId;
|
||||||
|
if (pQueryAttr->vgId == 0 && orderColId != PRIMARYKEY_TIMESTAMP_COL_INDEX && orderColId != INT32_MIN) {
|
||||||
|
op = OP_Order;
|
||||||
|
taosArrayPush(plan, &op);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (pQueryAttr->limit.limit > 0 || pQueryAttr->limit.offset > 0) {
|
if (pQueryAttr->limit.limit > 0 || pQueryAttr->limit.offset > 0) {
|
||||||
op = OP_Limit;
|
op = OP_Limit;
|
||||||
|
@ -693,7 +698,7 @@ SArray* createGlobalMergePlan(SQueryAttr* pQueryAttr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fill operator
|
// fill operator
|
||||||
if (pQueryAttr->fillType != TSDB_FILL_NONE && (!pQueryAttr->pointInterpQuery)) {
|
if (pQueryAttr->fillType != TSDB_FILL_NONE && pQueryAttr->interval.interval > 0) {
|
||||||
op = OP_Fill;
|
op = OP_Fill;
|
||||||
taosArrayPush(plan, &op);
|
taosArrayPush(plan, &op);
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,9 +223,12 @@ static STSGroupBlockInfoEx* addOneGroupInfo(STSBuf* pTSBuf, int32_t id) {
|
||||||
static void shrinkBuffer(STSList* ptsData) {
|
static void shrinkBuffer(STSList* ptsData) {
|
||||||
// shrink tmp buffer size if it consumes too many memory compared to the pre-defined size
|
// shrink tmp buffer size if it consumes too many memory compared to the pre-defined size
|
||||||
if (ptsData->allocSize >= ptsData->threshold * 2) {
|
if (ptsData->allocSize >= ptsData->threshold * 2) {
|
||||||
ptsData->rawBuf = realloc(ptsData->rawBuf, MEM_BUF_SIZE);
|
char* rawBuf = realloc(ptsData->rawBuf, MEM_BUF_SIZE);
|
||||||
|
if(rawBuf) {
|
||||||
|
ptsData->rawBuf = rawBuf;
|
||||||
ptsData->allocSize = MEM_BUF_SIZE;
|
ptsData->allocSize = MEM_BUF_SIZE;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t getTagAreaLength(tVariant* pa) {
|
static int32_t getTagAreaLength(tVariant* pa) {
|
||||||
|
|
|
@ -30,6 +30,18 @@ typedef struct SCompSupporter {
|
||||||
int32_t order;
|
int32_t order;
|
||||||
} SCompSupporter;
|
} SCompSupporter;
|
||||||
|
|
||||||
|
int32_t getRowNumForMultioutput(SQueryAttr* pQueryAttr, bool topBottomQuery, bool stable) {
|
||||||
|
if (pQueryAttr && (!stable)) {
|
||||||
|
for (int16_t i = 0; i < pQueryAttr->numOfOutput; ++i) {
|
||||||
|
if (pQueryAttr->pExpr1[i].base.functionId == TSDB_FUNC_TOP || pQueryAttr->pExpr1[i].base.functionId == TSDB_FUNC_BOTTOM) {
|
||||||
|
return (int32_t)pQueryAttr->pExpr1[i].base.param[0].i64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t getOutputInterResultBufSize(SQueryAttr* pQueryAttr) {
|
int32_t getOutputInterResultBufSize(SQueryAttr* pQueryAttr) {
|
||||||
int32_t size = 0;
|
int32_t size = 0;
|
||||||
|
|
||||||
|
|
|
@ -397,7 +397,11 @@ void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uin
|
||||||
SThreadObj *pThreadObj = pClientObj->pThreadObj[index];
|
SThreadObj *pThreadObj = pClientObj->pThreadObj[index];
|
||||||
|
|
||||||
SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip);
|
SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip);
|
||||||
|
#if defined(_TD_WINDOWS_64) || defined(_TD_WINDOWS_32)
|
||||||
|
if (fd == (SOCKET)-1) return NULL;
|
||||||
|
#else
|
||||||
if (fd <= 0) return NULL;
|
if (fd <= 0) return NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
uint16_t localPort = 0;
|
uint16_t localPort = 0;
|
||||||
|
|
|
@ -18,6 +18,9 @@
|
||||||
|
|
||||||
#define TSDB_FS_VERSION 0
|
#define TSDB_FS_VERSION 0
|
||||||
|
|
||||||
|
// ================== TSDB global config
|
||||||
|
extern bool tsdbForceKeepFile;
|
||||||
|
|
||||||
// ================== CURRENT file header info
|
// ================== CURRENT file header info
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t version; // Current file system version (relating to code)
|
uint32_t version; // Current file system version (relating to code)
|
||||||
|
|
|
@ -24,8 +24,7 @@ typedef struct STable {
|
||||||
tstr* name; // NOTE: there a flexible string here
|
tstr* name; // NOTE: there a flexible string here
|
||||||
uint64_t suid;
|
uint64_t suid;
|
||||||
struct STable* pSuper; // super table pointer
|
struct STable* pSuper; // super table pointer
|
||||||
uint8_t numOfSchemas;
|
SArray* schema;
|
||||||
STSchema* schema[TSDB_MAX_TABLE_SCHEMAS];
|
|
||||||
STSchema* tagSchema;
|
STSchema* tagSchema;
|
||||||
SKVRow tagVal;
|
SKVRow tagVal;
|
||||||
SSkipList* pIndex; // For TSDB_SUPER_TABLE, it is the skiplist index
|
SSkipList* pIndex; // For TSDB_SUPER_TABLE, it is the skiplist index
|
||||||
|
@ -107,10 +106,9 @@ static FORCE_INLINE STSchema* tsdbGetTableSchemaImpl(STable* pTable, bool lock,
|
||||||
|
|
||||||
if (lock) TSDB_RLOCK_TABLE(pDTable);
|
if (lock) TSDB_RLOCK_TABLE(pDTable);
|
||||||
if (_version < 0) { // get the latest version of schema
|
if (_version < 0) { // get the latest version of schema
|
||||||
pTSchema = pDTable->schema[pDTable->numOfSchemas - 1];
|
pTSchema = *(STSchema **)taosArrayGetLast(pDTable->schema);
|
||||||
} else { // get the schema with version
|
} else { // get the schema with version
|
||||||
void* ptr = taosbsearch(&_version, pDTable->schema, pDTable->numOfSchemas, sizeof(STSchema*),
|
void* ptr = taosArraySearch(pDTable->schema, &_version, tsdbCompareSchemaVersion, TD_EQ);
|
||||||
tsdbCompareSchemaVersion, TD_EQ);
|
|
||||||
if (ptr == NULL) {
|
if (ptr == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION;
|
terrno = TSDB_CODE_TDB_IVD_TB_SCHEMA_VERSION;
|
||||||
goto _exit;
|
goto _exit;
|
||||||
|
|
|
@ -722,7 +722,7 @@ static int tsdbInitCommitH(SCommitH *pCommith, STsdbRepo *pRepo) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pCommith->pDataCols = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock);
|
pCommith->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
||||||
if (pCommith->pDataCols == NULL) {
|
if (pCommith->pDataCols == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
tsdbDestroyCommitH(pCommith);
|
tsdbDestroyCommitH(pCommith);
|
||||||
|
@ -920,7 +920,6 @@ int tsdbWriteBlockImpl(STsdbRepo *pRepo, STable *pTable, SDFile *pDFile, SDataCo
|
||||||
SDataCol * pDataCol = pDataCols->cols + ncol;
|
SDataCol * pDataCol = pDataCols->cols + ncol;
|
||||||
SBlockCol *pBlockCol = pBlockData->cols + nColsNotAllNull;
|
SBlockCol *pBlockCol = pBlockData->cols + nColsNotAllNull;
|
||||||
|
|
||||||
// if (isNEleNull(pDataCol, rowsToWrite)) { // all data to commit are NULL, just ignore it
|
|
||||||
if (isAllRowsNull(pDataCol)) { // all data to commit are NULL, just ignore it
|
if (isAllRowsNull(pDataCol)) { // all data to commit are NULL, just ignore it
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1277,6 +1276,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt
|
||||||
|
|
||||||
if (key1 < key2) {
|
if (key1 < key2) {
|
||||||
for (int i = 0; i < pDataCols->numOfCols; i++) {
|
for (int i = 0; i < pDataCols->numOfCols; i++) {
|
||||||
|
//TODO: dataColAppendVal may fail
|
||||||
dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows,
|
dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows,
|
||||||
pTarget->maxPoints);
|
pTarget->maxPoints);
|
||||||
}
|
}
|
||||||
|
@ -1308,6 +1308,7 @@ static void tsdbLoadAndMergeFromCache(SDataCols *pDataCols, int *iter, SCommitIt
|
||||||
ASSERT(!isRowDel);
|
ASSERT(!isRowDel);
|
||||||
|
|
||||||
for (int i = 0; i < pDataCols->numOfCols; i++) {
|
for (int i = 0; i < pDataCols->numOfCols; i++) {
|
||||||
|
//TODO: dataColAppendVal may fail
|
||||||
dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows,
|
dataColAppendVal(pTarget->cols + i, tdGetColDataOfRow(pDataCols->cols + i, *iter), pTarget->numOfRows,
|
||||||
pTarget->maxPoints);
|
pTarget->maxPoints);
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,7 +296,7 @@ static int tsdbCompactMeta(STsdbRepo *pRepo) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pComph->pDataCols = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock);
|
pComph->pDataCols = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
||||||
if (pComph->pDataCols == NULL) {
|
if (pComph->pDataCols == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
tsdbDestroyCompactH(pComph);
|
tsdbDestroyCompactH(pComph);
|
||||||
|
|
|
@ -37,6 +37,7 @@ static void tsdbScanAndTryFixDFilesHeader(STsdbRepo *pRepo, int32_t *nExpired);
|
||||||
static int tsdbProcessExpiredFS(STsdbRepo *pRepo);
|
static int tsdbProcessExpiredFS(STsdbRepo *pRepo);
|
||||||
static int tsdbCreateMeta(STsdbRepo *pRepo);
|
static int tsdbCreateMeta(STsdbRepo *pRepo);
|
||||||
|
|
||||||
|
// For backward compatibility
|
||||||
// ================== CURRENT file header info
|
// ================== CURRENT file header info
|
||||||
static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) {
|
static int tsdbEncodeFSHeader(void **buf, SFSHeader *pHeader) {
|
||||||
int tlen = 0;
|
int tlen = 0;
|
||||||
|
@ -1048,6 +1049,26 @@ static int tsdbRestoreMeta(STsdbRepo *pRepo) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tsdbForceKeepFile) {
|
||||||
|
struct stat tfstat;
|
||||||
|
|
||||||
|
// Get real file size
|
||||||
|
if (fstat(pfs->cstatus->pmf->fd, &tfstat) < 0) {
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
tsdbCloseMFile(pfs->cstatus->pmf);
|
||||||
|
tfsClosedir(tdir);
|
||||||
|
regfree(®ex);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pfs->cstatus->pmf->info.size != tfstat.st_size) {
|
||||||
|
int64_t tfsize = pfs->cstatus->pmf->info.size;
|
||||||
|
pfs->cstatus->pmf->info.size = tfstat.st_size;
|
||||||
|
tsdbInfo("vgId:%d file %s header size is changed from %" PRId64 " to %" PRId64, REPO_ID(pRepo),
|
||||||
|
TSDB_FILE_FULL_NAME(pfs->cstatus->pmf), tfsize, pfs->cstatus->pmf->info.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tsdbCloseMFile(pfs->cstatus->pmf);
|
tsdbCloseMFile(pfs->cstatus->pmf);
|
||||||
}
|
}
|
||||||
} else if (code == REG_NOMATCH) {
|
} else if (code == REG_NOMATCH) {
|
||||||
|
@ -1212,6 +1233,24 @@ static int tsdbRestoreDFileSet(STsdbRepo *pRepo) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tsdbForceKeepFile) {
|
||||||
|
struct stat tfstat;
|
||||||
|
|
||||||
|
// Get real file size
|
||||||
|
if (fstat(pDFile->fd, &tfstat) < 0) {
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
taosArrayDestroy(fArray);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pDFile->info.size != tfstat.st_size) {
|
||||||
|
int64_t tfsize = pDFile->info.size;
|
||||||
|
pDFile->info.size = tfstat.st_size;
|
||||||
|
tsdbInfo("vgId:%d file %s header size is changed from %" PRId64 " to %" PRId64, REPO_ID(pRepo),
|
||||||
|
TSDB_FILE_FULL_NAME(pDFile), tfsize, pDFile->info.size);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
tsdbCloseDFile(pDFile);
|
tsdbCloseDFile(pDFile);
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -702,11 +702,12 @@ static int tsdbScanAndConvertSubmitMsg(STsdbRepo *pRepo, SSubmitMsg *pMsg) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//row1 has higher priority
|
//row1 has higher priority
|
||||||
static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRepo, STSchema **ppSchema1, STSchema **ppSchema2, STable* pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) {
|
static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRepo,
|
||||||
|
STSchema **ppSchema1, STSchema **ppSchema2,
|
||||||
|
STable* pTable, int32_t* pPoints, SMemRow* pLastRow) {
|
||||||
|
|
||||||
//for compatiblity, duplicate key inserted when update=0 should be also calculated as affected rows!
|
//for compatiblity, duplicate key inserted when update=0 should be also calculated as affected rows!
|
||||||
if(row1 == NULL && row2 == NULL && pRepo->config.update == TD_ROW_DISCARD_UPDATE) {
|
if(row1 == NULL && row2 == NULL && pRepo->config.update == TD_ROW_DISCARD_UPDATE) {
|
||||||
(*pAffectedRows)++;
|
|
||||||
(*pPoints)++;
|
(*pPoints)++;
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -715,7 +716,6 @@ static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRep
|
||||||
void* pMem = tsdbAllocBytes(pRepo, memRowTLen(row1));
|
void* pMem = tsdbAllocBytes(pRepo, memRowTLen(row1));
|
||||||
if(pMem == NULL) return NULL;
|
if(pMem == NULL) return NULL;
|
||||||
memRowCpy(pMem, row1);
|
memRowCpy(pMem, row1);
|
||||||
(*pAffectedRows)++;
|
|
||||||
(*pPoints)++;
|
(*pPoints)++;
|
||||||
*pLastRow = pMem;
|
*pLastRow = pMem;
|
||||||
return pMem;
|
return pMem;
|
||||||
|
@ -750,18 +750,16 @@ static SMemRow tsdbInsertDupKeyMerge(SMemRow row1, SMemRow row2, STsdbRepo* pRep
|
||||||
if(pMem == NULL) return NULL;
|
if(pMem == NULL) return NULL;
|
||||||
memRowCpy(pMem, tmp);
|
memRowCpy(pMem, tmp);
|
||||||
|
|
||||||
(*pAffectedRows)++;
|
|
||||||
(*pPoints)++;
|
(*pPoints)++;
|
||||||
|
|
||||||
*pLastRow = pMem;
|
*pLastRow = pMem;
|
||||||
return pMem;
|
return pMem;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void* tsdbInsertDupKeyMergePacked(void** args) {
|
static void* tsdbInsertDupKeyMergePacked(void** args) {
|
||||||
return tsdbInsertDupKeyMerge(args[0], args[1], args[2], (STSchema**)&args[3], (STSchema**)&args[4], args[5], args[6], args[7], args[8]);
|
return tsdbInsertDupKeyMerge(args[0], args[1], args[2], (STSchema**)&args[3], (STSchema**)&args[4], args[5], args[6], args[7]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STable *pTable, int32_t* pAffectedRows, int64_t* pPoints, SMemRow* pLastRow) {
|
static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STable *pTable, int32_t* pPoints, SMemRow* pLastRow) {
|
||||||
|
|
||||||
if(pSkipList->insertHandleFn == NULL) {
|
if(pSkipList->insertHandleFn == NULL) {
|
||||||
tGenericSavedFunc *dupHandleSavedFunc = genericSavedFuncInit((GenericVaFunc)&tsdbInsertDupKeyMergePacked, 9);
|
tGenericSavedFunc *dupHandleSavedFunc = genericSavedFuncInit((GenericVaFunc)&tsdbInsertDupKeyMergePacked, 9);
|
||||||
|
@ -769,17 +767,16 @@ static void tsdbSetupSkipListHookFns(SSkipList* pSkipList, STsdbRepo *pRepo, STa
|
||||||
dupHandleSavedFunc->args[3] = NULL;
|
dupHandleSavedFunc->args[3] = NULL;
|
||||||
dupHandleSavedFunc->args[4] = NULL;
|
dupHandleSavedFunc->args[4] = NULL;
|
||||||
dupHandleSavedFunc->args[5] = pTable;
|
dupHandleSavedFunc->args[5] = pTable;
|
||||||
dupHandleSavedFunc->args[6] = pAffectedRows;
|
|
||||||
dupHandleSavedFunc->args[7] = pPoints;
|
|
||||||
dupHandleSavedFunc->args[8] = pLastRow;
|
|
||||||
pSkipList->insertHandleFn = dupHandleSavedFunc;
|
pSkipList->insertHandleFn = dupHandleSavedFunc;
|
||||||
}
|
}
|
||||||
|
pSkipList->insertHandleFn->args[6] = pPoints;
|
||||||
|
pSkipList->insertHandleFn->args[7] = pLastRow;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t *pAffectedRows) {
|
static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t *pAffectedRows) {
|
||||||
|
|
||||||
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
||||||
int64_t points = 0;
|
int32_t points = 0;
|
||||||
STable *pTable = NULL;
|
STable *pTable = NULL;
|
||||||
SSubmitBlkIter blkIter = {0};
|
SSubmitBlkIter blkIter = {0};
|
||||||
SMemTable *pMemTable = NULL;
|
SMemTable *pMemTable = NULL;
|
||||||
|
@ -830,9 +827,10 @@ static int tsdbInsertDataToTable(STsdbRepo* pRepo, SSubmitBlk* pBlock, int32_t *
|
||||||
|
|
||||||
SMemRow lastRow = NULL;
|
SMemRow lastRow = NULL;
|
||||||
int64_t osize = SL_SIZE(pTableData->pData);
|
int64_t osize = SL_SIZE(pTableData->pData);
|
||||||
tsdbSetupSkipListHookFns(pTableData->pData, pRepo, pTable, pAffectedRows, &points, &lastRow);
|
tsdbSetupSkipListHookFns(pTableData->pData, pRepo, pTable, &points, &lastRow);
|
||||||
tSkipListPutBatchByIter(pTableData->pData, &blkIter, (iter_next_fn_t)tsdbGetSubmitBlkNext);
|
tSkipListPutBatchByIter(pTableData->pData, &blkIter, (iter_next_fn_t)tsdbGetSubmitBlkNext);
|
||||||
int64_t dsize = SL_SIZE(pTableData->pData) - osize;
|
int64_t dsize = SL_SIZE(pTableData->pData) - osize;
|
||||||
|
(*pAffectedRows) += points;
|
||||||
|
|
||||||
|
|
||||||
if(lastRow != NULL) {
|
if(lastRow != NULL) {
|
||||||
|
|
|
@ -17,7 +17,6 @@
|
||||||
#define TSDB_SUPER_TABLE_SL_LEVEL 5
|
#define TSDB_SUPER_TABLE_SL_LEVEL 5
|
||||||
#define DEFAULT_TAG_INDEX_COLUMN 0
|
#define DEFAULT_TAG_INDEX_COLUMN 0
|
||||||
|
|
||||||
static int tsdbCompareSchemaVersion(const void *key1, const void *key2);
|
|
||||||
static char * getTagIndexKey(const void *pData);
|
static char * getTagIndexKey(const void *pData);
|
||||||
static STable *tsdbNewTable();
|
static STable *tsdbNewTable();
|
||||||
static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pSTable);
|
static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pSTable);
|
||||||
|
@ -44,6 +43,8 @@ static int tsdbRemoveTableFromStore(STsdbRepo *pRepo, STable *pTable);
|
||||||
static int tsdbRmTableFromMeta(STsdbRepo *pRepo, STable *pTable);
|
static int tsdbRmTableFromMeta(STsdbRepo *pRepo, STable *pTable);
|
||||||
static int tsdbAdjustMetaTables(STsdbRepo *pRepo, int tid);
|
static int tsdbAdjustMetaTables(STsdbRepo *pRepo, int tid);
|
||||||
static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema);
|
static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema);
|
||||||
|
static int tsdbAddSchema(STable *pTable, STSchema *pSchema);
|
||||||
|
static void tsdbFreeTableSchema(STable *pTable);
|
||||||
|
|
||||||
// ------------------ OUTER FUNCTIONS ------------------
|
// ------------------ OUTER FUNCTIONS ------------------
|
||||||
int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg) {
|
int tsdbCreateTable(STsdbRepo *repo, STableCfg *pCfg) {
|
||||||
|
@ -723,17 +724,10 @@ void tsdbUpdateTableSchema(STsdbRepo *pRepo, STable *pTable, STSchema *pSchema,
|
||||||
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
STsdbMeta *pMeta = pRepo->tsdbMeta;
|
||||||
|
|
||||||
STable *pCTable = (TABLE_TYPE(pTable) == TSDB_CHILD_TABLE) ? pTable->pSuper : pTable;
|
STable *pCTable = (TABLE_TYPE(pTable) == TSDB_CHILD_TABLE) ? pTable->pSuper : pTable;
|
||||||
ASSERT(schemaVersion(pSchema) > schemaVersion(pCTable->schema[pCTable->numOfSchemas - 1]));
|
ASSERT(schemaVersion(pSchema) > schemaVersion(*(STSchema **)taosArrayGetLast(pCTable->schema)));
|
||||||
|
|
||||||
TSDB_WLOCK_TABLE(pCTable);
|
TSDB_WLOCK_TABLE(pCTable);
|
||||||
if (pCTable->numOfSchemas < TSDB_MAX_TABLE_SCHEMAS) {
|
tsdbAddSchema(pCTable, pSchema);
|
||||||
pCTable->schema[pCTable->numOfSchemas++] = pSchema;
|
|
||||||
} else {
|
|
||||||
ASSERT(pCTable->numOfSchemas == TSDB_MAX_TABLE_SCHEMAS);
|
|
||||||
tdFreeSchema(pCTable->schema[0]);
|
|
||||||
memmove(pCTable->schema, pCTable->schema + 1, sizeof(STSchema *) * (TSDB_MAX_TABLE_SCHEMAS - 1));
|
|
||||||
pCTable->schema[pCTable->numOfSchemas - 1] = pSchema;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (schemaNCols(pSchema) > pMeta->maxCols) pMeta->maxCols = schemaNCols(pSchema);
|
if (schemaNCols(pSchema) > pMeta->maxCols) pMeta->maxCols = schemaNCols(pSchema);
|
||||||
if (schemaTLen(pSchema) > pMeta->maxRowBytes) pMeta->maxRowBytes = schemaTLen(pSchema);
|
if (schemaTLen(pSchema) > pMeta->maxRowBytes) pMeta->maxRowBytes = schemaTLen(pSchema);
|
||||||
|
@ -829,9 +823,7 @@ static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pST
|
||||||
TABLE_TID(pTable) = -1;
|
TABLE_TID(pTable) = -1;
|
||||||
TABLE_SUID(pTable) = -1;
|
TABLE_SUID(pTable) = -1;
|
||||||
pTable->pSuper = NULL;
|
pTable->pSuper = NULL;
|
||||||
pTable->numOfSchemas = 1;
|
if (tsdbAddSchema(pTable, tdDupSchema(pCfg->schema)) < 0) {
|
||||||
pTable->schema[0] = tdDupSchema(pCfg->schema);
|
|
||||||
if (pTable->schema[0] == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
goto _err;
|
goto _err;
|
||||||
}
|
}
|
||||||
|
@ -842,7 +834,8 @@ static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pST
|
||||||
}
|
}
|
||||||
pTable->tagVal = NULL;
|
pTable->tagVal = NULL;
|
||||||
STColumn *pCol = schemaColAt(pTable->tagSchema, DEFAULT_TAG_INDEX_COLUMN);
|
STColumn *pCol = schemaColAt(pTable->tagSchema, DEFAULT_TAG_INDEX_COLUMN);
|
||||||
pTable->pIndex = tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), (uint8_t)(colBytes(pCol)), NULL, SL_ALLOW_DUP_KEY, getTagIndexKey);
|
pTable->pIndex = tSkipListCreate(TSDB_SUPER_TABLE_SL_LEVEL, colType(pCol), (uint8_t)(colBytes(pCol)), NULL,
|
||||||
|
SL_ALLOW_DUP_KEY, getTagIndexKey);
|
||||||
if (pTable->pIndex == NULL) {
|
if (pTable->pIndex == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
goto _err;
|
goto _err;
|
||||||
|
@ -871,9 +864,7 @@ static STable *tsdbCreateTableFromCfg(STableCfg *pCfg, bool isSuper, STable *pST
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
TABLE_SUID(pTable) = -1;
|
TABLE_SUID(pTable) = -1;
|
||||||
pTable->numOfSchemas = 1;
|
if (tsdbAddSchema(pTable, tdDupSchema(pCfg->schema)) < 0) {
|
||||||
pTable->schema[0] = tdDupSchema(pCfg->schema);
|
|
||||||
if (pTable->schema[0] == NULL) {
|
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
goto _err;
|
goto _err;
|
||||||
}
|
}
|
||||||
|
@ -907,9 +898,7 @@ static void tsdbFreeTable(STable *pTable) {
|
||||||
TABLE_UID(pTable));
|
TABLE_UID(pTable));
|
||||||
tfree(TABLE_NAME(pTable));
|
tfree(TABLE_NAME(pTable));
|
||||||
if (TABLE_TYPE(pTable) != TSDB_CHILD_TABLE) {
|
if (TABLE_TYPE(pTable) != TSDB_CHILD_TABLE) {
|
||||||
for (int i = 0; i < TSDB_MAX_TABLE_SCHEMAS; i++) {
|
tsdbFreeTableSchema(pTable);
|
||||||
tdFreeSchema(pTable->schema[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
||||||
tdFreeSchema(pTable->tagSchema);
|
tdFreeSchema(pTable->tagSchema);
|
||||||
|
@ -1261,9 +1250,10 @@ static int tsdbEncodeTable(void **buf, STable *pTable) {
|
||||||
tlen += taosEncodeFixedU64(buf, TABLE_SUID(pTable));
|
tlen += taosEncodeFixedU64(buf, TABLE_SUID(pTable));
|
||||||
tlen += tdEncodeKVRow(buf, pTable->tagVal);
|
tlen += tdEncodeKVRow(buf, pTable->tagVal);
|
||||||
} else {
|
} else {
|
||||||
tlen += taosEncodeFixedU8(buf, pTable->numOfSchemas);
|
tlen += taosEncodeFixedU8(buf, (uint8_t)taosArrayGetSize(pTable->schema));
|
||||||
for (int i = 0; i < pTable->numOfSchemas; i++) {
|
for (int i = 0; i < taosArrayGetSize(pTable->schema); i++) {
|
||||||
tlen += tdEncodeSchema(buf, pTable->schema[i]);
|
STSchema *pSchema = taosArrayGetP(pTable->schema, i);
|
||||||
|
tlen += tdEncodeSchema(buf, pSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
||||||
|
@ -1294,9 +1284,12 @@ static void *tsdbDecodeTable(void *buf, STable **pRTable) {
|
||||||
buf = taosDecodeFixedU64(buf, &TABLE_SUID(pTable));
|
buf = taosDecodeFixedU64(buf, &TABLE_SUID(pTable));
|
||||||
buf = tdDecodeKVRow(buf, &(pTable->tagVal));
|
buf = tdDecodeKVRow(buf, &(pTable->tagVal));
|
||||||
} else {
|
} else {
|
||||||
buf = taosDecodeFixedU8(buf, &(pTable->numOfSchemas));
|
uint8_t nSchemas;
|
||||||
for (int i = 0; i < pTable->numOfSchemas; i++) {
|
buf = taosDecodeFixedU8(buf, &nSchemas);
|
||||||
buf = tdDecodeSchema(buf, &(pTable->schema[i]));
|
for (int i = 0; i < nSchemas; i++) {
|
||||||
|
STSchema *pSchema;
|
||||||
|
buf = tdDecodeSchema(buf, &pSchema);
|
||||||
|
tsdbAddSchema(pTable, pSchema);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
if (TABLE_TYPE(pTable) == TSDB_SUPER_TABLE) {
|
||||||
|
@ -1458,3 +1451,38 @@ static int tsdbCheckTableTagVal(SKVRow *pKVRow, STSchema *pSchema) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int tsdbAddSchema(STable *pTable, STSchema *pSchema) {
|
||||||
|
ASSERT(TABLE_TYPE(pTable) != TSDB_CHILD_TABLE);
|
||||||
|
|
||||||
|
if (pTable->schema == NULL) {
|
||||||
|
pTable->schema = taosArrayInit(TSDB_MAX_TABLE_SCHEMAS, sizeof(SSchema *));
|
||||||
|
if (pTable->schema == NULL) {
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(taosArrayGetSize(pTable->schema) == 0 ||
|
||||||
|
schemaVersion(pSchema) > schemaVersion(*(STSchema **)taosArrayGetLast(pTable->schema)));
|
||||||
|
|
||||||
|
if (taosArrayPush(pTable->schema, &pSchema) == NULL) {
|
||||||
|
terrno = TAOS_SYSTEM_ERROR(errno);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void tsdbFreeTableSchema(STable *pTable) {
|
||||||
|
ASSERT(pTable != NULL);
|
||||||
|
|
||||||
|
if (pTable->schema) {
|
||||||
|
for (size_t i = 0; i < taosArrayGetSize(pTable->schema); i++) {
|
||||||
|
STSchema *pSchema = taosArrayGetP(pTable->schema, i);
|
||||||
|
tdFreeSchema(pSchema);
|
||||||
|
}
|
||||||
|
|
||||||
|
taosArrayDestroy(pTable->schema);
|
||||||
|
}
|
||||||
|
}
|
|
@ -466,7 +466,7 @@ static STsdbQueryHandle* tsdbQueryTablesImpl(STsdbRepo* tsdb, STsdbQueryCond* pC
|
||||||
STsdbMeta* pMeta = tsdbGetMeta(tsdb);
|
STsdbMeta* pMeta = tsdbGetMeta(tsdb);
|
||||||
assert(pMeta != NULL);
|
assert(pMeta != NULL);
|
||||||
|
|
||||||
pQueryHandle->pDataCols = tdNewDataCols(pMeta->maxRowBytes, pMeta->maxCols, pQueryHandle->pTsdb->config.maxRowsPerFileBlock);
|
pQueryHandle->pDataCols = tdNewDataCols(pMeta->maxCols, pQueryHandle->pTsdb->config.maxRowsPerFileBlock);
|
||||||
if (pQueryHandle->pDataCols == NULL) {
|
if (pQueryHandle->pDataCols == NULL) {
|
||||||
tsdbError("%p failed to malloc buf for pDataCols, %"PRIu64, pQueryHandle, pQueryHandle->qId);
|
tsdbError("%p failed to malloc buf for pDataCols, %"PRIu64, pQueryHandle, pQueryHandle->qId);
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
|
@ -691,6 +691,18 @@ static STableGroupInfo* trimTableGroup(STimeWindow* window, STableGroupInfo* pGr
|
||||||
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond* pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pRef) {
|
TsdbQueryHandleT tsdbQueryRowsInExternalWindow(STsdbRepo *tsdb, STsdbQueryCond* pCond, STableGroupInfo *groupList, uint64_t qId, SMemRef* pRef) {
|
||||||
STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);
|
STableGroupInfo* pNew = trimTableGroup(&pCond->twindow, groupList);
|
||||||
|
|
||||||
|
if (pNew->numOfTables == 0) {
|
||||||
|
tsdbDebug("update query time range to invalidate time window");
|
||||||
|
|
||||||
|
assert(taosArrayGetSize(pNew->pGroupList) == 0);
|
||||||
|
bool asc = ASCENDING_TRAVERSE(pCond->order);
|
||||||
|
if (asc) {
|
||||||
|
pCond->twindow.ekey = pCond->twindow.skey - 1;
|
||||||
|
} else {
|
||||||
|
pCond->twindow.skey = pCond->twindow.ekey - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, pNew, qId, pRef);
|
STsdbQueryHandle *pQueryHandle = (STsdbQueryHandle*) tsdbQueryTables(tsdb, pCond, pNew, qId, pRef);
|
||||||
pQueryHandle->loadExternalRow = true;
|
pQueryHandle->loadExternalRow = true;
|
||||||
pQueryHandle->currentLoadExternalRows = true;
|
pQueryHandle->currentLoadExternalRows = true;
|
||||||
|
@ -1446,7 +1458,7 @@ static int doBinarySearchKey(char* pValue, int num, TSKEY key, int order) {
|
||||||
return midPos;
|
return midPos;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) {
|
static int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity, int32_t numOfRows, int32_t start, int32_t end) {
|
||||||
char* pData = NULL;
|
char* pData = NULL;
|
||||||
int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1 : -1;
|
int32_t step = ASCENDING_TRAVERSE(pQueryHandle->order)? 1 : -1;
|
||||||
|
|
||||||
|
@ -1481,7 +1493,7 @@ int32_t doCopyRowsFromFileBlock(STsdbQueryHandle* pQueryHandle, int32_t capacity
|
||||||
pData = (char*)pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes;
|
pData = (char*)pColInfo->pData + (capacity - numOfRows - num) * pColInfo->info.bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pColInfo->info.colId == src->colId) {
|
if (!isAllRowsNull(src) && pColInfo->info.colId == src->colId) {
|
||||||
if (pColInfo->info.type != TSDB_DATA_TYPE_BINARY && pColInfo->info.type != TSDB_DATA_TYPE_NCHAR) {
|
if (pColInfo->info.type != TSDB_DATA_TYPE_BINARY && pColInfo->info.type != TSDB_DATA_TYPE_NCHAR) {
|
||||||
memmove(pData, (char*)src->pData + bytes * start, bytes * num);
|
memmove(pData, (char*)src->pData + bytes * start, bytes * num);
|
||||||
} else { // handle the var-string
|
} else { // handle the var-string
|
||||||
|
@ -3468,6 +3480,7 @@ void filterPrepare(void* expr, void* param) {
|
||||||
SArray *arr = (SArray *)(pCond->arr);
|
SArray *arr = (SArray *)(pCond->arr);
|
||||||
for (size_t i = 0; i < taosArrayGetSize(arr); i++) {
|
for (size_t i = 0; i < taosArrayGetSize(arr); i++) {
|
||||||
char* p = taosArrayGetP(arr, i);
|
char* p = taosArrayGetP(arr, i);
|
||||||
|
strtolower(varDataVal(p), varDataVal(p));
|
||||||
taosHashPut(pObj, varDataVal(p),varDataLen(p), &dummy, sizeof(dummy));
|
taosHashPut(pObj, varDataVal(p),varDataLen(p), &dummy, sizeof(dummy));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -42,14 +42,14 @@ int tsdbInitReadH(SReadH *pReadh, STsdbRepo *pRepo) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pReadh->pDCols[0] = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock);
|
pReadh->pDCols[0] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
||||||
if (pReadh->pDCols[0] == NULL) {
|
if (pReadh->pDCols[0] == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
tsdbDestroyReadH(pReadh);
|
tsdbDestroyReadH(pReadh);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
pReadh->pDCols[1] = tdNewDataCols(0, 0, pCfg->maxRowsPerFileBlock);
|
pReadh->pDCols[1] = tdNewDataCols(0, pCfg->maxRowsPerFileBlock);
|
||||||
if (pReadh->pDCols[1] == NULL) {
|
if (pReadh->pDCols[1] == NULL) {
|
||||||
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
terrno = TSDB_CODE_TDB_OUT_OF_MEMORY;
|
||||||
tsdbDestroyReadH(pReadh);
|
tsdbDestroyReadH(pReadh);
|
||||||
|
@ -463,7 +463,7 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat
|
||||||
SDataCol *pDataCol = &(pDataCols->cols[dcol]);
|
SDataCol *pDataCol = &(pDataCols->cols[dcol]);
|
||||||
if (dcol != 0 && ccol >= pBlockData->numOfCols) {
|
if (dcol != 0 && ccol >= pBlockData->numOfCols) {
|
||||||
// Set current column as NULL and forward
|
// Set current column as NULL and forward
|
||||||
dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints);
|
dataColReset(pDataCol);
|
||||||
dcol++;
|
dcol++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -503,7 +503,7 @@ static int tsdbLoadBlockDataImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *pDat
|
||||||
ccol++;
|
ccol++;
|
||||||
} else {
|
} else {
|
||||||
// Set current column as NULL and forward
|
// Set current column as NULL and forward
|
||||||
dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints);
|
dataColReset(pDataCol);
|
||||||
dcol++;
|
dcol++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -608,7 +608,7 @@ static int tsdbLoadBlockDataColsImpl(SReadH *pReadh, SBlock *pBlock, SDataCols *
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pBlockCol == NULL) {
|
if (pBlockCol == NULL) {
|
||||||
dataColSetNEleNull(pDataCol, pBlock->numOfRows, pDataCols->maxPoints);
|
dataColReset(pDataCol);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ extern "C" {
|
||||||
#define TSDB_PATTERN_MATCH 0
|
#define TSDB_PATTERN_MATCH 0
|
||||||
#define TSDB_PATTERN_NOMATCH 1
|
#define TSDB_PATTERN_NOMATCH 1
|
||||||
#define TSDB_PATTERN_NOWILDCARDMATCH 2
|
#define TSDB_PATTERN_NOWILDCARDMATCH 2
|
||||||
#define TSDB_PATTERN_STRING_MAX_LEN 20
|
#define TSDB_PATTERN_STRING_DEFAULT_LEN 100
|
||||||
|
|
||||||
#define FLT_COMPAR_TOL_FACTOR 4
|
#define FLT_COMPAR_TOL_FACTOR 4
|
||||||
#define FLT_EQUAL(_x, _y) (fabs((_x) - (_y)) <= (FLT_COMPAR_TOL_FACTOR * FLT_EPSILON))
|
#define FLT_EQUAL(_x, _y) (fabs((_x) - (_y)) <= (FLT_COMPAR_TOL_FACTOR * FLT_EPSILON))
|
||||||
|
@ -47,7 +47,7 @@ int WCSPatternMatch(const wchar_t *pattern, const wchar_t *str, size_t size, con
|
||||||
|
|
||||||
int32_t doCompare(const char* a, const char* b, int32_t type, size_t size);
|
int32_t doCompare(const char* a, const char* b, int32_t type, size_t size);
|
||||||
|
|
||||||
__compar_fn_t getKeyComparFunc(int32_t keyType);
|
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order);
|
||||||
|
|
||||||
__compar_fn_t getComparFunc(int32_t type, int32_t optr);
|
__compar_fn_t getComparFunc(int32_t type, int32_t optr);
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,7 @@ typedef struct {
|
||||||
extern SGlobalCfg tsGlobalConfig[];
|
extern SGlobalCfg tsGlobalConfig[];
|
||||||
extern int32_t tsGlobalConfigNum;
|
extern int32_t tsGlobalConfigNum;
|
||||||
extern char * tsCfgStatusStr[];
|
extern char * tsCfgStatusStr[];
|
||||||
|
extern bool tsdbForceKeepFile;
|
||||||
|
|
||||||
void taosReadGlobalLogCfg();
|
void taosReadGlobalLogCfg();
|
||||||
bool taosReadGlobalCfg();
|
bool taosReadGlobalCfg();
|
||||||
|
|
|
@ -16,28 +16,22 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "ttype.h"
|
#include "ttype.h"
|
||||||
#include "tcompare.h"
|
#include "tcompare.h"
|
||||||
#include "tarray.h"
|
|
||||||
#include "hash.h"
|
#include "hash.h"
|
||||||
|
|
||||||
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
|
int32_t setCompareBytes1(const void *pLeft, const void *pRight) {
|
||||||
int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight);
|
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 1) ? 1 : 0;
|
||||||
if (left > right) return 1;
|
|
||||||
if (left < right) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt64Val(const void *pLeft, const void *pRight) {
|
int32_t setCompareBytes2(const void *pLeft, const void *pRight) {
|
||||||
int64_t left = GET_INT64_VAL(pLeft), right = GET_INT64_VAL(pRight);
|
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 2) ? 1 : 0;
|
||||||
if (left > right) return 1;
|
|
||||||
if (left < right) return -1;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt16Val(const void *pLeft, const void *pRight) {
|
int32_t setCompareBytes4(const void *pLeft, const void *pRight) {
|
||||||
int16_t left = GET_INT16_VAL(pLeft), right = GET_INT16_VAL(pRight);
|
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 4) ? 1 : 0;
|
||||||
if (left > right) return 1;
|
}
|
||||||
if (left < right) return -1;
|
|
||||||
return 0;
|
int32_t setCompareBytes8(const void *pLeft, const void *pRight) {
|
||||||
|
return NULL != taosHashGet((SHashObj *)pRight, pLeft, 8) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareInt8Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt8Val(const void *pLeft, const void *pRight) {
|
||||||
|
@ -47,27 +41,76 @@ int32_t compareInt8Val(const void *pLeft, const void *pRight) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t compareUint32Val(const void *pLeft, const void *pRight) {
|
int32_t compareInt8ValDesc(const void *pLeft, const void *pRight) {
|
||||||
int32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight);
|
return compareInt8Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareInt16Val(const void *pLeft, const void *pRight) {
|
||||||
|
int16_t left = GET_INT16_VAL(pLeft), right = GET_INT16_VAL(pRight);
|
||||||
if (left > right) return 1;
|
if (left > right) return 1;
|
||||||
if (left < right) return -1;
|
if (left < right) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareInt16ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareInt16Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareInt32Val(const void *pLeft, const void *pRight) {
|
||||||
|
int32_t left = GET_INT32_VAL(pLeft), right = GET_INT32_VAL(pRight);
|
||||||
|
if (left > right) return 1;
|
||||||
|
if (left < right) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareInt32ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareInt32Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareInt64Val(const void *pLeft, const void *pRight) {
|
||||||
|
int64_t left = GET_INT64_VAL(pLeft), right = GET_INT64_VAL(pRight);
|
||||||
|
if (left > right) return 1;
|
||||||
|
if (left < right) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareInt64ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareInt64Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareUint32Val(const void *pLeft, const void *pRight) {
|
||||||
|
uint32_t left = GET_UINT32_VAL(pLeft), right = GET_UINT32_VAL(pRight);
|
||||||
|
if (left > right) return 1;
|
||||||
|
if (left < right) return -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t compareUint32ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareUint32Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareUint64Val(const void *pLeft, const void *pRight) {
|
int32_t compareUint64Val(const void *pLeft, const void *pRight) {
|
||||||
int64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight);
|
uint64_t left = GET_UINT64_VAL(pLeft), right = GET_UINT64_VAL(pRight);
|
||||||
if (left > right) return 1;
|
if (left > right) return 1;
|
||||||
if (left < right) return -1;
|
if (left < right) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareUint64ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareUint64Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareUint16Val(const void *pLeft, const void *pRight) {
|
int32_t compareUint16Val(const void *pLeft, const void *pRight) {
|
||||||
int16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight);
|
uint16_t left = GET_UINT16_VAL(pLeft), right = GET_UINT16_VAL(pRight);
|
||||||
if (left > right) return 1;
|
if (left > right) return 1;
|
||||||
if (left < right) return -1;
|
if (left < right) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareUint16ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareUint16Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareUint8Val(const void* pLeft, const void* pRight) {
|
int32_t compareUint8Val(const void* pLeft, const void* pRight) {
|
||||||
uint8_t left = GET_UINT8_VAL(pLeft), right = GET_UINT8_VAL(pRight);
|
uint8_t left = GET_UINT8_VAL(pLeft), right = GET_UINT8_VAL(pRight);
|
||||||
if (left > right) return 1;
|
if (left > right) return 1;
|
||||||
|
@ -75,6 +118,10 @@ int32_t compareUint8Val(const void* pLeft, const void* pRight) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareUint8ValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareUint8Val(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareFloatVal(const void *pLeft, const void *pRight) {
|
int32_t compareFloatVal(const void *pLeft, const void *pRight) {
|
||||||
float p1 = GET_FLOAT_VAL(pLeft);
|
float p1 = GET_FLOAT_VAL(pLeft);
|
||||||
float p2 = GET_FLOAT_VAL(pRight);
|
float p2 = GET_FLOAT_VAL(pRight);
|
||||||
|
@ -96,6 +143,10 @@ int32_t compareFloatVal(const void *pLeft, const void *pRight) {
|
||||||
return FLT_GREATER(p1, p2) ? 1: -1;
|
return FLT_GREATER(p1, p2) ? 1: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareFloatValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareFloatVal(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
|
int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
|
||||||
double p1 = GET_DOUBLE_VAL(pLeft);
|
double p1 = GET_DOUBLE_VAL(pLeft);
|
||||||
double p2 = GET_DOUBLE_VAL(pRight);
|
double p2 = GET_DOUBLE_VAL(pRight);
|
||||||
|
@ -117,6 +168,10 @@ int32_t compareDoubleVal(const void *pLeft, const void *pRight) {
|
||||||
return FLT_GREATER(p1, p2) ? 1: -1;
|
return FLT_GREATER(p1, p2) ? 1: -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareDoubleValDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareDoubleVal(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) {
|
int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) {
|
||||||
int32_t len1 = varDataLen(pLeft);
|
int32_t len1 = varDataLen(pLeft);
|
||||||
int32_t len2 = varDataLen(pRight);
|
int32_t len2 = varDataLen(pRight);
|
||||||
|
@ -133,6 +188,10 @@ int32_t compareLenPrefixedStr(const void *pLeft, const void *pRight) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareLenPrefixedStrDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareLenPrefixedStr(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) {
|
int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) {
|
||||||
int32_t len1 = varDataLen(pLeft);
|
int32_t len1 = varDataLen(pLeft);
|
||||||
int32_t len2 = varDataLen(pRight);
|
int32_t len2 = varDataLen(pRight);
|
||||||
|
@ -140,7 +199,7 @@ int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) {
|
||||||
if (len1 != len2) {
|
if (len1 != len2) {
|
||||||
return len1 > len2? 1:-1;
|
return len1 > len2? 1:-1;
|
||||||
} else {
|
} else {
|
||||||
int32_t ret = wcsncmp(varDataVal(pLeft), varDataVal(pRight), len1/TSDB_NCHAR_SIZE);
|
int32_t ret = memcmp((wchar_t*) pLeft, (wchar_t*) pRight, len1);
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
} else {
|
} else {
|
||||||
|
@ -149,6 +208,10 @@ int32_t compareLenPrefixedWStr(const void *pLeft, const void *pRight) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32_t compareLenPrefixedWStrDesc(const void* pLeft, const void* pRight) {
|
||||||
|
return compareLenPrefixedWStr(pRight, pLeft);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compare two strings
|
* Compare two strings
|
||||||
* TSDB_MATCH: Match
|
* TSDB_MATCH: Match
|
||||||
|
@ -262,12 +325,12 @@ int WCSPatternMatch(const wchar_t *patterStr, const wchar_t *str, size_t size, c
|
||||||
return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH;
|
return (str[j] == 0 || j >= size) ? TSDB_PATTERN_MATCH : TSDB_PATTERN_NOMATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t compareStrPatternComp(const void* pLeft, const void* pRight) {
|
int32_t compareStrPatternComp(const void* pLeft, const void* pRight) {
|
||||||
SPatternCompareInfo pInfo = {'%', '_'};
|
SPatternCompareInfo pInfo = {'%', '_'};
|
||||||
|
|
||||||
char pattern[128] = {0};
|
assert(varDataLen(pRight) <= TSDB_MAX_FIELD_LEN);
|
||||||
|
char *pattern = calloc(varDataLen(pRight) + 1, sizeof(char));
|
||||||
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
||||||
assert(varDataLen(pRight) < 128);
|
|
||||||
|
|
||||||
size_t sz = varDataLen(pLeft);
|
size_t sz = varDataLen(pLeft);
|
||||||
char *buf = malloc(sz + 1);
|
char *buf = malloc(sz + 1);
|
||||||
|
@ -276,6 +339,7 @@ static int32_t compareStrPatternComp(const void* pLeft, const void* pRight) {
|
||||||
|
|
||||||
int32_t ret = patternMatch(pattern, buf, sz, &pInfo);
|
int32_t ret = patternMatch(pattern, buf, sz, &pInfo);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
free(pattern);
|
||||||
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,30 +350,50 @@ int32_t taosArrayCompareString(const void* a, const void* b) {
|
||||||
return compareLenPrefixedStr(x, y);
|
return compareLenPrefixedStr(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
//static int32_t compareFindStrInArray(const void* pLeft, const void* pRight) {
|
int32_t compareFindItemInSet(const void *pLeft, const void* pRight) {
|
||||||
// const SArray* arr = (const SArray*) pRight;
|
|
||||||
// return taosArraySearchString(arr, pLeft, taosArrayCompareString, TD_EQ) == NULL ? 0 : 1;
|
|
||||||
//}
|
|
||||||
static int32_t compareFindItemInSet(const void *pLeft, const void* pRight) {
|
|
||||||
return NULL != taosHashGet((SHashObj *)pRight, varDataVal(pLeft), varDataLen(pLeft)) ? 1 : 0;
|
return NULL != taosHashGet((SHashObj *)pRight, varDataVal(pLeft), varDataLen(pLeft)) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
int32_t compareWStrPatternComp(const void* pLeft, const void* pRight) {
|
||||||
SPatternCompareInfo pInfo = {'%', '_'};
|
SPatternCompareInfo pInfo = {'%', '_'};
|
||||||
|
|
||||||
wchar_t pattern[128] = {0};
|
assert(varDataLen(pRight) <= TSDB_MAX_FIELD_LEN * TSDB_NCHAR_SIZE);
|
||||||
assert(TSDB_PATTERN_STRING_MAX_LEN < 128);
|
|
||||||
|
|
||||||
|
wchar_t *pattern = calloc(varDataLen(pRight) + 1, sizeof(wchar_t));
|
||||||
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
memcpy(pattern, varDataVal(pRight), varDataLen(pRight));
|
||||||
assert(varDataLen(pRight) < 128);
|
|
||||||
|
|
||||||
int32_t ret = WCSPatternMatch(pattern, varDataVal(pLeft), varDataLen(pLeft)/TSDB_NCHAR_SIZE, &pInfo);
|
int32_t ret = WCSPatternMatch(pattern, varDataVal(pLeft), varDataLen(pLeft)/TSDB_NCHAR_SIZE, &pInfo);
|
||||||
|
free(pattern);
|
||||||
|
|
||||||
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
return (ret == TSDB_PATTERN_MATCH) ? 0 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
__compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
__compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
||||||
__compar_fn_t comparFn = NULL;
|
__compar_fn_t comparFn = NULL;
|
||||||
|
|
||||||
|
if (optr == TSDB_RELATION_IN && (type != TSDB_DATA_TYPE_BINARY && type != TSDB_DATA_TYPE_NCHAR)) {
|
||||||
|
switch (type) {
|
||||||
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
|
return setCompareBytes1;
|
||||||
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
|
return setCompareBytes2;
|
||||||
|
case TSDB_DATA_TYPE_INT:
|
||||||
|
case TSDB_DATA_TYPE_UINT:
|
||||||
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
|
return setCompareBytes4;
|
||||||
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
|
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
|
return setCompareBytes8;
|
||||||
|
default:
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TSDB_DATA_TYPE_BOOL:
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
case TSDB_DATA_TYPE_TINYINT: comparFn = compareInt8Val; break;
|
case TSDB_DATA_TYPE_TINYINT: comparFn = compareInt8Val; break;
|
||||||
|
@ -334,6 +418,8 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
||||||
case TSDB_DATA_TYPE_NCHAR: {
|
case TSDB_DATA_TYPE_NCHAR: {
|
||||||
if (optr == TSDB_RELATION_LIKE) {
|
if (optr == TSDB_RELATION_LIKE) {
|
||||||
comparFn = compareWStrPatternComp;
|
comparFn = compareWStrPatternComp;
|
||||||
|
} else if (optr == TSDB_RELATION_IN) {
|
||||||
|
comparFn = compareFindItemInSet;
|
||||||
} else {
|
} else {
|
||||||
comparFn = compareLenPrefixedWStr;
|
comparFn = compareLenPrefixedWStr;
|
||||||
}
|
}
|
||||||
|
@ -353,50 +439,50 @@ __compar_fn_t getComparFunc(int32_t type, int32_t optr) {
|
||||||
return comparFn;
|
return comparFn;
|
||||||
}
|
}
|
||||||
|
|
||||||
__compar_fn_t getKeyComparFunc(int32_t keyType) {
|
__compar_fn_t getKeyComparFunc(int32_t keyType, int32_t order) {
|
||||||
__compar_fn_t comparFn = NULL;
|
__compar_fn_t comparFn = NULL;
|
||||||
|
|
||||||
switch (keyType) {
|
switch (keyType) {
|
||||||
case TSDB_DATA_TYPE_TINYINT:
|
case TSDB_DATA_TYPE_TINYINT:
|
||||||
case TSDB_DATA_TYPE_BOOL:
|
case TSDB_DATA_TYPE_BOOL:
|
||||||
comparFn = compareInt8Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareInt8Val:compareInt8ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_SMALLINT:
|
case TSDB_DATA_TYPE_SMALLINT:
|
||||||
comparFn = compareInt16Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareInt16Val:compareInt16ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_INT:
|
case TSDB_DATA_TYPE_INT:
|
||||||
comparFn = compareInt32Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareInt32Val:compareInt32ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_BIGINT:
|
case TSDB_DATA_TYPE_BIGINT:
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP:
|
case TSDB_DATA_TYPE_TIMESTAMP:
|
||||||
comparFn = compareInt64Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareInt64Val:compareInt64ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_FLOAT:
|
case TSDB_DATA_TYPE_FLOAT:
|
||||||
comparFn = compareFloatVal;
|
comparFn = (order == TSDB_ORDER_ASC)? compareFloatVal:compareFloatValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_DOUBLE:
|
case TSDB_DATA_TYPE_DOUBLE:
|
||||||
comparFn = compareDoubleVal;
|
comparFn = (order == TSDB_ORDER_ASC)? compareDoubleVal:compareDoubleValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_UTINYINT:
|
case TSDB_DATA_TYPE_UTINYINT:
|
||||||
comparFn = compareUint8Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareUint8Val:compareUint8ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_USMALLINT:
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
comparFn = compareUint16Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareUint16Val:compareUint16ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_UINT:
|
case TSDB_DATA_TYPE_UINT:
|
||||||
comparFn = compareUint32Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareUint32Val:compareUint32ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_UBIGINT:
|
case TSDB_DATA_TYPE_UBIGINT:
|
||||||
comparFn = compareUint64Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareUint64Val:compareUint64ValDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_BINARY:
|
case TSDB_DATA_TYPE_BINARY:
|
||||||
comparFn = compareLenPrefixedStr;
|
comparFn = (order == TSDB_ORDER_ASC)? compareLenPrefixedStr:compareLenPrefixedStrDesc;
|
||||||
break;
|
break;
|
||||||
case TSDB_DATA_TYPE_NCHAR:
|
case TSDB_DATA_TYPE_NCHAR:
|
||||||
comparFn = compareLenPrefixedWStr;
|
comparFn = (order == TSDB_ORDER_ASC)? compareLenPrefixedWStr:compareLenPrefixedWStrDesc;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
comparFn = compareInt32Val;
|
comparFn = (order == TSDB_ORDER_ASC)? compareInt32Val:compareInt32ValDesc;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -423,8 +509,7 @@ int32_t doCompare(const char* f1, const char* f2, int32_t type, size_t size) {
|
||||||
if (t1->len != t2->len) {
|
if (t1->len != t2->len) {
|
||||||
return t1->len > t2->len? 1:-1;
|
return t1->len > t2->len? 1:-1;
|
||||||
}
|
}
|
||||||
|
int32_t ret = memcmp((wchar_t*) t1, (wchar_t*) t2, t2->len);
|
||||||
int32_t ret = wcsncmp((wchar_t*) t1->data, (wchar_t*) t2->data, t2->len/TSDB_NCHAR_SIZE);
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ SSkipList *tSkipListCreate(uint8_t maxLevel, uint8_t keyType, uint16_t keyLen, _
|
||||||
pSkipList->keyFn = fn;
|
pSkipList->keyFn = fn;
|
||||||
pSkipList->seed = rand();
|
pSkipList->seed = rand();
|
||||||
if (comparFn == NULL) {
|
if (comparFn == NULL) {
|
||||||
pSkipList->comparFn = getKeyComparFunc(keyType);
|
pSkipList->comparFn = getKeyComparFunc(keyType, TSDB_ORDER_ASC);
|
||||||
} else {
|
} else {
|
||||||
pSkipList->comparFn = comparFn;
|
pSkipList->comparFn = comparFn;
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ void doubleSkipListTest() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void randKeyTest() {
|
void randKeyTest() {
|
||||||
SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), getKeyComparFunc(TSDB_DATA_TYPE_INT),
|
SSkipList* pSkipList = tSkipListCreate(10, TSDB_DATA_TYPE_INT, sizeof(int32_t), getKeyComparFunc(TSDB_DATA_TYPE_INT, TSDB_ORDER_ASC),
|
||||||
false, getkey);
|
false, getkey);
|
||||||
|
|
||||||
int32_t size = 200000;
|
int32_t size = 200000;
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#define TAOS_RANDOM_FILE_FAIL_TEST
|
#define TAOS_RANDOM_FILE_FAIL_TEST
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
#include "taoserror.h"
|
#include "taoserror.h"
|
||||||
|
#include "taosmsg.h"
|
||||||
#include "tchecksum.h"
|
#include "tchecksum.h"
|
||||||
#include "tfile.h"
|
#include "tfile.h"
|
||||||
#include "twal.h"
|
#include "twal.h"
|
||||||
|
@ -114,7 +115,7 @@ void walRemoveAllOldFiles(void *handle) {
|
||||||
#if defined(WAL_CHECKSUM_WHOLE)
|
#if defined(WAL_CHECKSUM_WHOLE)
|
||||||
|
|
||||||
static void walUpdateChecksum(SWalHead *pHead) {
|
static void walUpdateChecksum(SWalHead *pHead) {
|
||||||
pHead->sver = 1;
|
pHead->sver = 2;
|
||||||
pHead->cksum = 0;
|
pHead->cksum = 0;
|
||||||
pHead->cksum = taosCalcChecksum(0, (uint8_t *)pHead, sizeof(*pHead) + pHead->len);
|
pHead->cksum = taosCalcChecksum(0, (uint8_t *)pHead, sizeof(*pHead) + pHead->len);
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,7 @@ static void walUpdateChecksum(SWalHead *pHead) {
|
||||||
static int walValidateChecksum(SWalHead *pHead) {
|
static int walValidateChecksum(SWalHead *pHead) {
|
||||||
if (pHead->sver == 0) { // for compatible with wal before sver 1
|
if (pHead->sver == 0) { // for compatible with wal before sver 1
|
||||||
return taosCheckChecksumWhole((uint8_t *)pHead, sizeof(*pHead));
|
return taosCheckChecksumWhole((uint8_t *)pHead, sizeof(*pHead));
|
||||||
} else if (pHead->sver == 1) {
|
} else if (pHead->sver >= 1) {
|
||||||
uint32_t cksum = pHead->cksum;
|
uint32_t cksum = pHead->cksum;
|
||||||
pHead->cksum = 0;
|
pHead->cksum = 0;
|
||||||
return taosCheckChecksum((uint8_t *)pHead, sizeof(*pHead) + pHead->len, cksum);
|
return taosCheckChecksum((uint8_t *)pHead, sizeof(*pHead) + pHead->len, cksum);
|
||||||
|
@ -281,7 +282,7 @@ static int32_t walSkipCorruptedRecord(SWal *pWal, SWalHead *pHead, int64_t tfd,
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHead->sver == 1) {
|
if (pHead->sver >= 1) {
|
||||||
if (tfRead(tfd, pHead->cont, pHead->len) < pHead->len) {
|
if (tfRead(tfd, pHead->cont, pHead->len) < pHead->len) {
|
||||||
wError("vgId:%d, read to end of corrupted wal file, offset:%" PRId64, pWal->vgId, pos);
|
wError("vgId:%d, read to end of corrupted wal file, offset:%" PRId64, pWal->vgId, pos);
|
||||||
return TSDB_CODE_WAL_FILE_CORRUPTED;
|
return TSDB_CODE_WAL_FILE_CORRUPTED;
|
||||||
|
@ -306,7 +307,115 @@ static int32_t walSkipCorruptedRecord(SWal *pWal, SWalHead *pHead, int64_t tfd,
|
||||||
|
|
||||||
return TSDB_CODE_WAL_FILE_CORRUPTED;
|
return TSDB_CODE_WAL_FILE_CORRUPTED;
|
||||||
}
|
}
|
||||||
|
// Add SMemRowType ahead of SDataRow
|
||||||
|
static void expandSubmitBlk(SSubmitBlk *pDest, SSubmitBlk *pSrc, int32_t *lenExpand) {
|
||||||
|
// copy the header firstly
|
||||||
|
memcpy(pDest, pSrc, sizeof(SSubmitBlk));
|
||||||
|
|
||||||
|
int32_t nRows = htons(pDest->numOfRows);
|
||||||
|
int32_t dataLen = htonl(pDest->dataLen);
|
||||||
|
|
||||||
|
if ((nRows <= 0) || (dataLen <= 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pDestData = pDest->data;
|
||||||
|
char *pSrcData = pSrc->data;
|
||||||
|
for (int32_t i = 0; i < nRows; ++i) {
|
||||||
|
memRowSetType(pDestData, SMEM_ROW_DATA);
|
||||||
|
memcpy(memRowDataBody(pDestData), pSrcData, dataRowLen(pSrcData));
|
||||||
|
pDestData = POINTER_SHIFT(pDestData, memRowTLen(pDestData));
|
||||||
|
pSrcData = POINTER_SHIFT(pSrcData, dataRowLen(pSrcData));
|
||||||
|
++(*lenExpand);
|
||||||
|
}
|
||||||
|
pDest->dataLen = htonl(dataLen + nRows * sizeof(uint8_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check SDataRow by comparing the SDataRow len and SSubmitBlk dataLen
|
||||||
|
static bool walIsSDataRow(void *pBlkData, int nRows, int32_t dataLen) {
|
||||||
|
if ((nRows <= 0) || (dataLen <= 0)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
int32_t len = 0, kvLen = 0;
|
||||||
|
for (int i = 0; i < nRows; ++i) {
|
||||||
|
len += dataRowLen(pBlkData);
|
||||||
|
if (len > dataLen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For SDataRow between version [2.1.5.0 and 2.1.6.X], it would never conflict.
|
||||||
|
* For SKVRow between version [2.1.5.0 and 2.1.6.X], it may conflict in below scenario
|
||||||
|
* - with 1st type byte 0x01 and sversion 0x0101(257), thus do further check
|
||||||
|
*/
|
||||||
|
if (dataRowLen(pBlkData) == 257) {
|
||||||
|
SMemRow memRow = pBlkData;
|
||||||
|
SKVRow kvRow = memRowKvBody(memRow);
|
||||||
|
int nCols = kvRowNCols(kvRow);
|
||||||
|
uint16_t calcTsOffset = (uint16_t)(TD_KV_ROW_HEAD_SIZE + sizeof(SColIdx) * nCols);
|
||||||
|
uint16_t realTsOffset = (kvRowColIdx(kvRow))->offset;
|
||||||
|
if (calcTsOffset == realTsOffset) {
|
||||||
|
kvLen += memRowKvTLen(memRow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pBlkData = POINTER_SHIFT(pBlkData, dataRowLen(pBlkData));
|
||||||
|
}
|
||||||
|
if (len != dataLen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (kvLen == dataLen) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// for WAL SMemRow/SDataRow compatibility
|
||||||
|
static int walSMemRowCheck(SWalHead *pHead) {
|
||||||
|
if ((pHead->sver < 2) && (pHead->msgType == TSDB_MSG_TYPE_SUBMIT)) {
|
||||||
|
SSubmitMsg *pMsg = (SSubmitMsg *)pHead->cont;
|
||||||
|
int32_t numOfBlocks = htonl(pMsg->numOfBlocks);
|
||||||
|
if (numOfBlocks <= 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t nTotalRows = 0;
|
||||||
|
SSubmitBlk *pBlk = (SSubmitBlk *)pMsg->blocks;
|
||||||
|
for (int32_t i = 0; i < numOfBlocks; ++i) {
|
||||||
|
int32_t dataLen = htonl(pBlk->dataLen);
|
||||||
|
int32_t nRows = htons(pBlk->numOfRows);
|
||||||
|
nTotalRows += nRows;
|
||||||
|
if (!walIsSDataRow(pBlk->data, nRows, dataLen)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pBlk = (SSubmitBlk *)POINTER_SHIFT(pBlk, sizeof(SSubmitBlk) + dataLen);
|
||||||
|
}
|
||||||
|
ASSERT(nTotalRows >= 0);
|
||||||
|
SWalHead *pWalHead = (SWalHead *)calloc(sizeof(SWalHead) + pHead->len + nTotalRows * sizeof(uint8_t), 1);
|
||||||
|
if (pWalHead == NULL) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pWalHead, pHead, sizeof(SWalHead) + sizeof(SSubmitMsg));
|
||||||
|
|
||||||
|
SSubmitMsg *pDestMsg = (SSubmitMsg *)pWalHead->cont;
|
||||||
|
SSubmitBlk *pDestBlks = (SSubmitBlk *)pDestMsg->blocks;
|
||||||
|
SSubmitBlk *pSrcBlks = (SSubmitBlk *)pMsg->blocks;
|
||||||
|
int32_t lenExpand = 0;
|
||||||
|
for (int32_t i = 0; i < numOfBlocks; ++i) {
|
||||||
|
expandSubmitBlk(pDestBlks, pSrcBlks, &lenExpand);
|
||||||
|
pDestBlks = POINTER_SHIFT(pDestBlks, htonl(pDestBlks->dataLen) + sizeof(SSubmitBlk));
|
||||||
|
pSrcBlks = POINTER_SHIFT(pSrcBlks, htonl(pSrcBlks->dataLen) + sizeof(SSubmitBlk));
|
||||||
|
}
|
||||||
|
if (lenExpand > 0) {
|
||||||
|
pDestMsg->header.contLen = htonl(pDestMsg->length) + lenExpand;
|
||||||
|
pDestMsg->length = htonl(pDestMsg->header.contLen);
|
||||||
|
pWalHead->len = pWalHead->len + lenExpand;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(pHead, pWalHead, sizeof(SWalHead) + pWalHead->len);
|
||||||
|
tfree(pWalHead);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, char *name, int64_t fileId) {
|
static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, char *name, int64_t fileId) {
|
||||||
int32_t size = WAL_MAX_SIZE;
|
int32_t size = WAL_MAX_SIZE;
|
||||||
|
@ -346,7 +455,7 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(WAL_CHECKSUM_WHOLE)
|
#if defined(WAL_CHECKSUM_WHOLE)
|
||||||
if ((pHead->sver == 0 && !walValidateChecksum(pHead)) || pHead->sver < 0 || pHead->sver > 1) {
|
if ((pHead->sver == 0 && !walValidateChecksum(pHead)) || pHead->sver < 0 || pHead->sver > 2) {
|
||||||
wError("vgId:%d, file:%s, wal head cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name,
|
wError("vgId:%d, file:%s, wal head cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name,
|
||||||
pHead->version, pHead->len, offset);
|
pHead->version, pHead->len, offset);
|
||||||
code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset);
|
code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset);
|
||||||
|
@ -379,7 +488,7 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pHead->sver == 1 && !walValidateChecksum(pHead)) {
|
if ((pHead->sver >= 1) && !walValidateChecksum(pHead)) {
|
||||||
wError("vgId:%d, file:%s, wal whole cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name,
|
wError("vgId:%d, file:%s, wal whole cksum is messed up, hver:%" PRIu64 " len:%d offset:%" PRId64, pWal->vgId, name,
|
||||||
pHead->version, pHead->len, offset);
|
pHead->version, pHead->len, offset);
|
||||||
code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset);
|
code = walSkipCorruptedRecord(pWal, pHead, tfd, &offset);
|
||||||
|
@ -431,7 +540,14 @@ static int32_t walRestoreWalFile(SWal *pWal, void *pVnode, FWalWrite writeFp, ch
|
||||||
|
|
||||||
pWal->version = pHead->version;
|
pWal->version = pHead->version;
|
||||||
|
|
||||||
//wInfo("writeFp: %ld", offset);
|
// wInfo("writeFp: %ld", offset);
|
||||||
|
if (0 != walSMemRowCheck(pHead)) {
|
||||||
|
wError("vgId:%d, restore wal, fileId:%" PRId64 " hver:%" PRIu64 " wver:%" PRIu64 " len:%d offset:%" PRId64,
|
||||||
|
pWal->vgId, fileId, pHead->version, pWal->version, pHead->len, offset);
|
||||||
|
tfClose(tfd);
|
||||||
|
tfree(buffer);
|
||||||
|
return TAOS_SYSTEM_ERROR(errno);
|
||||||
|
}
|
||||||
(*writeFp)(pVnode, pHead, TAOS_QTYPE_WAL, NULL);
|
(*writeFp)(pVnode, pHead, TAOS_QTYPE_WAL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,8 @@ script_dir="$(dirname $(readlink -f $0))"
|
||||||
###### step 3: start build
|
###### step 3: start build
|
||||||
cd $script_dir
|
cd $script_dir
|
||||||
rm -f go.*
|
rm -f go.*
|
||||||
go mod init demotest
|
go mod init demotest > /dev/null 2>&1
|
||||||
go build
|
go mod tidy > /dev/null 2>&1
|
||||||
|
go build > /dev/null 2>&1
|
||||||
sleep 1s
|
sleep 1s
|
||||||
./demotest -h $1 -p $2
|
./demotest -h $1 -p $2
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue