feat: case when expression

This commit is contained in:
Xiaoyu Wang 2022-09-22 19:20:21 +08:00
parent c577897c1f
commit 50ebcb5006
17 changed files with 3043 additions and 2522 deletions

View File

@ -234,96 +234,100 @@
#define TK_CURRENT_USER 216 #define TK_CURRENT_USER 216
#define TK_COUNT 217 #define TK_COUNT 217
#define TK_LAST_ROW 218 #define TK_LAST_ROW 218
#define TK_BETWEEN 219 #define TK_CASE 219
#define TK_IS 220 #define TK_END 220
#define TK_NK_LT 221 #define TK_WHEN 221
#define TK_NK_GT 222 #define TK_THEN 222
#define TK_NK_LE 223 #define TK_ELSE 223
#define TK_NK_GE 224 #define TK_BETWEEN 224
#define TK_NK_NE 225 #define TK_IS 225
#define TK_MATCH 226 #define TK_NK_LT 226
#define TK_NMATCH 227 #define TK_NK_GT 227
#define TK_CONTAINS 228 #define TK_NK_LE 228
#define TK_IN 229 #define TK_NK_GE 229
#define TK_JOIN 230 #define TK_NK_NE 230
#define TK_INNER 231 #define TK_MATCH 231
#define TK_SELECT 232 #define TK_NMATCH 232
#define TK_DISTINCT 233 #define TK_CONTAINS 233
#define TK_WHERE 234 #define TK_IN 234
#define TK_PARTITION 235 #define TK_JOIN 235
#define TK_BY 236 #define TK_INNER 236
#define TK_SESSION 237 #define TK_SELECT 237
#define TK_STATE_WINDOW 238 #define TK_DISTINCT 238
#define TK_SLIDING 239 #define TK_WHERE 239
#define TK_FILL 240 #define TK_PARTITION 240
#define TK_VALUE 241 #define TK_BY 241
#define TK_NONE 242 #define TK_SESSION 242
#define TK_PREV 243 #define TK_STATE_WINDOW 243
#define TK_LINEAR 244 #define TK_SLIDING 244
#define TK_NEXT 245 #define TK_FILL 245
#define TK_HAVING 246 #define TK_VALUE 246
#define TK_RANGE 247 #define TK_NONE 247
#define TK_EVERY 248 #define TK_PREV 248
#define TK_ORDER 249 #define TK_LINEAR 249
#define TK_SLIMIT 250 #define TK_NEXT 250
#define TK_SOFFSET 251 #define TK_HAVING 251
#define TK_LIMIT 252 #define TK_RANGE 252
#define TK_OFFSET 253 #define TK_EVERY 253
#define TK_ASC 254 #define TK_ORDER 254
#define TK_NULLS 255 #define TK_SLIMIT 255
#define TK_ABORT 256 #define TK_SOFFSET 256
#define TK_AFTER 257 #define TK_LIMIT 257
#define TK_ATTACH 258 #define TK_OFFSET 258
#define TK_BEFORE 259 #define TK_ASC 259
#define TK_BEGIN 260 #define TK_NULLS 260
#define TK_BITAND 261 #define TK_ABORT 261
#define TK_BITNOT 262 #define TK_AFTER 262
#define TK_BITOR 263 #define TK_ATTACH 263
#define TK_BLOCKS 264 #define TK_BEFORE 264
#define TK_CHANGE 265 #define TK_BEGIN 265
#define TK_COMMA 266 #define TK_BITAND 266
#define TK_COMPACT 267 #define TK_BITNOT 267
#define TK_CONCAT 268 #define TK_BITOR 268
#define TK_CONFLICT 269 #define TK_BLOCKS 269
#define TK_COPY 270 #define TK_CHANGE 270
#define TK_DEFERRED 271 #define TK_COMMA 271
#define TK_DELIMITERS 272 #define TK_COMPACT 272
#define TK_DETACH 273 #define TK_CONCAT 273
#define TK_DIVIDE 274 #define TK_CONFLICT 274
#define TK_DOT 275 #define TK_COPY 275
#define TK_EACH 276 #define TK_DEFERRED 276
#define TK_END 277 #define TK_DELIMITERS 277
#define TK_FAIL 278 #define TK_DETACH 278
#define TK_FILE 279 #define TK_DIVIDE 279
#define TK_FOR 280 #define TK_DOT 280
#define TK_GLOB 281 #define TK_EACH 281
#define TK_ID 282 #define TK_FAIL 282
#define TK_IMMEDIATE 283 #define TK_FILE 283
#define TK_IMPORT 284 #define TK_FOR 284
#define TK_INITIALLY 285 #define TK_GLOB 285
#define TK_INSTEAD 286 #define TK_ID 286
#define TK_ISNULL 287 #define TK_IMMEDIATE 287
#define TK_KEY 288 #define TK_IMPORT 288
#define TK_NK_BITNOT 289 #define TK_INITIALLY 289
#define TK_NK_SEMI 290 #define TK_INSTEAD 290
#define TK_NOTNULL 291 #define TK_ISNULL 291
#define TK_OF 292 #define TK_KEY 292
#define TK_PLUS 293 #define TK_NK_BITNOT 293
#define TK_PRIVILEGE 294 #define TK_NK_SEMI 294
#define TK_RAISE 295 #define TK_NOTNULL 295
#define TK_REPLACE 296 #define TK_OF 296
#define TK_RESTRICT 297 #define TK_PLUS 297
#define TK_ROW 298 #define TK_PRIVILEGE 298
#define TK_SEMI 299 #define TK_RAISE 299
#define TK_STAR 300 #define TK_REPLACE 300
#define TK_STATEMENT 301 #define TK_RESTRICT 301
#define TK_STRING 302 #define TK_ROW 302
#define TK_TIMES 303 #define TK_SEMI 303
#define TK_UPDATE 304 #define TK_STAR 304
#define TK_VALUES 305 #define TK_STATEMENT 305
#define TK_VARIABLE 306 #define TK_STRING 306
#define TK_VIEW 307 #define TK_TIMES 307
#define TK_WAL 308 #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_SPACE 300
#define TK_NK_COMMENT 301 #define TK_NK_COMMENT 301

