Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
e00a9fa9
T
TDengine
项目概览
taosdata
/
TDengine
1 年多 前同步成功
通知
1185
Star
22016
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看板
未验证
提交
e00a9fa9
编写于
5月 21, 2022
作者:
X
Xiaoyu Wang
提交者:
GitHub
5月 21, 2022
浏览文件
操作
浏览文件
下载
差异文件
Merge pull request #12801 from taosdata/feature/3.0_wxy
fix: some prblems of parser and planner
上级
751140f6
bec1c246
变更
11
展开全部
隐藏空白更改
内联
并排
Showing
11 changed file
with
927 addition
and
794 deletion
+927
-794
include/libs/qcom/query.h
include/libs/qcom/query.h
+15
-15
source/libs/parser/inc/sql.y
source/libs/parser/inc/sql.y
+2
-2
source/libs/parser/src/parTranslater.c
source/libs/parser/src/parTranslater.c
+148
-86
source/libs/parser/src/sql.c
source/libs/parser/src/sql.c
+663
-665
source/libs/parser/test/parSelectTest.cpp
source/libs/parser/test/parSelectTest.cpp
+4
-0
source/libs/planner/src/planSpliter.c
source/libs/planner/src/planSpliter.c
+16
-2
source/libs/planner/test/planSetOpTest.cpp
source/libs/planner/test/planSetOpTest.cpp
+19
-0
source/libs/planner/test/planSubqueryTest.cpp
source/libs/planner/test/planSubqueryTest.cpp
+1
-3
source/libs/planner/test/planTestMain.cpp
source/libs/planner/test/planTestMain.cpp
+26
-16
source/libs/planner/test/planTestUtil.cpp
source/libs/planner/test/planTestUtil.cpp
+29
-2
source/libs/planner/test/planTestUtil.h
source/libs/planner/test/planTestUtil.h
+4
-3
未找到文件。
include/libs/qcom/query.h
浏览文件 @
e00a9fa9
...
...
@@ -228,23 +228,23 @@ extern int32_t (*queryProcessMsgRsp[TDMT_MAX])(void* output, char* msg, int32_t
taosPrintLog("QRY ", DEBUG_INFO, tsLogEmbedded ? 255 : qDebugFlag, __VA_ARGS__); \
} \
} while (0)
#define qDebug(...) \
do { \
if (qDebugFlag & DEBUG_DEBUG) { \
taosPrintLog("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
} \
#define qDebug(...)
\
do {
\
if (qDebugFlag & DEBUG_DEBUG) {
\
taosPrintLog("QRY ", DEBUG_DEBUG,
tsLogEmbedded ? 255 :
qDebugFlag, __VA_ARGS__); \
}
\
} while (0)
#define qTrace(...) \
do { \
if (qDebugFlag & DEBUG_TRACE) { \
taosPrintLog("QRY ", DEBUG_TRACE, qDebugFlag, __VA_ARGS__); \
} \
#define qTrace(...)
\
do {
\
if (qDebugFlag & DEBUG_TRACE) {
\
taosPrintLog("QRY ", DEBUG_TRACE,
tsLogEmbedded ? 255 :
qDebugFlag, __VA_ARGS__); \
}
\
} while (0)
#define qDebugL(...) \
do { \
if (qDebugFlag & DEBUG_DEBUG) { \
taosPrintLongString("QRY ", DEBUG_DEBUG, qDebugFlag, __VA_ARGS__); \
} \
#define qDebugL(...)
\
do {
\
if (qDebugFlag & DEBUG_DEBUG) {
\
taosPrintLongString("QRY ", DEBUG_DEBUG,
tsLogEmbedded ? 255 :
qDebugFlag, __VA_ARGS__); \
}
\
} while (0)
#define QRY_ERR_RET(c) \
...
...
source/libs/parser/inc/sql.y
浏览文件 @
e00a9fa9
...
...
@@ -241,7 +241,7 @@ alter_table_clause(A) ::=
alter_table_clause(A) ::=
full_table_name(B) RENAME TAG column_name(C) column_name(D). { A = createAlterTableRenameCol(pCxt, B, TSDB_ALTER_TABLE_UPDATE_TAG_NAME, &C, &D); }
alter_table_clause(A) ::=
full_table_name(B) SET TAG column_name(C) NK_EQ
literal(D). { A = createAlterTableSetTag(pCxt, B, &C, releaseRawExprNode(pCxt, D)
); }
full_table_name(B) SET TAG column_name(C) NK_EQ
signed_literal(D). { A = createAlterTableSetTag(pCxt, B, &C, D
); }
%type multi_create_clause { SNodeList* }
%destructor multi_create_clause { nodesDestroyList($$); }
...
...
@@ -448,7 +448,7 @@ agg_func_opt(A) ::= AGGREGATE.
%type bufsize_opt { int32_t }
%destructor bufsize_opt { }
bufsize_opt(A) ::= . { A = 0; }
bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A =
strtol
(B.z, NULL, 10); }
bufsize_opt(A) ::= BUFSIZE NK_INTEGER(B). { A =
taosStr2Int32
(B.z, NULL, 10); }
/************************************************ create/drop stream **************************************************/
cmd ::= CREATE STREAM not_exists_opt(E) stream_name(A)
...
...
source/libs/parser/src/parTranslater.c
浏览文件 @
e00a9fa9
...
...
@@ -694,66 +694,110 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
return
translateValueImpl
(
pCxt
,
pVal
,
pVal
->
node
.
resType
);
}
static
EDealRes
translateOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
if
(
nodesIsUnaryOp
(
pOp
))
{
if
(
OP_TYPE_MINUS
==
pOp
->
opType
)
{
if
(
!
IS_MATHABLE_TYPE
(((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pLeft
))
->
aliasName
);
}
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_DOUBLE
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_DOUBLE
].
bytes
;
}
else
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_BOOL
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_BOOL
].
bytes
;
static
bool
isMultiResFunc
(
SNode
*
pNode
)
{
if
(
NULL
==
pNode
)
{
return
false
;
}
if
(
QUERY_NODE_FUNCTION
!=
nodeType
(
pNode
)
||
!
fmIsMultiResFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
))
{
return
false
;
}
SNodeList
*
pParameterList
=
((
SFunctionNode
*
)
pNode
)
->
pParameterList
;
if
(
LIST_LENGTH
(
pParameterList
)
>
1
)
{
return
true
;
}
SNode
*
pParam
=
nodesListGetNode
(
pParameterList
,
0
);
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pParam
)
?
0
==
strcmp
(((
SColumnNode
*
)
pParam
)
->
colName
,
"*"
)
:
false
);
}
static
EDealRes
translateUnaryOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
if
(
OP_TYPE_MINUS
==
pOp
->
opType
)
{
if
(
!
IS_MATHABLE_TYPE
(((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pLeft
))
->
aliasName
);
}
return
DEAL_RES_CONTINUE
;
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_DOUBLE
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_DOUBLE
].
bytes
;
}
else
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_BOOL
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_BOOL
].
bytes
;
}
return
DEAL_RES_CONTINUE
;
}
static
EDealRes
translateArithmeticOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
SDataType
ldt
=
((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
;
SDataType
rdt
=
((
SExprNode
*
)(
pOp
->
pRight
))
->
resType
;
if
(
nodesIsArithmeticOp
(
pOp
))
{
if
(
TSDB_DATA_TYPE_JSON
==
ldt
.
type
||
TSDB_DATA_TYPE_BLOB
==
ldt
.
type
||
TSDB_DATA_TYPE_JSON
==
rdt
.
type
||
TSDB_DATA_TYPE_BLOB
==
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
if
(
TSDB_DATA_TYPE_JSON
==
ldt
.
type
||
TSDB_DATA_TYPE_BLOB
==
ldt
.
type
||
TSDB_DATA_TYPE_JSON
==
rdt
.
type
||
TSDB_DATA_TYPE_BLOB
==
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
if
((
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
)
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
(
IS_VAR_DATA_TYPE
(
rdt
.
type
)
||
IS_FLOAT_TYPE
(
rdt
.
type
)))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
(
IS_VAR_DATA_TYPE
(
ldt
.
type
)
||
IS_FLOAT_TYPE
(
ldt
.
type
))))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
if
((
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
IS_INTEGER_TYPE
(
rdt
.
type
))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
IS_INTEGER_TYPE
(
ldt
.
type
))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
TSDB_DATA_TYPE_BOOL
==
rdt
.
type
)
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
TSDB_DATA_TYPE_BOOL
==
ldt
.
type
))
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_TIMESTAMP
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_TIMESTAMP
].
bytes
;
}
else
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_DOUBLE
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_DOUBLE
].
bytes
;
}
return
DEAL_RES_CONTINUE
;
}
static
EDealRes
translateComparisonOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
SDataType
ldt
=
((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
;
SDataType
rdt
=
((
SExprNode
*
)(
pOp
->
pRight
))
->
resType
;
if
(
TSDB_DATA_TYPE_BLOB
==
ldt
.
type
||
TSDB_DATA_TYPE_JSON
==
rdt
.
type
||
TSDB_DATA_TYPE_BLOB
==
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
if
(
OP_TYPE_IN
==
pOp
->
opType
||
OP_TYPE_NOT_IN
==
pOp
->
opType
)
{
((
SExprNode
*
)
pOp
->
pRight
)
->
resType
=
((
SExprNode
*
)
pOp
->
pLeft
)
->
resType
;
}
if
(
nodesIsRegularOp
(
pOp
))
{
if
(
!
IS_STR_DATA_TYPE
(((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pLeft
))
->
aliasName
);
}
if
((
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
)
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
(
IS_VAR_DATA_TYPE
(
rdt
.
type
)
||
IS_FLOAT_TYPE
(
rdt
.
type
)))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
(
IS_VAR_DATA_TYPE
(
ldt
.
type
)
||
IS_FLOAT_TYPE
(
ldt
.
type
))))
{
if
(
QUERY_NODE_VALUE
!=
nodeType
(
pOp
->
pRight
)
||
!
IS_STR_DATA_TYPE
(((
SExprNode
*
)(
pOp
->
pRight
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
}
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_BOOL
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_BOOL
].
bytes
;
return
DEAL_RES_CONTINUE
;
}
if
((
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
IS_INTEGER_TYPE
(
rdt
.
type
))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
IS_INTEGER_TYPE
(
ldt
.
type
))
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
ldt
.
type
&&
TSDB_DATA_TYPE_BOOL
==
rdt
.
type
)
||
(
TSDB_DATA_TYPE_TIMESTAMP
==
rdt
.
type
&&
TSDB_DATA_TYPE_BOOL
==
ldt
.
type
))
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_TIMESTAMP
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_TIMESTAMP
].
bytes
;
}
else
{
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_DOUBLE
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_DOUBLE
].
bytes
;
}
static
EDealRes
translateJsonOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
SDataType
ldt
=
((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
;
SDataType
rdt
=
((
SExprNode
*
)(
pOp
->
pRight
))
->
resType
;
if
(
TSDB_DATA_TYPE_JSON
!=
ldt
.
type
||
TSDB_DATA_TYPE_BINARY
!=
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_JSON
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_JSON
].
bytes
;
return
DEAL_RES_CONTINUE
;
}
static
EDealRes
translateOperator
(
STranslateContext
*
pCxt
,
SOperatorNode
*
pOp
)
{
if
(
isMultiResFunc
(
pOp
->
pLeft
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pLeft
))
->
aliasName
);
}
if
(
isMultiResFunc
(
pOp
->
pRight
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
if
(
nodesIsUnaryOp
(
pOp
))
{
return
translateUnaryOperator
(
pCxt
,
pOp
);
}
else
if
(
nodesIsArithmeticOp
(
pOp
))
{
return
translateArithmeticOperator
(
pCxt
,
pOp
);
}
else
if
(
nodesIsComparisonOp
(
pOp
))
{
if
(
TSDB_DATA_TYPE_BLOB
==
ldt
.
type
||
TSDB_DATA_TYPE_JSON
==
rdt
.
type
||
TSDB_DATA_TYPE_BLOB
==
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
if
(
OP_TYPE_IN
==
pOp
->
opType
||
OP_TYPE_NOT_IN
==
pOp
->
opType
)
{
((
SExprNode
*
)
pOp
->
pRight
)
->
resType
=
((
SExprNode
*
)
pOp
->
pLeft
)
->
resType
;
}
if
(
nodesIsRegularOp
(
pOp
))
{
if
(
!
IS_STR_DATA_TYPE
(((
SExprNode
*
)(
pOp
->
pLeft
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pLeft
))
->
aliasName
);
}
if
(
QUERY_NODE_VALUE
!=
nodeType
(
pOp
->
pRight
)
||
!
IS_STR_DATA_TYPE
(((
SExprNode
*
)(
pOp
->
pRight
))
->
resType
.
type
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
}
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_BOOL
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_BOOL
].
bytes
;
return
translateComparisonOperator
(
pCxt
,
pOp
);
}
else
if
(
nodesIsJsonOp
(
pOp
))
{
if
(
TSDB_DATA_TYPE_JSON
!=
ldt
.
type
||
TSDB_DATA_TYPE_BINARY
!=
rdt
.
type
)
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)(
pOp
->
pRight
))
->
aliasName
);
}
pOp
->
node
.
resType
.
type
=
TSDB_DATA_TYPE_JSON
;
pOp
->
node
.
resType
.
bytes
=
tDataTypes
[
TSDB_DATA_TYPE_JSON
].
bytes
;
return
translateJsonOperator
(
pCxt
,
pOp
);
}
return
DEAL_RES_CONTINUE
;
}
...
...
@@ -808,6 +852,13 @@ static bool hasInvalidFuncNesting(SNodeList* pParameterList) {
}
static
EDealRes
translateFunction
(
STranslateContext
*
pCxt
,
SFunctionNode
*
pFunc
)
{
SNode
*
pParam
=
NULL
;
FOREACH
(
pParam
,
pFunc
->
pParameterList
)
{
if
(
isMultiResFunc
(
pParam
))
{
return
generateDealNodeErrMsg
(
pCxt
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)
pParam
)
->
aliasName
);
}
}
SFmGetFuncInfoParam
param
=
{.
pCtg
=
pCxt
->
pParseCxt
->
pCatalog
,
.
pRpc
=
pCxt
->
pParseCxt
->
pTransporter
,
.
pMgmtEps
=
&
pCxt
->
pParseCxt
->
mgmtEpSet
,
...
...
@@ -926,9 +977,10 @@ typedef struct SCheckExprForGroupByCxt {
STranslateContext
*
pTranslateCxt
;
int32_t
selectFuncNum
;
bool
hasSelectValFunc
;
bool
hasOtherAggFunc
;
}
SCheckExprForGroupByCxt
;
static
EDealRes
rewriteColToSelectValFunc
(
STranslateContext
*
pCxt
,
bool
*
pHasSelectValFunc
,
SNode
**
pNode
)
{
static
EDealRes
rewriteColToSelectValFunc
(
STranslateContext
*
pCxt
,
SNode
**
pNode
)
{
SFunctionNode
*
pFunc
=
nodesMakeNode
(
QUERY_NODE_FUNCTION
);
if
(
NULL
==
pFunc
)
{
pCxt
->
errCode
=
TSDB_CODE_OUT_OF_MEMORY
;
...
...
@@ -942,9 +994,6 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, bool* pHasSel
}
if
(
TSDB_CODE_SUCCESS
==
pCxt
->
errCode
)
{
*
pNode
=
(
SNode
*
)
pFunc
;
if
(
NULL
!=
pHasSelectValFunc
)
{
*
pHasSelectValFunc
=
true
;
}
}
else
{
nodesDestroyNode
(
pFunc
);
}
...
...
@@ -956,8 +1005,12 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
if
(
!
nodesIsExprNode
(
*
pNode
)
||
isAliasColumn
(
*
pNode
))
{
return
DEAL_RES_CONTINUE
;
}
pCxt
->
selectFuncNum
+=
isSelectFunc
(
*
pNode
)
?
1
:
0
;
if
(
pCxt
->
selectFuncNum
>
1
&&
pCxt
->
hasSelectValFunc
)
{
if
(
isSelectFunc
(
*
pNode
))
{
++
(
pCxt
->
selectFuncNum
);
}
else
if
(
isAggFunc
(
*
pNode
))
{
pCxt
->
hasOtherAggFunc
=
true
;
}
if
((
pCxt
->
selectFuncNum
>
1
&&
pCxt
->
hasSelectValFunc
)
||
(
pCxt
->
hasOtherAggFunc
&&
pCxt
->
hasSelectValFunc
))
{
return
generateDealNodeErrMsg
(
pCxt
->
pTranslateCxt
,
getGroupByErrorCode
(
pCxt
->
pTranslateCxt
));
}
if
(
isAggFunc
(
*
pNode
)
&&
!
isDistinctOrderBy
(
pCxt
->
pTranslateCxt
))
{
...
...
@@ -970,10 +1023,11 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
}
}
if
(
isScanPseudoColumnFunc
(
*
pNode
)
||
QUERY_NODE_COLUMN
==
nodeType
(
*
pNode
))
{
if
(
pCxt
->
selectFuncNum
>
1
)
{
if
(
pCxt
->
selectFuncNum
>
1
||
pCxt
->
hasOtherAggFunc
)
{
return
generateDealNodeErrMsg
(
pCxt
->
pTranslateCxt
,
getGroupByErrorCode
(
pCxt
->
pTranslateCxt
));
}
else
{
return
rewriteColToSelectValFunc
(
pCxt
->
pTranslateCxt
,
&
pCxt
->
hasSelectValFunc
,
pNode
);
pCxt
->
hasSelectValFunc
=
true
;
return
rewriteColToSelectValFunc
(
pCxt
->
pTranslateCxt
,
pNode
);
}
}
if
(
isAggFunc
(
*
pNode
)
&&
isDistinctOrderBy
(
pCxt
->
pTranslateCxt
))
{
...
...
@@ -983,7 +1037,8 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) {
}
static
int32_t
checkExprForGroupBy
(
STranslateContext
*
pCxt
,
SNode
**
pNode
)
{
SCheckExprForGroupByCxt
cxt
=
{.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
};
SCheckExprForGroupByCxt
cxt
=
{
.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
,
.
hasOtherAggFunc
=
false
};
nodesRewriteExpr
(
pNode
,
doCheckExprForGroupBy
,
&
cxt
);
if
(
cxt
.
selectFuncNum
!=
1
&&
cxt
.
hasSelectValFunc
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
getGroupByErrorCode
(
pCxt
));
...
...
@@ -995,7 +1050,8 @@ static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList
if
(
NULL
==
getGroupByList
(
pCxt
))
{
return
TSDB_CODE_SUCCESS
;
}
SCheckExprForGroupByCxt
cxt
=
{.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
};
SCheckExprForGroupByCxt
cxt
=
{
.
pTranslateCxt
=
pCxt
,
.
selectFuncNum
=
0
,
.
hasSelectValFunc
=
false
,
.
hasOtherAggFunc
=
false
};
nodesRewriteExprs
(
pList
,
doCheckExprForGroupBy
,
&
cxt
);
if
(
cxt
.
selectFuncNum
!=
1
&&
cxt
.
hasSelectValFunc
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
getGroupByErrorCode
(
pCxt
));
...
...
@@ -1008,7 +1064,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) {
return
DEAL_RES_IGNORE_CHILD
;
}
if
(
isScanPseudoColumnFunc
(
*
pNode
)
||
QUERY_NODE_COLUMN
==
nodeType
(
*
pNode
))
{
return
rewriteColToSelectValFunc
((
STranslateContext
*
)
pContext
,
NULL
,
pNode
);
return
rewriteColToSelectValFunc
((
STranslateContext
*
)
pContext
,
pNode
);
}
return
DEAL_RES_CONTINUE
;
}
...
...
@@ -1027,11 +1083,16 @@ typedef struct CheckAggColCoexistCxt {
bool
existCol
;
bool
existNonstdFunc
;
int32_t
selectFuncNum
;
bool
existOtherAggFunc
;
}
CheckAggColCoexistCxt
;
static
EDealRes
doCheckAggColCoexist
(
SNode
*
pNode
,
void
*
pContext
)
{
CheckAggColCoexistCxt
*
pCxt
=
(
CheckAggColCoexistCxt
*
)
pContext
;
pCxt
->
selectFuncNum
+=
isSelectFunc
(
pNode
)
?
1
:
0
;
if
(
isSelectFunc
(
pNode
))
{
++
(
pCxt
->
selectFuncNum
);
}
else
if
(
isAggFunc
(
pNode
))
{
pCxt
->
existOtherAggFunc
=
true
;
}
if
(
isAggFunc
(
pNode
))
{
pCxt
->
existAggFunc
=
true
;
return
DEAL_RES_IGNORE_CHILD
;
...
...
@@ -1050,13 +1111,17 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect)
if
(
NULL
!=
pSelect
->
pGroupByList
)
{
return
TSDB_CODE_SUCCESS
;
}
CheckAggColCoexistCxt
cxt
=
{
.
pTranslateCxt
=
pCxt
,
.
existAggFunc
=
false
,
.
existCol
=
false
,
.
existNonstdFunc
=
false
};
CheckAggColCoexistCxt
cxt
=
{.
pTranslateCxt
=
pCxt
,
.
existAggFunc
=
false
,
.
existCol
=
false
,
.
existNonstdFunc
=
false
,
.
selectFuncNum
=
0
,
.
existOtherAggFunc
=
false
};
nodesWalkExprs
(
pSelect
->
pProjectionList
,
doCheckAggColCoexist
,
&
cxt
);
if
(
!
pSelect
->
isDistinct
)
{
nodesWalkExprs
(
pSelect
->
pOrderByList
,
doCheckAggColCoexist
,
&
cxt
);
}
if
(
1
==
cxt
.
selectFuncNum
)
{
if
(
1
==
cxt
.
selectFuncNum
&&
!
cxt
.
existOtherAggFunc
)
{
return
rewriteColsToSelectValFunc
(
pCxt
,
pSelect
);
}
if
((
cxt
.
selectFuncNum
>
1
||
cxt
.
existAggFunc
||
NULL
!=
pSelect
->
pWindow
)
&&
cxt
.
existCol
)
{
...
...
@@ -1230,18 +1295,6 @@ static int32_t createAllColumns(STranslateContext* pCxt, SNodeList** pCols) {
return
TSDB_CODE_SUCCESS
;
}
static
bool
isMultiResFunc
(
SNode
*
pNode
)
{
if
(
QUERY_NODE_FUNCTION
!=
nodeType
(
pNode
)
||
!
fmIsMultiResFunc
(((
SFunctionNode
*
)
pNode
)
->
funcId
))
{
return
false
;
}
SNodeList
*
pParameterList
=
((
SFunctionNode
*
)
pNode
)
->
pParameterList
;
if
(
LIST_LENGTH
(
pParameterList
)
>
1
)
{
return
true
;
}
SNode
*
pParam
=
nodesListGetNode
(
pParameterList
,
0
);
return
(
QUERY_NODE_COLUMN
==
nodeType
(
pParam
)
?
0
==
strcmp
(((
SColumnNode
*
)
pParam
)
->
colName
,
"*"
)
:
false
);
}
static
SNode
*
createMultiResFunc
(
SFunctionNode
*
pSrcFunc
,
SExprNode
*
pExpr
)
{
SFunctionNode
*
pFunc
=
nodesMakeNode
(
QUERY_NODE_FUNCTION
);
if
(
NULL
==
pFunc
)
{
...
...
@@ -1872,7 +1925,7 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
}
static
bool
dataTypeEqual
(
const
SDataType
*
l
,
const
SDataType
*
r
)
{
return
(
l
->
type
==
r
->
type
&&
l
->
bytes
==
l
->
bytes
&&
l
->
precision
==
r
->
precision
&&
l
->
scale
==
l
->
scale
);
return
(
l
->
type
==
r
->
type
&&
l
->
bytes
==
r
->
bytes
&&
l
->
precision
==
r
->
precision
&&
l
->
scale
==
r
->
scale
);
}
static
int32_t
createCastFunc
(
STranslateContext
*
pCxt
,
SNode
*
pExpr
,
SDataType
dt
,
SNode
**
pCast
)
{
...
...
@@ -2726,8 +2779,11 @@ static int32_t buildCreateStbReq(STranslateContext* pCxt, SCreateTableStmt* pStm
SName
tableName
;
tNameExtractFullName
(
toName
(
pCxt
->
pParseCxt
->
acctId
,
pStmt
->
dbName
,
pStmt
->
tableName
,
&
tableName
),
pReq
->
name
);
return
buildRollupAst
(
pCxt
,
pStmt
,
pReq
);
int32_t
code
=
collectUseTable
(
&
tableName
,
pCxt
->
pTables
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
buildRollupAst
(
pCxt
,
pStmt
,
pReq
);
}
return
code
;
}
static
int32_t
translateCreateSuperTable
(
STranslateContext
*
pCxt
,
SCreateTableStmt
*
pStmt
)
{
...
...
@@ -4032,13 +4088,18 @@ static int32_t createValueFromFunction(STranslateContext* pCxt, SFunctionNode* p
return
scalarCalculateConstants
((
SNode
*
)
pFunc
,
(
SNode
**
)
pVal
);
}
static
int32_t
colDataBytesToValueDataBytes
(
uint8_t
type
,
int32_t
bytes
)
{
if
(
TSDB_DATA_TYPE_VARCHAR
==
type
||
TSDB_DATA_TYPE_BINARY
==
type
||
TSDB_DATA_TYPE_VARBINARY
==
type
)
{
return
bytes
-
VARSTR_HEADER_SIZE
;
}
else
if
(
TSDB_DATA_TYPE_NCHAR
==
type
)
{
return
(
bytes
-
VARSTR_HEADER_SIZE
)
/
TSDB_NCHAR_SIZE
;
}
return
bytes
;
}
static
SDataType
schemaToDataType
(
SSchema
*
pSchema
)
{
SDataType
dt
=
{.
type
=
pSchema
->
type
,
.
bytes
=
pSchema
->
bytes
,
.
precision
=
0
,
.
scale
=
0
};
if
(
TSDB_DATA_TYPE_VARCHAR
==
dt
.
type
||
TSDB_DATA_TYPE_BINARY
==
dt
.
type
||
TSDB_DATA_TYPE_VARBINARY
==
dt
.
type
)
{
dt
.
bytes
-=
VARSTR_HEADER_SIZE
;
}
else
if
(
TSDB_DATA_TYPE_NCHAR
==
dt
.
type
)
{
dt
.
bytes
=
(
dt
.
bytes
-
VARSTR_HEADER_SIZE
)
/
TSDB_NCHAR_SIZE
;
}
dt
.
bytes
=
colDataBytesToValueDataBytes
(
pSchema
->
type
,
pSchema
->
bytes
);
return
dt
;
}
...
...
@@ -4440,7 +4501,8 @@ static int32_t buildUpdateColReq(STranslateContext* pCxt, SAlterTableStmt* pStmt
SSchema
*
pSchema
=
getColSchema
(
pTableMeta
,
pStmt
->
colName
);
if
(
NULL
==
pSchema
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_INVALID_COLUMN
,
pStmt
->
colName
);
}
else
if
(
!
IS_VAR_DATA_TYPE
(
pSchema
->
type
)
||
pSchema
->
bytes
>=
pReq
->
colModBytes
)
{
}
else
if
(
!
IS_VAR_DATA_TYPE
(
pSchema
->
type
)
||
pSchema
->
type
!=
pStmt
->
dataType
.
type
||
pSchema
->
bytes
>=
pReq
->
colModBytes
)
{
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_INVALID_MODIFY_COL
);
}
...
...
source/libs/parser/src/sql.c
浏览文件 @
e00a9fa9
此差异已折叠。
点击以展开。
source/libs/parser/test/parSelectTest.cpp
浏览文件 @
e00a9fa9
...
...
@@ -239,6 +239,10 @@ TEST_F(ParserSelectTest, semanticError) {
// TSDB_CODE_PAR_WRONG_VALUE_TYPE
run
(
"SELECT timestamp '2010a' FROM t1"
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT LAST(*) + SUM(c1) FROM t1"
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
PARSER_STAGE_TRANSLATE
);
run
(
"SELECT CEIL(LAST(ts, c1)) FROM t1"
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
PARSER_STAGE_TRANSLATE
);
// TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
run
(
"SELECT c2 FROM t1 tt1 join t1 tt2 on COUNT(*) > 0"
,
TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION
,
PARSER_STAGE_TRANSLATE
);
...
...
source/libs/planner/src/planSpliter.c
浏览文件 @
e00a9fa9
...
...
@@ -248,6 +248,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode)
pSubplan
->
id
.
groupId
=
pCxt
->
groupId
;
pSubplan
->
subplanType
=
SUBPLAN_TYPE_SCAN
;
pSubplan
->
pNode
=
pNode
;
pNode
->
pParent
=
NULL
;
return
pSubplan
;
}
...
...
@@ -408,17 +409,30 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc
static
const
int32_t
splitRuleNum
=
(
sizeof
(
splitRuleSet
)
/
sizeof
(
SSplitRule
));
static
void
dumpLogicSubplan
(
const
char
*
pRuleName
,
SLogicSubplan
*
pSubplan
)
{
char
*
pStr
=
NULL
;
nodesNodeToString
(
pSubplan
,
false
,
&
pStr
,
NULL
);
qDebugL
(
"apply %s rule: %s"
,
pRuleName
,
pStr
);
taosMemoryFree
(
pStr
);
}
static
int32_t
applySplitRule
(
SLogicSubplan
*
pSubplan
)
{
SSplitContext
cxt
=
{.
queryId
=
pSubplan
->
id
.
queryId
,
.
groupId
=
pSubplan
->
id
.
groupId
+
1
,
.
split
=
false
};
bool
split
=
false
;
do
{
cxt
.
split
=
false
;
split
=
false
;
for
(
int32_t
i
=
0
;
i
<
splitRuleNum
;
++
i
)
{
cxt
.
split
=
false
;
int32_t
code
=
splitRuleSet
[
i
].
splitFunc
(
&
cxt
,
pSubplan
);
if
(
TSDB_CODE_SUCCESS
!=
code
)
{
return
code
;
}
if
(
cxt
.
split
)
{
split
=
true
;
dumpLogicSubplan
(
splitRuleSet
[
i
].
pName
,
pSubplan
);
}
}
}
while
(
cxt
.
split
);
}
while
(
split
);
return
TSDB_CODE_SUCCESS
;
}
...
...
source/libs/planner/test/planSetOpTest.cpp
浏览文件 @
e00a9fa9
...
...
@@ -23,7 +23,12 @@ class PlanSetOpTest : public PlannerTestBase {};
TEST_F
(
PlanSetOpTest
,
unionAll
)
{
useDb
(
"root"
,
"test"
);
// sql 1: single UNION ALL operator
run
(
"SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20"
);
// sql 2: multi UNION ALL operator
run
(
"SELECT c1, c2 FROM t1 WHERE c1 > 10 "
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 20 "
"UNION ALL SELECT c1, c2 FROM t1 WHERE c1 > 30"
);
}
TEST_F
(
PlanSetOpTest
,
unionAllSubquery
)
{
...
...
@@ -44,7 +49,12 @@ TEST_F(PlanSetOpTest, unionAllWithSubquery) {
TEST_F
(
PlanSetOpTest
,
union
)
{
useDb
(
"root"
,
"test"
);
// single UNION operator
run
(
"SELECT c1, c2 FROM t1 WHERE c1 > 10 UNION SELECT c1, c2 FROM t1 WHERE c1 > 20"
);
// multi UNION operator
run
(
"SELECT c1, c2 FROM t1 WHERE c1 > 10 "
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 20 "
"UNION SELECT c1, c2 FROM t1 WHERE c1 > 30"
);
}
TEST_F
(
PlanSetOpTest
,
unionContainJoin
)
{
...
...
@@ -62,3 +72,12 @@ TEST_F(PlanSetOpTest, unionSubquery) {
run
(
"SELECT * FROM (SELECT c1, c2 FROM t1 UNION SELECT c1, c2 FROM t1)"
);
}
TEST_F
(
PlanSetOpTest
,
bug001
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT c2 FROM t1 WHERE c1 IS NOT NULL GROUP BY c2 "
"UNION "
"SELECT 'abcdefghijklmnopqrstuvwxyz' FROM t1 "
"WHERE 'abcdefghijklmnopqrstuvwxyz' IS NOT NULL GROUP BY 'abcdefghijklmnopqrstuvwxyz'"
);
}
source/libs/planner/test/planSubqueryTest.cpp
浏览文件 @
e00a9fa9
...
...
@@ -23,9 +23,7 @@ class PlanSubqeuryTest : public PlannerTestBase {};
TEST_F
(
PlanSubqeuryTest
,
basic
)
{
useDb
(
"root"
,
"test"
);
if
(
0
==
g_skipSql
)
{
run
(
"SELECT * FROM (SELECT * FROM t1)"
);
}
run
(
"SELECT * FROM (SELECT * FROM t1)"
);
run
(
"SELECT LAST(c1) FROM (SELECT * FROM t1)"
);
}
...
...
source/libs/planner/test/planTestMain.cpp
浏览文件 @
e00a9fa9
...
...
@@ -35,18 +35,19 @@ class PlannerEnv : public testing::Environment {
private:
void
initLog
(
const
char
*
path
)
{
dDebugFlag
=
143
;
vDebugFlag
=
0
;
mDebugFlag
=
143
;
cDebugFlag
=
0
;
jniDebugFlag
=
0
;
tmrDebugFlag
=
135
;
uDebugFlag
=
135
;
rpcDebugFlag
=
143
;
qDebugFlag
=
143
;
wDebugFlag
=
0
;
sDebugFlag
=
0
;
tsdbDebugFlag
=
0
;
int32_t
logLevel
=
getLogLevel
();
dDebugFlag
=
logLevel
;
vDebugFlag
=
logLevel
;
mDebugFlag
=
logLevel
;
cDebugFlag
=
logLevel
;
jniDebugFlag
=
logLevel
;
tmrDebugFlag
=
logLevel
;
uDebugFlag
=
logLevel
;
rpcDebugFlag
=
logLevel
;
qDebugFlag
=
logLevel
;
wDebugFlag
=
logLevel
;
sDebugFlag
=
logLevel
;
tsdbDebugFlag
=
logLevel
;
tsLogEmbedded
=
1
;
tsAsyncLog
=
0
;
...
...
@@ -60,17 +61,26 @@ class PlannerEnv : public testing::Environment {
};
static
void
parseArg
(
int
argc
,
char
*
argv
[])
{
int
opt
=
0
;
const
char
*
optstring
=
""
;
int
opt
=
0
;
const
char
*
optstring
=
""
;
// clang-format off
static
struct
option
long_options
[]
=
{
{
"dump"
,
optional_argument
,
NULL
,
'd'
},
{
"skipSql"
,
optional_argument
,
NULL
,
's'
},
{
0
,
0
,
0
,
0
}};
{
"dump"
,
optional_argument
,
NULL
,
'd'
},
{
"skipSql"
,
required_argument
,
NULL
,
's'
},
{
"log"
,
required_argument
,
NULL
,
'l'
},
{
0
,
0
,
0
,
0
}
};
// clang-format on
while
((
opt
=
getopt_long
(
argc
,
argv
,
optstring
,
long_options
,
NULL
))
!=
-
1
)
{
switch
(
opt
)
{
case
'd'
:
setDumpModule
(
optarg
);
break
;
case
's'
:
g_skipSql
=
1
;
setSkipSqlNum
(
optarg
);
break
;
case
'l'
:
setLogLevel
(
optarg
);
break
;
default:
break
;
...
...
source/libs/planner/test/planTestUtil.cpp
浏览文件 @
e00a9fa9
...
...
@@ -48,6 +48,7 @@ enum DumpModule {
DumpModule
g_dumpModule
=
DUMP_MODULE_NOTHING
;
int32_t
g_skipSql
=
0
;
int32_t
g_logLevel
=
131
;
void
setDumpModule
(
const
char
*
pModule
)
{
if
(
NULL
==
pModule
)
{
...
...
@@ -71,14 +72,26 @@ void setDumpModule(const char* pModule) {
}
}
void
setSkipSqlNum
(
const
char
*
pNum
)
{
g_skipSql
=
stoi
(
optarg
);
}
void
setLogLevel
(
const
char
*
pLogLevel
)
{
g_logLevel
=
stoi
(
pLogLevel
);
}
int32_t
getLogLevel
()
{
return
g_logLevel
;
}
class
PlannerTestBaseImpl
{
public:
void
useDb
(
const
string
&
acctId
,
const
string
&
db
)
{
caseEnv_
.
acctId_
=
acctId
;
caseEnv_
.
db_
=
db
;
caseEnv_
.
nsql_
=
g_skipSql
;
}
void
run
(
const
string
&
sql
)
{
if
(
caseEnv_
.
nsql_
>
0
)
{
--
(
caseEnv_
.
nsql_
);
return
;
}
reset
();
try
{
SQuery
*
pQuery
=
nullptr
;
...
...
@@ -109,6 +122,10 @@ class PlannerTestBaseImpl {
}
void
prepare
(
const
string
&
sql
)
{
if
(
caseEnv_
.
nsql_
>
0
)
{
return
;
}
reset
();
try
{
doParseSql
(
sql
,
&
stmtEnv_
.
pQuery_
,
true
);
...
...
@@ -119,6 +136,10 @@ class PlannerTestBaseImpl {
}
void
bindParams
(
TAOS_MULTI_BIND
*
pParams
,
int32_t
colIdx
)
{
if
(
caseEnv_
.
nsql_
>
0
)
{
return
;
}
try
{
doBindParams
(
stmtEnv_
.
pQuery_
,
pParams
,
colIdx
);
}
catch
(...)
{
...
...
@@ -128,6 +149,11 @@ class PlannerTestBaseImpl {
}
void
exec
()
{
if
(
caseEnv_
.
nsql_
>
0
)
{
--
(
caseEnv_
.
nsql_
);
return
;
}
try
{
doParseBoundSql
(
stmtEnv_
.
pQuery_
);
...
...
@@ -157,8 +183,9 @@ class PlannerTestBaseImpl {
private:
struct
caseEnv
{
string
acctId_
;
string
db_
;
string
acctId_
;
string
db_
;
int32_t
nsql_
;
};
struct
stmtEnv
{
...
...
source/libs/planner/test/planTestUtil.h
浏览文件 @
e00a9fa9
...
...
@@ -37,8 +37,9 @@ class PlannerTestBase : public testing::Test {
std
::
unique_ptr
<
PlannerTestBaseImpl
>
impl_
;
};
extern
int32_t
g_skipSql
;
extern
void
setDumpModule
(
const
char
*
pModule
);
extern
void
setDumpModule
(
const
char
*
pModule
);
extern
void
setSkipSqlNum
(
const
char
*
pNum
);
extern
void
setLogLevel
(
const
char
*
pLogLevel
);
extern
int32_t
getLogLevel
();
#endif // PLAN_TEST_UTIL_H
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录