From fb3bd53ea0b1855a9e536310cba556fe833dcf29 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Fri, 11 Feb 2022 20:59:23 -0500 Subject: [PATCH 1/2] TD-13495 planner refactoring --- include/libs/nodes/nodes.h | 2 +- include/libs/nodes/querynodes.h | 25 ++- include/util/taoserror.h | 1 - source/libs/nodes/src/nodesTraverseFuncs.c | 57 +++++ source/libs/nodes/src/nodesUtilFuncs.c | 110 +++++++++- source/libs/parser/src/astCreateFuncs.c | 10 +- source/libs/parser/src/parserImpl.c | 29 +-- source/libs/planner/inc/plannerImpl.h | 1 + source/libs/planner/src/plannerImpl.c | 244 ++++++++++++--------- 9 files changed, 346 insertions(+), 133 deletions(-) diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h index 068b80cf59..1ea1f0316a 100644 --- a/include/libs/nodes/nodes.h +++ b/include/libs/nodes/nodes.h @@ -100,7 +100,7 @@ SNode* nodesMakeNode(ENodeType type); void nodesDestroyNode(SNode* pNode); SNodeList* nodesMakeList(); -SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode); +int32_t nodesListAppend(SNodeList* pList, SNode* pNode); SListCell* nodesListErase(SNodeList* pList, SListCell* pCell); SNode* nodesListGetNode(SNodeList* pList, int32_t index); void nodesDestroyList(SNodeList* pList); diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index ea9653e4a8..6046770ed1 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -50,6 +50,7 @@ typedef enum EColumnType { typedef struct SColumnNode { SExprNode node; // QUERY_NODE_COLUMN + uint64_t tableId; int16_t colId; EColumnType colType; // column or tag char dbName[TSDB_DB_NAME_LEN]; @@ -59,10 +60,11 @@ typedef struct SColumnNode { SNode* pProjectRef; } SColumnNode; -typedef struct SColumnRef { +typedef struct SColumnRefNode { ENodeType type; + int32_t tupleId; int32_t slotId; -} SColumnRef; +} SColumnRefNode; typedef struct SValueNode { SExprNode node; // QUERY_NODE_VALUE @@ -269,6 +271,25 @@ typedef struct SSetOperator { SNode* pLimit; } SSetOperator; +typedef enum ESqlClause { + SQL_CLAUSE_FROM = 1, + SQL_CLAUSE_WHERE, + SQL_CLAUSE_PARTITION_BY, + SQL_CLAUSE_WINDOW, + SQL_CLAUSE_GROUP_BY, + SQL_CLAUSE_HAVING, + SQL_CLAUSE_SELECT, + SQL_CLAUSE_ORDER_BY +} ESqlClause; + +void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext); +void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext); + +int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, uint64_t tableId, bool realCol, SNodeList** pCols); + +typedef bool (*FFuncClassifier)(int32_t funcId); +int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs); + bool nodesIsExprNode(const SNode* pNode); bool nodesIsArithmeticOp(const SOperatorNode* pOp); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 5c12d29b50..0a822927ad 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -459,7 +459,6 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260A) //Not a GROUP BY expression #define TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION TAOS_DEF_ERROR_CODE(0, 0x260B) //Not SELECTed expression #define TSDB_CODE_PAR_NOT_SINGLE_GROUP TAOS_DEF_ERROR_CODE(0, 0x260C) //Not a single-group group function -#define TSDB_CODE_PAR_OUT_OF_MEMORY TAOS_DEF_ERROR_CODE(0, 0x260D) //Out of memory #ifdef __cplusplus } diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c index b7e7ad6f0b..e61375b202 100644 --- a/source/libs/nodes/src/nodesTraverseFuncs.c +++ b/source/libs/nodes/src/nodesTraverseFuncs.c @@ -264,3 +264,60 @@ void nodesRewriteNodePostOrder(SNode** pNode, FNodeRewriter rewriter, void* pCon void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* pContext) { (void)rewriteList(pList, TRAVERSAL_POSTORDER, rewriter, pContext); } + +void nodesWalkSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeWalker walker, void* pContext) { + if (NULL == pSelect) { + return; + } + + switch (clause) { + case SQL_CLAUSE_FROM: + nodesWalkNode(pSelect->pFromTable, walker, pContext); + nodesWalkNode(pSelect->pWhere, walker, pContext); + case SQL_CLAUSE_WHERE: + nodesWalkList(pSelect->pPartitionByList, walker, pContext); + case SQL_CLAUSE_PARTITION_BY: + nodesWalkNode(pSelect->pWindow, walker, pContext); + case SQL_CLAUSE_WINDOW: + nodesWalkList(pSelect->pGroupByList, walker, pContext); + case SQL_CLAUSE_GROUP_BY: + nodesWalkNode(pSelect->pHaving, walker, pContext); + case SQL_CLAUSE_HAVING: + nodesWalkList(pSelect->pProjectionList, walker, pContext); + case SQL_CLAUSE_SELECT: + nodesWalkList(pSelect->pOrderByList, walker, pContext); + case SQL_CLAUSE_ORDER_BY: + default: + break; + } + + return; +} + +void nodesRewriteSelectStmt(SSelectStmt* pSelect, ESqlClause clause, FNodeRewriter rewriter, void* pContext) { + if (NULL == pSelect) { + return; + } + + switch (clause) { + case SQL_CLAUSE_FROM: + nodesRewriteNode(&(pSelect->pFromTable), rewriter, pContext); + nodesRewriteNode(&(pSelect->pWhere), rewriter, pContext); + case SQL_CLAUSE_WHERE: + nodesRewriteList(pSelect->pPartitionByList, rewriter, pContext); + case SQL_CLAUSE_PARTITION_BY: + nodesRewriteNode(&(pSelect->pWindow), rewriter, pContext); + case SQL_CLAUSE_WINDOW: + nodesRewriteList(pSelect->pGroupByList, rewriter, pContext); + case SQL_CLAUSE_GROUP_BY: + nodesRewriteNode(&(pSelect->pHaving), rewriter, pContext); + case SQL_CLAUSE_HAVING: + nodesRewriteList(pSelect->pProjectionList, rewriter, pContext); + case SQL_CLAUSE_SELECT: + nodesRewriteList(pSelect->pOrderByList, rewriter, pContext); + default: + break; + } + + return; +} diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index d94ef4d378..50ddd14bf5 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -15,7 +15,9 @@ #include "querynodes.h" #include "nodesShowStmts.h" +#include "taos.h" #include "taoserror.h" +#include "thash.h" static SNode* makeNode(ENodeType type, size_t size) { SNode* p = calloc(1, size); @@ -98,14 +100,14 @@ SNodeList* nodesMakeList() { return p; } -SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode) { +int32_t nodesListAppend(SNodeList* pList, SNode* pNode) { if (NULL == pList || NULL == pNode) { - return NULL; + return TSDB_CODE_SUCCESS; } SListCell* p = calloc(1, sizeof(SListCell)); if (NULL == p) { - terrno = TSDB_CODE_TSC_OUT_OF_MEMORY; - return pList; + terrno = TSDB_CODE_OUT_OF_MEMORY; + return TSDB_CODE_OUT_OF_MEMORY; } p->pNode = pNode; if (NULL == pList->pHead) { @@ -116,7 +118,7 @@ SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode) { } pList->pTail = p; ++(pList->length); - return pList; + return TSDB_CODE_SUCCESS; } SListCell* nodesListErase(SNodeList* pList, SListCell* pCell) { @@ -207,4 +209,100 @@ bool nodesIsTimeorderQuery(const SNode* pQuery) { bool nodesIsTimelineQuery(const SNode* pQuery) { return false; -} \ No newline at end of file +} + +typedef struct SCollectColumnsCxt { + int32_t errCode; + uint64_t tableId; + bool realCol; + SNodeList* pCols; + SHashObj* pColIdHash; +} SCollectColumnsCxt; + +static EDealRes doCollect(SCollectColumnsCxt* pCxt, int32_t id, SNode* pNode) { + if (NULL == taosHashGet(pCxt->pColIdHash, &id, sizeof(id))) { + pCxt->errCode = taosHashPut(pCxt->pColIdHash, &id, sizeof(id), NULL, 0); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pCxt->errCode = nodesListAppend(pCxt->pCols, pNode); + } + return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR); + } + return DEAL_RES_CONTINUE; +} + +static EDealRes collectColumns(SNode* pNode, void* pContext) { + SCollectColumnsCxt* pCxt = (SCollectColumnsCxt*)pContext; + + if (pCxt->realCol && QUERY_NODE_COLUMN == nodeType(pNode)) { + SColumnNode* pCol = (SColumnNode*)pNode; + int32_t colId = pCol->colId; + if (pCxt->tableId == pCol->tableId && colId > 0) { + return doCollect(pCxt, colId, pNode); + } + } else if (!pCxt->realCol && QUERY_NODE_COLUMN_REF == nodeType(pNode)) { + return doCollect(pCxt, ((SColumnRefNode*)pNode)->slotId, pNode); + } + return DEAL_RES_CONTINUE; +} + +int32_t nodesCollectColumns(SSelectStmt* pSelect, ESqlClause clause, uint64_t tableId, bool realCol, SNodeList** pCols) { + if (NULL == pSelect || NULL == pCols) { + return TSDB_CODE_SUCCESS; + } + + SCollectColumnsCxt cxt = { + .errCode = TSDB_CODE_SUCCESS, + .realCol = realCol, + .pCols = nodesMakeList(), + .pColIdHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK) + }; + if (NULL == cxt.pCols || NULL == cxt.pColIdHash) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + nodesWalkSelectStmt(pSelect, clause, collectColumns, &cxt); + taosHashCleanup(cxt.pColIdHash); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyList(cxt.pCols); + return cxt.errCode; + } + *pCols = cxt.pCols; + return TSDB_CODE_SUCCESS; +} + +typedef struct SCollectFuncsCxt { + int32_t errCode; + FFuncClassifier classifier; + SNodeList* pFuncs; +} SCollectFuncsCxt; + +static EDealRes collectFuncs(SNode* pNode, void* pContext) { + SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext; + if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId)) { + pCxt->errCode = nodesListAppend(pCxt->pFuncs, pNode); + return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR); + } + return DEAL_RES_CONTINUE; +} + +int32_t nodesCollectFuncs(SSelectStmt* pSelect, FFuncClassifier classifier, SNodeList** pFuncs) { + if (NULL == pSelect || NULL == pFuncs) { + return TSDB_CODE_SUCCESS; + } + + SCollectFuncsCxt cxt = { + .errCode = TSDB_CODE_SUCCESS, + .classifier = classifier, + .pFuncs = nodesMakeList() + }; + if (NULL == cxt.pFuncs) { + return TSDB_CODE_OUT_OF_MEMORY; + } + nodesWalkSelectStmt(pSelect, SQL_CLAUSE_GROUP_BY, collectFuncs, &cxt); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyList(cxt.pFuncs); + return cxt.errCode; + } + *pFuncs = cxt.pFuncs; + return TSDB_CODE_SUCCESS; +} diff --git a/source/libs/parser/src/astCreateFuncs.c b/source/libs/parser/src/astCreateFuncs.c index 2615aca7f3..c129ebeef1 100644 --- a/source/libs/parser/src/astCreateFuncs.c +++ b/source/libs/parser/src/astCreateFuncs.c @@ -96,11 +96,17 @@ SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) { SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode) { SNodeList* list = nodesMakeList(); CHECK_OUT_OF_MEM(list); - return nodesListAppend(list, pNode); + if (TSDB_CODE_SUCCESS != nodesListAppend(list, pNode)) { + pCxt->valid = false; + } + return list; } SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode) { - return nodesListAppend(pList, pNode); + if (TSDB_CODE_SUCCESS != nodesListAppend(pList, pNode)) { + pCxt->valid = false; + } + return pList; } SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableAlias, const SToken* pColumnName) { diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c index a2602c42ee..ec53f266bf 100644 --- a/source/libs/parser/src/parserImpl.c +++ b/source/libs/parser/src/parserImpl.c @@ -241,17 +241,6 @@ abort_parse: return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; } -typedef enum ESqlClause { - SQL_CLAUSE_FROM = 1, - SQL_CLAUSE_WHERE, - SQL_CLAUSE_PARTITION_BY, - SQL_CLAUSE_WINDOW, - SQL_CLAUSE_GROUP_BY, - SQL_CLAUSE_HAVING, - SQL_CLAUSE_SELECT, - SQL_CLAUSE_ORDER_BY -} ESqlClause; - static bool afterGroupBy(ESqlClause clause) { return clause > SQL_CLAUSE_GROUP_BY; } @@ -298,7 +287,7 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Not SELECTed expression"; case TSDB_CODE_PAR_NOT_SINGLE_GROUP: return "Not a single-group group function"; - case TSDB_CODE_PAR_OUT_OF_MEMORY: + case TSDB_CODE_OUT_OF_MEMORY: return "Out of memory"; default: return "Unknown error"; @@ -376,7 +365,7 @@ static void setColumnInfoBySchema(const STableNode* pTable, const SSchema* pColS static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SColumnNode* pCol) { pCol->pProjectRef = (SNode*)pExpr; - pExpr->pAssociationList = nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); + nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); if (NULL != pTable) { strcpy(pCol->tableAlias, pTable->tableAlias); } @@ -391,7 +380,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode for (int32_t i = 0; i < nums; ++i) { SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); } setColumnInfoBySchema(pTable, pMeta->schema + i, pCol); nodesListAppend(pList, (SNode*)pCol); @@ -402,7 +391,7 @@ static int32_t createColumnNodeByTable(STranslateContext* pCxt, const STableNode FOREACH(pNode, pProjectList) { SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); } setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol); nodesListAppend(pList, (SNode*)pCol); @@ -572,7 +561,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { int32_t n = strlen(pVal->literal); pVal->datum.p = calloc(1, n); if (NULL == pVal->datum.p) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); return DEAL_RES_ERROR; } trimStringCopy(pVal->literal, n, pVal->datum.p); @@ -582,7 +571,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) { int32_t n = strlen(pVal->literal); char* tmp = calloc(1, n); if (NULL == tmp) { - generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); return DEAL_RES_ERROR; } int32_t len = trimStringCopy(pVal->literal, n, tmp); @@ -830,7 +819,7 @@ static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool size_t nums = taosArrayGetSize(pTables); pSelect->pProjectionList = nodesMakeList(); if (NULL == pSelect->pProjectionList) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); } for (size_t i = 0; i < nums; ++i) { STableNode* pTable = taosArrayGetP(pTables, i); @@ -897,7 +886,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro } else { SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); if (NULL == pCol) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); } setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol); ((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol; @@ -1036,7 +1025,7 @@ int32_t setReslutSchema(STranslateContext* pCxt, SQuery* pQuery) { pQuery->numOfResCols = LIST_LENGTH(pSelect->pProjectionList); pQuery->pResSchema = calloc(pQuery->numOfResCols, sizeof(SSchema)); if (NULL == pQuery->pResSchema) { - return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY); + return generateSyntaxErrMsg(pCxt, TSDB_CODE_OUT_OF_MEMORY); } SNode* pNode; int32_t index = 0; diff --git a/source/libs/planner/inc/plannerImpl.h b/source/libs/planner/inc/plannerImpl.h index 1f8df990b1..dbfbeb7efc 100644 --- a/source/libs/planner/inc/plannerImpl.h +++ b/source/libs/planner/inc/plannerImpl.h @@ -25,6 +25,7 @@ extern "C" { typedef struct SLogicNode { ENodeType type; + int32_t id; SNodeList* pTargets; SNode* pConditions; SNodeList* pChildren; diff --git a/source/libs/planner/src/plannerImpl.c b/source/libs/planner/src/plannerImpl.c index ddb3023bb3..9b82b4d58e 100644 --- a/source/libs/planner/src/plannerImpl.c +++ b/source/libs/planner/src/plannerImpl.c @@ -16,71 +16,32 @@ #include "plannerImpl.h" #include "functionMgt.h" -static SLogicNode* createQueryLogicNode(SNode* pStmt); +#define CHECK_ALLOC(p, res) \ + do { \ + if (NULL == p) { \ + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; \ + return res; \ + } \ + } while (0) -typedef struct SCollectColumnsCxt { - SNodeList* pCols; - SHashObj* pColIdHash; -} SCollectColumnsCxt; +#define CHECK_CODE(exec, res) \ + do { \ + int32_t code = exec; \ + if (TSDB_CODE_SUCCESS != code) { \ + pCxt->errCode = code; \ + return res; \ + } \ + } while (0) -static EDealRes doCollectColumns(SNode* pNode, void* pContext) { - if (QUERY_NODE_COLUMN == nodeType(pNode)) { - SCollectColumnsCxt* pCxt = (SCollectColumnsCxt*)pContext; - int16_t colId = ((SColumnNode*)pNode)->colId; - if (colId > 0) { - if (NULL == taosHashGet(pCxt->pColIdHash, &colId, sizeof(colId))) { - taosHashPut(pCxt->pColIdHash, &colId, sizeof(colId), NULL, 0); - nodesListAppend(pCxt->pCols, pNode); - } - } - } - return DEAL_RES_CONTINUE; -} - -static SNodeList* collectColumns(SSelectStmt* pSelect) { - SCollectColumnsCxt cxt = { .pCols = nodesMakeList(), .pColIdHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BIGINT), true, HASH_NO_LOCK) }; - if (NULL == cxt.pCols || NULL == cxt.pColIdHash) { - return NULL; - } - nodesWalkNode(pSelect->pFromTable, doCollectColumns, &cxt); - nodesWalkNode(pSelect->pWhere, doCollectColumns, &cxt); - nodesWalkList(pSelect->pPartitionByList, doCollectColumns, &cxt); - nodesWalkNode(pSelect->pWindow, doCollectColumns, &cxt); - nodesWalkList(pSelect->pGroupByList, doCollectColumns, &cxt); - nodesWalkNode(pSelect->pHaving, doCollectColumns, &cxt); - nodesWalkList(pSelect->pProjectionList, doCollectColumns, &cxt); - nodesWalkList(pSelect->pOrderByList, doCollectColumns, &cxt); - taosHashCleanup(cxt.pColIdHash); - return cxt.pCols; -} - -typedef struct SCollectAggFuncsCxt { - SNodeList* pAggFuncs; -} SCollectAggFuncsCxt; - -static EDealRes doCollectAggFuncs(SNode* pNode, void* pContext) { - if (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsAggFunc(((SFunctionNode*)pNode)->funcId)) { - SCollectAggFuncsCxt* pCxt = (SCollectAggFuncsCxt*)pContext; - nodesListAppend(pCxt->pAggFuncs, pNode); - return DEAL_RES_IGNORE_CHILD; - } - return DEAL_RES_CONTINUE; -} - -static SNodeList* collectAggFuncs(SSelectStmt* pSelect) { - SCollectAggFuncsCxt cxt = { .pAggFuncs = nodesMakeList() }; - if (NULL == cxt.pAggFuncs) { - return NULL; - } - nodesWalkNode(pSelect->pHaving, doCollectAggFuncs, &cxt); - nodesWalkList(pSelect->pProjectionList, doCollectAggFuncs, &cxt); - if (!pSelect->isDistinct) { - nodesWalkList(pSelect->pOrderByList, doCollectAggFuncs, &cxt); - } - return cxt.pAggFuncs; -} +typedef struct SPlanContext { + int32_t errCode; + int32_t planNodeId; + SNodeList* pResource; +} SPlanContext; typedef struct SRewriteExprCxt { + int32_t errCode; + int32_t planNodeId; SNodeList* pTargets; } SRewriteExprCxt; @@ -90,9 +51,15 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { int32_t index = 0; FOREACH(pTarget, pCxt->pTargets) { if (nodesEqualNode(pTarget, *pNode)) { + SColumnRefNode* pCol = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF); + if (NULL == pCol) { + pCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; + return DEAL_RES_ERROR; + } + pCol->tupleId = pCxt->planNodeId; + pCol->slotId = index; nodesDestroyNode(*pNode); - *pNode = nodesMakeNode(QUERY_NODE_COLUMN_REF); - ((SColumnRef*)*pNode)->slotId = index; + *pNode = (SNode*)pCol; return DEAL_RES_IGNORE_CHILD; } ++index; @@ -100,59 +67,93 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { return DEAL_RES_CONTINUE; } -static int32_t rewriteExpr(SNodeList* pTargets, SSelectStmt* pSelect) { - SRewriteExprCxt cxt = { .pTargets = pTargets }; - nodesRewriteNode(&(pSelect->pFromTable), doRewriteExpr, &cxt); - nodesRewriteNode(&(pSelect->pWhere), doRewriteExpr, &cxt); - nodesRewriteList(pSelect->pPartitionByList, doRewriteExpr, &cxt); - nodesRewriteNode(&(pSelect->pWindow), doRewriteExpr, &cxt); - nodesRewriteList(pSelect->pGroupByList, doRewriteExpr, &cxt); - nodesRewriteNode(&(pSelect->pHaving), doRewriteExpr, &cxt); - nodesRewriteList(pSelect->pProjectionList, doRewriteExpr, &cxt); - nodesRewriteList(pSelect->pOrderByList, doRewriteExpr, &cxt); - return TSDB_CODE_SUCCESS; +static int32_t rewriteExpr(int32_t planNodeId, SNodeList* pTargets, SSelectStmt* pSelect, ESqlClause clause) { + SRewriteExprCxt cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = planNodeId, .pTargets = pTargets }; + nodesRewriteSelectStmt(pSelect, clause, doRewriteExpr, &cxt); + return cxt.errCode; } -static SLogicNode* pushLogicNode(SLogicNode* pRoot, SLogicNode* pNode) { +static SLogicNode* pushLogicNode(SPlanContext* pCxt, SLogicNode* pRoot, SLogicNode* pNode) { + if (TSDB_CODE_SUCCESS != pCxt->errCode) { + goto error; + } + if (NULL == pRoot) { return pNode; } + if (NULL == pNode) { return pRoot; } - pRoot->pParent = pNode; + if (NULL == pNode->pChildren) { pNode->pChildren = nodesMakeList(); + if (NULL == pNode->pChildren) { + goto error; + } } - nodesListAppend(pNode->pChildren, (SNode*)pRoot); + if (TSDB_CODE_SUCCESS != nodesListAppend(pNode->pChildren, (SNode*)pRoot)) { + goto error; + } + pRoot->pParent = pNode; return pNode; +error: + nodesDestroyNode((SNode*)pNode); + return pRoot; } -static SNodeList* createScanTargets(SNodeList* pCols) { - +static SNodeList* createScanTargets(int32_t planNodeId, int32_t numOfScanCols) { + SNodeList* pTargets = nodesMakeList(); + if (NULL == pTargets) { + return NULL; + } + for (int32_t i = 0; i < numOfScanCols; ++i) { + SColumnRefNode* pCol = (SColumnRefNode*)nodesMakeNode(QUERY_NODE_COLUMN_REF); + if (NULL == pCol || TSDB_CODE_SUCCESS != nodesListAppend(pTargets, (SNode*)pCol)) { + nodesDestroyList(pTargets); + return NULL; + } + pCol->tupleId = planNodeId; + pCol->slotId = i; + } + return pTargets; } -static SLogicNode* createScanLogicNode(SSelectStmt* pSelect, SRealTableNode* pRealTable) { +static SLogicNode* createScanLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SRealTableNode* pRealTable) { SScanLogicNode* pScan = (SScanLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_SCAN); - SNodeList* pCols = collectColumns(pSelect); - pScan->pScanCols = nodesCloneList(pCols); - // - rewriteExpr(pScan->pScanCols, pSelect); - pScan->node.pTargets = createScanTargets(pCols); + CHECK_ALLOC(pScan, NULL); + pScan->node.id = pCxt->planNodeId++; + pScan->pMeta = pRealTable->pMeta; + + // set columns to scan + SNodeList* pCols = NULL; + CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_FROM, pScan->pMeta->uid, true, &pCols), (SLogicNode*)pScan); + pScan->pScanCols = nodesCloneList(pCols); + CHECK_ALLOC(pScan->pScanCols, (SLogicNode*)pScan); + + // pScanCols of SScanLogicNode is equivalent to pTargets of other logic nodes + CHECK_CODE(rewriteExpr(pScan->node.id, pScan->pScanCols, pSelect, SQL_CLAUSE_FROM), (SLogicNode*)pScan); + + // set output + pScan->node.pTargets = createScanTargets(pScan->node.id, LIST_LENGTH(pScan->pScanCols)); + CHECK_ALLOC(pScan->node.pTargets, (SLogicNode*)pScan); + return (SLogicNode*)pScan; } -static SLogicNode* createSubqueryLogicNode(SSelectStmt* pSelect, STempTableNode* pTable) { - return createQueryLogicNode(pTable->pSubquery); +static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt); + +static SLogicNode* createSubqueryLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, STempTableNode* pTable) { + return createQueryLogicNode(pCxt, pTable->pSubquery); } -static SLogicNode* createLogicNodeByTable(SSelectStmt* pSelect, SNode* pTable) { +static SLogicNode* createLogicNodeByTable(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pTable) { switch (nodeType(pTable)) { case QUERY_NODE_REAL_TABLE: - return createScanLogicNode(pSelect, (SRealTableNode*)pTable); + return createScanLogicNode(pCxt, pSelect, (SRealTableNode*)pTable); case QUERY_NODE_TEMP_TABLE: - return createSubqueryLogicNode(pSelect, (STempTableNode*)pTable); + return createSubqueryLogicNode(pCxt, pSelect, (STempTableNode*)pTable); case QUERY_NODE_JOIN_TABLE: default: break; @@ -160,45 +161,86 @@ static SLogicNode* createLogicNodeByTable(SSelectStmt* pSelect, SNode* pTable) { return NULL; } -static SLogicNode* createFilterLogicNode(SNode* pWhere) { +static SLogicNode* createFilterLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SNode* pWhere) { if (NULL == pWhere) { return NULL; } + SFilterLogicNode* pFilter = (SFilterLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FILTER); + CHECK_ALLOC(pFilter, NULL); + pFilter->node.id = pCxt->planNodeId++; + + // set filter conditions pFilter->node.pConditions = nodesCloneNode(pWhere); + CHECK_ALLOC(pFilter->node.pConditions, (SLogicNode*)pFilter); + + // set the output and rewrite the expression in subsequent clauses with the output + SNodeList* pCols = NULL; + CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, 0, false, &pCols), (SLogicNode*)pFilter); + pFilter->node.pTargets = nodesCloneList(pCols); + CHECK_ALLOC(pFilter->node.pTargets, (SLogicNode*)pFilter); + CHECK_CODE(rewriteExpr(pFilter->node.id, pFilter->node.pTargets, pSelect, SQL_CLAUSE_WHERE), (SLogicNode*)pFilter); + return (SLogicNode*)pFilter; } -static SLogicNode* createAggLogicNode(SSelectStmt* pSelect, SNodeList* pGroupByList, SNode* pHaving) { - SNodeList* pAggFuncs = collectAggFuncs(pSelect); +static SLogicNode* createAggLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect, SNodeList* pGroupByList, SNode* pHaving) { + SNodeList* pAggFuncs = NULL; + CHECK_CODE(nodesCollectFuncs(pSelect, fmIsAggFunc, &pAggFuncs), NULL); if (NULL == pAggFuncs && NULL == pGroupByList) { return NULL; } + SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG); + CHECK_ALLOC(pAgg, NULL); + pAgg->node.id = pCxt->planNodeId++; + + // set grouyp keys, agg funcs and having conditions pAgg->pGroupKeys = nodesCloneList(pGroupByList); + CHECK_ALLOC(pAgg->pGroupKeys, (SLogicNode*)pAgg); pAgg->pAggFuncs = nodesCloneList(pAggFuncs); + CHECK_ALLOC(pAgg->pAggFuncs, (SLogicNode*)pAgg); pAgg->node.pConditions = nodesCloneNode(pHaving); + CHECK_ALLOC(pAgg->node.pConditions, (SLogicNode*)pAgg); + + // set the output and rewrite the expression in subsequent clauses with the output + SNodeList* pCols = NULL; + CHECK_CODE(nodesCollectColumns(pSelect, SQL_CLAUSE_HAVING, 0, false, &pCols), (SLogicNode*)pAgg); + pAgg->node.pTargets = nodesCloneList(pCols); + CHECK_ALLOC(pAgg->node.pTargets, (SLogicNode*)pAgg); + CHECK_CODE(rewriteExpr(pAgg->node.id, pAgg->node.pTargets, pSelect, SQL_CLAUSE_HAVING), (SLogicNode*)pAgg); + return (SLogicNode*)pAgg; } -static SLogicNode* createSelectLogicNode(SSelectStmt* pSelect) { - SLogicNode* pRoot = createLogicNodeByTable(pSelect, pSelect->pFromTable); - pRoot = pushLogicNode(pRoot, createFilterLogicNode(pSelect->pWhere)); - pRoot = pushLogicNode(pRoot, createAggLogicNode(pSelect, pSelect->pGroupByList, pSelect->pHaving)); - // pRoot = pushLogicNode(pRoot, createProjectLogicNode(pSelect, pSelect->pProjectionList)); +static SLogicNode* createSelectLogicNode(SPlanContext* pCxt, SSelectStmt* pSelect) { + SLogicNode* pRoot = createLogicNodeByTable(pCxt, pSelect, pSelect->pFromTable); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pRoot = pushLogicNode(pCxt, pRoot, createFilterLogicNode(pCxt, pSelect, pSelect->pWhere)); + } + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pRoot = pushLogicNode(pCxt, pRoot, createAggLogicNode(pCxt, pSelect, pSelect->pGroupByList, pSelect->pHaving)); + } + // pRoot = pushLogicNode(pCxt, pRoot, createProjectLogicNode(pSelect, pSelect->pProjectionList)); return pRoot; } -static SLogicNode* createQueryLogicNode(SNode* pStmt) { +static SLogicNode* createQueryLogicNode(SPlanContext* pCxt, SNode* pStmt) { switch (nodeType(pStmt)) { case QUERY_NODE_SELECT_STMT: - return createSelectLogicNode((SSelectStmt*)pStmt); + return createSelectLogicNode(pCxt, (SSelectStmt*)pStmt); default: break; } } int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) { - *pLogicNode = createQueryLogicNode(pNode); + SPlanContext cxt = { .errCode = TSDB_CODE_SUCCESS, .planNodeId = 0 }; + SLogicNode* pRoot = createQueryLogicNode(&cxt, pNode); + if (TSDB_CODE_SUCCESS != cxt.errCode) { + nodesDestroyNode((SNode*)pRoot); + return cxt.errCode; + } + *pLogicNode = pRoot; return TSDB_CODE_SUCCESS; } From 0b8b1e7950a180279e39a9626c5c11e90e71ee27 Mon Sep 17 00:00:00 2001 From: Shuduo Sang Date: Thu, 17 Feb 2022 12:20:48 +0800 Subject: [PATCH 2/2] Test/sangshuduo/td 13408 move example back for 3.0 (#10296) * [TD-13408]: move examples back to TDegnine for 3.0 * update tests for 3.0 * [TD-13408]: move rust example back for 3.0 --- .gitmodules | 3 +++ examples/rust | 1 + 2 files changed, 4 insertions(+) create mode 160000 examples/rust diff --git a/.gitmodules b/.gitmodules index 5298fd26a6..616e252a93 100644 --- a/.gitmodules +++ b/.gitmodules @@ -14,3 +14,6 @@ path = tests url = https://github.com/taosdata/tests branch = 3.0 +[submodule "examples/rust"] + path = examples/rust + url = https://github.com/songtianyi/tdengine-rust-bindings.git diff --git a/examples/rust b/examples/rust new file mode 160000 index 0000000000..1c8924dc66 --- /dev/null +++ b/examples/rust @@ -0,0 +1 @@ +Subproject commit 1c8924dc668e6aa848214c2fc54e3ace3f5bf8df