View File

@ -103,6 +103,8 @@ typedef enum ENodeType {
QUERY_NODE_STREAM_OPTIONS, QUERY_NODE_STREAM_OPTIONS,
QUERY_NODE_LEFT_VALUE, QUERY_NODE_LEFT_VALUE,
QUERY_NODE_COLUMN_REF, QUERY_NODE_COLUMN_REF,
QUERY_NODE_WHEN_THEN,
QUERY_NODE_CASE_WHEN,
// Statement nodes are used in parser and planner module. // Statement nodes are used in parser and planner module.
QUERY_NODE_SET_OPERATOR = 100, QUERY_NODE_SET_OPERATOR = 100,

View File

@ -241,6 +241,19 @@ typedef struct SFillNode {
STimeWindow timeRange; STimeWindow timeRange;
} SFillNode; } 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 { typedef struct SSelectStmt {
ENodeType type; // QUERY_NODE_SELECT_STMT ENodeType type; // QUERY_NODE_SELECT_STMT
bool isDistinct; bool isDistinct;

View File

@ -324,6 +324,21 @@ static int32_t fillNodeCopy(const SFillNode* pSrc, SFillNode* pDst) {
return TSDB_CODE_SUCCESS; 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) { static int32_t logicNodeCopy(const SLogicNode* pSrc, SLogicNode* pDst) {
CLONE_NODE_LIST_FIELD(pTargets); CLONE_NODE_LIST_FIELD(pTargets);
CLONE_NODE_FIELD(pConditions); CLONE_NODE_FIELD(pConditions);
@ -711,6 +726,12 @@ SNode* nodesCloneNode(const SNode* pNode) {
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
code = TSDB_CODE_SUCCESS; code = TSDB_CODE_SUCCESS;
break; 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: case QUERY_NODE_SELECT_STMT:
code = selectStmtCopy((const SSelectStmt*)pNode, (SSelectStmt*)pDst); code = selectStmtCopy((const SSelectStmt*)pNode, (SSelectStmt*)pDst);
break; break;

View File

@ -81,6 +81,10 @@ const char* nodesNodeName(ENodeType type) {
return "IndexOptions"; return "IndexOptions";
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
return "LeftValue"; return "LeftValue";
case QUERY_NODE_WHEN_THEN:
return "WhenThen";
case QUERY_NODE_CASE_WHEN:
return "CaseWhen";
case QUERY_NODE_SET_OPERATOR: case QUERY_NODE_SET_OPERATOR:
return "SetOperator"; return "SetOperator";
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -3903,6 +3907,75 @@ static int32_t jsonToDatabaseOptions(const SJson* pJson, void* pObj) {
return code; 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* jkDataBlockDescDataBlockId = "DataBlockId";
static const char* jkDataBlockDescSlots = "Slots"; static const char* jkDataBlockDescSlots = "Slots";
static const char* jkDataBlockTotalRowSize = "TotalRowSize"; static const char* jkDataBlockTotalRowSize = "TotalRowSize";
@ -4385,6 +4458,10 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) {
return databaseOptionsToJson(pObj, pJson); return databaseOptionsToJson(pObj, pJson);
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to serialize. 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: case QUERY_NODE_SET_OPERATOR:
return setOperatorToJson(pObj, pJson); return setOperatorToJson(pObj, pJson);
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -4548,6 +4625,10 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) {
return jsonToDatabaseOptions(pJson, pObj); return jsonToDatabaseOptions(pJson, pObj);
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
return TSDB_CODE_SUCCESS; // SLeftValueNode has no fields to deserialize. 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: case QUERY_NODE_SET_OPERATOR:
return jsonToSetOperator(pJson, pObj); return jsonToSetOperator(pJson, pObj);
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:

View File

@ -140,6 +140,19 @@ static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
return true; 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) { bool nodesEqualNode(const SNode* a, const SNode* b) {
if (a == b) { if (a == b) {
return true; return true;
@ -164,13 +177,17 @@ bool nodesEqualNode(const SNode* a, const SNode* b) {
return logicConditionNodeEqual((const SLogicConditionNode*)a, (const SLogicConditionNode*)b); return logicConditionNodeEqual((const SLogicConditionNode*)a, (const SLogicConditionNode*)b);
case QUERY_NODE_FUNCTION: case QUERY_NODE_FUNCTION:
return functionNodeEqual((const SFunctionNode*)a, (const SFunctionNode*)b); 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_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE: case QUERY_NODE_TEMP_TABLE:
case QUERY_NODE_JOIN_TABLE: case QUERY_NODE_JOIN_TABLE:
case QUERY_NODE_GROUPING_SET: case QUERY_NODE_GROUPING_SET:
case QUERY_NODE_ORDER_BY_EXPR: case QUERY_NODE_ORDER_BY_EXPR:
case QUERY_NODE_LIMIT: case QUERY_NODE_LIMIT:
return false; // todo return false;
default: default:
break; break;
} }

View File

@ -1733,6 +1733,92 @@ static int32_t msgToDownstreamSourceNode(STlvDecoder* pDecoder, void* pObj) {
return code; 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 { enum {
PHY_NODE_CODE_OUTPUT_DESC = 1, PHY_NODE_CODE_OUTPUT_DESC = 1,
PHY_NODE_CODE_CONDITIONS, PHY_NODE_CODE_CONDITIONS,
@ -3434,9 +3520,16 @@ static int32_t specificNodeToMsg(const void* pObj, STlvEncoder* pEncoder) {
code = slotDescNodeToMsg(pObj, pEncoder); code = slotDescNodeToMsg(pObj, pEncoder);
break; break;
case QUERY_NODE_DOWNSTREAM_SOURCE: case QUERY_NODE_DOWNSTREAM_SOURCE:
return downstreamSourceNodeToMsg(pObj, pEncoder); code = downstreamSourceNodeToMsg(pObj, pEncoder);
break;
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
break; 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_TAG_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
code = physiScanNodeToMsg(pObj, pEncoder); code = physiScanNodeToMsg(pObj, pEncoder);
@ -3563,9 +3656,15 @@ static int32_t msgToSpecificNode(STlvDecoder* pDecoder, void* pObj) {
code = msgToSlotDescNode(pDecoder, pObj); code = msgToSlotDescNode(pDecoder, pObj);
break; break;
case QUERY_NODE_DOWNSTREAM_SOURCE: case QUERY_NODE_DOWNSTREAM_SOURCE:
return msgToDownstreamSourceNode(pDecoder, pObj); code = msgToDownstreamSourceNode(pDecoder, pObj);
case QUERY_NODE_LEFT_VALUE: case QUERY_NODE_LEFT_VALUE:
break; 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_TAG_SCAN:
case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN: case QUERY_NODE_PHYSICAL_PLAN_BLOCK_DIST_SCAN:
code = msgToPhysiScanNode(pDecoder, pObj); code = msgToPhysiScanNode(pDecoder, pObj);

View File

@ -146,6 +146,25 @@ static EDealRes dispatchExpr(SNode* pNode, ETraversalOrder order, FNodeWalker wa
case QUERY_NODE_TARGET: case QUERY_NODE_TARGET:
res = walkExpr(((STargetNode*)pNode)->pExpr, order, walker, pContext); res = walkExpr(((STargetNode*)pNode)->pExpr, order, walker, pContext);
break; 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: default:
break; break;
} }
@ -291,6 +310,25 @@ static EDealRes rewriteExpr(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
case QUERY_NODE_TARGET: case QUERY_NODE_TARGET:
res = rewriteExpr(&(((STargetNode*)pNode)->pExpr), order, rewriter, pContext); res = rewriteExpr(&(((STargetNode*)pNode)->pExpr), order, rewriter, pContext);
break; 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: default:
break; break;
} }

View File

@ -291,6 +291,10 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SLeftValueNode)); return makeNode(type, sizeof(SLeftValueNode));
case QUERY_NODE_COLUMN_REF: case QUERY_NODE_COLUMN_REF:
return makeNode(type, sizeof(SColumnDefNode)); 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: case QUERY_NODE_SET_OPERATOR:
return makeNode(type, sizeof(SSetOperator)); return makeNode(type, sizeof(SSetOperator));
case QUERY_NODE_SELECT_STMT: case QUERY_NODE_SELECT_STMT:
@ -738,7 +742,21 @@ void nodesDestroyNode(SNode* pNode) {
break; break;
} }
case QUERY_NODE_LEFT_VALUE: // no pointer field case QUERY_NODE_LEFT_VALUE: // no pointer field
case QUERY_NODE_COLUMN_REF: // no pointer field
break; 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: { case QUERY_NODE_SET_OPERATOR: {
SSetOperator* pStmt = (SSetOperator*)pNode; SSetOperator* pStmt = (SSetOperator*)pNode;
nodesDestroyList(pStmt->pProjectionList); nodesDestroyList(pStmt->pProjectionList);

View File

@ -119,6 +119,8 @@ SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode
SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues); SNode* createFillNode(SAstCreateContext* pCxt, EFillMode mode, SNode* pValues);
SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode); SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode);
SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd); 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* addWhereClause(SAstCreateContext* pCxt, SNode* pStmt, SNode* pWhere);
SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList); SNode* addPartitionByClause(SAstCreateContext* pCxt, SNode* pStmt, SNodeList* pPartitionByList);

View File

@ -625,42 +625,44 @@ stream_name(A) ::= NK_ID(B).
cgroup_name(A) ::= NK_ID(B). { A = B; } cgroup_name(A) ::= NK_ID(B). { A = B; }
/************************************************ expression **********************************************************/ /************************************************ expression **********************************************************/
expr_or_subquery(A) ::= expression(B). { A = B; }
expr_or_subquery(A) ::= subquery(B). { A = B; }
expression(A) ::= literal(B). { A = B; } expression(A) ::= literal(B). { A = B; }
expression(A) ::= pseudo_column(B). { A = B; } expression(A) ::= pseudo_column(B). { A = B; }
expression(A) ::= column_reference(B). { A = B; } expression(A) ::= column_reference(B). { A = B; }
expression(A) ::= function_expression(B). { A = B; } expression(A) ::= function_expression(B). { A = B; }
//expression(A) ::= case_expression(B). { A = B; } expression(A) ::= case_when_expression(B). { A = B; }
expression(A) ::= subquery(B). { A = B; }
expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); } expression(A) ::= NK_LP(B) expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); }
expression(A) ::= NK_PLUS(B) expression(C). { expression(A) ::= NK_PLUS(B) expr_or_subquery(C). {
SToken t = getTokenFromRawExprNode(pCxt, C); SToken t = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &B, &t, releaseRawExprNode(pCxt, C)); A = createRawExprNodeExt(pCxt, &B, &t, releaseRawExprNode(pCxt, C));
} }
expression(A) ::= NK_MINUS(B) expression(C). { expression(A) ::= NK_MINUS(B) expr_or_subquery(C). {
SToken t = getTokenFromRawExprNode(pCxt, C); SToken t = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &B, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, C), NULL)); A = createRawExprNodeExt(pCxt, &B, &t, createOperatorNode(pCxt, OP_TYPE_MINUS, releaseRawExprNode(pCxt, C), NULL));
} }
expression(A) ::= expression(B) NK_PLUS expression(C). { expression(A) ::= expr_or_subquery(B) NK_PLUS expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_ADD, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
} }
expression(A) ::= expression(B) NK_MINUS expression(C). { expression(A) ::= expr_or_subquery(B) NK_MINUS expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_SUB, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
} }
expression(A) ::= expression(B) NK_STAR expression(C). { expression(A) ::= expr_or_subquery(B) NK_STAR expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_MULTI, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
} }
expression(A) ::= expression(B) NK_SLASH expression(C). { expression(A) ::= expr_or_subquery(B) NK_SLASH expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_DIV, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
} }
expression(A) ::= expression(B) NK_REM expression(C). { expression(A) ::= expr_or_subquery(B) NK_REM expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_REM, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
@ -669,12 +671,12 @@ expression(A) ::= column_reference(B) NK_ARROW NK_STRING(C).
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, B), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &C))); A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_JSON_GET_VALUE, releaseRawExprNode(pCxt, B), createValueNode(pCxt, TSDB_DATA_TYPE_BINARY, &C)));
} }
expression(A) ::= expression(B) NK_BITAND expression(C). { expression(A) ::= expr_or_subquery(B) NK_BITAND expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_AND, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
} }
expression(A) ::= expression(B) NK_BITOR expression(C). { expression(A) ::= expr_or_subquery(B) NK_BITOR expr_or_subquery(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, C); SToken e = getTokenFromRawExprNode(pCxt, C);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, OP_TYPE_BIT_OR, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)));
@ -682,8 +684,8 @@ expression(A) ::= expression(B) NK_BITOR expression(C).
%type expression_list { SNodeList* } %type expression_list { SNodeList* }
%destructor expression_list { nodesDestroyList($$); } %destructor expression_list { nodesDestroyList($$); }
expression_list(A) ::= expression(B). { A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); } expression_list(A) ::= expr_or_subquery(B). { A = createNodeList(pCxt, releaseRawExprNode(pCxt, B)); }
expression_list(A) ::= expression_list(B) NK_COMMA expression(C). { A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); } expression_list(A) ::= expression_list(B) NK_COMMA expr_or_subquery(C). { A = addNodeToList(pCxt, B, releaseRawExprNode(pCxt, C)); }
column_reference(A) ::= column_name(B). { A = createRawExprNode(pCxt, &B, createColumnNode(pCxt, NULL, &B)); } column_reference(A) ::= column_name(B). { A = createRawExprNode(pCxt, &B, createColumnNode(pCxt, NULL, &B)); }
column_reference(A) ::= table_name(B) NK_DOT column_name(C). { A = createRawExprNodeExt(pCxt, &B, &C, createColumnNode(pCxt, &B, &C)); } column_reference(A) ::= table_name(B) NK_DOT column_name(C). { A = createRawExprNodeExt(pCxt, &B, &C, createColumnNode(pCxt, &B, &C)); }
@ -700,7 +702,8 @@ pseudo_column(A) ::= WDURATION(B).
function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); } function_expression(A) ::= function_name(B) NK_LP expression_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
function_expression(A) ::= star_func(B) NK_LP star_func_para_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); } function_expression(A) ::= star_func(B) NK_LP star_func_para_list(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, createFunctionNode(pCxt, &B, C)); }
function_expression(A) ::= CAST(B) NK_LP expression(C) AS type_name(D) NK_RP(E). { A = createRawExprNodeExt(pCxt, &B, &E, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, C), D)); } function_expression(A) ::=
CAST(B) NK_LP expr_or_subquery(C) AS type_name(D) NK_RP(E). { A = createRawExprNodeExt(pCxt, &B, &E, createCastFunctionNode(pCxt, releaseRawExprNode(pCxt, C), D)); }
function_expression(A) ::= literal_func(B). { A = B; } function_expression(A) ::= literal_func(B). { A = B; }
literal_func(A) ::= noarg_func(B) NK_LP NK_RP(C). { A = createRawExprNodeExt(pCxt, &B, &C, createFunctionNode(pCxt, &B, NULL)); } literal_func(A) ::= noarg_func(B) NK_LP NK_RP(C). { A = createRawExprNodeExt(pCxt, &B, &C, createFunctionNode(pCxt, &B, NULL)); }
@ -735,35 +738,52 @@ star_func_para_list(A) ::= other_para_list(B).
other_para_list(A) ::= star_func_para(B). { A = createNodeList(pCxt, B); } other_para_list(A) ::= star_func_para(B). { A = createNodeList(pCxt, B); }
other_para_list(A) ::= other_para_list(B) NK_COMMA star_func_para(C). { A = addNodeToList(pCxt, B, C); } other_para_list(A) ::= other_para_list(B) NK_COMMA star_func_para(C). { A = addNodeToList(pCxt, B, C); }
star_func_para(A) ::= expression(B). { A = releaseRawExprNode(pCxt, B); } star_func_para(A) ::= expr_or_subquery(B). { A = releaseRawExprNode(pCxt, B); }
star_func_para(A) ::= table_name(B) NK_DOT NK_STAR(C). { A = createColumnNode(pCxt, &B, &C); } star_func_para(A) ::= table_name(B) NK_DOT NK_STAR(C). { A = createColumnNode(pCxt, &B, &C); }
case_when_expression(A) ::=
CASE(E) when_then_list(C) case_when_else_opt(D) END(F). { A = createRawExprNodeExt(pCxt, &E, &F, createCaseWhenNode(pCxt, NULL, C, D)); }
case_when_expression(A) ::=
CASE(E) common_expression(B) when_then_list(C) case_when_else_opt(D) END(F). { A = createRawExprNodeExt(pCxt, &E, &F, createCaseWhenNode(pCxt, releaseRawExprNode(pCxt, B), C, D)); }
%type when_then_list { SNodeList* }
%destructor when_then_list { nodesDestroyList($$); }
when_then_list(A) ::= when_then_expr(B). { A = createNodeList(pCxt, B); }
when_then_list(A) ::= when_then_list(B) when_then_expr(C). { A = addNodeToList(pCxt, B, C); }
when_then_expr(A) ::= WHEN common_expression(B) THEN common_expression(C). { A = createWhenThenNode(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); }
case_when_else_opt(A) ::= . { A = NULL; }
case_when_else_opt(A) ::= ELSE common_expression(B). { A = releaseRawExprNode(pCxt, B); }
/************************************************ predicate ***********************************************************/ /************************************************ predicate ***********************************************************/
predicate(A) ::= expression(B) compare_op(C) expression(D). { predicate(A) ::= expr_or_subquery(B) compare_op(C) expr_or_subquery(D). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, D); SToken e = getTokenFromRawExprNode(pCxt, D);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D)));
} }
//predicate(A) ::= expression(B) compare_op sub_type expression(B). //predicate(A) ::= expression(B) compare_op sub_type expression(B).
predicate(A) ::= expression(B) BETWEEN expression(C) AND expression(D). { predicate(A) ::=
expr_or_subquery(B) BETWEEN expr_or_subquery(C) AND expr_or_subquery(D). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, D); SToken e = getTokenFromRawExprNode(pCxt, D);
A = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D))); A = createRawExprNodeExt(pCxt, &s, &e, createBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D)));
} }
predicate(A) ::= expression(B) NOT BETWEEN expression(C) AND expression(D). { predicate(A) ::=
expr_or_subquery(B) NOT BETWEEN expr_or_subquery(C) AND expr_or_subquery(D). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, D); SToken e = getTokenFromRawExprNode(pCxt, D);
A = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D))); A = createRawExprNodeExt(pCxt, &s, &e, createNotBetweenAnd(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C), releaseRawExprNode(pCxt, D)));
} }
predicate(A) ::= expression(B) IS NULL(C). { predicate(A) ::= expr_or_subquery(B) IS NULL(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, B), NULL)); A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, B), NULL));
} }
predicate(A) ::= expression(B) IS NOT NULL(C). { predicate(A) ::= expr_or_subquery(B) IS NOT NULL(C). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, B), NULL)); A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, B), NULL));
} }
predicate(A) ::= expression(B) in_op(C) in_predicate_value(D). { predicate(A) ::= expr_or_subquery(B) in_op(C) in_predicate_value(D). {
SToken s = getTokenFromRawExprNode(pCxt, B); SToken s = getTokenFromRawExprNode(pCxt, B);
SToken e = getTokenFromRawExprNode(pCxt, D); SToken e = getTokenFromRawExprNode(pCxt, D);
A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D))); A = createRawExprNodeExt(pCxt, &s, &e, createOperatorNode(pCxt, C, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, D)));
@ -813,7 +833,7 @@ boolean_primary(A) ::= predicate(B).
boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, releaseRawExprNode(pCxt, B)); } boolean_primary(A) ::= NK_LP(C) boolean_value_expression(B) NK_RP(D). { A = createRawExprNodeExt(pCxt, &C, &D, releaseRawExprNode(pCxt, B)); }
/************************************************ common_expression ********************************************/ /************************************************ common_expression ********************************************/
common_expression(A) ::= expression(B). { A = B; } common_expression(A) ::= expr_or_subquery(B). { A = B; }
common_expression(A) ::= boolean_value_expression(B). { A = B; } common_expression(A) ::= boolean_value_expression(B). { A = B; }
/************************************************ from_clause_opt *********************************************************/ /************************************************ from_clause_opt *********************************************************/
@ -894,7 +914,7 @@ partition_by_clause_opt(A) ::= PARTITION BY expression_list(B).
twindow_clause_opt(A) ::= . { A = NULL; } twindow_clause_opt(A) ::= . { A = NULL; }
twindow_clause_opt(A) ::= twindow_clause_opt(A) ::=
SESSION NK_LP column_reference(B) NK_COMMA duration_literal(C) NK_RP. { A = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); } SESSION NK_LP column_reference(B) NK_COMMA duration_literal(C) NK_RP. { A = createSessionWindowNode(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); }
twindow_clause_opt(A) ::= STATE_WINDOW NK_LP expression(B) NK_RP. { A = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, B)); } twindow_clause_opt(A) ::= STATE_WINDOW NK_LP expr_or_subquery(B) NK_RP. { A = createStateWindowNode(pCxt, releaseRawExprNode(pCxt, B)); }
twindow_clause_opt(A) ::= twindow_clause_opt(A) ::=
INTERVAL NK_LP duration_literal(B) NK_RP sliding_opt(C) fill_opt(D). { A = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, B), NULL, C, D); } INTERVAL NK_LP duration_literal(B) NK_RP sliding_opt(C) fill_opt(D). { A = createIntervalWindowNode(pCxt, releaseRawExprNode(pCxt, B), NULL, C, D); }
twindow_clause_opt(A) ::= twindow_clause_opt(A) ::=
@ -923,14 +943,15 @@ group_by_clause_opt(A) ::= GROUP BY group_by_list(B).
%type group_by_list { SNodeList* } %type group_by_list { SNodeList* }
%destructor group_by_list { nodesDestroyList($$); } %destructor group_by_list { nodesDestroyList($$); }
group_by_list(A) ::= expression(B). { A = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, B))); } group_by_list(A) ::= expr_or_subquery(B). { A = createNodeList(pCxt, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, B))); }
group_by_list(A) ::= group_by_list(B) NK_COMMA expression(C). { A = addNodeToList(pCxt, B, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, C))); } group_by_list(A) ::= group_by_list(B) NK_COMMA expr_or_subquery(C). { A = addNodeToList(pCxt, B, createGroupingSetNode(pCxt, releaseRawExprNode(pCxt, C))); }
having_clause_opt(A) ::= . { A = NULL; } having_clause_opt(A) ::= . { A = NULL; }
having_clause_opt(A) ::= HAVING search_condition(B). { A = B; } having_clause_opt(A) ::= HAVING search_condition(B). { A = B; }
range_opt(A) ::= . { A = NULL; } range_opt(A) ::= . { A = NULL; }
range_opt(A) ::= RANGE NK_LP expression(B) NK_COMMA expression(C) NK_RP. { A = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); } range_opt(A) ::=
RANGE NK_LP expr_or_subquery(B) NK_COMMA expr_or_subquery(C) NK_RP. { A = createInterpTimeRange(pCxt, releaseRawExprNode(pCxt, B), releaseRawExprNode(pCxt, C)); }
every_opt(A) ::= . { A = NULL; } every_opt(A) ::= . { A = NULL; }
every_opt(A) ::= EVERY NK_LP duration_literal(B) NK_RP. { A = releaseRawExprNode(pCxt, B); } every_opt(A) ::= EVERY NK_LP duration_literal(B) NK_RP. { A = releaseRawExprNode(pCxt, B); }
@ -974,6 +995,7 @@ limit_clause_opt(A) ::= LIMIT NK_INTEGER(C) NK_COMMA NK_INTEGER(B).
/************************************************ subquery ************************************************************/ /************************************************ subquery ************************************************************/
subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); } subquery(A) ::= NK_LP(B) query_expression(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, C); }
subquery(A) ::= NK_LP(B) subquery(C) NK_RP(D). { A = createRawExprNodeExt(pCxt, &B, &D, releaseRawExprNode(pCxt, C)); }
/************************************************ search_condition ****************************************************/ /************************************************ search_condition ****************************************************/
search_condition(A) ::= common_expression(B). { A = releaseRawExprNode(pCxt, B); } search_condition(A) ::= common_expression(B). { A = releaseRawExprNode(pCxt, B); }
@ -986,7 +1008,7 @@ sort_specification_list(A) ::=
sort_specification_list(B) NK_COMMA sort_specification(C). { A = addNodeToList(pCxt, B, C); } sort_specification_list(B) NK_COMMA sort_specification(C). { A = addNodeToList(pCxt, B, C); }
sort_specification(A) ::= sort_specification(A) ::=
expression(B) ordering_specification_opt(C) null_ordering_opt(D). { A = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, B), C, D); } expr_or_subquery(B) ordering_specification_opt(C) null_ordering_opt(D). { A = createOrderByExprNode(pCxt, releaseRawExprNode(pCxt, B), C, D); }
%type ordering_specification_opt EOrder %type ordering_specification_opt EOrder
%destructor ordering_specification_opt { } %destructor ordering_specification_opt { }

