Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
taosdata
TDengine
提交
50ebcb50
T
TDengine
项目概览
taosdata
/
TDengine
大约 1 年 前同步成功
通知
1184
Star
22015
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看板
体验新版 GitCode,发现更多精彩内容 >>
提交
50ebcb50
编写于
9月 22, 2022
作者:
X
Xiaoyu Wang
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
feat: case when expression
上级
c577897c
变更
17
展开全部
隐藏空白更改
内联
并排
Showing
17 changed file
with
3053 addition
and
2532 deletion
+3053
-2532
include/common/ttokendef.h
include/common/ttokendef.h
+94
-90
include/libs/nodes/nodes.h
include/libs/nodes/nodes.h
+2
-0
include/libs/nodes/querynodes.h
include/libs/nodes/querynodes.h
+13
-0
source/libs/nodes/src/nodesCloneFuncs.c
source/libs/nodes/src/nodesCloneFuncs.c
+21
-0
source/libs/nodes/src/nodesCodeFuncs.c
source/libs/nodes/src/nodesCodeFuncs.c
+81
-0
source/libs/nodes/src/nodesEqualFuncs.c
source/libs/nodes/src/nodesEqualFuncs.c
+18
-1
source/libs/nodes/src/nodesMsgFuncs.c
source/libs/nodes/src/nodesMsgFuncs.c
+101
-2
source/libs/nodes/src/nodesTraverseFuncs.c
source/libs/nodes/src/nodesTraverseFuncs.c
+38
-0
source/libs/nodes/src/nodesUtilFuncs.c
source/libs/nodes/src/nodesUtilFuncs.c
+18
-0
source/libs/parser/inc/parAst.h
source/libs/parser/inc/parAst.h
+2
-0
source/libs/parser/inc/sql.y
source/libs/parser/inc/sql.y
+49
-27
source/libs/parser/src/parAstCreater.c
source/libs/parser/src/parAstCreater.c
+19
-0
source/libs/parser/src/parTokenizer.c
source/libs/parser/src/parTokenizer.c
+5
-0
source/libs/parser/src/parTranslater.c
source/libs/parser/src/parTranslater.c
+57
-21
source/libs/parser/src/sql.c
source/libs/parser/src/sql.c
+2523
-2391
source/libs/parser/test/parSelectTest.cpp
source/libs/parser/test/parSelectTest.cpp
+5
-0
source/libs/planner/test/planBasicTest.cpp
source/libs/planner/test/planBasicTest.cpp
+7
-0
未找到文件。
include/common/ttokendef.h
浏览文件 @
50ebcb50
...
...
@@ -234,96 +234,100 @@
#define TK_CURRENT_USER 216
#define TK_COUNT 217
#define TK_LAST_ROW 218
#define TK_BETWEEN 219
#define TK_IS 220
#define TK_NK_LT 221
#define TK_NK_GT 222
#define TK_NK_LE 223
#define TK_NK_GE 224
#define TK_NK_NE 225
#define TK_MATCH 226
#define TK_NMATCH 227
#define TK_CONTAINS 228
#define TK_IN 229
#define TK_JOIN 230
#define TK_INNER 231
#define TK_SELECT 232
#define TK_DISTINCT 233
#define TK_WHERE 234
#define TK_PARTITION 235
#define TK_BY 236
#define TK_SESSION 237
#define TK_STATE_WINDOW 238
#define TK_SLIDING 239
#define TK_FILL 240
#define TK_VALUE 241
#define TK_NONE 242
#define TK_PREV 243
#define TK_LINEAR 244
#define TK_NEXT 245
#define TK_HAVING 246
#define TK_RANGE 247
#define TK_EVERY 248
#define TK_ORDER 249
#define TK_SLIMIT 250
#define TK_SOFFSET 251
#define TK_LIMIT 252
#define TK_OFFSET 253
#define TK_ASC 254
#define TK_NULLS 255
#define TK_ABORT 256
#define TK_AFTER 257
#define TK_ATTACH 258
#define TK_BEFORE 259
#define TK_BEGIN 260
#define TK_BITAND 261
#define TK_BITNOT 262
#define TK_BITOR 263
#define TK_BLOCKS 264
#define TK_CHANGE 265
#define TK_COMMA 266
#define TK_COMPACT 267
#define TK_CONCAT 268
#define TK_CONFLICT 269
#define TK_COPY 270
#define TK_DEFERRED 271
#define TK_DELIMITERS 272
#define TK_DETACH 273
#define TK_DIVIDE 274
#define TK_DOT 275
#define TK_EACH 276
#define TK_END 277
#define TK_FAIL 278
#define TK_FILE 279
#define TK_FOR 280
#define TK_GLOB 281
#define TK_ID 282
#define TK_IMMEDIATE 283
#define TK_IMPORT 284
#define TK_INITIALLY 285
#define TK_INSTEAD 286
#define TK_ISNULL 287
#define TK_KEY 288
#define TK_NK_BITNOT 289
#define TK_NK_SEMI 290
#define TK_NOTNULL 291
#define TK_OF 292
#define TK_PLUS 293
#define TK_PRIVILEGE 294
#define TK_RAISE 295
#define TK_REPLACE 296
#define TK_RESTRICT 297
#define TK_ROW 298
#define TK_SEMI 299
#define TK_STAR 300
#define TK_STATEMENT 301
#define TK_STRING 302
#define TK_TIMES 303
#define TK_UPDATE 304
#define TK_VALUES 305
#define TK_VARIABLE 306
#define TK_VIEW 307
#define TK_WAL 308
#define TK_CASE 219
#define TK_END 220
#define TK_WHEN 221
#define TK_THEN 222
#define TK_ELSE 223
#define TK_BETWEEN 224
#define TK_IS 225
#define TK_NK_LT 226
#define TK_NK_GT 227
#define TK_NK_LE 228
#define TK_NK_GE 229
#define TK_NK_NE 230
#define TK_MATCH 231
#define TK_NMATCH 232
#define TK_CONTAINS 233
#define TK_IN 234
#define TK_JOIN 235
#define TK_INNER 236
#define TK_SELECT 237
#define TK_DISTINCT 238
#define TK_WHERE 239
#define TK_PARTITION 240
#define TK_BY 241
#define TK_SESSION 242
#define TK_STATE_WINDOW 243
#define TK_SLIDING 244
#define TK_FILL 245
#define TK_VALUE 246
#define TK_NONE 247
#define TK_PREV 248
#define TK_LINEAR 249
#define TK_NEXT 250
#define TK_HAVING 251
#define TK_RANGE 252
#define TK_EVERY 253
#define TK_ORDER 254
#define TK_SLIMIT 255
#define TK_SOFFSET 256
#define TK_LIMIT 257
#define TK_OFFSET 258
#define TK_ASC 259
#define TK_NULLS 260
#define TK_ABORT 261
#define TK_AFTER 262
#define TK_ATTACH 263
#define TK_BEFORE 264
#define TK_BEGIN 265
#define TK_BITAND 266
#define TK_BITNOT 267
#define TK_BITOR 268
#define TK_BLOCKS 269
#define TK_CHANGE 270
#define TK_COMMA 271
#define TK_COMPACT 272
#define TK_CONCAT 273
#define TK_CONFLICT 274
#define TK_COPY 275
#define TK_DEFERRED 276
#define TK_DELIMITERS 277
#define TK_DETACH 278
#define TK_DIVIDE 279
#define TK_DOT 280
#define TK_EACH 281
#define TK_FAIL 282
#define TK_FILE 283
#define TK_FOR 284
#define TK_GLOB 285
#define TK_ID 286
#define TK_IMMEDIATE 287
#define TK_IMPORT 288
#define TK_INITIALLY 289
#define TK_INSTEAD 290
#define TK_ISNULL 291
#define TK_KEY 292
#define TK_NK_BITNOT 293
#define TK_NK_SEMI 294
#define TK_NOTNULL 295
#define TK_OF 296
#define TK_PLUS 297
#define TK_PRIVILEGE 298
#define TK_RAISE 299
#define TK_REPLACE 300
#define TK_RESTRICT 301
#define TK_ROW 302
#define TK_SEMI 303
#define TK_STAR 304
#define TK_STATEMENT 305
#define TK_STRING 306
#define TK_TIMES 307
#define TK_UPDATE 308
#define TK_VALUES 309
#define TK_VARIABLE 310
#define TK_VIEW 311
#define TK_WAL 312
#define TK_NK_SPACE 300
#define TK_NK_COMMENT 301
...
...
include/libs/nodes/nodes.h
浏览文件 @
50ebcb50
...
...
@@ -103,6 +103,8 @@ typedef enum ENodeType {
QUERY_NODE_STREAM_OPTIONS
,
QUERY_NODE_LEFT_VALUE
,
QUERY_NODE_COLUMN_REF
,
QUERY_NODE_WHEN_THEN
,
QUERY_NODE_CASE_WHEN
,
// Statement nodes are used in parser and planner module.
QUERY_NODE_SET_OPERATOR
=
100
,
...
...
include/libs/nodes/querynodes.h
浏览文件 @
50ebcb50
...
...
@@ -241,6 +241,19 @@ typedef struct SFillNode {
STimeWindow
timeRange
;
}
SFillNode
;
typedef
struct
SWhenThenNode
{
SExprNode
node
;
// QUERY_NODE_WHEN_THEN
SNode
*
pWhen
;
SNode
*
pThen
;
}
SWhenThenNode
;
typedef
struct
SCaseWhenNode
{
SExprNode
node
;
// QUERY_NODE_CASE_WHEN
SNode
*
pCase
;
SNode
*
pElse
;
SNodeList
*
pWhenThenList
;
}
SCaseWhenNode
;
typedef
struct
SSelectStmt
{
ENodeType
type
;
// QUERY_NODE_SELECT_STMT
bool
isDistinct
;
...
...
source/libs/nodes/src/nodesCloneFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -324,6 +324,21 @@ static int32_t fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) {
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
whenThenNodeCopy
(
const
SWhenThenNode
*
pSrc
,
SWhenThenNode
*
pDst
)
{
COPY_BASE_OBJECT_FIELD
(
node
,
exprNodeCopy
);
CLONE_NODE_FIELD
(
pWhen
);
CLONE_NODE_FIELD
(
pThen
);
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
caseWhenNodeCopy
(
const
SCaseWhenNode
*
pSrc
,
SCaseWhenNode
*
pDst
)
{
COPY_BASE_OBJECT_FIELD
(
node
,
exprNodeCopy
);
CLONE_NODE_FIELD
(
pCase
);
CLONE_NODE_FIELD
(
pElse
);
CLONE_NODE_LIST_FIELD
(
pWhenThenList
);
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
logicNodeCopy
(
const
SLogicNode
*
pSrc
,
SLogicNode
*
pDst
)
{
CLONE_NODE_LIST_FIELD
(
pTargets
);
CLONE_NODE_FIELD
(
pConditions
);
...
...
@@ -711,6 +726,12 @@ SNode* nodesCloneNode(const SNode* pNode) {
case
QUERY_NODE_LEFT_VALUE
:
code
=
TSDB_CODE_SUCCESS
;
break
;
case
QUERY_NODE_WHEN_THEN
:
code
=
whenThenNodeCopy
((
const
SWhenThenNode
*
)
pNode
,
(
SWhenThenNode
*
)
pDst
);
break
;
case
QUERY_NODE_CASE_WHEN
:
code
=
caseWhenNodeCopy
((
const
SCaseWhenNode
*
)
pNode
,
(
SCaseWhenNode
*
)
pDst
);
break
;
case
QUERY_NODE_SELECT_STMT
:
code
=
selectStmtCopy
((
const
SSelectStmt
*
)
pNode
,
(
SSelectStmt
*
)
pDst
);
break
;
...
...
source/libs/nodes/src/nodesCodeFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -81,6 +81,10 @@ const char* nodesNodeName(ENodeType type) {
return
"IndexOptions"
;
case
QUERY_NODE_LEFT_VALUE
:
return
"LeftValue"
;
case
QUERY_NODE_WHEN_THEN
:
return
"WhenThen"
;
case
QUERY_NODE_CASE_WHEN
:
return
"CaseWhen"
;
case
QUERY_NODE_SET_OPERATOR
:
return
"SetOperator"
;
case
QUERY_NODE_SELECT_STMT
:
...
...
@@ -3903,6 +3907,75 @@ static int32_t jsonToDatabaseOptions(const SJson* pJson, void* pObj) {
return
code
;
}
static
const
char
*
jkWhenThenWhen
=
"When"
;
static
const
char
*
jkWhenThenThen
=
"Then"
;
static
int32_t
whenThenNodeToJson
(
const
void
*
pObj
,
SJson
*
pJson
)
{
const
SWhenThenNode
*
pNode
=
(
const
SWhenThenNode
*
)
pObj
;
int32_t
code
=
exprNodeToJson
(
pObj
,
pJson
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tjsonAddObject
(
pJson
,
jkWhenThenWhen
,
nodeToJson
,
pNode
->
pWhen
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tjsonAddObject
(
pJson
,
jkWhenThenThen
,
nodeToJson
,
pNode
->
pThen
);
}
return
code
;
}
static
int32_t
jsonToWhenThenNode
(
const
SJson
*
pJson
,
void
*
pObj
)
{
SWhenThenNode
*
pNode
=
(
SWhenThenNode
*
)
pObj
;
int32_t
code
=
jsonToExprNode
(
pJson
,
pObj
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
jsonToNodeObject
(
pJson
,
jkWhenThenWhen
,
&
pNode
->
pWhen
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
jsonToNodeObject
(
pJson
,
jkWhenThenThen
,
&
pNode
->
pThen
);
}
return
code
;
}
static
const
char
*
jkCaseWhenCase
=
"Case"
;
static
const
char
*
jkCaseWhenWhenThenList
=
"WhenThenList"
;
static
const
char
*
jkCaseWhenElse
=
"Else"
;
static
int32_t
caseWhenNodeToJson
(
const
void
*
pObj
,
SJson
*
pJson
)
{
const
SCaseWhenNode
*
pNode
=
(
const
SCaseWhenNode
*
)
pObj
;
int32_t
code
=
exprNodeToJson
(
pObj
,
pJson
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tjsonAddObject
(
pJson
,
jkCaseWhenCase
,
nodeToJson
,
pNode
->
pCase
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
nodeListToJson
(
pJson
,
jkCaseWhenWhenThenList
,
pNode
->
pWhenThenList
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tjsonAddObject
(
pJson
,
jkCaseWhenElse
,
nodeToJson
,
pNode
->
pElse
);
}
return
code
;
}
static
int32_t
jsonToCaseWhenNode
(
const
SJson
*
pJson
,
void
*
pObj
)
{
SCaseWhenNode
*
pNode
=
(
SCaseWhenNode
*
)
pObj
;
int32_t
code
=
jsonToExprNode
(
pJson
,
pObj
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
jsonToNodeObject
(
pJson
,
jkCaseWhenCase
,
&
pNode
->
pCase
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
jsonToNodeList
(
pJson
,
jkCaseWhenWhenThenList
,
&
pNode
->
pWhenThenList
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
jsonToNodeObject
(
pJson
,
jkCaseWhenElse
,
&
pNode
->
pElse
);
}
return
code
;
}
static
const
char
*
jkDataBlockDescDataBlockId
=
"DataBlockId"
;
static
const
char
*
jkDataBlockDescSlots
=
"Slots"
;
static
const
char
*
jkDataBlockTotalRowSize
=
"TotalRowSize"
;
...
...
@@ -4385,6 +4458,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return
databaseOptionsToJson
(
pObj
,
pJson
);
case
QUERY_NODE_LEFT_VALUE
:
return
TSDB_CODE_SUCCESS
;
// SLeftValueNode has no fields to serialize.
case
QUERY_NODE_WHEN_THEN
:
return
whenThenNodeToJson
(
pObj
,
pJson
);
case
QUERY_NODE_CASE_WHEN
:
return
caseWhenNodeToJson
(
pObj
,
pJson
);
case
QUERY_NODE_SET_OPERATOR
:
return
setOperatorToJson
(
pObj
,
pJson
);
case
QUERY_NODE_SELECT_STMT
:
...
...
@@ -4548,6 +4625,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return
jsonToDatabaseOptions
(
pJson
,
pObj
);
case
QUERY_NODE_LEFT_VALUE
:
return
TSDB_CODE_SUCCESS
;
// SLeftValueNode has no fields to deserialize.
case
QUERY_NODE_WHEN_THEN
:
return
jsonToWhenThenNode
(
pJson
,
pObj
);
case
QUERY_NODE_CASE_WHEN
:
return
jsonToCaseWhenNode
(
pJson
,
pObj
);
case
QUERY_NODE_SET_OPERATOR
:
return
jsonToSetOperator
(
pJson
,
pObj
);
case
QUERY_NODE_SELECT_STMT
:
...
...
source/libs/nodes/src/nodesEqualFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -140,6 +140,19 @@ static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
return
true
;
}
static
bool
whenThenNodeEqual
(
const
SWhenThenNode
*
a
,
const
SWhenThenNode
*
b
)
{
COMPARE_NODE_FIELD
(
pWhen
);
COMPARE_NODE_FIELD
(
pThen
);
return
true
;
}
static
bool
caseWhenNodeEqual
(
const
SCaseWhenNode
*
a
,
const
SCaseWhenNode
*
b
)
{
COMPARE_NODE_FIELD
(
pCase
);
COMPARE_NODE_FIELD
(
pElse
);
COMPARE_NODE_LIST_FIELD
(
pWhenThenList
);
return
true
;
}
bool
nodesEqualNode
(
const
SNode
*
a
,
const
SNode
*
b
)
{
if
(
a
==
b
)
{
return
true
;
...
...
@@ -164,13 +177,17 @@ bool nodesEqualNode(const SNode* a, const SNode* b) {
return
logicConditionNodeEqual
((
const
SLogicConditionNode
*
)
a
,
(
const
SLogicConditionNode
*
)
b
);
case
QUERY_NODE_FUNCTION
:
return
functionNodeEqual
((
const
SFunctionNode
*
)
a
,
(
const
SFunctionNode
*
)
b
);
case
QUERY_NODE_WHEN_THEN
:
return
whenThenNodeEqual
((
const
SWhenThenNode
*
)
a
,
(
const
SWhenThenNode
*
)
b
);
case
QUERY_NODE_CASE_WHEN
:
return
caseWhenNodeEqual
((
const
SCaseWhenNode
*
)
a
,
(
const
SCaseWhenNode
*
)
b
);
case
QUERY_NODE_REAL_TABLE
:
case
QUERY_NODE_TEMP_TABLE
:
case
QUERY_NODE_JOIN_TABLE
:
case
QUERY_NODE_GROUPING_SET
:
case
QUERY_NODE_ORDER_BY_EXPR
:
case
QUERY_NODE_LIMIT
:
return
false
;
// todo
return
false
;
default:
break
;
}
...
...
source/libs/nodes/src/nodesMsgFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -1733,6 +1733,92 @@ static int32_t msgToDownstreamSourceNode(STlvDecoder* pDecoder, void* pObj) {
return
code
;
}
enum
{
WHEN_THEN_CODE_EXPR_BASE
=
1
,
WHEN_THEN_CODE_WHEN
,
WHEN_THEN_CODE_THEN
};
static
int32_t
whenThenNodeToMsg
(
const
void
*
pObj
,
STlvEncoder
*
pEncoder
)
{
const
SWhenThenNode
*
pNode
=
(
const
SWhenThenNode
*
)
pObj
;
int32_t
code
=
tlvEncodeObj
(
pEncoder
,
WHEN_THEN_CODE_EXPR_BASE
,
exprNodeToMsg
,
pNode
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tlvEncodeObj
(
pEncoder
,
WHEN_THEN_CODE_WHEN
,
nodeToMsg
,
pNode
->
pWhen
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tlvEncodeObj
(
pEncoder
,
WHEN_THEN_CODE_THEN
,
nodeToMsg
,
pNode
->
pThen
);
}
return
code
;
}
static
int32_t
msgToWhenThenNode
(
STlvDecoder
*
pDecoder
,
void
*
pObj
)
{
SWhenThenNode
*
pNode
=
(
SWhenThenNode
*
)
pObj
;
int32_t
code
=
TSDB_CODE_SUCCESS
;
STlv
*
pTlv
=
NULL
;
tlvForEach
(
pDecoder
,
pTlv
,
code
)
{
switch
(
pTlv
->
type
)
{
case
WHEN_THEN_CODE_EXPR_BASE
:
code
=
tlvDecodeObjFromTlv
(
pTlv
,
msgToExprNode
,
&
pNode
->
node
);
break
;
case
WHEN_THEN_CODE_WHEN
:
code
=
msgToNodeFromTlv
(
pTlv
,
(
void
**
)
&
pNode
->
pWhen
);
break
;
case
WHEN_THEN_CODE_THEN
:
code
=
msgToNodeFromTlv
(
pTlv
,
(
void
**
)
&
pNode
->
pThen
);
break
;
default:
break
;
}
}
return
code
;
}
enum
{
CASE_WHEN_CODE_EXPR_BASE
=
1
,
CASE_WHEN_CODE_CASE
,
CASE_WHEN_CODE_ELSE
,
CASE_WHEN_CODE_WHEN_THEN_LIST
};
static
int32_t
caseWhenNodeToMsg
(
const
void
*
pObj
,
STlvEncoder
*
pEncoder
)
{
const
SCaseWhenNode
*
pNode
=
(
const
SCaseWhenNode
*
)
pObj
;
int32_t
code
=
tlvEncodeObj
(
pEncoder
,
CASE_WHEN_CODE_EXPR_BASE
,
exprNodeToMsg
,
pNode
);
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tlvEncodeObj
(
pEncoder
,
CASE_WHEN_CODE_CASE
,
nodeToMsg
,
pNode
->
pCase
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tlvEncodeObj
(
pEncoder
,
CASE_WHEN_CODE_ELSE
,
nodeToMsg
,
pNode
->
pElse
);
}
if
(
TSDB_CODE_SUCCESS
==
code
)
{
code
=
tlvEncodeObj
(
pEncoder
,
CASE_WHEN_CODE_WHEN_THEN_LIST
,
nodeListToMsg
,
pNode
->
pWhenThenList
);
}
return
code
;
}
static
int32_t
msgToCaseWhenNode
(
STlvDecoder
*
pDecoder
,
void
*
pObj
)
{
SCaseWhenNode
*
pNode
=
(
SCaseWhenNode
*
)
pObj
;
int32_t
code
=
TSDB_CODE_SUCCESS
;
STlv
*
pTlv
=
NULL
;
tlvForEach
(
pDecoder
,
pTlv
,
code
)
{
switch
(
pTlv
->
type
)
{
case
CASE_WHEN_CODE_EXPR_BASE
:
code
=
tlvDecodeObjFromTlv
(
pTlv
,
msgToExprNode
,
&
pNode
->
node
);
break
;
case
CASE_WHEN_CODE_CASE
:
code
=
msgToNodeFromTlv
(
pTlv
,
(
void
**
)
&
pNode
->
pCase
);
break
;
case
CASE_WHEN_CODE_ELSE
:
code
=
msgToNodeFromTlv
(
pTlv
,
(
void
**
)
&
pNode
->
pElse
);
break
;
case
CASE_WHEN_CODE_WHEN_THEN_LIST
:
code
=
msgToNodeListFromTlv
(
pTlv
,
(
void
**
)
&
pNode
->
pWhenThenList
);
break
;
default:
break
;
}
}
return
code
;
}
enum
{
PHY_NODE_CODE_OUTPUT_DESC
=
1
,
PHY_NODE_CODE_CONDITIONS
,
...
...
@@ -3434,9 +3520,16 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
code
=
slotDescNodeToMsg
(
pObj
,
pEncoder
);
break
;
case
QUERY_NODE_DOWNSTREAM_SOURCE
:
return
downstreamSourceNodeToMsg
(
pObj
,
pEncoder
);
code
=
downstreamSourceNodeToMsg
(
pObj
,
pEncoder
);
break
;
case
QUERY_NODE_LEFT_VALUE
:
break
;
case
QUERY_NODE_WHEN_THEN
:
code
=
whenThenNodeToMsg
(
pObj
,
pEncoder
);
break
;
case
QUERY_NODE_CASE_WHEN
:
code
=
caseWhenNodeToMsg
(
pObj
,
pEncoder
);
break
;
case
QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN
:
case
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN
:
code
=
physiScanNodeToMsg
(
pObj
,
pEncoder
);
...
...
@@ -3563,9 +3656,15 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) {
code
=
msgToSlotDescNode
(
pDecoder
,
pObj
);
break
;
case
QUERY_NODE_DOWNSTREAM_SOURCE
:
return
msgToDownstreamSourceNode
(
pDecoder
,
pObj
);
code
=
msgToDownstreamSourceNode
(
pDecoder
,
pObj
);
case
QUERY_NODE_LEFT_VALUE
:
break
;
case
QUERY_NODE_WHEN_THEN
:
code
=
msgToWhenThenNode
(
pDecoder
,
pObj
);
break
;
case
QUERY_NODE_CASE_WHEN
:
code
=
msgToCaseWhenNode
(
pDecoder
,
pObj
);
break
;
case
QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN
:
case
QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN
:
code
=
msgToPhysiScanNode
(
pDecoder
,
pObj
);
...
...
source/libs/nodes/src/nodesTraverseFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -146,6 +146,25 @@ static EDealRes dispatchExpr(SNode* pNode, ETraversalOrder order, FNodeWalker wa
case
QUERY_NODE_TARGET
:
res
=
walkExpr
(((
STargetNode
*
)
pNode
)
->
pExpr
,
order
,
walker
,
pContext
);
break
;
case
QUERY_NODE_WHEN_THEN
:
{
SWhenThenNode
*
pWhenThen
=
(
SWhenThenNode
*
)
pNode
;
res
=
walkExpr
(
pWhenThen
->
pWhen
,
order
,
walker
,
pContext
);
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
walkExpr
(
pWhenThen
->
pThen
,
order
,
walker
,
pContext
);
}
break
;
}
case
QUERY_NODE_CASE_WHEN
:
{
SCaseWhenNode
*
pCaseWhen
=
(
SCaseWhenNode
*
)
pNode
;
res
=
walkExpr
(
pCaseWhen
->
pCase
,
order
,
walker
,
pContext
);
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
walkExpr
(
pCaseWhen
->
pElse
,
order
,
walker
,
pContext
);
}
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
walkExprs
(
pCaseWhen
->
pWhenThenList
,
order
,
walker
,
pContext
);
}
break
;
}
default:
break
;
}
...
...
@@ -291,6 +310,25 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
case
QUERY_NODE_TARGET
:
res
=
rewriteExpr
(
&
(((
STargetNode
*
)
pNode
)
->
pExpr
),
order
,
rewriter
,
pContext
);
break
;
case
QUERY_NODE_WHEN_THEN
:
{
SWhenThenNode
*
pWhenThen
=
(
SWhenThenNode
*
)
pNode
;
res
=
rewriteExpr
(
&
pWhenThen
->
pWhen
,
order
,
rewriter
,
pContext
);
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
rewriteExpr
(
&
pWhenThen
->
pThen
,
order
,
rewriter
,
pContext
);
}
break
;
}
case
QUERY_NODE_CASE_WHEN
:
{
SCaseWhenNode
*
pCaseWhen
=
(
SCaseWhenNode
*
)
pNode
;
res
=
rewriteExpr
(
&
pCaseWhen
->
pCase
,
order
,
rewriter
,
pContext
);
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
rewriteExpr
(
&
pCaseWhen
->
pElse
,
order
,
rewriter
,
pContext
);
}
if
(
DEAL_RES_ERROR
!=
res
&&
DEAL_RES_END
!=
res
)
{
res
=
rewriteExprs
(
pCaseWhen
->
pWhenThenList
,
order
,
rewriter
,
pContext
);
}
break
;
}
default:
break
;
}
...
...
source/libs/nodes/src/nodesUtilFuncs.c
浏览文件 @
50ebcb50
...
...
@@ -291,6 +291,10 @@ SNode* nodesMakeNode(ENodeType type) {
return
makeNode
(
type
,
sizeof
(
SLeftValueNode
));
case
QUERY_NODE_COLUMN_REF
:
return
makeNode
(
type
,
sizeof
(
SColumnDefNode
));
case
QUERY_NODE_WHEN_THEN
:
return
makeNode
(
type
,
sizeof
(
SWhenThenNode
));
case
QUERY_NODE_CASE_WHEN
:
return
makeNode
(
type
,
sizeof
(
SCaseWhenNode
));
case
QUERY_NODE_SET_OPERATOR
:
return
makeNode
(
type
,
sizeof
(
SSetOperator
));
case
QUERY_NODE_SELECT_STMT
:
...
...
@@ -738,7 +742,21 @@ void nodesDestroyNode(SNode* pNode) {
break
;
}
case
QUERY_NODE_LEFT_VALUE
:
// no pointer field
case
QUERY_NODE_COLUMN_REF
:
// no pointer field
break
;
case
QUERY_NODE_WHEN_THEN
:
{
SWhenThenNode
*
pStmt
=
(
SWhenThenNode
*
)
pNode
;
nodesDestroyNode
(
pStmt
->
pWhen
);
nodesDestroyNode
(
pStmt
->
pThen
);
break
;
}
case
QUERY_NODE_CASE_WHEN
:
{
SCaseWhenNode
*
pStmt
=
(
SCaseWhenNode
*
)
pNode
;
nodesDestroyNode
(
pStmt
->
pCase
);
nodesDestroyNode
(
pStmt
->
pElse
);
nodesDestroyList
(
pStmt
->
pWhenThenList
);
break
;
}
case
QUERY_NODE_SET_OPERATOR
:
{
SSetOperator
*
pStmt
=
(
SSetOperator
*
)
pNode
;
nodesDestroyList
(
pStmt
->
pProjectionList
);
...
...
source/libs/parser/inc/parAst.h
浏览文件 @
50ebcb50
...
...
@@ -119,6 +119,8 @@ SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode
SNode
*
createFillNode
(
SAstCreateContext
*
pCxt
,
EFillMode
mode
,
SNode
*
pValues
);
SNode
*
createGroupingSetNode
(
SAstCreateContext
*
pCxt
,
SNode
*
pNode
);
SNode
*
createInterpTimeRange
(
SAstCreateContext
*
pCxt
,
SNode
*
pStart
,
SNode
*
pEnd
);
SNode
*
createWhenThenNode
(
SAstCreateContext
*
pCxt
,
SNode
*
pWhen
,
SNode
*
pThen
);
SNode
*
createCaseWhenNode
(
SAstCreateContext
*
pCxt
,
SNode
*
pCase
,
SNodeList
*
pWhenThenList
,
SNode
*
pElse
);
SNode
*
addWhereClause
(
SAstCreateContext
*
pCxt
,
SNode
*
pStmt
,
SNode
*
pWhere
);
SNode
*
addPartitionByClause
(
SAstCreateContext
*
pCxt
,
SNode
*
pStmt
,
SNodeList
*
pPartitionByList
);
...
...
source/libs/parser/inc/sql.y
浏览文件 @
50ebcb50
此差异已折叠。
点击以展开。
source/libs/parser/src/parAstCreater.c
浏览文件 @
50ebcb50
...
...
@@ -647,6 +647,25 @@ SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd
return
createBetweenAnd
(
pCxt
,
createPrimaryKeyCol
(
pCxt
,
NULL
),
pStart
,
pEnd
);
}
SNode
*
createWhenThenNode
(
SAstCreateContext
*
pCxt
,
SNode
*
pWhen
,
SNode
*
pThen
)
{
CHECK_PARSER_STATUS
(
pCxt
);
SWhenThenNode
*
pWhenThen
=
(
SWhenThenNode
*
)
nodesMakeNode
(
QUERY_NODE_WHEN_THEN
);
CHECK_OUT_OF_MEM
(
pWhenThen
);
pWhenThen
->
pWhen
=
pWhen
;
pWhenThen
->
pThen
=
pThen
;
return
(
SNode
*
)
pWhenThen
;
}
SNode
*
createCaseWhenNode
(
SAstCreateContext
*
pCxt
,
SNode
*
pCase
,
SNodeList
*
pWhenThenList
,
SNode
*
pElse
)
{
CHECK_PARSER_STATUS
(
pCxt
);
SCaseWhenNode
*
pCaseWhen
=
(
SCaseWhenNode
*
)
nodesMakeNode
(
QUERY_NODE_CASE_WHEN
);
CHECK_OUT_OF_MEM
(
pCaseWhen
);
pCaseWhen
->
pCase
=
pCase
;
pCaseWhen
->
pWhenThenList
=
pWhenThenList
;
pCaseWhen
->
pElse
=
pElse
;
return
(
SNode
*
)
pCaseWhen
;
}
SNode
*
setProjectionAlias
(
SAstCreateContext
*
pCxt
,
SNode
*
pNode
,
SToken
*
pAlias
)
{
CHECK_PARSER_STATUS
(
pCxt
);
trimEscape
(
pAlias
);
...
...
source/libs/parser/src/parTokenizer.c
浏览文件 @
50ebcb50
...
...
@@ -54,6 +54,7 @@ static SKeyword keywordTable[] = {
{
"CACHE"
,
TK_CACHE
},
{
"CACHEMODEL"
,
TK_CACHEMODEL
},
{
"CACHESIZE"
,
TK_CACHESIZE
},
{
"CASE"
,
TK_CASE
},
{
"CAST"
,
TK_CAST
},
{
"CLIENT_VERSION"
,
TK_CLIENT_VERSION
},
{
"CLUSTER"
,
TK_CLUSTER
},
...
...
@@ -82,7 +83,9 @@ static SKeyword keywordTable[] = {
{
"DOUBLE"
,
TK_DOUBLE
},
{
"DROP"
,
TK_DROP
},
{
"DURATION"
,
TK_DURATION
},
{
"ELSE"
,
TK_ELSE
},
{
"ENABLE"
,
TK_ENABLE
},
{
"END"
,
TK_END
},
{
"EXISTS"
,
TK_EXISTS
},
{
"EXPIRED"
,
TK_EXPIRED
},
{
"EXPLAIN"
,
TK_EXPLAIN
},
...
...
@@ -205,6 +208,7 @@ static SKeyword keywordTable[] = {
{
"TAG"
,
TK_TAG
},
{
"TAGS"
,
TK_TAGS
},
{
"TBNAME"
,
TK_TBNAME
},
{
"THEN"
,
TK_THEN
},
{
"TIMESTAMP"
,
TK_TIMESTAMP
},
{
"TIMEZONE"
,
TK_TIMEZONE
},
{
"TINYINT"
,
TK_TINYINT
},
...
...
@@ -240,6 +244,7 @@ static SKeyword keywordTable[] = {
{
"WAL_ROLL_PERIOD"
,
TK_WAL_ROLL_PERIOD
},
{
"WAL_SEGMENT_SIZE"
,
TK_WAL_SEGMENT_SIZE
},
{
"WATERMARK"
,
TK_WATERMARK
},
{
"WHEN"
,
TK_WHEN
},
{
"WHERE"
,
TK_WHERE
},
{
"WINDOW_CLOSE"
,
TK_WINDOW_CLOSE
},
{
"WITH"
,
TK_WITH
},
...
...
source/libs/parser/src/parTranslater.c
浏览文件 @
50ebcb50
...
...
@@ -1807,6 +1807,59 @@ static EDealRes translateLogicCond(STranslateContext* pCxt, SLogicConditionNode*
return
DEAL_RES_CONTINUE
;
}
static
int32_t
createCastFunc
(
STranslateContext
*
pCxt
,
SNode
*
pExpr
,
SDataType
dt
,
SNode
**
pCast
)
{
SFunctionNode
*
pFunc
=
(
SFunctionNode
*
)
nodesMakeNode
(
QUERY_NODE_FUNCTION
);
if
(
NULL
==
pFunc
)
{
return
TSDB_CODE_OUT_OF_MEMORY
;
}
strcpy
(
pFunc
->
functionName
,
"cast"
);
pFunc
->
node
.
resType
=
dt
;
if
(
TSDB_CODE_SUCCESS
!=
nodesListMakeAppend
(
&
pFunc
->
pParameterList
,
pExpr
))
{
nodesDestroyNode
((
SNode
*
)
pFunc
);
return
TSDB_CODE_OUT_OF_MEMORY
;
}
if
(
TSDB_CODE_SUCCESS
!=
getFuncInfo
(
pCxt
,
pFunc
))
{
nodesClearList
(
pFunc
->
pParameterList
);
pFunc
->
pParameterList
=
NULL
;
nodesDestroyNode
((
SNode
*
)
pFunc
);
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)
pExpr
)
->
aliasName
);
}
*
pCast
=
(
SNode
*
)
pFunc
;
return
TSDB_CODE_SUCCESS
;
}
static
EDealRes
translateWhenThen
(
STranslateContext
*
pCxt
,
SWhenThenNode
*
pWhenThen
)
{
pWhenThen
->
node
.
resType
=
((
SExprNode
*
)
pWhenThen
->
pThen
)
->
resType
;
return
DEAL_RES_CONTINUE
;
}
static
EDealRes
translateCaseWhen
(
STranslateContext
*
pCxt
,
SCaseWhenNode
*
pCaseWhen
)
{
bool
first
=
true
;
SNode
*
pNode
=
NULL
;
FOREACH
(
pNode
,
pCaseWhen
->
pWhenThenList
)
{
if
(
first
)
{
pCaseWhen
->
node
.
resType
=
((
SExprNode
*
)
pNode
)
->
resType
;
}
else
if
(
!
dataTypeEqual
(
&
pCaseWhen
->
node
.
resType
,
&
((
SExprNode
*
)
pNode
)
->
resType
))
{
SWhenThenNode
*
pWhenThen
=
(
SWhenThenNode
*
)
pNode
;
SNode
*
pCastFunc
=
NULL
;
if
(
TSDB_CODE_SUCCESS
!=
createCastFunc
(
pCxt
,
pWhenThen
->
pThen
,
pCaseWhen
->
node
.
resType
,
&
pCastFunc
))
{
return
generateSyntaxErrMsgExt
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
"CASE WHEN data type mismatch"
);
}
pWhenThen
->
pThen
=
pCastFunc
;
pWhenThen
->
node
.
resType
=
pCaseWhen
->
node
.
resType
;
}
}
if
(
NULL
!=
pCaseWhen
->
pElse
&&
!
dataTypeEqual
(
&
pCaseWhen
->
node
.
resType
,
&
((
SExprNode
*
)
pCaseWhen
->
pElse
)
->
resType
))
{
SNode
*
pCastFunc
=
NULL
;
if
(
TSDB_CODE_SUCCESS
!=
createCastFunc
(
pCxt
,
pCaseWhen
->
pElse
,
pCaseWhen
->
node
.
resType
,
&
pCastFunc
))
{
return
generateSyntaxErrMsgExt
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
"CASE WHEN data type mismatch"
);
}
pCaseWhen
->
pElse
=
pCastFunc
;
((
SExprNode
*
)
pCaseWhen
->
pElse
)
->
resType
=
pCaseWhen
->
node
.
resType
;
}
return
DEAL_RES_CONTINUE
;
}
static
EDealRes
doTranslateExpr
(
SNode
**
pNode
,
void
*
pContext
)
{
STranslateContext
*
pCxt
=
(
STranslateContext
*
)
pContext
;
switch
(
nodeType
(
*
pNode
))
{
...
...
@@ -1822,6 +1875,10 @@ static EDealRes doTranslateExpr(SNode** pNode, void* pContext) {
return
translateLogicCond
(
pCxt
,
(
SLogicConditionNode
*
)
*
pNode
);
case
QUERY_NODE_TEMP_TABLE
:
return
translateExprSubquery
(
pCxt
,
((
STempTableNode
*
)
*
pNode
)
->
pSubquery
);
case
QUERY_NODE_WHEN_THEN
:
return
translateWhenThen
(
pCxt
,
(
SWhenThenNode
*
)
*
pNode
);
case
QUERY_NODE_CASE_WHEN
:
return
translateCaseWhen
(
pCxt
,
(
SCaseWhenNode
*
)
*
pNode
);
default:
break
;
}
...
...
@@ -3208,27 +3265,6 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
return
(
SNode
*
)
pCol
;
}
static
int32_t
createCastFunc
(
STranslateContext
*
pCxt
,
SNode
*
pExpr
,
SDataType
dt
,
SNode
**
pCast
)
{
SFunctionNode
*
pFunc
=
(
SFunctionNode
*
)
nodesMakeNode
(
QUERY_NODE_FUNCTION
);
if
(
NULL
==
pFunc
)
{
return
TSDB_CODE_OUT_OF_MEMORY
;
}
strcpy
(
pFunc
->
functionName
,
"cast"
);
pFunc
->
node
.
resType
=
dt
;
if
(
TSDB_CODE_SUCCESS
!=
nodesListMakeAppend
(
&
pFunc
->
pParameterList
,
pExpr
))
{
nodesDestroyNode
((
SNode
*
)
pFunc
);
return
TSDB_CODE_OUT_OF_MEMORY
;
}
if
(
TSDB_CODE_SUCCESS
!=
getFuncInfo
(
pCxt
,
pFunc
))
{
nodesClearList
(
pFunc
->
pParameterList
);
pFunc
->
pParameterList
=
NULL
;
nodesDestroyNode
((
SNode
*
)
pFunc
);
return
generateSyntaxErrMsg
(
&
pCxt
->
msgBuf
,
TSDB_CODE_PAR_WRONG_VALUE_TYPE
,
((
SExprNode
*
)
pExpr
)
->
aliasName
);
}
*
pCast
=
(
SNode
*
)
pFunc
;
return
TSDB_CODE_SUCCESS
;
}
static
int32_t
translateSetOperProject
(
STranslateContext
*
pCxt
,
SSetOperator
*
pSetOperator
)
{
SNodeList
*
pLeftProjections
=
getProjectList
(
pSetOperator
->
pLeft
);
SNodeList
*
pRightProjections
=
getProjectList
(
pSetOperator
->
pRight
);
...
...
source/libs/parser/src/sql.c
浏览文件 @
50ebcb50
此差异已折叠。
点击以展开。
source/libs/parser/test/parSelectTest.cpp
浏览文件 @
50ebcb50
...
...
@@ -60,6 +60,9 @@ TEST_F(ParserSelectTest, expression) {
run
(
"SELECT ts > 0, c1 between 10 and 20 and c2 = 'qaz' FROM t1"
);
run
(
"SELECT c1 | 10, c2 & 20, c4 | c5 FROM t1"
);
run
(
"SELECT CASE WHEN ts > '2020-1-1 10:10:10' THEN c1 + 10 ELSE c1 - 10 END FROM t1 "
"WHERE CASE c1 WHEN c3 + 20 THEN c3 - 1 WHEN c3 + 10 THEN c3 - 2 ELSE 10 END > 0"
);
}
TEST_F
(
ParserSelectTest
,
condition
)
{
...
...
@@ -312,6 +315,8 @@ TEST_F(ParserSelectTest, subquery) {
run
(
"SELECT _C0 FROM (SELECT _ROWTS, ts FROM st1s1)"
);
run
(
"SELECT ts FROM (SELECT t1.ts FROM st1s1 t1)"
);
run
(
"(((SELECT t1.ts FROM st1s1 t1)))"
);
}
TEST_F
(
ParserSelectTest
,
subquerySemanticCheck
)
{
...
...
source/libs/planner/test/planBasicTest.cpp
浏览文件 @
50ebcb50
...
...
@@ -40,6 +40,13 @@ TEST_F(PlanBasicTest, whereClause) {
run
(
"SELECT ts, c1 FROM t1 WHERE ts > NOW AND ts IS NULL AND (c1 > 0 OR c3 < 20)"
);
}
TEST_F
(
PlanBasicTest
,
caseWhen
)
{
useDb
(
"root"
,
"test"
);
run
(
"SELECT CASE WHEN ts > '2020-1-1 10:10:10' THEN c1 + 10 ELSE c1 - 10 END FROM t1 "
"WHERE CASE c1 WHEN c2 + 20 THEN c4 - 1 WHEN c2 + 10 THEN c4 - 2 ELSE 10 END > 0"
);
}
TEST_F
(
PlanBasicTest
,
func
)
{
useDb
(
"root"
,
"test"
);
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录