Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
a531411e
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22017
Fork
4786
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
1
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
T
TDengine
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
1
Issue
1
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
a531411e
编写于
10月 26, 2021
作者:
H
Haojun Liao
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
[td-10564] refactor and add test cases.
上级
3f84c37d
变更
14
隐藏空白更改
内联
并排
Showing
14 changed file
with
857 addition
and
405 deletion
+857
-405
include/util/tdef.h
include/util/tdef.h
+1
-0
include/util/tutil.h
include/util/tutil.h
+1
-0
source/libs/function/src/taggfunction.c
source/libs/function/src/taggfunction.c
+63
-63
source/libs/function/src/tfunction.c
source/libs/function/src/tfunction.c
+5
-2
source/libs/parser/inc/parserInt.h
source/libs/parser/inc/parserInt.h
+3
-2
source/libs/parser/inc/parserUtil.h
source/libs/parser/inc/parserUtil.h
+4
-2
source/libs/parser/inc/queryInfoUtil.h
source/libs/parser/inc/queryInfoUtil.h
+4
-2
source/libs/parser/src/astValidate.c
source/libs/parser/src/astValidate.c
+267
-293
source/libs/parser/src/parser.c
source/libs/parser/src/parser.c
+5
-8
source/libs/parser/src/parserUtil.c
source/libs/parser/src/parserUtil.c
+59
-7
source/libs/parser/src/queryInfoUtil.c
source/libs/parser/src/queryInfoUtil.c
+37
-22
source/libs/parser/test/parserTests.cpp
source/libs/parser/test/parserTests.cpp
+365
-1
source/libs/parser/test/tokenizerTest.cpp
source/libs/parser/test/tokenizerTest.cpp
+14
-2
source/util/src/tutil.c
source/util/src/tutil.c
+29
-1
未找到文件。
include/util/tdef.h
浏览文件 @
a531411e
...
...
@@ -81,6 +81,7 @@ extern const int32_t TYPE_BYTES[15];
#define TSDB_ERR -1
#define TS_PATH_DELIMITER "."
#define TS_ESCAPE_CHAR '`'
#define TSDB_TIME_PRECISION_MILLI 0
#define TSDB_TIME_PRECISION_MICRO 1
...
...
include/util/tutil.h
浏览文件 @
a531411e
...
...
@@ -26,6 +26,7 @@ extern "C" {
#include "tdef.h"
int32_t
strdequote
(
char
*
src
);
int32_t
strndequote
(
char
*
dst
,
const
char
*
z
,
int32_t
len
);
int32_t
strRmquote
(
char
*
z
,
int32_t
len
);
size_t
strtrim
(
char
*
src
);
char
*
strnchr
(
char
*
haystack
,
char
needle
,
int32_t
len
,
bool
skipquote
);
...
...
source/libs/function/src/taggfunction.c
浏览文件 @
a531411e
...
...
@@ -4349,10 +4349,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 1
"sum"
,
FUNCTION_AGG
,
FUNCTION_SUM
,
FUNCTION_SUM
,
BASIC_FUNC_SO
,
FUNCTION_AGG
,
function_setup
,
sum_function
,
function_finalizer
,
...
...
@@ -4362,10 +4362,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 2
"avg"
,
FUNCTION_AGG
,
FUNCTION_AVG
,
FUNCTION_AVG
,
BASIC_FUNC_SO
,
FUNCTION_AGG
,
function_setup
,
avg_function
,
avg_finalizer
,
...
...
@@ -4375,10 +4375,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 3
"min"
,
FUNCTION_AGG
,
FUNCTION_MIN
,
FUNCTION_MIN
,
BASIC_FUNC_SO
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
min_func_setup
,
min_function
,
function_finalizer
,
...
...
@@ -4388,10 +4388,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 4
"max"
,
FUNCTION_MAX
,
FUNCTION_AGG
,
FUNCTION_MAX
,
FUNCTION_MAX
,
BASIC_FUNC_SO
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
max_func_setup
,
max_function
,
function_finalizer
,
...
...
@@ -4401,10 +4401,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 5
"stddev"
,
FUNCTION_STDDEV
,
FUNCTION_AGG
,
FUNCTION_STDDEV
,
FUNCTION_STDDEV_DST
,
FUNCSTATE_SO
|
FUNCSTATE_STREAM
,
FUNCTION_AGG
,
function_setup
,
stddev_function
,
stddev_finalizer
,
...
...
@@ -4414,10 +4414,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 6
"percentile"
,
FUNCTION_PERCT
,
FUNCTION_AGG
,
FUNCTION_PERCT
,
FUNCTION_INVALID_ID
,
FUNCSTATE_SO
|
FUNCSTATE_STREAM
,
FUNCTION_AGG
,
percentile_function_setup
,
percentile_function
,
percentile_finalizer
,
...
...
@@ -4427,10 +4427,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 7
"apercentile"
,
FUNCTION_APERCT
,
FUNCTION_AGG
,
FUNCTION_APERCT
,
FUNCTION_APERCT
,
FUNCSTATE_SO
|
FUNCSTATE_STREAM
|
FUNCSTATE_STABLE
,
FUNCTION_AGG
,
apercentile_function_setup
,
apercentile_function
,
apercentile_finalizer
,
...
...
@@ -4440,10 +4440,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 8
"first"
,
FUNCTION_FIRST
,
FUNCTION_AGG
,
FUNCTION_FIRST
,
FUNCTION_FIRST_DST
,
BASIC_FUNC_SO
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
function_setup
,
first_function
,
function_finalizer
,
...
...
@@ -4453,10 +4453,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 9
"last"
,
FUNCTION_LAST
,
FUNCTION_AGG
,
FUNCTION_LAST
,
FUNCTION_LAST_DST
,
BASIC_FUNC_SO
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
function_setup
,
last_function
,
function_finalizer
,
...
...
@@ -4466,10 +4466,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 10
"last_row"
,
FUNCTION_LAST_ROW
,
FUNCTION_AGG
,
FUNCTION_LAST_ROW
,
FUNCTION_LAST_ROW
,
FUNCSTATE_SO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
first_last_function_setup
,
last_row_function
,
last_row_finalizer
,
...
...
@@ -4479,10 +4479,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 11
"top"
,
FUNCTION_TOP
,
FUNCTION_AGG
,
FUNCTION_TOP
,
FUNCTION_TOP
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
top_bottom_function_setup
,
top_function
,
top_bottom_func_finalizer
,
...
...
@@ -4492,10 +4492,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 12
"bottom"
,
FUNCTION_BOTTOM
,
FUNCTION_AGG
,
FUNCTION_BOTTOM
,
FUNCTION_BOTTOM
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
top_bottom_function_setup
,
bottom_function
,
top_bottom_func_finalizer
,
...
...
@@ -4505,10 +4505,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 13
"spread"
,
FUNCTION_SPREAD
,
FUNCTION_AGG
,
FUNCTION_SPREAD
,
FUNCTION_SPREAD
,
BASIC_FUNC_SO
,
FUNCTION_AGG
,
spread_function_setup
,
spread_function
,
spread_function_finalizer
,
...
...
@@ -4518,10 +4518,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 14
"twa"
,
FUNCTION_TWA
,
FUNCTION_AGG
,
FUNCTION_TWA
,
FUNCTION_TWA
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
twa_function_setup
,
twa_function
,
twa_function_finalizer
,
...
...
@@ -4531,10 +4531,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 15
"leastsquares"
,
FUNCTION_LEASTSQR
,
FUNCTION_AGG
,
FUNCTION_LEASTSQR
,
FUNCTION_INVALID_ID
,
FUNCSTATE_SO
|
FUNCSTATE_STREAM
,
FUNCTION_AGG
,
leastsquares_function_setup
,
leastsquares_function
,
leastsquares_finalizer
,
...
...
@@ -4544,10 +4544,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 16
"ts"
,
FUNCTION_TS
,
FUNCTION_AGG
,
FUNCTION_TS
,
FUNCTION_TS
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
function_setup
,
date_col_output_function
,
doFinalizer
,
...
...
@@ -4557,10 +4557,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 17
"ts"
,
FUNCTION_TS_DUMMY
,
FUNCTION_AGG
,
FUNCTION_TS_DUMMY
,
FUNCTION_TS_DUMMY
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
function_setup
,
noop1
,
doFinalizer
,
...
...
@@ -4570,10 +4570,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 18
"tag_dummy"
,
FUNCTION_TAG_DUMMY
,
FUNCTION_AGG
,
FUNCTION_TAG_DUMMY
,
FUNCTION_TAG_DUMMY
,
BASIC_FUNC_SO
,
FUNCTION_AGG
,
function_setup
,
tag_function
,
doFinalizer
,
...
...
@@ -4583,10 +4583,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 19
"ts"
,
FUNCTION_TS_COMP
,
FUNCTION_AGG
,
FUNCTION_TS_COMP
,
FUNCTION_TS_COMP
,
FUNCSTATE_MO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
ts_comp_function_setup
,
ts_comp_function
,
ts_comp_finalize
,
...
...
@@ -4596,10 +4596,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 20
"tag"
,
FUNCTION_TAG
,
FUNCTION_AGG
,
FUNCTION_TAG
,
FUNCTION_TAG
,
BASIC_FUNC_SO
,
FUNCTION_AGG
,
function_setup
,
tag_function
,
doFinalizer
,
...
...
@@ -4609,10 +4609,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
//TODO this is a scala function
// 21, column project sql function
"colprj"
,
FUNCTION_PRJ
,
FUNCTION_AGG
,
FUNCTION_PRJ
,
FUNCTION_PRJ
,
BASIC_FUNC_MO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
function_setup
,
col_project_function
,
doFinalizer
,
...
...
@@ -4622,10 +4622,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 22, multi-output, tag function has only one result
"tagprj"
,
FUNCTION_TAGPRJ
,
FUNCTION_AGG
,
FUNCTION_TAGPRJ
,
FUNCTION_TAGPRJ
,
BASIC_FUNC_MO
,
FUNCTION_AGG
,
function_setup
,
tag_project_function
,
doFinalizer
,
...
...
@@ -4635,10 +4635,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 23
"arithmetic"
,
FUNCTION_ARITHM
,
FUNCTION_AGG
,
FUNCTION_ARITHM
,
FUNCTION_ARITHM
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
function_setup
,
arithmetic_function
,
doFinalizer
,
...
...
@@ -4648,10 +4648,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 24
"diff"
,
FUNCTION_DIFF
,
FUNCTION_AGG
,
FUNCTION_DIFF
,
FUNCTION_INVALID_ID
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
diff_function_setup
,
diff_function
,
doFinalizer
,
...
...
@@ -4662,10 +4662,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 25
"first_dist"
,
FUNCTION_FIRST_DST
,
FUNCTION_AGG
,
FUNCTION_FIRST_DST
,
FUNCTION_FIRST_DST
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
first_last_function_setup
,
first_dist_function
,
function_finalizer
,
...
...
@@ -4675,10 +4675,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 26
"last_dist"
,
FUNCTION_LAST_DST
,
FUNCTION_AGG
,
FUNCTION_LAST_DST
,
FUNCTION_LAST_DST
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
first_last_function_setup
,
last_dist_function
,
function_finalizer
,
...
...
@@ -4688,10 +4688,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 27
"stddev"
,
// return table id and the corresponding tags for join match and subscribe
FUNCTION_STDDEV_DST
,
FUNCTION_AGG
,
FUNCTION_STDDEV_DST
,
FUNCTION_AVG
,
FUNCSTATE_SO
|
FUNCSTATE_STABLE
,
FUNCTION_AGG
,
function_setup
,
stddev_dst_function
,
stddev_dst_finalizer
,
...
...
@@ -4701,10 +4701,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 28
"interp"
,
FUNCTION_INTERP
,
FUNCTION_AGG
,
FUNCTION_INTERP
,
FUNCTION_INTERP
,
FUNCSTATE_SO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
function_setup
,
interp_function
,
doFinalizer
,
...
...
@@ -4714,10 +4714,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 29
"rate"
,
FUNCTION_RATE
,
FUNCTION_AGG
,
FUNCTION_RATE
,
FUNCTION_RATE
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
rate_function_setup
,
rate_function
,
rate_finalizer
,
...
...
@@ -4727,10 +4727,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 30
"irate"
,
FUNCTION_IRATE
,
FUNCTION_AGG
,
FUNCTION_IRATE
,
FUNCTION_IRATE
,
BASIC_FUNC_SO
|
FUNCSTATE_NEED_TS
,
FUNCTION_AGG
,
rate_function_setup
,
irate_function
,
rate_finalizer
,
...
...
@@ -4740,10 +4740,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 31
"tbid"
,
// return table id and the corresponding tags for join match and subscribe
FUNCTION_TID_TAG
,
FUNCTION_AGG
,
FUNCTION_TID_TAG
,
FUNCTION_TID_TAG
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
,
FUNCTION_AGG
,
function_setup
,
noop1
,
noop1
,
...
...
@@ -4752,10 +4752,10 @@ SAggFunctionInfo aggFunc[34] = {{
},
{
//32
"derivative"
,
// return table id and the corresponding tags for join match and subscribe
FUNCTION_DERIVATIVE
,
FUNCTION_AGG
,
FUNCTION_DERIVATIVE
,
FUNCTION_INVALID_ID
,
FUNCSTATE_MO
|
FUNCSTATE_STABLE
|
FUNCSTATE_NEED_TS
|
FUNCSTATE_SELECTIVITY
,
FUNCTION_AGG
,
deriv_function_setup
,
deriv_function
,
doFinalizer
,
...
...
@@ -4765,10 +4765,10 @@ SAggFunctionInfo aggFunc[34] = {{
{
// 33
"_block_dist"
,
// return table id and the corresponding tags for join match and subscribe
FUNCTION_BLKINFO
,
FUNCTION_AGG
,
FUNCTION_BLKINFO
,
FUNCTION_BLKINFO
,
FUNCSTATE_SO
|
FUNCSTATE_STABLE
,
FUNCTION_AGG
,
function_setup
,
blockInfo_func
,
blockinfo_func_finalizer
,
...
...
source/libs/function/src/tfunction.c
浏览文件 @
a531411e
...
...
@@ -12,13 +12,16 @@ static void doInitFunctionHashTable() {
functionHashTable
=
taosHashInit
(
numOfEntries
,
MurmurHash3_32
,
false
,
false
);
for
(
int32_t
i
=
0
;
i
<
numOfEntries
;
i
++
)
{
int32_t
len
=
(
uint32_t
)
strlen
(
aggFunc
[
i
].
name
);
taosHashPut
(
functionHashTable
,
aggFunc
[
i
].
name
,
len
,
(
void
*
)
&
aggFunc
[
i
],
POINTER_BYTES
);
SAggFunctionInfo
*
ptr
=
&
aggFunc
[
i
];
taosHashPut
(
functionHashTable
,
aggFunc
[
i
].
name
,
len
,
(
void
*
)
&
ptr
,
POINTER_BYTES
);
}
numOfEntries
=
tListLen
(
scalarFunc
);
for
(
int32_t
i
=
0
;
i
<
numOfEntries
;
++
i
)
{
int32_t
len
=
(
int32_t
)
strlen
(
scalarFunc
[
i
].
name
);
taosHashPut
(
functionHashTable
,
scalarFunc
[
i
].
name
,
len
,
(
void
*
)
&
scalarFunc
[
i
],
POINTER_BYTES
);
SScalarFunctionInfo
*
ptr
=
&
scalarFunc
[
i
];
taosHashPut
(
functionHashTable
,
scalarFunc
[
i
].
name
,
len
,
(
void
*
)
&
ptr
,
POINTER_BYTES
);
}
}
...
...
source/libs/parser/inc/parserInt.h
浏览文件 @
a531411e
...
...
@@ -48,8 +48,6 @@ typedef struct SSqlExpr {
SColIndex
colInfo
;
uint64_t
uid
;
// table uid, todo refactor use the pointer
int32_t
interBytes
;
// inter result buffer size
// int16_t colType; // table column type
// int16_t colBytes; // table column bytes
int16_t
numOfParams
;
// argument value of each function
SVariant
param
[
3
];
// parameters are not more than 3
}
SSqlExpr
;
...
...
@@ -101,6 +99,9 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pSqlInfo, SQ
*/
int32_t
evaluateSqlNode
(
SSqlNode
*
pNode
,
int32_t
tsPrecision
,
SMsgBuf
*
pMsgBuf
);
int32_t
validateSqlNode
(
SSqlNode
*
pSqlNode
,
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
);
void
initQueryInfo
(
SQueryStmtInfo
*
pQueryInfo
);
/**
* Extract request meta info from the sql statement
* @param pSqlInfo
...
...
source/libs/parser/inc/parserUtil.h
浏览文件 @
a531411e
...
...
@@ -37,7 +37,7 @@ extern "C" {
(((metaInfo)->pTableMeta != NULL) && ((metaInfo)->pTableMeta->tableType == TSDB_TEMP_TABLE))
TAOS_FIELD
createField
(
const
SSchema
*
pSchema
);
void
setSchemaVal
(
SSchema
*
pSchema
,
uint8_t
type
,
int16_t
bytes
,
int16_t
colId
,
const
char
*
name
);
SSchema
createSchema
(
uint8_t
type
,
int16_t
bytes
,
int16_t
colId
,
const
char
*
name
);
SInternalField
*
insertFieldInfo
(
SFieldInfo
*
pFieldInfo
,
int32_t
index
,
SSchema
*
field
);
int32_t
getNumOfFields
(
SFieldInfo
*
pFieldInfo
);
...
...
@@ -45,7 +45,7 @@ SInternalField* getInternalField(SFieldInfo* pFieldInfo, int32_t index);
int32_t
parserValidateIdToken
(
SToken
*
pToken
);
int32_t
buildInvalidOperationMsg
(
SMsgBuf
*
pMsgBuf
,
const
char
*
msg
);
int32_t
parserSet
SyntaxErrMsg
(
char
*
dst
,
int32_t
dstBufLen
,
const
char
*
additionalInfo
,
const
char
*
sourceStr
);
int32_t
build
SyntaxErrMsg
(
char
*
dst
,
int32_t
dstBufLen
,
const
char
*
additionalInfo
,
const
char
*
sourceStr
);
int32_t
createProjectionExpr
(
SQueryStmtInfo
*
pQueryInfo
,
STableMetaInfo
*
pTableMetaInfo
,
SExprInfo
***
pExpr
,
int32_t
*
num
);
STableMetaInfo
*
addEmptyMetaInfo
(
SQueryStmtInfo
*
pQueryInfo
);
...
...
@@ -60,6 +60,8 @@ SColumn* insertPrimaryTsColumn(SArray* pColumnList, uint64_t tableUid);
void
cleanupTagCond
(
STagCond
*
pTagCond
);
void
cleanupColumnCond
(
SArray
**
pCond
);
uint32_t
convertRelationalOperator
(
SToken
*
pToken
);
#ifdef __cplusplus
}
#endif
...
...
source/libs/parser/inc/queryInfoUtil.h
浏览文件 @
a531411e
...
...
@@ -30,8 +30,10 @@ SSchema *getTableTagSchema(const STableMeta* pTableMeta);
SSchema
*
getOneColumnSchema
(
const
STableMeta
*
pTableMeta
,
int32_t
colIndex
);
size_t
getNumOfExprs
(
SQueryStmtInfo
*
pQueryInfo
);
SExprInfo
*
createExprInfo
(
STableMetaInfo
*
pTableMetaInfo
,
int16_t
functionId
,
SColumnIndex
*
pColIndex
,
SSchema
*
pResSchema
,
int16_t
interSize
);
SExprInfo
*
createExprInfo
(
STableMetaInfo
*
pTableMetaInfo
,
int16_t
functionId
,
SColumnIndex
*
pColIndex
,
struct
tExprNode
*
pParamExpr
,
SSchema
*
pResSchema
,
int16_t
interSize
);
SExprInfo
*
createBinaryExprInfo
(
struct
tExprNode
*
pNode
,
SSchema
*
pResSchema
);
void
addExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
index
,
SExprInfo
*
pExprInfo
);
void
updateExprInfo
(
SExprInfo
*
pExprInfo
,
int16_t
functionId
,
int32_t
colId
,
int16_t
srcColumnIndex
,
int16_t
resType
,
int16_t
resSize
);
void
assignExprInfo
(
SExprInfo
*
dst
,
const
SExprInfo
*
src
);
...
...
source/libs/parser/src/astValidate.c
浏览文件 @
a531411e
...
...
@@ -13,9 +13,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <function.h>
#include "astGenerator.h"
#include "function.h"
#include "astGenerator.h"
#include "parserInt.h"
#include "parserUtil.h"
#include "queryInfoUtil.h"
...
...
@@ -34,16 +33,15 @@
static
int32_t
validateSelectNodeList
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pSelNodeList
,
bool
outerQuery
,
SMsgBuf
*
pMsgBuf
);
void
get
ColumnName
(
tSqlExprItem
*
pItem
,
char
*
resColumnName
,
char
*
rawName
,
int32_t
nameLength
)
{
void
setTokenAndRes
ColumnName
(
tSqlExprItem
*
pItem
,
char
*
resColumnName
,
char
*
rawName
,
int32_t
nameLength
)
{
memset
(
resColumnName
,
0
,
nameLength
);
int32_t
len
=
((
int32_t
)
pItem
->
pNode
->
exprToken
.
n
<
nameLength
)
?
(
int32_t
)
pItem
->
pNode
->
exprToken
.
n
:
nameLength
;
strncpy
(
rawName
,
pItem
->
pNode
->
exprToken
.
z
,
len
);
if
(
pItem
->
aliasName
!=
NULL
)
{
int32_t
aliasNameLen
=
(
int32_t
)
strlen
(
pItem
->
aliasName
);
len
=
(
aliasNameLen
<
nameLength
)
?
aliasNameLen
:
nameLength
;
strncpy
(
resColumnName
,
pItem
->
aliasName
,
len
);
assert
(
strlen
(
pItem
->
aliasName
)
<
nameLength
);
tstrncpy
(
resColumnName
,
pItem
->
aliasName
,
len
);
}
else
{
strncpy
(
resColumnName
,
rawName
,
len
);
}
...
...
@@ -227,12 +225,7 @@ static STableMeta* extractTempTableMetaFromSubquery(SQueryStmtInfo* pUpstream) {
}
void
initQueryInfo
(
SQueryStmtInfo
*
pQueryInfo
)
{
assert
(
pQueryInfo
->
fieldsInfo
.
internalField
==
NULL
);
//assert(0);
// pQueryInfo->fieldsInfo.internalField = taosArrayInit(4, sizeof(SInternalField));
assert
(
pQueryInfo
->
exprList
==
NULL
);
pQueryInfo
->
fieldsInfo
.
internalField
=
taosArrayInit
(
4
,
sizeof
(
SInternalField
));
pQueryInfo
->
exprList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
pQueryInfo
->
colList
=
taosArrayInit
(
4
,
POINTER_BYTES
);
pQueryInfo
->
udColumnId
=
TSDB_UD_COLUMN_INDEX
;
...
...
@@ -245,8 +238,6 @@ void initQueryInfo(SQueryStmtInfo* pQueryInfo) {
pQueryInfo
->
window
=
TSWINDOW_INITIALIZER
;
}
int32_t
validateSqlNode
(
SSqlNode
*
pSqlNode
,
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
);
static
int32_t
doValidateSubquery
(
SSqlNode
*
pSqlNode
,
int32_t
index
,
SQueryStmtInfo
*
pQueryInfo
,
SMsgBuf
*
pMsgBuf
)
{
SRelElementPair
*
subInfo
=
taosArrayGet
(
pSqlNode
->
from
->
list
,
index
);
...
...
@@ -653,7 +644,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
const
char
*
msg8
=
"condition missing for join query"
;
int32_t
code
=
TSDB_CODE_SUCCESS
;
STableMetaInfo
*
pTableMetaInfo
=
addEmptyMetaInfo
(
pQueryInfo
);
/*
* handle the sql expression without from subclause
...
...
@@ -751,15 +741,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
// }
}
// disable group result mixed up if interval/session window query exists.
// if (isTimeWindowQuery(pQueryInfo)) {
// size_t num = taosArrayGetSize(pQueryInfo->pUpstream);
// for(int32_t i = 0; i < num; ++i) {
// SQueryStmtInfo* pUp = taosArrayGetP(pQueryInfo->pUpstream, i);
// pUp->multigroupResult = false;
// }
// }
// parse the having clause in the first place
int32_t
joinQuery
=
(
pSqlNode
->
from
!=
NULL
&&
taosArrayGetSize
(
pSqlNode
->
from
->
list
)
>
1
);
if
(
validateHavingNode
(
pQueryInfo
,
pSqlNode
,
pMsgBuf
)
!=
...
...
@@ -776,13 +757,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// if ((code = doFunctionsCompatibleCheck(pCmd, pQueryInfo, pMsgBuf)) != TSDB_CODE_SUCCESS) {
// return code;
// }
// updateFunctionInterBuf(pQueryInfo, false);
// updateLastScanOrderIfNeeded(pQueryInfo);
if
((
code
=
validateFillNode
(
pQueryInfo
,
pSqlNode
,
pMsgBuf
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
...
...
@@ -794,6 +768,7 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
bool
isSTable
=
UTIL_TABLE_IS_SUPER_TABLE
(
pTableMetaInfo
);
int32_t
type
=
isSTable
?
TSDB_QUERY_TYPE_STABLE_QUERY
:
TSDB_QUERY_TYPE_TABLE_QUERY
;
...
...
@@ -846,16 +821,6 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// if (tscQueryTags(pQueryInfo)) {
// SExprInfo* pExpr1 = getExprInfo(pQueryInfo, 0);
//
// if (pExpr1->base.functionId != FUNCTION_TID_TAG) {
// if ((pQueryInfo->colCond && taosArrayGetSize(pQueryInfo->colCond) > 0) || IS_TSWINDOW_SPECIFIED(pQueryInfo->window)) {
// return buildInvalidOperationMsg(pMsgBuf, msg5);
// }
// }
// }
// parse the having clause in the first place
if
(
validateHavingNode
(
pQueryInfo
,
pSqlNode
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
...
...
@@ -880,29 +845,10 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
return
TSDB_CODE_SUCCESS
;
}
// if (!hasTimestampForPointInterpQuery(pQueryInfo)) {
// return buildInvalidOperationMsg(pMsgBuf, msg1);
// }
// // in case of join query, time range is required.
// if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) {
// uint64_t timeRange = (uint64_t)pQueryInfo->window.ekey - pQueryInfo->window.skey;
// if (timeRange == 0 && pQueryInfo->window.skey == 0) {
// return buildInvalidOperationMsg(pMsgBuf, msg3);
// }
// }
if
((
code
=
validateLimitNode
(
pQueryInfo
,
pSqlNode
,
pMsgBuf
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
// if ((code = doFunctionsCompatibleCheck(pCmd, pQueryInfo,pMsgBuf)) != TSDB_CODE_SUCCESS) {
// return code;
// }
// updateLastScanOrderIfNeeded(pQueryInfo);
// tscFieldInfoUpdateOffset(pQueryInfo);
// updateFunctionInterBuf(pQueryInfo, isSTable);
if
((
code
=
validateFillNode
(
pQueryInfo
,
pSqlNode
,
pMsgBuf
))
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
...
...
@@ -911,7 +857,7 @@ int32_t validateSqlNode(SSqlNode* pSqlNode, SQueryStmtInfo* pQueryInfo, SMsgBuf*
// set the query info
SExprInfo
**
p
=
NULL
;
int32_t
numOfExpr
=
0
;
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
code
=
createProjectionExpr
(
pQueryInfo
,
pTableMetaInfo
,
&
p
,
&
numOfExpr
);
if
(
pQueryInfo
->
exprList1
==
NULL
)
{
pQueryInfo
->
exprList1
=
taosArrayInit
(
4
,
POINTER_BYTES
);
...
...
@@ -948,18 +894,8 @@ static int32_t getNewResColId() {
return
resColId
++
;
}
int32_t
addResColumnInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputIndex
,
SColumnIndex
*
pColIndex
,
SSchema
*
pSchema
,
SExprInfo
*
pSqlExpr
)
{
int32_t
tableIndex
=
pColIndex
->
tableIndex
;
STableMeta
*
pTableMeta
=
pQueryInfo
->
pTableMetaInfo
[
tableIndex
]
->
pTableMeta
;
assert
(
pColIndex
->
columnIndex
<
getNumOfColumns
(
pTableMeta
));
uint64_t
uid
=
pTableMeta
->
uid
;
SSchema
*
pSchema1
=
getOneColumnSchema
(
pTableMeta
,
pColIndex
->
columnIndex
);
columnListInsert
(
pQueryInfo
->
colList
,
pColIndex
->
columnIndex
,
uid
,
pSchema1
);
int32_t
addResColumnInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputIndex
,
SSchema
*
pSchema
,
SExprInfo
*
pSqlExpr
)
{
SInternalField
*
pInfo
=
insertFieldInfo
(
&
pQueryInfo
->
fieldsInfo
,
outputIndex
,
pSchema
);
pInfo
->
pExpr
=
pSqlExpr
;
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -990,33 +926,29 @@ void setResultColName(char* name, tSqlExprItem* pItem, SToken* pToken, SToken* f
}
}
SExprInfo
*
addExprInSelect
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputColIndex
,
int16_t
functionId
,
SColumnIndex
*
pIndex
,
SSchema
*
pColSchema
)
{
SExprInfo
*
doAddOneExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputColIndex
,
int16_t
functionId
,
SColumnIndex
*
pIndex
,
SSchema
*
pColSchema
,
const
char
*
token
)
{
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pIndex
->
tableIndex
);
SSchema
resultSchema
=
{
0
};
setSchemaVal
(
&
resultSchema
,
pColSchema
->
type
,
pColSchema
->
bytes
,
getNewResColId
(),
pColSchema
->
name
);
SSchema
resultSchema
=
createSchema
(
pColSchema
->
type
,
pColSchema
->
bytes
,
getNewResColId
(),
pColSchema
->
name
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
pIndex
,
&
resultSchema
,
0
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
pIndex
,
NULL
,
&
resultSchema
,
0
);
addExprInfo
(
pQueryInfo
,
outputColIndex
,
pExpr
);
tstrncpy
(
pExpr
->
base
.
token
,
pColSchema
->
name
,
sizeof
(
pExpr
->
base
.
token
));
tstrncpy
(
pExpr
->
base
.
token
,
token
,
sizeof
(
pExpr
->
base
.
token
));
pExpr
->
base
.
colInfo
.
flag
=
pIndex
->
type
;
if
(
TSDB_COL_IS_TAG
(
pIndex
->
type
))
{
columnListInsert
(
pTableMetaInfo
->
tagColList
,
pIndex
->
columnIndex
,
pTableMetaInfo
->
pTableMeta
->
uid
,
pColSchema
);
}
else
{
addResColumnInfo
(
pQueryInfo
,
outputColIndex
,
pIndex
,
pColSchema
,
pExpr
);
}
columnListInsert
(
pTableMetaInfo
->
tagColList
,
pIndex
->
columnIndex
,
pTableMetaInfo
->
pTableMeta
->
uid
,
pColSchema
);
addResColumnInfo
(
pQueryInfo
,
outputColIndex
,
pColSchema
,
pExpr
);
return
pExpr
;
}
void
doAddResColumnOrSourceColumn
(
SQueryStmtInfo
*
pQueryInfo
,
SColumnIndex
*
index
,
int32_t
outputIndex
,
SExprInfo
*
pExpr
,
SSchema
*
pColSchema
,
bool
finalResult
)
{
columnListInsert
(
pQueryInfo
->
colList
,
index
->
columnIndex
,
pExpr
->
base
.
uid
,
pColSchema
);
if
(
finalResult
)
{
addResColumnInfo
(
pQueryInfo
,
outputIndex
,
index
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
}
else
{
columnListInsert
(
pQueryInfo
->
colList
,
index
->
columnIndex
,
pExpr
->
base
.
uid
,
pColSchema
);
addResColumnInfo
(
pQueryInfo
,
outputIndex
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
}
if
(
TSDB_COL_IS_NORMAL_COL
(
index
->
type
))
{
...
...
@@ -1024,7 +956,7 @@ void doAddResColumnOrSourceColumn(SQueryStmtInfo* pQueryInfo, SColumnIndex* inde
}
}
static
int32_t
set
ExprInfoForFunctions
(
SQueryStmtInfo
*
pQueryInfo
,
SSchema
*
pSchema
,
int32_t
functionId
,
static
int32_t
set
MultipleExprsInSelect
(
SQueryStmtInfo
*
pQueryInfo
,
SSchema
*
pSchema
,
int32_t
functionId
,
const
char
*
name
,
int32_t
resColIdx
,
SColumnIndex
*
pColIndex
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"not support column types"
;
...
...
@@ -1041,16 +973,63 @@ static int32_t setExprInfoForFunctions(SQueryStmtInfo* pQueryInfo, SSchema* pSch
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pColIndex
->
tableIndex
);
SSchema
resultSchema
=
{
0
};
setSchemaVal
(
&
resultSchema
,
resType
,
resBytes
,
getNewResColId
(),
name
);
SSchema
resultSchema
=
createSchema
(
resType
,
resBytes
,
getNewResColId
(),
name
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
pColIndex
,
&
resultSchema
,
interBufSize
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
pColIndex
,
NULL
,
&
resultSchema
,
interBufSize
);
addExprInfo
(
pQueryInfo
,
resColIdx
,
pExpr
);
tstrncpy
(
pExpr
->
base
.
token
,
resultSchema
.
name
,
tListLen
(
pExpr
->
base
.
token
));
doAddResColumnOrSourceColumn
(
pQueryInfo
,
pColIndex
,
resColIdx
,
pExpr
,
pSchema
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
checkForAliasName
(
SMsgBuf
*
pMsgBuf
,
char
*
aliasName
)
{
const
char
*
msg1
=
"column alias name too long"
;
if
(
aliasName
!=
NULL
&&
strlen
(
aliasName
)
>=
TSDB_COL_NAME_LEN
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
validateComplexExpr
(
tSqlExpr
*
pExpr
,
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pColList
,
int32_t
*
type
,
SMsgBuf
*
pMsgBuf
);
static
int32_t
sqlExprToExprNode
(
tExprNode
**
pExpr
,
const
tSqlExpr
*
pSqlExpr
,
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pCols
,
uint64_t
*
uid
,
SMsgBuf
*
pMsgBuf
);
static
int64_t
getTickPerSecond
(
SVariant
*
pVariant
,
int32_t
precision
,
int64_t
*
tickPerSec
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg10
=
"derivative duration should be greater than 1 Second"
;
if
(
taosVariantDump
(
pVariant
,
(
char
*
)
tickPerSec
,
TSDB_DATA_TYPE_BIGINT
,
true
)
<
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
precision
==
TSDB_TIME_PRECISION_MILLI
)
{
*
tickPerSec
/=
TSDB_TICK_PER_SECOND
(
TSDB_TIME_PRECISION_MICRO
);
}
else
if
(
precision
==
TSDB_TIME_PRECISION_MICRO
)
{
*
tickPerSec
/=
TSDB_TICK_PER_SECOND
(
TSDB_TIME_PRECISION_MILLI
);
}
if
(
*
tickPerSec
<=
0
||
*
tickPerSec
<
TSDB_TICK_PER_SECOND
(
precision
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg10
);
}
return
TSDB_CODE_SUCCESS
;
}
// set the first column ts for top/bottom query
static
void
setTsOutputExprInfo
(
SQueryStmtInfo
*
pQueryInfo
,
STableMetaInfo
*
pTableMetaInfo
,
int32_t
outputIndex
,
int32_t
tableIndex
)
{
SColumnIndex
indexTS
=
{.
tableIndex
=
tableIndex
,
.
columnIndex
=
PRIMARYKEY_TIMESTAMP_COL_INDEX
,
.
type
=
TSDB_COL_NORMAL
};
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_TIMESTAMP
,
TSDB_KEYSIZE
,
getNewResColId
(),
"ts"
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
FUNCTION_TS_DUMMY
,
&
indexTS
,
NULL
,
&
s
,
TSDB_KEYSIZE
);
addExprInfo
(
pQueryInfo
,
outputIndex
,
pExpr
);
SSchema
*
pSourceSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
indexTS
.
columnIndex
);
columnListInsert
(
pQueryInfo
->
colList
,
indexTS
.
columnIndex
,
pTableMetaInfo
->
pTableMeta
->
uid
,
pSourceSchema
);
addResColumnInfo
(
pQueryInfo
,
outputIndex
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
}
static
int32_t
multiColumnListInsert
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pColumnList
,
SMsgBuf
*
pMsgBuf
);
int32_t
addExprAndResColumn
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
colIndex
,
tSqlExprItem
*
pItem
,
bool
finalResult
,
SMsgBuf
*
pMsgBuf
)
{
STableMetaInfo
*
pTableMetaInfo
=
NULL
;
int32_t
functionId
=
pItem
->
functionId
;
...
...
@@ -1067,6 +1046,11 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
const
char
*
msg10
=
"derivative duration should be greater than 1 Second"
;
const
char
*
msg11
=
"third parameter in derivative should be 0 or 1"
;
const
char
*
msg12
=
"parameter is out of range [1, 100]"
;
const
char
*
msg13
=
"nested function is not supported"
;
if
(
checkForAliasName
(
pMsgBuf
,
pItem
->
aliasName
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
switch
(
functionId
)
{
case
FUNCTION_COUNT
:
{
...
...
@@ -1102,23 +1086,19 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
if
(
getColumnIndexByName
(
pToken
,
pQueryInfo
,
&
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
}
}
else
{
// count(*) is equalled to count(primary_timestamp_key)
index
=
(
SColumnIndex
){
0
,
PRIMARYKEY_TIMESTAMP_COL_INDEX
,
false
};
}
// todo validate.....
int32_t
size
=
tDataTypes
[
TSDB_DATA_TYPE_BIGINT
].
bytes
;
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_BIGINT
,
size
,
getNewResColId
(),
""
);
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_BIGINT
,
size
,
getNewResColId
(),
""
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
size
);
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
NULL
,
&
s
,
size
);
addExprInfo
(
pQueryInfo
,
colIndex
,
pExpr
);
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
getColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
setTokenAndResColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
int32_t
outputColumnIndex
=
getNumOfFields
(
&
pQueryInfo
->
fieldsInfo
);
SSchema
*
ps
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
index
.
columnIndex
);
...
...
@@ -1148,37 +1128,66 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
}
tSqlExprItem
*
pParamElem
=
taosArrayGet
(
pItem
->
pNode
->
Expr
.
paramList
,
0
);
if
(
pParamElem
->
pNode
->
tokenId
!=
TK_ALL
&&
pParamElem
->
pNode
->
tokenId
!=
TK_ID
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
tExprNode
*
pNode
=
NULL
;
int32_t
tokenId
=
pParamElem
->
pNode
->
tokenId
;
SColumnIndex
index
=
COLUMN_INDEX_INITIALIZER
;
if
((
getColumnIndexByName
(
&
pParamElem
->
pNode
->
columnName
,
pQueryInfo
,
&
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
SSchema
columnSchema
=
{
0
};
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
STableComInfo
info
=
getTableInfo
(
pTableMetaInfo
->
pTableMeta
);
if
(
tokenId
==
TK_ALL
||
tokenId
==
TK_ID
)
{
// simple parameter
if
((
getColumnIndexByName
(
&
pParamElem
->
pNode
->
columnName
,
pQueryInfo
,
&
index
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
// functions can not be applied to tags
if
(
index
.
columnIndex
==
TSDB_TBNAME_COLUMN_INDEX
||
(
index
.
columnIndex
>=
getNumOfColumns
(
pTableMetaInfo
->
pTableMeta
)
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg6
);
}
// functions can not be applied to tags
if
(
TSDB_COL_IS_TAG
(
index
.
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg6
);
}
// 2. check if sql function can be applied on this column data type
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
index
.
columnIndex
);
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
if
(
!
IS_NUMERIC_TYPE
(
pSchema
->
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
else
if
(
IS_UNSIGNED_NUMERIC_TYPE
(
pSchema
->
type
)
&&
(
functionId
==
FUNCTION_DIFF
||
functionId
==
FUNCTION_DERIVATIVE
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg9
);
// 2. check if sql function can be applied on this column data type
columnSchema
=
*
(
SSchema
*
)
getOneColumnSchema
(
pTableMetaInfo
->
pTableMeta
,
index
.
columnIndex
);
if
(
!
IS_NUMERIC_TYPE
(
columnSchema
.
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
else
if
(
IS_UNSIGNED_NUMERIC_TYPE
(
columnSchema
.
type
)
&&
(
functionId
==
FUNCTION_DIFF
||
functionId
==
FUNCTION_DERIVATIVE
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg9
);
}
}
else
if
(
tokenId
==
TK_PLUS
||
tokenId
==
TK_MINUS
||
tokenId
==
TK_TIMES
||
tokenId
==
TK_REM
||
tokenId
==
TK_CONCAT
)
{
int32_t
arithmeticType
=
NON_ARITHMEIC_EXPR
;
SArray
*
pColumnList
=
taosArrayInit
(
4
,
sizeof
(
SColumnIndex
));
if
(
validateComplexExpr
(
pParamElem
->
pNode
,
pQueryInfo
,
pColumnList
,
&
arithmeticType
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
if
(
arithmeticType
!=
NORMAL_ARITHMETIC
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg13
);
}
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
0
);
// get the first table meta.
columnSchema
=
createSchema
(
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
""
);
SArray
*
colList
=
taosArrayInit
(
10
,
sizeof
(
SColIndex
));
int32_t
ret
=
sqlExprToExprNode
(
&
pNode
,
pItem
->
pNode
,
pQueryInfo
,
colList
,
NULL
,
pMsgBuf
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
taosArrayDestroy
(
colList
);
tExprTreeDestroy
(
pNode
,
NULL
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
multiColumnListInsert
(
pQueryInfo
,
pColumnList
,
pMsgBuf
);
}
else
{
assert
(
0
);
}
int32_t
precision
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
precision
;
int16_t
resultType
=
0
;
int16_t
resultSize
=
0
;
int32_t
intermediateResSize
=
0
;
if
(
getResultDataInfo
(
pSchema
->
type
,
pSchema
->
bytes
,
functionId
,
0
,
&
resultType
,
&
resultSize
,
if
(
getResultDataInfo
(
columnSchema
.
type
,
columnSchema
.
bytes
,
functionId
,
0
,
&
resultType
,
&
resultSize
,
&
intermediateResSize
,
0
,
false
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
...
...
@@ -1186,23 +1195,13 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
// set the first column ts for diff query
int32_t
numOfOutput
=
getNumOfFields
(
&
pQueryInfo
->
fieldsInfo
);
if
(
functionId
==
FUNCTION_DIFF
||
functionId
==
FUNCTION_DERIVATIVE
)
{
SColumnIndex
indexTS
=
{.
tableIndex
=
index
.
tableIndex
,
.
columnIndex
=
0
,
.
type
=
TSDB_COL_NORMAL
};
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_TIMESTAMP
,
TSDB_KEYSIZE
,
getNewResColId
(),
"ts"
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
FUNCTION_TS_DUMMY
,
&
indexTS
,
&
s
,
TSDB_KEYSIZE
);
addExprInfo
(
pQueryInfo
,
numOfOutput
,
pExpr
);
//todo set the correct result field name
assert
(
numOfOutput
==
0
);
addResColumnInfo
(
pQueryInfo
,
numOfOutput
,
&
index
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
setTsOutputExprInfo
(
pQueryInfo
,
pTableMetaInfo
,
numOfOutput
,
index
.
tableIndex
);
numOfOutput
+=
1
;
}
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
resultType
,
resultSize
,
getNewResColId
(),
"ts"
);
SSchema
s
=
createSchema
(
resultType
,
resultSize
,
getNewResColId
(),
"ts"
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
intermediateResSize
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
pNode
,
&
s
,
intermediateResSize
);
addExprInfo
(
pQueryInfo
,
numOfOutput
,
pExpr
);
if
(
functionId
==
FUNCTION_LEASTSQR
)
{
// set the leastsquares parameters
...
...
@@ -1220,23 +1219,14 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_DOUBLE
,
DOUBLE_BYTES
);
}
else
if
(
functionId
==
FUNCTION_IRATE
)
{
addExprInfoParam
(
&
pExpr
->
base
,
(
char
*
)
&
info
.
precision
,
TSDB_DATA_TYPE_BIGINT
,
LONG_BYTES
);
addExprInfoParam
(
&
pExpr
->
base
,
(
char
*
)
&
precision
,
TSDB_DATA_TYPE_BIGINT
,
LONG_BYTES
);
}
else
if
(
functionId
==
FUNCTION_DERIVATIVE
)
{
char
val
[
8
]
=
{
0
};
int64_t
tickPerSec
=
0
;
if
(
taosVariantDump
(
&
pParamElem
[
1
].
pNode
->
value
,
(
char
*
)
&
tickPerSec
,
TSDB_DATA_TYPE_BIGINT
,
true
)
<
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
if
(
info
.
precision
==
TSDB_TIME_PRECISION_MILLI
)
{
tickPerSec
/=
TSDB_TICK_PER_SECOND
(
TSDB_TIME_PRECISION_MICRO
);
}
else
if
(
info
.
precision
==
TSDB_TIME_PRECISION_MICRO
)
{
tickPerSec
/=
TSDB_TICK_PER_SECOND
(
TSDB_TIME_PRECISION_MILLI
);
}
if
(
tickPerSec
<=
0
||
tickPerSec
<
TSDB_TICK_PER_SECOND
(
info
.
precision
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg10
);
int32_t
code
=
getTickPerSecond
(
&
pParamElem
[
1
].
pNode
->
value
,
precision
,
(
char
*
)
&
tickPerSec
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
addExprInfoParam
(
&
pExpr
->
base
,
(
char
*
)
&
tickPerSec
,
TSDB_DATA_TYPE_BIGINT
,
LONG_BYTES
);
...
...
@@ -1253,10 +1243,10 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_BIGINT
,
LONG_BYTES
);
}
get
ColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
setTokenAndRes
ColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
numOfOutput
=
getNumOfFields
(
&
pQueryInfo
->
fieldsInfo
);
doAddResColumnOrSourceColumn
(
pQueryInfo
,
&
index
,
numOfOutput
,
pExpr
,
p
Schema
,
finalResult
);
doAddResColumnOrSourceColumn
(
pQueryInfo
,
&
index
,
numOfOutput
,
pExpr
,
&
column
Schema
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1273,7 +1263,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
if
(
taosArrayGetSize
(
pParamList
)
>
1
&&
(
pItem
->
aliasName
!=
NULL
&&
strlen
(
pItem
->
aliasName
)
>
0
))
{
if
(
taosArrayGetSize
(
pParamList
)
>
1
&&
(
pItem
->
aliasName
!=
NULL
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg8
);
}
...
...
@@ -1302,8 +1292,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
SToken
t
=
{.
z
=
pSchema
[
j
].
name
,
.
n
=
(
uint32_t
)
strnlen
(
pSchema
[
j
].
name
,
TSDB_COL_NAME_LEN
)};
setResultColName
(
name
,
pItem
,
&
t
,
&
pItem
->
pNode
->
exprToken
,
true
);
if
(
setExprInfoForFunctions
(
pQueryInfo
,
&
pSchema
[
j
],
functionId
,
name
,
colIndex
++
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
if
(
setMultipleExprsInSelect
(
pQueryInfo
,
&
pSchema
[
j
],
functionId
,
name
,
colIndex
++
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
...
...
@@ -1326,13 +1315,13 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
bool
multiColOutput
=
taosArrayGetSize
(
pItem
->
pNode
->
Expr
.
paramList
)
>
1
;
setResultColName
(
name
,
pItem
,
&
pParamElem
->
pNode
->
columnName
,
&
pItem
->
pNode
->
exprToken
,
multiColOutput
);
if
(
set
ExprInfoForFunctions
(
pQueryInfo
,
pSchema
,
functionId
,
name
,
colIndex
++
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
if
(
set
MultipleExprsInSelect
(
pQueryInfo
,
pSchema
,
functionId
,
name
,
colIndex
++
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
}
}
else
{
// select
*
from xxx
}
else
{
// select
function(*)
from xxx
int32_t
numOfFields
=
0
;
// multicolumn selection does not support alias name
...
...
@@ -1345,14 +1334,13 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
SSchema
*
pSchema
=
getTableColumnSchema
(
pTableMetaInfo
->
pTableMeta
);
for
(
int32_t
i
=
0
;
i
<
getNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
++
i
)
{
SColumnIndex
index
=
{.
tableIndex
=
j
,
.
columnIndex
=
i
};
SColumnIndex
index
=
{.
tableIndex
=
j
,
.
columnIndex
=
i
,
.
type
=
TSDB_COL_NORMAL
};
char
name
[
TSDB_COL_NAME_LEN
]
=
{
0
};
SToken
t
=
{.
z
=
pSchema
[
i
].
name
,
.
n
=
(
uint32_t
)
strnlen
(
pSchema
[
i
].
name
,
TSDB_COL_NAME_LEN
)};
setResultColName
(
name
,
pItem
,
&
t
,
&
pItem
->
pNode
->
exprToken
,
true
);
setResultColName
(
name
,
pItem
,
&
t
,
&
pItem
->
pNode
->
Expr
.
operand
,
true
);
if
(
setExprInfoForFunctions
(
pQueryInfo
,
&
pSchema
[
index
.
columnIndex
],
functionId
,
name
,
colIndex
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
if
(
setMultipleExprsInSelect
(
pQueryInfo
,
&
pSchema
[
index
.
columnIndex
],
functionId
,
name
,
colIndex
,
&
index
,
finalResult
,
pMsgBuf
)
!=
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
colIndex
++
;
...
...
@@ -1428,10 +1416,9 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
*/
colIndex
+=
1
;
// the first column is ts
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
resultType
,
resultSize
,
getNewResColId
(),
""
);
SSchema
s
=
createSchema
(
resultType
,
resultSize
,
getNewResColId
(),
""
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
interResult
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
NULL
,
&
s
,
interResult
);
addExprInfo
(
pQueryInfo
,
colIndex
,
pExpr
);
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
));
}
else
{
...
...
@@ -1443,26 +1430,17 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
}
// set the first column ts for top/bottom query
SColumnIndex
index1
=
{
index
.
tableIndex
,
PRIMARYKEY_TIMESTAMP_COL_INDEX
,
.
type
=
TSDB_COL_NORMAL
};
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_TIMESTAMP
,
TSDB_KEYSIZE
,
getNewResColId
(),
"ts"
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
FUNCTION_TS
,
&
index1
,
&
s
,
0
);
addExprInfo
(
pQueryInfo
,
colIndex
,
pExpr
);
addResColumnInfo
(
pQueryInfo
,
colIndex
,
&
index1
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
setTsOutputExprInfo
(
pQueryInfo
,
pTableMetaInfo
,
colIndex
,
index
.
tableIndex
);
colIndex
+=
1
;
// the first column is ts
setSchemaVal
(
&
s
,
resultType
,
resultSize
,
getNewResColId
(),
""
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
resultSize
);
SSchema
s
=
createSchema
(
resultType
,
resultSize
,
getNewResColId
(),
""
);
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
NULL
,
&
s
,
resultSize
);
addExprInfo
(
pQueryInfo
,
colIndex
,
pExpr
);
addExprInfoParam
(
&
pExpr
->
base
,
val
,
TSDB_DATA_TYPE_BIGINT
,
sizeof
(
int64_t
));
}
get
ColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
setTokenAndRes
ColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
doAddResColumnOrSourceColumn
(
pQueryInfo
,
&
index
,
colIndex
,
pExpr
,
pSchema
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1533,8 +1511,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
s
.
colId
=
getNewResColId
();
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
TSDB_QUERY_TYPE_TAG_FILTER_QUERY
);
addExprInSelect
(
pQueryInfo
,
0
,
FUNCTION_TID_TAG
,
&
index
,
&
s
);
doAddOneExprInfo
(
pQueryInfo
,
0
,
FUNCTION_TID_TAG
,
&
index
,
&
s
,
s
.
name
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1544,7 +1521,7 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
SColumnIndex
index
=
{.
tableIndex
=
0
,
.
columnIndex
=
0
,
.
type
=
TSDB_COL_
TAG
};
SColumnIndex
index
=
{.
tableIndex
=
0
,
.
columnIndex
=
0
,
.
type
=
TSDB_COL_
NORMAL
};
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
int32_t
inter
=
0
;
...
...
@@ -1553,13 +1530,15 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
getResultDataInfo
(
TSDB_DATA_TYPE_INT
,
4
,
functionId
,
0
,
&
resType
,
&
bytes
,
&
inter
,
0
,
0
);
SSchema
s
=
{
0
}
;
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_BINARY
,
bytes
,
getNewResColId
(),
"block_dist"
);
SExprInfo
*
pExpr
=
addExprInSelect
(
pQueryInfo
,
0
,
FUNCTION_BLKINFO
,
&
index
,
&
s
);
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_BINARY
,
bytes
,
getNewResColId
(),
"block_dist"
)
;
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
NULL
,
&
s
,
0
);
addExprInfo
(
pQueryInfo
,
0
,
pExpr
);
pExpr
->
base
.
numOfParams
=
1
;
pExpr
->
base
.
param
[
0
].
i64
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
rowSize
;
pExpr
->
base
.
param
[
0
].
nType
=
TSDB_DATA_TYPE_BIGINT
;
setTokenAndResColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
TSDB_COL_NAME_LEN
);
int64_t
rowSize
=
pTableMetaInfo
->
pTableMeta
->
tableInfo
.
rowSize
;
addExprInfoParam
(
&
pExpr
->
base
,
(
char
*
)
&
rowSize
,
TSDB_DATA_TYPE_BIGINT
,
8
);
doAddResColumnOrSourceColumn
(
pQueryInfo
,
&
index
,
0
,
pExpr
,
&
s
,
true
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1596,14 +1575,13 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
int16_t
bytes
=
0
;
getResultDataInfo
(
TSDB_DATA_TYPE_INT
,
4
,
functionId
,
0
,
&
resType
,
&
bytes
,
&
inter
,
0
,
false
/*, pUdfInfo*/
);
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
resType
,
bytes
,
getNewResColId
(),
""
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
inter
);
SSchema
s
=
createSchema
(
resType
,
bytes
,
getNewResColId
(),
""
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
NULL
,
&
s
,
inter
);
addExprInfo
(
pQueryInfo
,
colIndex
,
pExpr
);
get
ColumnName
(
pItem
,
s
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
setTokenAndRes
ColumnName
(
pItem
,
s
.
name
,
pExpr
->
base
.
token
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
)
-
1
);
s
etSchemaVal
(
&
s
,
resType
,
bytes
,
pExpr
->
base
.
colInfo
.
colId
,
""
);
s
=
createSchema
(
resType
,
bytes
,
pExpr
->
base
.
colInfo
.
colId
,
""
);
doAddResColumnOrSourceColumn
(
pQueryInfo
,
&
index
,
colIndex
,
pExpr
,
&
s
,
finalResult
);
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1613,34 +1591,25 @@ int32_t addExprAndResColumn(SQueryStmtInfo* pQueryInfo, int32_t colIndex, tSqlEx
}
SExprInfo
*
doAddProjectCol
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
outputColIndex
,
SColumnIndex
*
pColIndex
,
const
char
*
aliasName
,
int32_t
colId
)
{
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
pColIndex
->
tableIndex
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
pColIndex
->
tableIndex
)
->
pTableMeta
;
int32_t
numOfCols
=
getNumOfColumns
(
pTableMeta
);
SSchema
*
pSchema
=
getOneColumnSchema
(
pTableMeta
,
pColIndex
->
columnIndex
);
SColumnIndex
index
=
*
pColIndex
;
int16_t
functionId
=
TSDB_COL_IS_TAG
(
index
.
type
)
?
FUNCTION_TAGPRJ
:
FUNCTION_PRJ
;
if
(
functionId
==
FUNCTION_TAGPRJ
)
{
int16_t
functionId
=
0
;
if
(
TSDB_COL_IS_TAG
(
index
.
type
))
{
int32_t
numOfCols
=
getNumOfColumns
(
pTableMeta
);
index
.
columnIndex
=
pColIndex
->
columnIndex
-
numOfCols
;
columnListInsert
(
pTableMetaInfo
->
tagColList
,
index
.
columnIndex
,
pTableMeta
->
uid
,
pSchema
)
;
functionId
=
FUNCTION_TAGPRJ
;
}
else
{
index
.
columnIndex
=
pColIndex
->
columnIndex
;
functionId
=
FUNCTION_PRJ
;
}
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
pSchema
->
type
,
pSchema
->
bytes
,
colId
,
pSchema
->
name
);
SExprInfo
*
pExpr
=
createExprInfo
(
pTableMetaInfo
,
functionId
,
&
index
,
&
s
,
0
);
if
(
aliasName
==
NULL
)
{
tstrncpy
(
pExpr
->
base
.
resSchema
.
name
,
pSchema
->
name
,
sizeof
(
pExpr
->
base
.
resSchema
.
name
));
}
else
{
tstrncpy
(
pExpr
->
base
.
resSchema
.
name
,
aliasName
,
TSDB_COL_NAME_LEN
);
}
const
char
*
name
=
(
aliasName
==
NULL
)
?
pSchema
->
name
:
aliasName
;
SSchema
s
=
createSchema
(
pSchema
->
type
,
pSchema
->
bytes
,
colId
,
name
);
addExprInfo
(
pQueryInfo
,
outputColIndex
,
pExpr
);
addResColumnInfo
(
pQueryInfo
,
outputColIndex
,
pColIndex
,
pSchema
,
pExpr
);
return
doAddOneExprInfo
(
pQueryInfo
,
outputColIndex
,
functionId
,
&
index
,
&
s
,
pSchema
->
name
);
}
static
int32_t
doAddProjectionExprAndResColumn
(
SQueryStmtInfo
*
pQueryInfo
,
SColumnIndex
*
pIndex
,
int32_t
startPos
)
{
...
...
@@ -1699,9 +1668,12 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
const
char
*
msg2
=
"invalid column name"
;
const
char
*
msg3
=
"tbname not allowed in outer query"
;
if
(
checkForAliasName
(
pMsgBuf
,
pItem
->
aliasName
)
!=
TSDB_CODE_SUCCESS
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
int32_t
startPos
=
(
int32_t
)
tscNumOfExprs
(
pQueryInfo
);
int32_t
tokenId
=
pItem
->
pNode
->
tokenId
;
if
(
tokenId
==
TK_ALL
)
{
// project on all fields
TSDB_QUERY_SET_TYPE
(
pQueryInfo
->
type
,
TSDB_QUERY_TYPE_PROJECTION_QUERY
);
...
...
@@ -1729,7 +1701,10 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
}
else
if
(
tokenId
==
TK_STRING
||
tokenId
==
TK_INTEGER
||
tokenId
==
TK_FLOAT
)
{
// simple column projection query
SColumnIndex
index
=
createConstantColumnIndex
(
&
pQueryInfo
->
udColumnId
);
SSchema
colSchema
=
createConstantColumnSchema
(
&
pItem
->
pNode
->
value
,
&
pItem
->
pNode
->
exprToken
,
pItem
->
aliasName
);
SExprInfo
*
pExpr
=
addExprInSelect
(
pQueryInfo
,
startPos
,
FUNCTION_PRJ
,
&
index
,
&
colSchema
);
char
rawName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
tstrncpy
(
rawName
,
pItem
->
pNode
->
exprToken
.
z
,
MIN
(
TSDB_COL_NAME_LEN
,
TSDB_COL_NAME_LEN
));
SExprInfo
*
pExpr
=
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
FUNCTION_PRJ
,
&
index
,
&
colSchema
,
rawName
);
// NOTE: the first parameter is reserved for the tag column id during join query process.
pExpr
->
base
.
numOfParams
=
2
;
...
...
@@ -1741,13 +1716,16 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
}
if
(
index
.
columnIndex
==
TSDB_TBNAME_COLUMN_INDEX
)
{
if
(
outerQuery
)
{
// todo??
SSchema
colSchema
=
{
0
};
int32_t
functionId
=
0
;
if
(
outerQuery
)
{
// todo??
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
bool
existed
=
false
;
bool
existed
=
false
;
SSchema
*
pSchema
=
pTableMetaInfo
->
pTableMeta
->
schema
;
int32_t
numOfCols
=
getNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
int32_t
numOfCols
=
getNumOfColumns
(
pTableMetaInfo
->
pTableMeta
);
for
(
int32_t
i
=
0
;
i
<
numOfCols
;
++
i
)
{
if
(
strncasecmp
(
pSchema
[
i
].
name
,
TSQL_TBNAME_L
,
tListLen
(
pSchema
[
i
].
name
))
==
0
)
{
existed
=
true
;
...
...
@@ -1760,24 +1738,17 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
SSchema
colSchema
=
pSchema
[
index
.
columnIndex
];
colSchema
.
colId
=
getNewResColId
();
char
name
[
TSDB_COL_NAME_LEN
]
=
{
0
};
getColumnName
(
pItem
,
name
,
colSchema
.
name
,
sizeof
(
colSchema
.
name
)
-
1
);
tstrncpy
(
colSchema
.
name
,
name
,
TSDB_COL_NAME_LEN
);
addExprInSelect
(
pQueryInfo
,
startPos
,
FUNCTION_PRJ
,
&
index
,
&
colSchema
);
colSchema
=
pSchema
[
index
.
columnIndex
];
functionId
=
FUNCTION_PRJ
;
}
else
{
SSchema
colSchema
=
*
getTbnameColumnSchema
();
char
name
[
TSDB_COL_NAME_LEN
]
=
{
0
};
getColumnName
(
pItem
,
name
,
colSchema
.
name
,
sizeof
(
colSchema
.
name
)
-
1
);
tstrncpy
(
colSchema
.
name
,
name
,
TSDB_COL_NAME_LEN
);
colSchema
.
colId
=
getNewResColId
();
addExprInSelect
(
pQueryInfo
,
startPos
,
FUNCTION_TAGPRJ
,
&
index
,
&
colSchema
);
colSchema
=
*
getTbnameColumnSchema
();
functionId
=
FUNCTION_TAGPRJ
;
}
colSchema
.
colId
=
getNewResColId
();
char
rawName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
setTokenAndResColumnName
(
pItem
,
colSchema
.
name
,
rawName
,
sizeof
(
colSchema
.
name
)
-
1
);
doAddOneExprInfo
(
pQueryInfo
,
startPos
,
functionId
,
&
index
,
&
colSchema
,
rawName
);
}
else
{
STableMetaInfo
*
pTableMetaInfo
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
);
if
(
TSDB_COL_IS_TAG
(
index
.
type
)
&&
UTIL_TABLE_IS_NORMAL_TABLE
(
pTableMetaInfo
))
{
...
...
@@ -1785,7 +1756,6 @@ int32_t addProjectionExprAndResColumn(SQueryStmtInfo* pQueryInfo, tSqlExprItem*
}
doAddProjectCol
(
pQueryInfo
,
startPos
,
&
index
,
pItem
->
aliasName
,
getNewResColId
());
pQueryInfo
->
type
|=
TSDB_QUERY_TYPE_PROJECTION_QUERY
;
}
// add the primary timestamp column even though it is not required by user
...
...
@@ -1880,7 +1850,7 @@ static int32_t validateExprLeafNode(tSqlExpr* pExpr, SQueryStmtInfo* pQueryInfo,
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
validateArithmeticSql
Expr
(
tSqlExpr
*
pExpr
,
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pColList
,
int32_t
*
type
,
SMsgBuf
*
pMsgBuf
)
{
int32_t
validateComplex
Expr
(
tSqlExpr
*
pExpr
,
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pColList
,
int32_t
*
type
,
SMsgBuf
*
pMsgBuf
)
{
if
(
pExpr
==
NULL
)
{
return
TSDB_CODE_SUCCESS
;
}
...
...
@@ -1890,7 +1860,7 @@ static int32_t validateArithmeticSqlExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQuery
uint64_t
uidRight
=
0
;
if
(
pLeft
->
type
==
SQL_NODE_EXPR
)
{
int32_t
ret
=
validate
ArithmeticSql
Expr
(
pLeft
,
pQueryInfo
,
pColList
,
type
,
pMsgBuf
);
int32_t
ret
=
validate
Complex
Expr
(
pLeft
,
pQueryInfo
,
pColList
,
type
,
pMsgBuf
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
...
...
@@ -1903,7 +1873,7 @@ static int32_t validateArithmeticSqlExpr(tSqlExpr* pExpr, SQueryStmtInfo* pQuery
tSqlExpr
*
pRight
=
pExpr
->
pRight
;
if
(
pRight
->
type
==
SQL_NODE_EXPR
)
{
int32_t
ret
=
validate
ArithmeticSql
Expr
(
pRight
,
pQueryInfo
,
pColList
,
type
,
pMsgBuf
);
int32_t
ret
=
validate
Complex
Expr
(
pRight
,
pQueryInfo
,
pColList
,
type
,
pMsgBuf
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
return
ret
;
}
...
...
@@ -1995,7 +1965,6 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
pQueryInfo
->
curTableIdx
=
index
.
tableIndex
;
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
index
.
tableIndex
)
->
pTableMeta
;
int32_t
numOfColumns
=
getNumOfColumns
(
pTableMeta
);
*
pExpr
=
calloc
(
1
,
sizeof
(
tExprNode
));
(
*
pExpr
)
->
nodeType
=
TEXPR_COL_NODE
;
...
...
@@ -2009,7 +1978,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
tstrncpy
(
colIndex
.
name
,
pSchema
->
name
,
sizeof
(
colIndex
.
name
));
colIndex
.
colId
=
pSchema
->
colId
;
colIndex
.
colIndex
=
index
.
columnIndex
;
colIndex
.
flag
=
(
index
.
columnIndex
>=
numOfColumns
)
?
1
:
0
;
colIndex
.
flag
=
index
.
type
;
taosArrayPush
(
pCols
,
&
colIndex
);
}
...
...
@@ -2058,9 +2027,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
(
*
pExpr
)
->
_node
.
pRight
=
pRight
;
SToken
t
=
{.
type
=
pSqlExpr
->
tokenId
};
#if 0
(
*
pExpr
)
->
_node
.
optr
=
convertRelationalOperator
(
&
t
);
#endif
assert
((
*
pExpr
)
->
_node
.
optr
!=
0
);
...
...
@@ -2068,9 +2035,9 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
if
((
*
pExpr
)
->
_node
.
optr
==
TSDB_BINARY_OP_DIVIDE
)
{
if
(
pRight
->
nodeType
==
TEXPR_VALUE_NODE
)
{
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_INT
&&
pRight
->
pVal
->
i64
==
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid expr (divide by 0)"
)
;
}
else
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_FLOAT
&&
pRight
->
pVal
->
d
==
0
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid expr (divide by 0)"
)
;
}
}
}
...
...
@@ -2079,7 +2046,7 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
if
((
*
pExpr
)
->
_node
.
optr
!=
TSDB_RELATION_EQUAL
&&
(
*
pExpr
)
->
_node
.
optr
!=
TSDB_RELATION_NOT_EQUAL
)
{
if
(
pRight
!=
NULL
&&
pRight
->
nodeType
==
TEXPR_VALUE_NODE
)
{
if
(
pRight
->
pVal
->
nType
==
TSDB_DATA_TYPE_BOOL
&&
pLeft
->
pSchema
->
type
==
TSDB_DATA_TYPE_BOOL
)
{
return
TSDB_CODE_TSC_INVALID_OPERATION
;
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid operator for bool"
)
;
}
}
}
...
...
@@ -2088,33 +2055,41 @@ int32_t sqlExprToExprNode(tExprNode **pExpr, const tSqlExpr* pSqlExpr, SQuerySt
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
handleArithmeticExpr
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
exprIndex
,
tSqlExprItem
*
pItem
,
SMsgBuf
*
pMsgBuf
)
{
static
int32_t
multiColumnListInsert
(
SQueryStmtInfo
*
pQueryInfo
,
SArray
*
pColumnList
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg3
=
"tag columns can not be used in arithmetic expression"
;
SColumnIndex
*
p1
=
taosArrayGet
(
pColumnList
,
0
);
STableMeta
*
pTableMeta
=
getMetaInfo
(
pQueryInfo
,
p1
->
tableIndex
)
->
pTableMeta
;
size_t
numOfNode
=
taosArrayGetSize
(
pColumnList
);
for
(
int32_t
k
=
0
;
k
<
numOfNode
;
++
k
)
{
SColumnIndex
*
pIndex
=
taosArrayGet
(
pColumnList
,
k
);
if
(
TSDB_COL_IS_TAG
(
pIndex
->
type
))
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
SSchema
*
ps
=
getOneColumnSchema
(
pTableMeta
,
pIndex
->
columnIndex
);
columnListInsert
(
pQueryInfo
->
colList
,
pIndex
->
columnIndex
,
pTableMeta
->
uid
,
ps
);
}
insertPrimaryTsColumn
(
pQueryInfo
->
colList
,
pTableMeta
->
uid
);
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
createComplexExpr
(
SQueryStmtInfo
*
pQueryInfo
,
int32_t
exprIndex
,
tSqlExprItem
*
pItem
,
SMsgBuf
*
pMsgBuf
)
{
const
char
*
msg1
=
"invalid column name, illegal column type, or columns in arithmetic expression from two tables"
;
const
char
*
msg2
=
"invalid arithmetic expression in select clause"
;
const
char
*
msg3
=
"tag columns can not be used in arithmetic expression"
;
const
char
*
msg4
=
"columns from different table mixed up in arithmetic expression"
;
int32_t
arithmeticType
=
NON_ARITHMEIC_EXPR
;
SArray
*
pColumnList
=
taosArrayInit
(
4
,
sizeof
(
SColumnIndex
));
if
(
validate
ArithmeticSql
Expr
(
pItem
->
pNode
,
pQueryInfo
,
pColumnList
,
&
arithmeticType
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
if
(
validate
Complex
Expr
(
pItem
->
pNode
,
pQueryInfo
,
pColumnList
,
&
arithmeticType
,
pMsgBuf
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
int32_t
tableIndex
=
((
SColumnIndex
*
)(
taosArrayGet
(
pColumnList
,
0
)))
->
tableIndex
;
if
(
arithmeticType
==
NORMAL_ARITHMETIC
)
{
pQueryInfo
->
type
|=
TSDB_QUERY_TYPE_PROJECTION_QUERY
;
// expr string is set as the parameter of function
SColumnIndex
index
=
{.
tableIndex
=
tableIndex
,
.
type
=
TSDB_COL_NORMAL
};
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
""
);
char
*
name
=
(
pItem
->
aliasName
!=
NULL
)
?
pItem
->
aliasName
:
pItem
->
pNode
->
exprToken
.
z
;
size_t
len
=
MIN
(
sizeof
(
s
.
name
),
pItem
->
pNode
->
exprToken
.
n
+
1
);
tstrncpy
(
s
.
name
,
name
,
len
);
SExprInfo
*
pExpr
=
createExprInfo
(
NULL
,
FUNCTION_ARITHM
,
&
index
,
&
s
,
sizeof
(
double
));
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
""
);
tExprNode
*
pNode
=
NULL
;
SArray
*
colList
=
taosArrayInit
(
10
,
sizeof
(
SColIndex
));
...
...
@@ -2125,16 +2100,16 @@ static int32_t handleArithmeticExpr(SQueryStmtInfo* pQueryInfo, int32_t exprInde
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg2
);
}
// check for if there is a tag in the arithmetic express
size_t
numOfNode
=
taosArrayGetSize
(
colList
);
for
(
int32_t
k
=
0
;
k
<
numOfNode
;
++
k
)
{
SColIndex
*
pIndex
=
taosArrayGet
(
colList
,
k
);
if
(
TSDB_COL_IS_TAG
(
pIndex
->
flag
))
{
tExprTreeDestroy
(
pNode
,
NULL
);
taosArrayDestroy
(
colList
);
SExprInfo
*
pExpr
=
createBinaryExprInfo
(
pNode
,
&
s
);
addExprInfo
(
pQueryInfo
,
exprIndex
,
pExpr
);
setTokenAndResColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
TSDB_COL_NAME_LEN
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg3
);
}
// check for if there is a tag in the arithmetic express
int32_t
code
=
multiColumnListInsert
(
pQueryInfo
,
pColumnList
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
taosArrayDestroy
(
colList
);
tExprTreeDestroy
(
pNode
,
NULL
);
return
code
;
}
SBufferWriter
bw
=
tbufInitWriter
(
NULL
,
false
);
...
...
@@ -2147,16 +2122,13 @@ static int32_t handleArithmeticExpr(SQueryStmtInfo* pQueryInfo, int32_t exprInde
// TODO: other error handling
// } END_TRY
len
=
tbufTell
(
&
bw
);
int32_t
len
=
tbufTell
(
&
bw
);
char
*
c
=
tbufGetData
(
&
bw
,
false
);
// set the serialized binary string as the parameter of arithmetic expression
SColumnIndex
*
index1
=
taosArrayGet
(
pColumnList
,
0
);
addExprInfoParam
(
&
pExpr
->
base
,
c
,
TSDB_DATA_TYPE_BINARY
,
(
int32_t
)
len
);
addResColumnInfo
(
pQueryInfo
,
exprIndex
,
index1
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
// add ts column
insertPrimaryTsColumn
(
pQueryInfo
->
colList
,
pExpr
->
base
.
uid
);
addResColumnInfo
(
pQueryInfo
,
exprIndex
,
&
pExpr
->
base
.
resSchema
,
pExpr
);
tbufCloseWriter
(
&
bw
);
taosArrayDestroy
(
colList
);
...
...
@@ -2164,47 +2136,38 @@ static int32_t handleArithmeticExpr(SQueryStmtInfo* pQueryInfo, int32_t exprInde
}
else
{
SColumnIndex
columnIndex
=
{
0
};
char
rawName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
char
aliasName
[
TSDB_COL_NAME_LEN
]
=
{
0
};
getColumnName
(
pItem
,
aliasName
,
rawName
,
TSDB_COL_NAME_LEN
);
SSchema
s
=
{
0
};
setSchemaVal
(
&
s
,
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
aliasName
);
addResColumnInfo
(
pQueryInfo
,
exprIndex
,
&
columnIndex
,
&
s
,
NULL
);
SSchema
s
=
createSchema
(
TSDB_DATA_TYPE_DOUBLE
,
sizeof
(
double
),
getNewResColId
(),
""
);
addResColumnInfo
(
pQueryInfo
,
exprIndex
,
&
s
,
NULL
);
int32_t
slot
=
getNumOfFields
(
&
pQueryInfo
->
fieldsInfo
)
-
1
;
SInternalField
*
pInfo
=
getInternalField
(
&
pQueryInfo
->
fieldsInfo
,
slot
);
assert
(
pInfo
->
pExpr
==
NULL
);
SExprInfo
*
pExpr
=
createExprInfo
(
NULL
,
FUNCTION_ARITHM
,
&
columnIndex
,
&
s
,
0
);
strncpy
(
pExpr
->
base
.
token
,
rawName
,
tListLen
(
pExpr
->
base
.
token
));
pExpr
->
base
.
numOfParams
=
1
;
int32_t
ret
=
sqlExprToExprNode
(
&
pExpr
->
pExpr
,
pItem
->
pNode
,
pQueryInfo
,
NULL
,
&
(
pExpr
->
base
.
uid
),
pMsgBuf
);
tExprNode
*
pNode
=
NULL
;
int32_t
ret
=
sqlExprToExprNode
(
&
pNode
,
pItem
->
pNode
,
pQueryInfo
,
NULL
,
NULL
,
pMsgBuf
);
if
(
ret
!=
TSDB_CODE_SUCCESS
)
{
tExprTreeDestroy
(
p
Expr
->
pExpr
,
NULL
);
tExprTreeDestroy
(
p
Node
,
NULL
);
return
buildInvalidOperationMsg
(
pMsgBuf
,
"invalid expression in select clause"
);
}
pInfo
->
pExpr
=
pExpr
;
SExprInfo
*
pExpr
=
createBinaryExprInfo
(
pNode
,
&
s
);
addExprInfo
(
pQueryInfo
,
exprIndex
,
pExpr
);
setTokenAndResColumnName
(
pItem
,
pExpr
->
base
.
resSchema
.
name
,
pExpr
->
base
.
token
,
TSDB_COL_NAME_LEN
);
SBufferWriter
bw
=
tbufInitWriter
(
NULL
,
false
)
;
pExpr
->
base
.
numOfParams
=
1
;
SBufferWriter
bw
=
tbufInitWriter
(
NULL
,
false
);
// TRY(0) {
exprTreeToBinary
(
&
bw
,
p
Info
->
p
Expr
->
pExpr
);
exprTreeToBinary
(
&
bw
,
pExpr
->
pExpr
);
// } CATCH(code) {
// tbufCloseWriter(&bw);
// UNUSED(code);
// TODO: other error handling
// } END_TRY
SSqlExpr
*
pSqlExpr
=
&
p
Info
->
p
Expr
->
base
;
SSqlExpr
*
pSqlExpr
=
&
pExpr
->
base
;
pSqlExpr
->
param
[
0
].
nLen
=
(
int16_t
)
tbufTell
(
&
bw
);
pSqlExpr
->
param
[
0
].
pz
=
tbufGetData
(
&
bw
,
true
);
pSqlExpr
->
param
[
0
].
nType
=
TSDB_DATA_TYPE_BINARY
;
tbufCloseWriter
(
&
bw
);
// tbufCloseWriter(&bw); // TODO there is a memory leak
}
...
...
@@ -2268,7 +2231,7 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
}
else
if
(
type
==
SQL_NODE_EXPR
)
{
int32_t
code
=
handleArithmetic
Expr
(
pQueryInfo
,
i
,
pItem
,
pMsgBuf
);
int32_t
code
=
createComplex
Expr
(
pQueryInfo
,
i
,
pItem
,
pMsgBuf
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
...
...
@@ -2285,10 +2248,6 @@ int32_t validateSelectNodeList(SQueryStmtInfo* pQueryInfo, SArray* pSelNodeList,
// size_t numOfSrcCols = taosArrayGetSize(pQueryInfo->colList);
// if ((numOfSrcCols <= 0 || !hasNoneUserDefineExpr(pQueryInfo)) && !tscQueryTags(pQueryInfo) && !tscQueryBlockInfo(pQueryInfo)) {
// addPrimaryTsColIntoResult(pQueryInfo, pCmd);
// }
// if (!functionCompatibleCheck(pQueryInfo, joinQuery, timeWindowQuery)) {
// return buildInvalidOperationMsg(pMsgBuf, msg2);
// }
return
TSDB_CODE_SUCCESS
;
...
...
@@ -2306,6 +2265,16 @@ int32_t evaluateSqlNode(SSqlNode* pNode, int32_t tsPrecision, SMsgBuf* pMsgBuf)
return
code
;
}
size_t
size
=
taosArrayGetSize
(
pNode
->
pSelNodeList
);
for
(
int32_t
i
=
0
;
i
<
size
;
++
i
)
{
tSqlExprItem
*
pItem
=
taosArrayGet
(
pNode
->
pSelNodeList
,
i
);
code
=
evaluateImpl
(
pItem
->
pNode
,
tsPrecision
);
if
(
code
!=
TSDB_CODE_SUCCESS
)
{
return
code
;
}
}
code
=
evaluateImpl
(
pNode
->
pSelNodeList
,
tsPrecision
);
return
code
;
}
...
...
@@ -2782,6 +2751,11 @@ int32_t qParserValidateSqlNode(struct SCatalog* pCatalog, SSqlInfo* pInfo, SQuer
}
}
for
(
int32_t
i
=
0
;
i
<
len
;
++
i
)
{
SSqlNode
*
p
=
taosArrayGetP
(
pInfo
->
list
,
i
);
validateSqlNode
(
p
,
pQueryInfo
,
&
buf
);
}
// convert the sqlnode into queryinfo
return
code
;
}
source/libs/parser/src/parser.c
浏览文件 @
a531411e
...
...
@@ -23,7 +23,7 @@ bool qIsInsertSql(const char* pStr, size_t length) {
int32_t
index
=
0
;
do
{
SToken
t0
=
tStrGetToken
(
pStr
,
&
index
,
false
);
SToken
t0
=
tStrGetToken
(
(
char
*
)
pStr
,
&
index
,
false
);
if
(
t0
.
type
!=
TK_LP
)
{
return
t0
.
type
==
TK_INSERT
||
t0
.
type
==
TK_IMPORT
;
}
...
...
@@ -120,17 +120,12 @@ int32_t getTableNameFromSqlNode(SSqlNode* pSqlNode, SArray* tableNameList, SMsgB
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
// tscDequoteAndTrimToken(t);
if
(
parserValidateIdToken
(
t
)
!=
TSDB_CODE_SUCCESS
)
{
return
buildInvalidOperationMsg
(
pMsgBuf
,
msg1
);
}
SName
name
=
{
0
};
// int32_t code = tscSetTableFullName(&name, t, pSql);
// if (code != TSDB_CODE_SUCCESS) {
// return code;
// }
strndequote
(
name
.
tname
,
t
->
z
,
t
->
n
);
taosArrayPush
(
tableNameList
,
&
name
);
}
...
...
@@ -183,7 +178,7 @@ int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMet
assert
(
t
!=
NULL
);
if
(
t
->
n
>=
TSDB_FUNC_NAME_LEN
)
{
return
parserSet
SyntaxErrMsg
(
msg
,
msgBufLen
,
"too long function name"
,
t
->
z
);
return
build
SyntaxErrMsg
(
msg
,
msgBufLen
,
"too long function name"
,
t
->
z
);
}
// Let's assume that it is an UDF/UDAF, if it is not a built-in function.
...
...
@@ -193,4 +188,6 @@ int32_t qParserExtractRequestedMetaInfo(const SSqlInfo* pSqlInfo, SMetaReq* pMet
}
}
}
return
code
;
}
\ No newline at end of file
source/libs/parser/src/parserUtil.c
浏览文件 @
a531411e
...
...
@@ -26,6 +26,11 @@ int32_t parserValidateIdToken(SToken* pToken) {
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
// it is a token quoted with escape char '`'
if
(
pToken
->
z
[
0
]
==
TS_ESCAPE_CHAR
&&
pToken
->
z
[
pToken
->
n
-
1
]
==
TS_ESCAPE_CHAR
)
{
return
TSDB_CODE_SUCCESS
;
}
char
*
sep
=
strnchr
(
pToken
->
z
,
TS_PATH_DELIMITER
[
0
],
pToken
->
n
,
true
);
if
(
sep
==
NULL
)
{
// It is a single part token, not a complex type
if
(
isNumber
(
pToken
))
{
...
...
@@ -83,7 +88,7 @@ int32_t buildInvalidOperationMsg(SMsgBuf* pBuf, const char* msg) {
return
TSDB_CODE_TSC_INVALID_OPERATION
;
}
int32_t
parserSet
SyntaxErrMsg
(
char
*
dst
,
int32_t
dstBufLen
,
const
char
*
additionalInfo
,
const
char
*
sourceStr
)
{
int32_t
build
SyntaxErrMsg
(
char
*
dst
,
int32_t
dstBufLen
,
const
char
*
additionalInfo
,
const
char
*
sourceStr
)
{
const
char
*
msgFormat1
=
"syntax error near
\'
%s
\'
"
;
const
char
*
msgFormat2
=
"syntax error near
\'
%s
\'
(%s)"
;
const
char
*
msgFormat3
=
"%s"
;
...
...
@@ -499,13 +504,14 @@ TAOS_FIELD createField(const SSchema* pSchema) {
return
f
;
}
void
setSchemaVal
(
SSchema
*
pSchema
,
uint8_t
type
,
int16_t
bytes
,
int16_t
colId
,
const
char
*
name
)
{
assert
(
pSchema
!=
NULL
)
;
pSchema
->
type
=
type
;
pSchema
->
bytes
=
bytes
;
pSchema
->
colId
=
colId
;
SSchema
createSchema
(
uint8_t
type
,
int16_t
bytes
,
int16_t
colId
,
const
char
*
name
)
{
SSchema
s
=
{
0
}
;
s
.
type
=
type
;
s
.
bytes
=
bytes
;
s
.
colId
=
colId
;
tstrncpy
(
pSchema
->
name
,
name
,
tListLen
(
pSchema
->
name
));
tstrncpy
(
s
.
name
,
name
,
tListLen
(
s
.
name
));
return
s
;
}
int32_t
getNumOfFields
(
SFieldInfo
*
pFieldInfo
)
{
...
...
@@ -1598,6 +1604,52 @@ int32_t getTagFilterSerializeLen(SQueryStmtInfo* pQueryInfo) {
return
0
;
}
uint32_t
convertRelationalOperator
(
SToken
*
pToken
)
{
switch
(
pToken
->
type
)
{
case
TK_LT
:
return
TSDB_RELATION_LESS
;
case
TK_LE
:
return
TSDB_RELATION_LESS_EQUAL
;
case
TK_GT
:
return
TSDB_RELATION_GREATER
;
case
TK_GE
:
return
TSDB_RELATION_GREATER_EQUAL
;
case
TK_NE
:
return
TSDB_RELATION_NOT_EQUAL
;
case
TK_AND
:
return
TSDB_RELATION_AND
;
case
TK_OR
:
return
TSDB_RELATION_OR
;
case
TK_EQ
:
return
TSDB_RELATION_EQUAL
;
case
TK_PLUS
:
return
TSDB_BINARY_OP_ADD
;
case
TK_MINUS
:
return
TSDB_BINARY_OP_SUBTRACT
;
case
TK_STAR
:
return
TSDB_BINARY_OP_MULTIPLY
;
case
TK_SLASH
:
case
TK_DIVIDE
:
return
TSDB_BINARY_OP_DIVIDE
;
case
TK_REM
:
return
TSDB_BINARY_OP_REMAINDER
;
case
TK_LIKE
:
return
TSDB_RELATION_LIKE
;
case
TK_MATCH
:
return
TSDB_RELATION_MATCH
;
case
TK_NMATCH
:
return
TSDB_RELATION_NMATCH
;
case
TK_ISNULL
:
return
TSDB_RELATION_ISNULL
;
case
TK_NOTNULL
:
return
TSDB_RELATION_NOTNULL
;
case
TK_IN
:
return
TSDB_RELATION_IN
;
default:
{
return
0
;
}
}
}
#if 0
int32_t tscCreateQueryFromQueryInfo(SQueryStmtInfo* pQueryInfo, SQueryAttr* pQueryAttr, void* addr) {
memset(pQueryAttr, 0, sizeof(SQueryAttr));
...
...
source/libs/parser/src/queryInfoUtil.c
浏览文件 @
a531411e
...
...
@@ -55,11 +55,16 @@ SSchema* getTableTagSchema(const STableMeta* pTableMeta) {
return
getOneColumnSchema
(
pTableMeta
,
getTableInfo
(
pTableMeta
).
numOfColumns
);
}
static
tExprNode
*
createUnaryFunctionExprNode
(
int32_t
functionId
,
SSchema
*
pSchema
)
{
tExprNode
*
pColumnNode
=
calloc
(
1
,
sizeof
(
tExprNode
));
pColumnNode
->
nodeType
=
TEXPR_COL_NODE
;
pColumnNode
->
pSchema
=
calloc
(
1
,
sizeof
(
SSchema
));
memcpy
(
pColumnNode
->
pSchema
,
pSchema
,
sizeof
(
SSchema
));
static
tExprNode
*
createUnaryFunctionExprNode
(
int32_t
functionId
,
SSchema
*
pSchema
,
tExprNode
*
pColumnNode
)
{
if
(
pColumnNode
==
NULL
)
{
pColumnNode
=
calloc
(
1
,
sizeof
(
tExprNode
));
pColumnNode
->
nodeType
=
TEXPR_COL_NODE
;
pColumnNode
->
pSchema
=
calloc
(
1
,
sizeof
(
SSchema
));
memcpy
(
pColumnNode
->
pSchema
,
pSchema
,
sizeof
(
SSchema
));
}
else
{
assert
(
pSchema
==
NULL
);
}
tExprNode
*
pNode
=
calloc
(
1
,
sizeof
(
tExprNode
));
pNode
->
nodeType
=
TEXPR_UNARYEXPR_NODE
;
...
...
@@ -69,7 +74,20 @@ static tExprNode* createUnaryFunctionExprNode(int32_t functionId, SSchema* pSche
return
pNode
;
}
SExprInfo
*
createExprInfo
(
STableMetaInfo
*
pTableMetaInfo
,
int16_t
functionId
,
SColumnIndex
*
pColIndex
,
SSchema
*
pResSchema
,
int16_t
interSize
)
{
SExprInfo
*
createBinaryExprInfo
(
tExprNode
*
pNode
,
SSchema
*
pResSchema
)
{
assert
(
pNode
!=
NULL
&&
pResSchema
!=
NULL
);
SExprInfo
*
pExpr
=
calloc
(
1
,
sizeof
(
SExprInfo
));
if
(
pExpr
==
NULL
)
{
return
NULL
;
}
pExpr
->
pExpr
=
pNode
;
memcpy
(
&
pExpr
->
base
.
resSchema
,
pResSchema
,
sizeof
(
SSchema
));
return
pExpr
;
}
SExprInfo
*
createExprInfo
(
STableMetaInfo
*
pTableMetaInfo
,
int16_t
functionId
,
SColumnIndex
*
pColIndex
,
tExprNode
*
pParamExpr
,
SSchema
*
pResSchema
,
int16_t
interSize
)
{
SExprInfo
*
pExpr
=
calloc
(
1
,
sizeof
(
SExprInfo
));
if
(
pExpr
==
NULL
)
{
return
NULL
;
...
...
@@ -77,29 +95,26 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
SSqlExpr
*
p
=
&
pExpr
->
base
;
// set the correct columnIndex index
if
(
pColIndex
->
columnIndex
==
TSDB_TBNAME_COLUMN_INDEX
)
{
if
(
pParamExpr
!=
NULL
)
{
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
NULL
,
pParamExpr
);
}
else
if
(
pColIndex
->
columnIndex
==
TSDB_TBNAME_COLUMN_INDEX
)
{
assert
(
pParamExpr
==
NULL
);
SSchema
*
s
=
getTbnameColumnSchema
();
p
->
colInfo
.
colId
=
TSDB_TBNAME_COLUMN_INDEX
;
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
s
);
}
else
if
(
pColIndex
->
columnIndex
<=
TSDB_UD_COLUMN_INDEX
)
{
p
->
colInfo
.
colId
=
pColIndex
->
columnIndex
;
SSchema
s
=
{.
colId
=
pColIndex
->
columnIndex
,
.
bytes
=
pResSchema
->
bytes
,
.
type
=
pResSchema
->
type
};
tstrncpy
(
s
.
name
,
pResSchema
->
name
,
TSDB_COL_NAME_LEN
);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
&
s
);
}
else
if
(
functionId
==
FUNCTION_BLKINFO
)
{
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
s
,
pParamExpr
);
}
else
if
(
pColIndex
->
columnIndex
<=
TSDB_UD_COLUMN_INDEX
||
functionId
==
FUNCTION_BLKINFO
)
{
assert
(
pParamExpr
==
NULL
);
p
->
colInfo
.
colId
=
pColIndex
->
columnIndex
;
SSchema
s
=
{.
colId
=
pColIndex
->
columnIndex
,
.
bytes
=
pResSchema
->
bytes
,
.
type
=
pResSchema
->
type
};
tstrncpy
(
s
.
name
,
pResSchema
->
name
,
TSDB_COL_NAME_LEN
);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
&
s
);
// p->colBytes = TSDB_MAX_BINARY_LEN;
// p->colType = TSDB_DATA_TYPE_BINARY;
SSchema
s
=
createSchema
(
pResSchema
->
type
,
pResSchema
->
bytes
,
pColIndex
->
columnIndex
,
pResSchema
->
name
);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
&
s
,
pParamExpr
);
}
else
{
int32_t
len
=
tListLen
(
p
->
colInfo
.
name
);
if
(
TSDB_COL_IS_TAG
(
pColIndex
->
type
))
{
SSchema
*
pSchema
=
getTableTagSchema
(
pTableMetaInfo
->
pTableMeta
);
p
->
colInfo
.
colId
=
pSchema
[
pColIndex
->
columnIndex
].
colId
;
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
&
pSchema
[
pColIndex
->
columnIndex
]);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
&
pSchema
[
pColIndex
->
columnIndex
]
,
pParamExpr
);
snprintf
(
p
->
colInfo
.
name
,
len
,
"%s.%s"
,
pTableMetaInfo
->
aliasName
,
pSchema
[
pColIndex
->
columnIndex
].
name
);
}
else
if
(
pTableMetaInfo
->
pTableMeta
!=
NULL
)
{
// in handling select database/version/server_status(), the pTableMeta is NULL
...
...
@@ -107,7 +122,7 @@ SExprInfo* createExprInfo(STableMetaInfo* pTableMetaInfo, int16_t functionId, SC
p
->
colInfo
.
colId
=
pSchema
->
colId
;
snprintf
(
p
->
colInfo
.
name
,
len
,
"%s.%s"
,
pTableMetaInfo
->
aliasName
,
pSchema
->
name
);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
pSchema
);
pExpr
->
pExpr
=
createUnaryFunctionExprNode
(
functionId
,
pSchema
,
pParamExpr
);
}
}
...
...
source/libs/parser/test/parserTests.cpp
浏览文件 @
a531411e
...
...
@@ -11,4 +11,368 @@
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
\ No newline at end of file
*/
#include <gtest/gtest.h>
#include <iostream>
#pragma GCC diagnostic ignored "-Wwrite-strings"
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#include "os.h"
#include "astGenerator.h"
#include "parserInt.h"
#include "taos.h"
#include "tdef.h"
#include "tvariant.h"
namespace
{
void
setSchema
(
SSchema
*
p
,
int32_t
type
,
int32_t
bytes
,
const
char
*
name
,
int32_t
colId
)
{
p
->
colId
=
colId
;
p
->
bytes
=
bytes
;
p
->
type
=
type
;
strcpy
(
p
->
name
,
name
);
}
void
setTableMetaInfo
(
SQueryStmtInfo
*
pQueryInfo
,
SMetaReq
*
req
)
{
pQueryInfo
->
numOfTables
=
1
;
pQueryInfo
->
pTableMetaInfo
=
(
STableMetaInfo
**
)
calloc
(
1
,
POINTER_BYTES
);
STableMetaInfo
*
pTableMetaInfo
=
(
STableMetaInfo
*
)
calloc
(
1
,
sizeof
(
STableMetaInfo
));
pQueryInfo
->
pTableMetaInfo
[
0
]
=
pTableMetaInfo
;
SName
*
name
=
(
SName
*
)
taosArrayGet
(
req
->
pTableName
,
0
);
memcpy
(
&
pTableMetaInfo
->
name
,
taosArrayGet
(
req
->
pTableName
,
0
),
sizeof
(
SName
));
pTableMetaInfo
->
pTableMeta
=
(
STableMeta
*
)
calloc
(
1
,
sizeof
(
STableMeta
)
+
4
*
sizeof
(
SSchema
));
strcpy
(
pTableMetaInfo
->
aliasName
,
name
->
tname
);
STableMeta
*
pTableMeta
=
pTableMetaInfo
->
pTableMeta
;
pTableMeta
->
tableType
=
TSDB_NORMAL_TABLE
;
pTableMeta
->
tableInfo
.
numOfColumns
=
4
;
pTableMeta
->
tableInfo
.
rowSize
=
28
;
pTableMeta
->
uid
=
110
;
pTableMetaInfo
->
tagColList
=
(
SArray
*
)
taosArrayInit
(
4
,
POINTER_BYTES
);
SSchema
*
pSchema
=
pTableMetaInfo
->
pTableMeta
->
schema
;
setSchema
(
&
pSchema
[
0
],
TSDB_DATA_TYPE_TIMESTAMP
,
8
,
"ts"
,
0
);
setSchema
(
&
pSchema
[
1
],
TSDB_DATA_TYPE_INT
,
4
,
"a"
,
1
);
setSchema
(
&
pSchema
[
2
],
TSDB_DATA_TYPE_DOUBLE
,
8
,
"b"
,
2
);
setSchema
(
&
pSchema
[
3
],
TSDB_DATA_TYPE_DOUBLE
,
8
,
"col"
,
3
);
}
}
TEST
(
testCase
,
validateAST_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select a a1111, a+b + 22, tbname from `t.1abc` where ts<now+2h and `col` < 20 + 99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
3
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_INT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1111"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.a"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
1
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"a"
);
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
3
);
SExprInfo
*
p2
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
1
);
ASSERT_EQ
(
p2
->
base
.
uid
,
0
);
ASSERT_EQ
(
p2
->
base
.
numOfParams
,
1
);
// it is the serialized binary string of expression.
ASSERT_EQ
(
p2
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p2
->
base
.
resSchema
.
name
,
"a+b + 22"
);
// ASSERT_STRCASEEQ(p2->base.colInfo.name, "t.1abc.a");
// ASSERT_EQ(p1->base.colInfo.colId, 1);
// ASSERT_EQ(p1->base.colInfo.flag, TSDB_COL_NORMAL);
ASSERT_STRCASEEQ
(
p2
->
base
.
token
,
"a+b + 22"
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
3
);
}
TEST
(
testCase
,
function_Test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select count(a) from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BIGINT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"count(a)"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.a"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
1
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"count(a)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
8
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
2
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
}
TEST
(
testCase
,
function_Test2
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select count(a) abc from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BIGINT
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"abc"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.a"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
1
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"count(a)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
8
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
2
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
}
TEST
(
testCase
,
function_Test3
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select first(*) from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
4
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_TIMESTAMP
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"first(ts)"
);
ASSERT_STRCASEEQ
(
p1
->
base
.
colInfo
.
name
,
"t.1abc.ts"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
colId
,
0
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"first(ts)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
24
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
4
);
}
TEST
(
testCase
,
function_Test4
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select _block_dist() as a1 from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_BINARY
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
// ASSERT_EQ(p1->base.colInfo.colId, 0);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"_block_dist()"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
1
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
}
TEST
(
testCase
,
function_Test5
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select sum(a) + avg(b) as a1 from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
3
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
0
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
1
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
// ASSERT_STRCASEEQ(p1->base.colInfo.name, "t.1abc.ts");
// ASSERT_EQ(p1->base.colInfo.colId, 0);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"sum(a) + avg(b)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
}
TEST
(
testCase
,
function_Test6
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select sum(a+b) as a1 from `t.1abc`"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMsgBuf
buf
;
buf
.
len
=
128
;
buf
.
buf
=
msg
;
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
buf
);
ASSERT_EQ
(
code
,
0
);
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
SQueryStmtInfo
*
pQueryInfo
=
(
SQueryStmtInfo
*
)
calloc
(
1
,
sizeof
(
SQueryStmtInfo
));
initQueryInfo
(
pQueryInfo
);
setTableMetaInfo
(
pQueryInfo
,
&
req
);
SSqlNode
*
pSqlNode
=
(
SSqlNode
*
)
taosArrayGetP
(
info1
.
list
,
0
);
ret
=
validateSqlNode
(
pSqlNode
,
pQueryInfo
,
&
buf
);
ASSERT_EQ
(
ret
,
0
);
SArray
*
pExprList
=
pQueryInfo
->
exprList
;
ASSERT_EQ
(
taosArrayGetSize
(
pExprList
),
1
);
SExprInfo
*
p1
=
(
SExprInfo
*
)
taosArrayGetP
(
pExprList
,
0
);
ASSERT_EQ
(
p1
->
base
.
uid
,
110
);
ASSERT_EQ
(
p1
->
base
.
numOfParams
,
0
);
ASSERT_EQ
(
p1
->
base
.
resSchema
.
type
,
TSDB_DATA_TYPE_DOUBLE
);
ASSERT_STRCASEEQ
(
p1
->
base
.
resSchema
.
name
,
"a1"
);
ASSERT_EQ
(
p1
->
base
.
colInfo
.
flag
,
TSDB_COL_NORMAL
);
ASSERT_STRCASEEQ
(
p1
->
base
.
token
,
"sum(a+b)"
);
ASSERT_EQ
(
p1
->
base
.
interBytes
,
16
);
ASSERT_EQ
(
taosArrayGetSize
(
pQueryInfo
->
colList
),
3
);
ASSERT_EQ
(
pQueryInfo
->
fieldsInfo
.
numOfOutput
,
1
);
}
\ No newline at end of file
source/libs/parser/test/tokenizerTest.cpp
浏览文件 @
a531411e
...
...
@@ -4,7 +4,6 @@
#pragma GCC diagnostic ignored "-Wunused-function"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wsign-compare"
#include "os.h"
...
...
@@ -89,6 +88,9 @@ TEST(testCase, validateToken_test) {
char
t01
[]
=
"abc"
;
EXPECT_EQ
(
testValidateName
(
t01
),
TSDB_CODE_SUCCESS
);
char
t110
[]
=
"`1233abc.911`"
;
EXPECT_EQ
(
testValidateName
(
t110
),
TSDB_CODE_SUCCESS
);
char
t02
[]
=
"'abc'"
;
EXPECT_EQ
(
testValidateName
(
t02
),
TSDB_CODE_TSC_INVALID_OPERATION
);
...
...
@@ -689,7 +691,7 @@ TEST(testCase, generateAST_test) {
}
TEST
(
testCase
,
evaluateAST_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select a, b+22 from `t.1abc` where ts<now+2h and
col
< 20 + 99"
);
SSqlInfo
info1
=
doGenerateAST
(
"select a, b+22 from `t.1abc` where ts<now+2h and
`col`
< 20 + 99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
...
...
@@ -700,6 +702,16 @@ TEST(testCase, evaluateAST_test) {
SSqlNode
*
pNode
=
(
SSqlNode
*
)
taosArrayGetP
(((
SArray
*
)
info1
.
list
),
0
);
int32_t
code
=
evaluateSqlNode
(
pNode
,
TSDB_TIME_PRECISION_NANO
,
&
msgBuf
);
ASSERT_EQ
(
code
,
0
);
}
TEST
(
testCase
,
extractMeta_test
)
{
SSqlInfo
info1
=
doGenerateAST
(
"select a, b+22 from `t.1abc` where ts<now+2h and `col` < 20 + 99"
);
ASSERT_EQ
(
info1
.
valid
,
true
);
char
msg
[
128
]
=
{
0
};
SMetaReq
req
=
{
0
};
int32_t
ret
=
qParserExtractRequestedMetaInfo
(
&
info1
,
&
req
,
msg
,
128
);
ASSERT_EQ
(
ret
,
0
);
ASSERT_EQ
(
taosArrayGetSize
(
req
.
pTableName
),
1
);
}
source/util/src/tutil.c
浏览文件 @
a531411e
...
...
@@ -22,7 +22,7 @@ int32_t strdequote(char *z) {
}
int32_t
quote
=
z
[
0
];
if
(
quote
!=
'\''
&&
quote
!=
'"'
)
{
if
(
quote
!=
'\''
&&
quote
!=
'"'
&&
quote
!=
'`'
)
{
return
(
int32_t
)
strlen
(
z
);
}
...
...
@@ -78,6 +78,34 @@ int32_t strRmquote(char *z, int32_t len){
return
len
-
2
-
cnt
;
}
int32_t
strndequote
(
char
*
dst
,
const
char
*
z
,
int32_t
len
)
{
assert
(
dst
!=
NULL
);
if
(
z
==
NULL
||
len
==
0
)
{
return
0
;
}
int32_t
quote
=
z
[
0
];
int32_t
i
=
1
,
j
=
0
;
while
(
z
[
i
]
!=
0
)
{
if
(
z
[
i
]
==
quote
)
{
if
(
z
[
i
+
1
]
==
quote
)
{
dst
[
j
++
]
=
(
char
)
quote
;
i
++
;
}
else
{
dst
[
j
++
]
=
0
;
return
(
j
-
1
);
}
}
else
{
dst
[
j
++
]
=
z
[
i
];
}
i
++
;
}
return
j
+
1
;
// only one quote, do nothing
}
size_t
strtrim
(
char
*
z
)
{
int32_t
i
=
0
;
int32_t
j
=
0
;
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录