From cdd60902d75f13ed2a010ff1fe6913755592bcaa Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Thu, 10 Feb 2022 05:43:14 -0500 Subject: [PATCH] TD-13338 SELECT statement translate code --- include/libs/function/functionMgt.h | 2 +- include/nodes/nodes.h | 274 ++--------------------- include/nodes/querynodes.h | 280 ++++++++++++++++++++++++ source/libs/parser/inc/astCreateFuncs.h | 2 +- source/libs/parser/inc/parserImpl.h | 3 +- source/libs/planner/inc/plannerImpl.h | 27 +++ source/libs/planner/src/plannerImpl.c | 19 ++ source/nodes/src/nodesEqualFuncs.c | 2 +- source/nodes/src/nodesTraverseFuncs.c | 142 +++++++++++- source/nodes/src/nodesUtilFuncs.c | 2 +- source/nodes/test/nodesTest.cpp | 38 +++- 11 files changed, 520 insertions(+), 271 deletions(-) create mode 100644 include/nodes/querynodes.h create mode 100644 source/libs/planner/inc/plannerImpl.h create mode 100644 source/libs/planner/src/plannerImpl.c diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index bf3a45fcca..c3c8b5c4ce 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -20,7 +20,7 @@ extern "C" { #endif -#include "nodes.h" +#include "querynodes.h" typedef enum EFunctionType { // aggregate function diff --git a/include/nodes/nodes.h b/include/nodes/nodes.h index b182063808..321190d254 100644 --- a/include/nodes/nodes.h +++ b/include/nodes/nodes.h @@ -40,7 +40,11 @@ extern "C" { (NULL == cell1 ? (node1 = NULL, false) : (node1 = cell1->pNode, true)), (NULL == cell2 ? (node2 = NULL, false) : (node2 = cell2->pNode, true)), (node1 != NULL && node2 != NULL); \ cell1 = cell1->pNext, cell2 = cell2->pNext) +#define FOREACH_FOR_REWRITE(node, list) \ + for (SListCell* cell = (NULL != (list) ? (list)->pHead : NULL); (NULL != cell ? (node = &(cell->pNode), true) : (node = NULL, false)); cell = cell->pNext) + typedef enum ENodeType { + // Syntax nodes are used in parser and planner module, and some are also used in executor module, such as COLUMN, VALUE, OPERATOR, FUNCTION and so on. QUERY_NODE_COLUMN = 1, QUERY_NODE_VALUE, QUERY_NODE_OPERATOR, @@ -59,9 +63,10 @@ typedef enum ENodeType { QUERY_NODE_NODE_LIST, QUERY_NODE_FILL, - // only for parser + // Only be used in parser module. QUERY_NODE_RAW_EXPR, + // Statement nodes are used in parser and planner module. QUERY_NODE_SET_OPERATOR, QUERY_NODE_SELECT_STMT, QUERY_NODE_SHOW_STMT @@ -87,248 +92,6 @@ typedef struct SNodeList { SListCell* pTail; } SNodeList; -typedef struct SRawExprNode { - ENodeType nodeType; - char* p; - uint32_t n; - SNode* pNode; -} SRawExprNode; - -typedef struct SDataType { - uint8_t type; - uint8_t precision; - uint8_t scale; - int32_t bytes; -} SDataType; - -typedef struct SExprNode { - ENodeType nodeType; - SDataType resType; - char aliasName[TSDB_COL_NAME_LEN]; - SNodeList* pAssociationList; -} SExprNode; - -typedef enum EColumnType { - COLUMN_TYPE_COLUMN = 1, - COLUMN_TYPE_TAG -} EColumnType; - -typedef struct SColumnNode { - SExprNode node; // QUERY_NODE_COLUMN - int16_t colId; - EColumnType colType; // column or tag - char dbName[TSDB_DB_NAME_LEN]; - char tableName[TSDB_TABLE_NAME_LEN]; - char tableAlias[TSDB_TABLE_NAME_LEN]; - char colName[TSDB_COL_NAME_LEN]; - SNode* pProjectRef; -} SColumnNode; - -typedef struct SValueNode { - SExprNode node; // QUERY_NODE_VALUE - char* literal; - bool isDuration; - union { - bool b; - int64_t i; - uint64_t u; - double d; - char* p; - } datum; -} SValueNode; - -typedef enum EOperatorType { - // arithmetic operator - OP_TYPE_ADD = 1, - OP_TYPE_SUB, - OP_TYPE_MULTI, - OP_TYPE_DIV, - OP_TYPE_MOD, - - // comparison operator - OP_TYPE_GREATER_THAN, - OP_TYPE_GREATER_EQUAL, - OP_TYPE_LOWER_THAN, - OP_TYPE_LOWER_EQUAL, - OP_TYPE_EQUAL, - OP_TYPE_NOT_EQUAL, - OP_TYPE_IN, - OP_TYPE_NOT_IN, - OP_TYPE_LIKE, - OP_TYPE_NOT_LIKE, - OP_TYPE_MATCH, - OP_TYPE_NMATCH, - - // json operator - OP_TYPE_JSON_GET_VALUE, - OP_TYPE_JSON_CONTAINS -} EOperatorType; - -typedef struct SOperatorNode { - SExprNode node; // QUERY_NODE_OPERATOR - EOperatorType opType; - SNode* pLeft; - SNode* pRight; -} SOperatorNode; - -typedef enum ELogicConditionType { - LOGIC_COND_TYPE_AND, - LOGIC_COND_TYPE_OR, - LOGIC_COND_TYPE_NOT, -} ELogicConditionType; - -typedef struct SLogicConditionNode { - ENodeType type; // QUERY_NODE_LOGIC_CONDITION - ELogicConditionType condType; - SNodeList* pParameterList; -} SLogicConditionNode; - -typedef struct SIsNullCondNode { - ENodeType type; // QUERY_NODE_IS_NULL_CONDITION - SNode* pExpr; - bool isNull; -} SIsNullCondNode; - -typedef struct SNodeListNode { - ENodeType type; // QUERY_NODE_NODE_LIST - SNodeList* pNodeList; -} SNodeListNode; - -typedef struct SFunctionNode { - SExprNode node; // QUERY_NODE_FUNCTION - char functionName[TSDB_FUNC_NAME_LEN]; - int32_t funcId; - int32_t funcType; - SNodeList* pParameterList; -} SFunctionNode; - -typedef struct STableNode { - ENodeType type; - char dbName[TSDB_DB_NAME_LEN]; - char tableName[TSDB_TABLE_NAME_LEN]; - char tableAlias[TSDB_TABLE_NAME_LEN]; -} STableNode; - -struct STableMeta; - -typedef struct SRealTableNode { - STableNode table; // QUERY_NODE_REAL_TABLE - struct STableMeta* pMeta; -} SRealTableNode; - -typedef struct STempTableNode { - STableNode table; // QUERY_NODE_TEMP_TABLE - SNode* pSubquery; -} STempTableNode; - -typedef enum EJoinType { - JOIN_TYPE_INNER = 1 -} EJoinType; - -typedef struct SJoinTableNode { - STableNode table; // QUERY_NODE_JOIN_TABLE - EJoinType joinType; - SNode* pLeft; - SNode* pRight; - SNode* pOnCond; -} SJoinTableNode; - -typedef enum EGroupingSetType { - GP_TYPE_NORMAL = 1 -} EGroupingSetType; - -typedef struct SGroupingSetNode { - ENodeType type; // QUERY_NODE_GROUPING_SET - EGroupingSetType groupingSetType; - SNodeList* pParameterList; -} SGroupingSetNode; - -typedef enum EOrder { - ORDER_ASC = 1, - ORDER_DESC -} EOrder; - -typedef enum ENullOrder { - NULL_ORDER_DEFAULT = 1, - NULL_ORDER_FIRST, - NULL_ORDER_LAST -} ENullOrder; - -typedef struct SOrderByExprNode { - ENodeType type; // QUERY_NODE_ORDER_BY_EXPR - SNode* pExpr; - EOrder order; - ENullOrder nullOrder; -} SOrderByExprNode; - -typedef struct SLimitNode { - ENodeType type; // QUERY_NODE_LIMIT - uint64_t limit; - uint64_t offset; -} SLimitNode; - -typedef struct SStateWindowNode { - ENodeType type; // QUERY_NODE_STATE_WINDOW - SNode* pCol; -} SStateWindowNode; - -typedef struct SSessionWindowNode { - ENodeType type; // QUERY_NODE_SESSION_WINDOW - int64_t gap; // gap between two session window(in microseconds) - SNode* pCol; -} SSessionWindowNode; - -typedef struct SIntervalWindowNode { - ENodeType type; // QUERY_NODE_INTERVAL_WINDOW - SNode* pInterval; // SValueNode - SNode* pOffset; // SValueNode - SNode* pSliding; // SValueNode - SNode* pFill; -} SIntervalWindowNode; - -typedef enum EFillMode { - FILL_MODE_NONE = 1, - FILL_MODE_VALUE, - FILL_MODE_PREV, - FILL_MODE_NULL, - FILL_MODE_LINEAR, - FILL_MODE_NEXT -} EFillMode; - -typedef struct SFillNode { - ENodeType type; // QUERY_NODE_FILL - EFillMode mode; - SNode* pValues; // SNodeListNode -} SFillNode; - -typedef struct SSelectStmt { - ENodeType type; // QUERY_NODE_SELECT_STMT - bool isDistinct; - SNodeList* pProjectionList; // SNode - SNode* pFromTable; - SNode* pWhere; - SNodeList* pPartitionByList; // SNode - SNode* pWindow; - SNodeList* pGroupByList; // SGroupingSetNode - SNode* pHaving; - SNodeList* pOrderByList; // SOrderByExprNode - SNode* pLimit; - SNode* pSlimit; -} SSelectStmt; - -typedef enum ESetOperatorType { - SET_OP_TYPE_UNION_ALL = 1 -} ESetOperatorType; - -typedef struct SSetOperator { - ENodeType type; // QUERY_NODE_SET_OPERATOR - ESetOperatorType opType; - SNode* pLeft; - SNode* pRight; - SNodeList* pOrderByList; // SOrderByExprNode - SNode* pLimit; -} SSetOperator; - SNode* nodesMakeNode(ENodeType type); void nodesDestroyNode(SNode* pNode); @@ -343,12 +106,18 @@ typedef enum EDealRes { DEAL_RES_IGNORE_CHILD, DEAL_RES_ERROR, } EDealRes; -typedef EDealRes (*FQueryNodeWalker)(SNode* pNode, void* pContext); -void nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext); -void nodesWalkList(SNodeList* pList, FQueryNodeWalker walker, void* pContext); -void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContext); -void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext); +typedef EDealRes (*FNodeWalker)(SNode* pNode, void* pContext); +void nodesWalkNode(SNode* pNode, FNodeWalker walker, void* pContext); +void nodesWalkList(SNodeList* pList, FNodeWalker walker, void* pContext); +void nodesWalkNodePostOrder(SNode* pNode, FNodeWalker walker, void* pContext); +void nodesWalkListPostOrder(SNodeList* pList, FNodeWalker walker, void* pContext); + +typedef EDealRes (*FNodeRewriter)(SNode** pNode, void* pContext); +void nodesRewriteNode(SNode** pNode, FNodeRewriter rewriter, void* pContext); +void nodesRewriteList(SNodeList* pList, FNodeRewriter rewriter, void* pContext); +void nodesRewriteNodePostOrder(SNode** pNode, FNodeRewriter rewriter, void* pContext); +void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* pContext); bool nodesEqualNode(const SNode* a, const SNode* b); @@ -357,15 +126,6 @@ void nodesCloneNode(const SNode* pNode); int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen); int32_t nodesStringToNode(const char* pStr, SNode** pNode); -bool nodesIsExprNode(const SNode* pNode); - -bool nodesIsArithmeticOp(const SOperatorNode* pOp); -bool nodesIsComparisonOp(const SOperatorNode* pOp); -bool nodesIsJsonOp(const SOperatorNode* pOp); - -bool nodesIsTimeorderQuery(const SNode* pQuery); -bool nodesIsTimelineQuery(const SNode* pQuery); - #ifdef __cplusplus } #endif diff --git a/include/nodes/querynodes.h b/include/nodes/querynodes.h new file mode 100644 index 0000000000..646ea63c83 --- /dev/null +++ b/include/nodes/querynodes.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _TD_QUERY_NODES_H_ +#define _TD_QUERY_NODES_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "nodes.h" + +typedef struct SRawExprNode { + ENodeType nodeType; + char* p; + uint32_t n; + SNode* pNode; +} SRawExprNode; + +typedef struct SDataType { + uint8_t type; + uint8_t precision; + uint8_t scale; + int32_t bytes; +} SDataType; + +typedef struct SExprNode { + ENodeType nodeType; + SDataType resType; + char aliasName[TSDB_COL_NAME_LEN]; + SNodeList* pAssociationList; +} SExprNode; + +typedef enum EColumnType { + COLUMN_TYPE_COLUMN = 1, + COLUMN_TYPE_TAG +} EColumnType; + +typedef struct SColumnNode { + SExprNode node; // QUERY_NODE_COLUMN + int16_t colId; + EColumnType colType; // column or tag + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + char tableAlias[TSDB_TABLE_NAME_LEN]; + char colName[TSDB_COL_NAME_LEN]; + SNode* pProjectRef; +} SColumnNode; + +typedef struct SValueNode { + SExprNode node; // QUERY_NODE_VALUE + char* literal; + bool isDuration; + union { + bool b; + int64_t i; + uint64_t u; + double d; + char* p; + } datum; +} SValueNode; + +typedef enum EOperatorType { + // arithmetic operator + OP_TYPE_ADD = 1, + OP_TYPE_SUB, + OP_TYPE_MULTI, + OP_TYPE_DIV, + OP_TYPE_MOD, + + // comparison operator + OP_TYPE_GREATER_THAN, + OP_TYPE_GREATER_EQUAL, + OP_TYPE_LOWER_THAN, + OP_TYPE_LOWER_EQUAL, + OP_TYPE_EQUAL, + OP_TYPE_NOT_EQUAL, + OP_TYPE_IN, + OP_TYPE_NOT_IN, + OP_TYPE_LIKE, + OP_TYPE_NOT_LIKE, + OP_TYPE_MATCH, + OP_TYPE_NMATCH, + + // json operator + OP_TYPE_JSON_GET_VALUE, + OP_TYPE_JSON_CONTAINS +} EOperatorType; + +typedef struct SOperatorNode { + SExprNode node; // QUERY_NODE_OPERATOR + EOperatorType opType; + SNode* pLeft; + SNode* pRight; +} SOperatorNode; + +typedef enum ELogicConditionType { + LOGIC_COND_TYPE_AND, + LOGIC_COND_TYPE_OR, + LOGIC_COND_TYPE_NOT, +} ELogicConditionType; + +typedef struct SLogicConditionNode { + ENodeType type; // QUERY_NODE_LOGIC_CONDITION + ELogicConditionType condType; + SNodeList* pParameterList; +} SLogicConditionNode; + +typedef struct SIsNullCondNode { + ENodeType type; // QUERY_NODE_IS_NULL_CONDITION + SNode* pExpr; + bool isNull; +} SIsNullCondNode; + +typedef struct SNodeListNode { + ENodeType type; // QUERY_NODE_NODE_LIST + SNodeList* pNodeList; +} SNodeListNode; + +typedef struct SFunctionNode { + SExprNode node; // QUERY_NODE_FUNCTION + char functionName[TSDB_FUNC_NAME_LEN]; + int32_t funcId; + int32_t funcType; + SNodeList* pParameterList; +} SFunctionNode; + +typedef struct STableNode { + ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; + char tableName[TSDB_TABLE_NAME_LEN]; + char tableAlias[TSDB_TABLE_NAME_LEN]; +} STableNode; + +struct STableMeta; + +typedef struct SRealTableNode { + STableNode table; // QUERY_NODE_REAL_TABLE + struct STableMeta* pMeta; +} SRealTableNode; + +typedef struct STempTableNode { + STableNode table; // QUERY_NODE_TEMP_TABLE + SNode* pSubquery; +} STempTableNode; + +typedef enum EJoinType { + JOIN_TYPE_INNER = 1 +} EJoinType; + +typedef struct SJoinTableNode { + STableNode table; // QUERY_NODE_JOIN_TABLE + EJoinType joinType; + SNode* pLeft; + SNode* pRight; + SNode* pOnCond; +} SJoinTableNode; + +typedef enum EGroupingSetType { + GP_TYPE_NORMAL = 1 +} EGroupingSetType; + +typedef struct SGroupingSetNode { + ENodeType type; // QUERY_NODE_GROUPING_SET + EGroupingSetType groupingSetType; + SNodeList* pParameterList; +} SGroupingSetNode; + +typedef enum EOrder { + ORDER_ASC = 1, + ORDER_DESC +} EOrder; + +typedef enum ENullOrder { + NULL_ORDER_DEFAULT = 1, + NULL_ORDER_FIRST, + NULL_ORDER_LAST +} ENullOrder; + +typedef struct SOrderByExprNode { + ENodeType type; // QUERY_NODE_ORDER_BY_EXPR + SNode* pExpr; + EOrder order; + ENullOrder nullOrder; +} SOrderByExprNode; + +typedef struct SLimitNode { + ENodeType type; // QUERY_NODE_LIMIT + uint64_t limit; + uint64_t offset; +} SLimitNode; + +typedef struct SStateWindowNode { + ENodeType type; // QUERY_NODE_STATE_WINDOW + SNode* pCol; +} SStateWindowNode; + +typedef struct SSessionWindowNode { + ENodeType type; // QUERY_NODE_SESSION_WINDOW + int64_t gap; // gap between two session window(in microseconds) + SNode* pCol; +} SSessionWindowNode; + +typedef struct SIntervalWindowNode { + ENodeType type; // QUERY_NODE_INTERVAL_WINDOW + SNode* pInterval; // SValueNode + SNode* pOffset; // SValueNode + SNode* pSliding; // SValueNode + SNode* pFill; +} SIntervalWindowNode; + +typedef enum EFillMode { + FILL_MODE_NONE = 1, + FILL_MODE_VALUE, + FILL_MODE_PREV, + FILL_MODE_NULL, + FILL_MODE_LINEAR, + FILL_MODE_NEXT +} EFillMode; + +typedef struct SFillNode { + ENodeType type; // QUERY_NODE_FILL + EFillMode mode; + SNode* pValues; // SNodeListNode +} SFillNode; + +typedef struct SSelectStmt { + ENodeType type; // QUERY_NODE_SELECT_STMT + bool isDistinct; + SNodeList* pProjectionList; // SNode + SNode* pFromTable; + SNode* pWhere; + SNodeList* pPartitionByList; // SNode + SNode* pWindow; + SNodeList* pGroupByList; // SGroupingSetNode + SNode* pHaving; + SNodeList* pOrderByList; // SOrderByExprNode + SNode* pLimit; + SNode* pSlimit; +} SSelectStmt; + +typedef enum ESetOperatorType { + SET_OP_TYPE_UNION_ALL = 1 +} ESetOperatorType; + +typedef struct SSetOperator { + ENodeType type; // QUERY_NODE_SET_OPERATOR + ESetOperatorType opType; + SNode* pLeft; + SNode* pRight; + SNodeList* pOrderByList; // SOrderByExprNode + SNode* pLimit; +} SSetOperator; + +bool nodesIsExprNode(const SNode* pNode); + +bool nodesIsArithmeticOp(const SOperatorNode* pOp); +bool nodesIsComparisonOp(const SOperatorNode* pOp); +bool nodesIsJsonOp(const SOperatorNode* pOp); + +bool nodesIsTimeorderQuery(const SNode* pQuery); +bool nodesIsTimelineQuery(const SNode* pQuery); + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_QUERY_NODES_H_*/ \ No newline at end of file diff --git a/source/libs/parser/inc/astCreateFuncs.h b/source/libs/parser/inc/astCreateFuncs.h index 5b97a0e0c6..43bc5349e4 100644 --- a/source/libs/parser/inc/astCreateFuncs.h +++ b/source/libs/parser/inc/astCreateFuncs.h @@ -20,7 +20,7 @@ extern "C" { #endif -#include "nodes.h" +#include "querynodes.h" #include "nodesShowStmts.h" #include "astCreateContext.h" #include "ttoken.h" diff --git a/source/libs/parser/inc/parserImpl.h b/source/libs/parser/inc/parserImpl.h index 183075d465..b55060def7 100644 --- a/source/libs/parser/inc/parserImpl.h +++ b/source/libs/parser/inc/parserImpl.h @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "nodes.h" +#include "querynodes.h" #include "parser.h" #ifndef _TD_AST_CREATE_FUNCS_H_ @@ -25,6 +25,7 @@ extern "C" { typedef struct SQuery { SNode* pRoot; + // todo reslut meta } SQuery; int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery); diff --git a/source/libs/planner/inc/plannerImpl.h b/source/libs/planner/inc/plannerImpl.h new file mode 100644 index 0000000000..050329693c --- /dev/null +++ b/source/libs/planner/inc/plannerImpl.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _TD_PLANNER_IMPL_H_ +#define _TD_PLANNER_IMPL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef __cplusplus +} +#endif + +#endif /*_TD_PLANNER_IMPL_H_*/ diff --git a/source/libs/planner/src/plannerImpl.c b/source/libs/planner/src/plannerImpl.c new file mode 100644 index 0000000000..804f673fff --- /dev/null +++ b/source/libs/planner/src/plannerImpl.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + + +int32_t getPlan(SNode* pRoot, SQueryPlanNode** pQueryPlan) { + +} \ No newline at end of file diff --git a/source/nodes/src/nodesEqualFuncs.c b/source/nodes/src/nodesEqualFuncs.c index 41d1e5b05d..65eb6e9b32 100644 --- a/source/nodes/src/nodesEqualFuncs.c +++ b/source/nodes/src/nodesEqualFuncs.c @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "nodes.h" +#include "querynodes.h" #define COMPARE_SCALAR_FIELD(fldname) \ do { \ diff --git a/source/nodes/src/nodesTraverseFuncs.c b/source/nodes/src/nodesTraverseFuncs.c index 796aab611b..d1ded390db 100644 --- a/source/nodes/src/nodesTraverseFuncs.c +++ b/source/nodes/src/nodesTraverseFuncs.c @@ -13,16 +13,16 @@ * along with this program. If not, see . */ -#include "nodes.h" +#include "querynodes.h" typedef enum ETraversalOrder { TRAVERSAL_PREORDER = 1, TRAVERSAL_POSTORDER } ETraversalOrder; -static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext); +static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FNodeWalker walker, void* pContext); -static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) { +static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FNodeWalker walker, void* pContext) { if (NULL == pNode) { return DEAL_RES_CONTINUE; } @@ -119,7 +119,7 @@ static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker w return res; } -static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) { +static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FNodeWalker walker, void* pContext) { SNode* node; FOREACH(node, pNodeList) { if (DEAL_RES_ERROR == walkNode(node, order, walker, pContext)) { @@ -129,18 +129,144 @@ static EDealRes walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNode return DEAL_RES_CONTINUE; } -void nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) { +void nodesWalkNode(SNode* pNode, FNodeWalker walker, void* pContext) { (void)walkNode(pNode, TRAVERSAL_PREORDER, walker, pContext); } -void nodesWalkList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext) { +void nodesWalkList(SNodeList* pNodeList, FNodeWalker walker, void* pContext) { (void)walkList(pNodeList, TRAVERSAL_PREORDER, walker, pContext); } -void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContext) { +void nodesWalkNodePostOrder(SNode* pNode, FNodeWalker walker, void* pContext) { (void)walkNode(pNode, TRAVERSAL_POSTORDER, walker, pContext); } -void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext) { +void nodesWalkListPostOrder(SNodeList* pList, FNodeWalker walker, void* pContext) { (void)walkList(pList, TRAVERSAL_POSTORDER, walker, pContext); } + +static EDealRes rewriteList(SNodeList* pNodeList, ETraversalOrder order, FNodeRewriter rewriter, void* pContext); + +static EDealRes rewriteNode(SNode** pRawNode, ETraversalOrder order, FNodeRewriter rewriter, void* pContext) { + if (NULL == pRawNode || NULL == *pRawNode) { + return DEAL_RES_CONTINUE; + } + + EDealRes res = DEAL_RES_CONTINUE; + + if (TRAVERSAL_PREORDER == order) { + res = rewriter(pRawNode, pContext); + if (DEAL_RES_CONTINUE != res) { + return res; + } + } + + SNode* pNode = *pRawNode; + switch (nodeType(pNode)) { + case QUERY_NODE_COLUMN: + case QUERY_NODE_VALUE: + case QUERY_NODE_LIMIT: + // these node types with no subnodes + break; + case QUERY_NODE_OPERATOR: { + SOperatorNode* pOpNode = (SOperatorNode*)pNode; + res = rewriteNode(&(pOpNode->pLeft), order, rewriter, pContext); + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pOpNode->pRight), order, rewriter, pContext); + } + break; + } + case QUERY_NODE_LOGIC_CONDITION: + res = rewriteList(((SLogicConditionNode*)pNode)->pParameterList, order, rewriter, pContext); + break; + case QUERY_NODE_IS_NULL_CONDITION: + res = rewriteNode(&(((SIsNullCondNode*)pNode)->pExpr), order, rewriter, pContext); + break; + case QUERY_NODE_FUNCTION: + res = rewriteList(((SFunctionNode*)pNode)->pParameterList, order, rewriter, pContext); + break; + case QUERY_NODE_REAL_TABLE: + case QUERY_NODE_TEMP_TABLE: + break; // todo + case QUERY_NODE_JOIN_TABLE: { + SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode; + res = rewriteNode(&(pJoinTableNode->pLeft), order, rewriter, pContext); + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pJoinTableNode->pRight), order, rewriter, pContext); + } + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pJoinTableNode->pOnCond), order, rewriter, pContext); + } + break; + } + case QUERY_NODE_GROUPING_SET: + res = rewriteList(((SGroupingSetNode*)pNode)->pParameterList, order, rewriter, pContext); + break; + case QUERY_NODE_ORDER_BY_EXPR: + res = rewriteNode(&(((SOrderByExprNode*)pNode)->pExpr), order, rewriter, pContext); + break; + case QUERY_NODE_STATE_WINDOW: + res = rewriteNode(&(((SStateWindowNode*)pNode)->pCol), order, rewriter, pContext); + break; + case QUERY_NODE_SESSION_WINDOW: + res = rewriteNode(&(((SSessionWindowNode*)pNode)->pCol), order, rewriter, pContext); + break; + case QUERY_NODE_INTERVAL_WINDOW: { + SIntervalWindowNode* pInterval = (SIntervalWindowNode*)pNode; + res = rewriteNode(&(pInterval->pInterval), order, rewriter, pContext); + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pInterval->pOffset), order, rewriter, pContext); + } + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pInterval->pSliding), order, rewriter, pContext); + } + if (DEAL_RES_ERROR != res) { + res = rewriteNode(&(pInterval->pFill), order, rewriter, pContext); + } + break; + } + case QUERY_NODE_NODE_LIST: + res = rewriteList(((SNodeListNode*)pNode)->pNodeList, order, rewriter, pContext); + break; + case QUERY_NODE_FILL: + res = rewriteNode(&(((SFillNode*)pNode)->pValues), order, rewriter, pContext); + break; + case QUERY_NODE_RAW_EXPR: + res = rewriteNode(&(((SRawExprNode*)pNode)->pNode), order, rewriter, pContext); + break; + default: + break; + } + + if (DEAL_RES_ERROR != res && TRAVERSAL_POSTORDER == order) { + res = rewriter(pRawNode, pContext); + } + + return res; +} + +static EDealRes rewriteList(SNodeList* pNodeList, ETraversalOrder order, FNodeRewriter rewriter, void* pContext) { + SNode** pNode; + FOREACH_FOR_REWRITE(pNode, pNodeList) { + if (DEAL_RES_ERROR == rewriteNode(pNode, order, rewriter, pContext)) { + return DEAL_RES_ERROR; + } + } + return DEAL_RES_CONTINUE; +} + +void nodesRewriteNode(SNode** pNode, FNodeRewriter rewriter, void* pContext) { + (void)rewriteNode(pNode, TRAVERSAL_PREORDER, rewriter, pContext); +} + +void nodesRewriteList(SNodeList* pList, FNodeRewriter rewriter, void* pContext) { + (void)rewriteList(pList, TRAVERSAL_PREORDER, rewriter, pContext); +} + +void nodesRewriteNodePostOrder(SNode** pNode, FNodeRewriter rewriter, void* pContext) { + (void)rewriteNode(pNode, TRAVERSAL_POSTORDER, rewriter, pContext); +} + +void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* pContext) { + (void)rewriteList(pList, TRAVERSAL_POSTORDER, rewriter, pContext); +} diff --git a/source/nodes/src/nodesUtilFuncs.c b/source/nodes/src/nodesUtilFuncs.c index e0e589157c..5d4ddd0e03 100644 --- a/source/nodes/src/nodesUtilFuncs.c +++ b/source/nodes/src/nodesUtilFuncs.c @@ -13,7 +13,7 @@ * along with this program. If not, see . */ -#include "nodes.h" +#include "querynodes.h" #include "nodesShowStmts.h" #include "taoserror.h" diff --git a/source/nodes/test/nodesTest.cpp b/source/nodes/test/nodesTest.cpp index 7df3cd8b4c..c116faf4ce 100644 --- a/source/nodes/test/nodesTest.cpp +++ b/source/nodes/test/nodesTest.cpp @@ -15,8 +15,44 @@ #include +#include "querynodes.h" + +using namespace std; + +static EDealRes rewriterTest(SNode** pNode, void* pContext) { + EDealRes* pRes = (EDealRes*)pContext; + if (QUERY_NODE_OPERATOR == nodeType(*pNode)) { + SOperatorNode* pOp = (SOperatorNode*)(*pNode); + if (QUERY_NODE_VALUE != nodeType(pOp->pLeft) || QUERY_NODE_VALUE != nodeType(pOp->pRight)) { + *pRes = DEAL_RES_ERROR; + } + SValueNode* pVal = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); + string tmp = to_string(stoi(((SValueNode*)(pOp->pLeft))->literal) + stoi(((SValueNode*)(pOp->pRight))->literal)); + pVal->literal = strdup(tmp.c_str()); + nodesDestroyNode(*pNode); + *pNode = (SNode*)pVal; + } + return DEAL_RES_CONTINUE; +} + TEST(NodesTest, traverseTest) { - // todo + SNode* pRoot = nodesMakeNode(QUERY_NODE_OPERATOR); + SOperatorNode* pOp = (SOperatorNode*)pRoot; + SOperatorNode* pLeft = (SOperatorNode*)nodesMakeNode(QUERY_NODE_OPERATOR); + pLeft->pLeft = nodesMakeNode(QUERY_NODE_VALUE); + ((SValueNode*)(pLeft->pLeft))->literal = strdup("10"); + pLeft->pRight = nodesMakeNode(QUERY_NODE_VALUE); + ((SValueNode*)(pLeft->pRight))->literal = strdup("5"); + pOp->pLeft = (SNode*)pLeft; + pOp->pRight = nodesMakeNode(QUERY_NODE_VALUE); + ((SValueNode*)(pOp->pRight))->literal = strdup("3"); + + EXPECT_EQ(nodeType(pRoot), QUERY_NODE_OPERATOR); + EDealRes res = DEAL_RES_CONTINUE; + nodesRewriteNodePostOrder(&pRoot, rewriterTest, &res); + EXPECT_EQ(res, DEAL_RES_CONTINUE); + EXPECT_EQ(nodeType(pRoot), QUERY_NODE_VALUE); + EXPECT_EQ(string(((SValueNode*)pRoot)->literal), "18"); } int main(int argc, char* argv[]) {