View File

@ -647,6 +647,25 @@ SNode* createInterpTimeRange(SAstCreateContext* pCxt, SNode* pStart, SNode* pEnd
return createBetweenAnd(pCxt, createPrimaryKeyCol(pCxt, NULL), pStart, 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) { SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, SToken* pAlias) {
CHECK_PARSER_STATUS(pCxt); CHECK_PARSER_STATUS(pCxt);
trimEscape(pAlias); trimEscape(pAlias);

View File

@ -54,6 +54,7 @@ static SKeyword keywordTable[] = {
{"CACHE", TK_CACHE}, {"CACHE", TK_CACHE},
{"CACHEMODEL", TK_CACHEMODEL}, {"CACHEMODEL", TK_CACHEMODEL},
{"CACHESIZE", TK_CACHESIZE}, {"CACHESIZE", TK_CACHESIZE},
{"CASE", TK_CASE},
{"CAST", TK_CAST}, {"CAST", TK_CAST},
{"CLIENT_VERSION", TK_CLIENT_VERSION}, {"CLIENT_VERSION", TK_CLIENT_VERSION},
{"CLUSTER", TK_CLUSTER}, {"CLUSTER", TK_CLUSTER},
@ -82,7 +83,9 @@ static SKeyword keywordTable[] = {
{"DOUBLE", TK_DOUBLE}, {"DOUBLE", TK_DOUBLE},
{"DROP", TK_DROP}, {"DROP", TK_DROP},
{"DURATION", TK_DURATION}, {"DURATION", TK_DURATION},
{"ELSE", TK_ELSE},
{"ENABLE", TK_ENABLE}, {"ENABLE", TK_ENABLE},
{"END", TK_END},
{"EXISTS", TK_EXISTS}, {"EXISTS", TK_EXISTS},
{"EXPIRED", TK_EXPIRED}, {"EXPIRED", TK_EXPIRED},
{"EXPLAIN", TK_EXPLAIN}, {"EXPLAIN", TK_EXPLAIN},
@ -205,6 +208,7 @@ static SKeyword keywordTable[] = {
{"TAG", TK_TAG}, {"TAG", TK_TAG},
{"TAGS", TK_TAGS}, {"TAGS", TK_TAGS},
{"TBNAME", TK_TBNAME}, {"TBNAME", TK_TBNAME},
{"THEN", TK_THEN},
{"TIMESTAMP", TK_TIMESTAMP}, {"TIMESTAMP", TK_TIMESTAMP},
{"TIMEZONE", TK_TIMEZONE}, {"TIMEZONE", TK_TIMEZONE},
{"TINYINT", TK_TINYINT}, {"TINYINT", TK_TINYINT},
@ -240,6 +244,7 @@ static SKeyword keywordTable[] = {
{"WAL_ROLL_PERIOD", TK_WAL_ROLL_PERIOD}, {"WAL_ROLL_PERIOD", TK_WAL_ROLL_PERIOD},
{"WAL_SEGMENT_SIZE", TK_WAL_SEGMENT_SIZE}, {"WAL_SEGMENT_SIZE", TK_WAL_SEGMENT_SIZE},
{"WATERMARK", TK_WATERMARK}, {"WATERMARK", TK_WATERMARK},
{"WHEN", TK_WHEN},
{"WHERE", TK_WHERE}, {"WHERE", TK_WHERE},
{"WINDOW_CLOSE", TK_WINDOW_CLOSE}, {"WINDOW_CLOSE", TK_WINDOW_CLOSE},
{"WITH", TK_WITH}, {"WITH", TK_WITH},

View File

@ -1807,6 +1807,59 @@ static EDealRes translateLogicCond(STranslateContext* pCxt, SLogicConditionNode*
return DEAL_RES_CONTINUE; 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) { static EDealRes doTranslateExpr(SNode** pNode, void* pContext) {
STranslateContext* pCxt = (STranslateContext*)pContext; STranslateContext* pCxt = (STranslateContext*)pContext;
switch (nodeType(*pNode)) { switch (nodeType(*pNode)) {
@ -1822,6 +1875,10 @@ static EDealRes doTranslateExpr(SNode** pNode, void* pContext) {
return translateLogicCond(pCxt, (SLogicConditionNode*)*pNode); return translateLogicCond(pCxt, (SLogicConditionNode*)*pNode);
case QUERY_NODE_TEMP_TABLE: case QUERY_NODE_TEMP_TABLE:
return translateExprSubquery(pCxt, ((STempTableNode*)*pNode)->pSubquery); 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: default:
break; break;
} }
@ -3208,27 +3265,6 @@ static SNode* createSetOperProject(const char* pTableAlias, SNode* pNode) {
return (SNode*)pCol; 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) { static int32_t translateSetOperProject(STranslateContext* pCxt, SSetOperator* pSetOperator) {
SNodeList* pLeftProjections = getProjectList(pSetOperator->pLeft); SNodeList* pLeftProjections = getProjectList(pSetOperator->pLeft);
SNodeList* pRightProjections = getProjectList(pSetOperator->pRight); SNodeList* pRightProjections = getProjectList(pSetOperator->pRight);

File diff suppressed because it is too large Load Diff

View File

@ -60,6 +60,9 @@ TEST_F(ParserSelectTest, expression) {
run("SELECT ts > 0, c1 between 10 and 20 and c2 = 'qaz' FROM t1"); 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 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) { TEST_F(ParserSelectTest, condition) {
@ -312,6 +315,8 @@ TEST_F(ParserSelectTest, subquery) {
run("SELECT _C0 FROM (SELECT _ROWTS, ts FROM st1s1)"); run("SELECT _C0 FROM (SELECT _ROWTS, ts FROM st1s1)");
run("SELECT ts FROM (SELECT t1.ts FROM st1s1 t1)"); run("SELECT ts FROM (SELECT t1.ts FROM st1s1 t1)");
run("(((SELECT t1.ts FROM st1s1 t1)))");
} }
TEST_F(ParserSelectTest, subquerySemanticCheck) { TEST_F(ParserSelectTest, subquerySemanticCheck) {

View File

@ -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)"); 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) { TEST_F(PlanBasicTest, func) {
useDb("root", "test"); useDb("root", "test");