From e7a19755c66118ae120e1b0e1da03ca298a15028 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Tue, 28 Feb 2023 16:02:49 +0800 Subject: [PATCH 1/2] fix: a plan error of set operator subquery --- source/libs/parser/src/parCalcConst.c | 57 ++++++++++++++++++++++++--- 1 file changed, 52 insertions(+), 5 deletions(-) diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c index d4f4949df0..5afd61a054 100644 --- a/source/libs/parser/src/parCalcConst.c +++ b/source/libs/parser/src/parCalcConst.c @@ -320,6 +320,57 @@ static int32_t calcConstInsert(SCalcConstContext* pCxt, SInsertStmt* pInsert) { return code; } +static SNodeList* getChildProjection(SNode* pStmt) { + switch (nodeType(pStmt)) { + case QUERY_NODE_SELECT_STMT: + return ((SSelectStmt*)pStmt)->pProjectionList; + case QUERY_NODE_SET_OPERATOR: + return ((SSetOperator*)pStmt)->pProjectionList; + default: + break; + } + return NULL; +} + +static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) { + SNodeList* pLeftProjs = getChildProjection(pSetOp->pLeft); + nodesListErase(pLeftProjs, nodesListGetCell(pLeftProjs, index)); + SNodeList* pRightProjs = getChildProjection(pSetOp->pRight); + nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index)); +} + +static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) { + int32_t index = 0; + SNode* pProj = NULL; + WHERE_EACH(pProj, pSetOp->pProjectionList) { + if (subquery && isUselessCol((SExprNode*)pProj)) { + ERASE_NODE(pSetOp->pProjectionList); + eraseSetOpChildProjection(pSetOp, index); + continue; + } + ++index; + WHERE_NEXT; + } + if (0 == LIST_LENGTH(pSetOp->pProjectionList)) { + return nodesListStrictAppend(pSetOp->pProjectionList, createConstantValue()); + } + return TSDB_CODE_SUCCESS; +} + +static int32_t calcConstSetOperator(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) { + int32_t code = calcConstSetOpProjections(pCxt, pSetOp, subquery); + if (TSDB_CODE_SUCCESS == code) { + code = calcConstQuery(pCxt, pSetOp->pLeft, false); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstQuery(pCxt, pSetOp->pRight, false); + } + if (TSDB_CODE_SUCCESS == code) { + code = calcConstList(pSetOp->pOrderByList); + } + return code; +} + static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subquery) { int32_t code = TSDB_CODE_SUCCESS; switch (nodeType(pStmt)) { @@ -330,11 +381,7 @@ static int32_t calcConstQuery(SCalcConstContext* pCxt, SNode* pStmt, bool subque code = calcConstQuery(pCxt, ((SExplainStmt*)pStmt)->pQuery, subquery); break; case QUERY_NODE_SET_OPERATOR: { - SSetOperator* pSetOp = (SSetOperator*)pStmt; - code = calcConstQuery(pCxt, pSetOp->pLeft, false); - if (TSDB_CODE_SUCCESS == code) { - code = calcConstQuery(pCxt, pSetOp->pRight, false); - } + code = calcConstSetOperator(pCxt, (SSetOperator*)pStmt, subquery); break; } case QUERY_NODE_DELETE_STMT: From ca624678b139a3d657122d3921b8f4d81a1834d4 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Tue, 28 Feb 2023 17:28:23 +0800 Subject: [PATCH 2/2] fix: a plan error of set operator subquery --- source/libs/parser/src/parCalcConst.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/source/libs/parser/src/parCalcConst.c b/source/libs/parser/src/parCalcConst.c index 5afd61a054..b2fc88add1 100644 --- a/source/libs/parser/src/parCalcConst.c +++ b/source/libs/parser/src/parCalcConst.c @@ -339,11 +339,33 @@ static void eraseSetOpChildProjection(SSetOperator* pSetOp, int32_t index) { nodesListErase(pRightProjs, nodesListGetCell(pRightProjs, index)); } +typedef struct SNotRefByOrderByCxt { + SColumnNode* pCol; + bool hasThisCol; +} SNotRefByOrderByCxt; + +static EDealRes notRefByOrderByImpl(SNode* pNode, void* pContext) { + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + SNotRefByOrderByCxt* pCxt = (SNotRefByOrderByCxt*)pContext; + if (nodesEqualNode((SNode*)pCxt->pCol, pNode)) { + pCxt->hasThisCol = true; + return DEAL_RES_END; + } + } + return DEAL_RES_CONTINUE; +} + +static bool notRefByOrderBy(SColumnNode* pCol, SNodeList* pOrderByList) { + SNotRefByOrderByCxt cxt = {.pCol = pCol, .hasThisCol = false}; + nodesWalkExprs(pOrderByList, notRefByOrderByImpl, &cxt); + return !cxt.hasThisCol; +} + static int32_t calcConstSetOpProjections(SCalcConstContext* pCxt, SSetOperator* pSetOp, bool subquery) { int32_t index = 0; SNode* pProj = NULL; WHERE_EACH(pProj, pSetOp->pProjectionList) { - if (subquery && isUselessCol((SExprNode*)pProj)) { + if (subquery && notRefByOrderBy((SColumnNode*)pProj, pSetOp->pOrderByList) && isUselessCol((SExprNode*)pProj)) { ERASE_NODE(pSetOp->pProjectionList); eraseSetOpChildProjection(pSetOp, index); continue;