diff --git a/include/nodes/nodes.h b/include/nodes/nodes.h index 39638b37578f63006955ddf189b35c1b4a0b4770..ccb135aa0dcc42f096c1505596ac2d736baf151e 100644 --- a/include/nodes/nodes.h +++ b/include/nodes/nodes.h @@ -78,6 +78,11 @@ typedef struct SNodeList { SListCell* pTail; } SNodeList; +typedef struct SNameStr { + int32_t len; + char* pName; +} SNameStr; + typedef struct SDataType { uint8_t type; uint8_t precision; @@ -89,6 +94,7 @@ typedef struct SExprNode { ENodeType nodeType; SDataType resType; char aliasName[TSDB_COL_NAME_LEN]; + SNodeList* pAssociationList; } SExprNode; typedef enum EColumnType { @@ -102,7 +108,9 @@ typedef struct SColumnNode { 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 { @@ -176,13 +184,16 @@ typedef struct SFunctionNode { typedef struct STableNode { ENodeType type; + char dbName[TSDB_DB_NAME_LEN]; char tableName[TSDB_TABLE_NAME_LEN]; - char tableAliasName[TSDB_COL_NAME_LEN]; + char tableAlias[TSDB_TABLE_NAME_LEN]; } STableNode; +struct STableMeta; + typedef struct SRealTableNode { STableNode table; // QUERY_NODE_REAL_TABLE - char dbName[TSDB_DB_NAME_LEN]; + struct STableMeta* pMeta; } SRealTableNode; typedef struct STempTableNode { @@ -273,7 +284,6 @@ typedef struct SFillNode { typedef struct SSelectStmt { ENodeType type; // QUERY_NODE_SELECT_STMT bool isDistinct; - bool isStar; SNodeList* pProjectionList; // SNode SNode* pFromTable; SNode* pWhere; @@ -295,6 +305,8 @@ typedef struct SSetOperator { ESetOperatorType opType; SNode* pLeft; SNode* pRight; + SNodeList* pOrderByList; // SOrderByExprNode + SNode* pLimit; } SSetOperator; SNode* nodesMakeNode(ENodeType type); @@ -306,8 +318,10 @@ void nodesDestroyList(SNodeList* pList); typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext); -bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext); -bool nodesWalkList(SNodeList* pList, FQueryNodeWalker walker, 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); bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index 50af44a94c6370117b04b7d2eb273b9babd82a41..b5740b0118c1286a1d38a73575d3227c998f3e10 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -440,7 +440,10 @@ int32_t* taosGetErrno(); #define TSDB_CODE_SCH_STATUS_ERROR TAOS_DEF_ERROR_CODE(0, 0x2501) //scheduler status error #define TSDB_CODE_SCH_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2502) //scheduler internal error - +//parser +#define TSDB_CODE_PARSER_INVALID_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2601) //invalid column name +#define TSDB_CODE_PARSER_TABLE_NOT_EXIST TAOS_DEF_ERROR_CODE(0, 0x2602) //table not exist +#define TSDB_CODE_PARSER_AMBIGUOUS_COLUMN TAOS_DEF_ERROR_CODE(0, 0x2603) //ambiguous column #ifdef __cplusplus } diff --git a/source/libs/parser/src/astCreateFuncs.c b/source/libs/parser/src/astCreateFuncs.c index f054649e1a5af6871ebf1cbf23412201d2f06520..75b2fb2e65f213f48e427202f30be1f4fc5f977c 100644 --- a/source/libs/parser/src/astCreateFuncs.c +++ b/source/libs/parser/src/astCreateFuncs.c @@ -150,7 +150,7 @@ SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SRealTableNode* realTable = (SRealTableNode*)nodesMakeNode(QUERY_NODE_REAL_TABLE); CHECK_OUT_OF_MEM(realTable); if (NULL != pDbName) { - strncpy(realTable->dbName, pDbName->z, pDbName->n); + strncpy(realTable->table.dbName, pDbName->z, pDbName->n); } strncpy(realTable->table.tableName, pTableName->z, pTableName->n); return (SNode*)realTable; @@ -288,9 +288,6 @@ SNode* createSelectStmt(SAstCreateContext* pCxt, bool isDistinct, SNodeList* pPr SSelectStmt* select = (SSelectStmt*)nodesMakeNode(QUERY_NODE_SELECT_STMT); CHECK_OUT_OF_MEM(select); select->isDistinct = isDistinct; - if (NULL == pProjectionList) { - select->isStar = true; - } select->pProjectionList = pProjectionList; select->pFromTable = pTable; return (SNode*)select; diff --git a/source/libs/parser/src/astTranslate.c b/source/libs/parser/src/astTranslate.c deleted file mode 100644 index ff68c4b22c110abd8d087604dcc8baefc31aabb7..0000000000000000000000000000000000000000 --- a/source/libs/parser/src/astTranslate.c +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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 doTranslate() { - -// } diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c index fdedafcbb49e596be898c446bbe4aa4e15fd488c..971b6fe8acad87f675ce387f260d3f580e043986 100644 --- a/source/libs/parser/src/parserImpl.c +++ b/source/libs/parser/src/parserImpl.c @@ -15,8 +15,9 @@ #include "parserImpl.h" -#include "ttoken.h" #include "astCreateContext.h" +#include "parserInt.h" +#include "ttoken.h" typedef void* (*FMalloc)(size_t); typedef void (*FFree)(void*); @@ -25,7 +26,7 @@ extern void* NewParseAlloc(FMalloc); extern void NewParse(void*, int, SToken, void*); extern void NewParseFree(void*, FFree); -uint32_t toNewTokenId(uint32_t tokenId) { +static uint32_t toNewTokenId(uint32_t tokenId) { switch (tokenId) { case TK_UNION: return NEW_TK_UNION; @@ -73,7 +74,7 @@ uint32_t toNewTokenId(uint32_t tokenId) { return tokenId; } -uint32_t getToken(const char* z, uint32_t* tokenId) { +static uint32_t getToken(const char* z, uint32_t* tokenId) { uint32_t n = tGetToken(z, tokenId); *tokenId = toNewTokenId(*tokenId); return n; @@ -137,3 +138,289 @@ abort_parse: pQuery->pRoot = cxt.pRootNode; return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED; } + +// typedef struct SNamespace { +// int16_t level; // todo for correlated subquery +// char dbName[TSDB_DB_NAME_LEN]; +// char tableAlias[TSDB_TABLE_NAME_LEN]; +// SHashObj* pColHash; // key is colname, value is index of STableMeta.schema +// STableMeta* pMeta; +// } SNamespace; + +typedef struct STranslateContext { + SParseContext* pParseCxt; + int32_t errCode; + SMsgBuf msgBuf; + SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode* + int32_t currLevel; +} STranslateContext; + +static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode); + +static char* getSyntaxErrFormat(int32_t errCode) { + switch (errCode) { + case TSDB_CODE_PARSER_INVALID_COLUMN: + return "Invalid column name : %s"; + case TSDB_CODE_PARSER_TABLE_NOT_EXIST: + return "Table does not exist : %s"; + case TSDB_CODE_PARSER_AMBIGUOUS_COLUMN: + return "Column ambiguously defined : %s"; + default: + return "Unknown error"; + } +} + +static int32_t generateSyntaxErrMsg(STranslateContext* pCxt, int32_t errCode, const char* additionalInfo) { + snprintf(pCxt->msgBuf.buf, pCxt->msgBuf.len, getSyntaxErrFormat(errCode), additionalInfo); + pCxt->errCode = errCode; + return errCode; +} + +static int32_t addNamespace(STranslateContext* pCxt, void* pTable) { + SArray* pTables = NULL; + if (taosArrayGetSize(pCxt->pNsLevel) > pCxt->currLevel) { + pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + } else { + pTables = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES); + } + taosArrayPush(pTables, &pTable); + return TSDB_CODE_SUCCESS; +} + +static SName* toName(const SRealTableNode* pRealTable, SName* pName) { + strncpy(pName->dbname, pRealTable->table.dbName, strlen(pRealTable->table.dbName)); + strncpy(pName->dbname, pRealTable->table.tableName, strlen(pRealTable->table.tableName)); + return pName; +} + +static bool belongTable(const char* currentDb, const SColumnNode* pCol, const STableNode* pTable) { + int cmp = 0; + if ('\0' != pCol->dbName[0]) { + cmp = strcmp(pCol->dbName, pTable->dbName); + } else { + cmp = strcmp(currentDb, pTable->dbName); + } + if (0 == cmp) { + cmp = strcmp(pCol->tableAlias, pTable->tableAlias); + } + return (0 == cmp); +} + +static SNodeList* getProjectList(SNode* pNode) { + if (QUERY_NODE_SELECT_STMT == nodeType(pNode)) { + return ((SSelectStmt*)pNode)->pProjectionList; + } + return NULL; +} + +static int32_t createColumnNodeByTable(const STableNode* pTable, SNodeList* pList) { + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; + int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns; + for (int32_t i = 0; i < nums; ++i) { + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + pCol->colId = pMeta->schema[i].colId; + pCol->colType = pMeta->schema[i].type; + pCol->node.resType.bytes = pMeta->schema[i].bytes; + nodesListAppend(pList, (SNode*)pCol); + } + } else { + SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); + SNode* pNode; + FOREACH(pNode, pProjectList) { + SExprNode* pExpr = (SExprNode*)pNode; + SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN); + pCol->pProjectRef = (SNode*)pExpr; + pExpr->pAssociationList = nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); + pCol->node.resType = pExpr->resType; + nodesListAppend(pList, (SNode*)pCol); + } + } +} + +static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) { + bool found = false; + if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) { + const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta; + int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns; + for (int32_t i = 0; i < nums; ++i) { + if (0 == strcmp(pCol->colName, pMeta->schema[i].name)) { + pCol->colId = pMeta->schema[i].colId; + pCol->colType = pMeta->schema[i].type; + pCol->node.resType.bytes = pMeta->schema[i].bytes; + found = true; + break; + } + } + } else { + SNodeList* pProjectList = getProjectList(((STempTableNode*)pTable)->pSubquery); + SNode* pNode; + FOREACH(pNode, pProjectList) { + SExprNode* pExpr = (SExprNode*)pNode; + if (0 == strcmp(pCol->colName, pExpr->aliasName)) { + pCol->pProjectRef = (SNode*)pExpr; + pExpr->pAssociationList = nodesListAppend(pExpr->pAssociationList, (SNode*)pCol); + pCol->node.resType = pExpr->resType; + found = true; + break; + } + } + } + return found; +} + +static bool doTranslateExpr(SNode* pNode, void* pContext) { + STranslateContext* pCxt = (STranslateContext*)pContext; + switch (nodeType(pNode)) { + case QUERY_NODE_COLUMN: { + SColumnNode* pCol = (SColumnNode*)pNode; + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + size_t nums = taosArrayGetSize(pTables); + bool hasTableAlias = ('\0' != pCol->tableAlias[0]); + bool found = false; + for (size_t i = 0; i < nums; ++i) { + STableNode* pTable = taosArrayGetP(pTables, i); + if (hasTableAlias) { + if (belongTable(pCxt->pParseCxt->db, pCol, pTable)) { + if (findAndSetColumn(pCol, pTable)) { + break; + } + generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_INVALID_COLUMN, pCol->colName); + return false; + } + } else { + if (findAndSetColumn(pCol, pTable)) { + if (found) { + generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_AMBIGUOUS_COLUMN, pCol->colName); + return false; + } + found = true; + } + } + } + break; + } + case QUERY_NODE_VALUE: + break; // todo check literal format + case QUERY_NODE_OPERATOR: { + + break; + } + case QUERY_NODE_FUNCTION: + break; // todo + case QUERY_NODE_TEMP_TABLE: + return translateSubquery(pCxt, ((STempTableNode*)pNode)->pSubquery); + default: + break; + } + return true; +} + +static int32_t translateExpr(STranslateContext* pCxt, SNode* pNode) { + nodesWalkNodePostOrder(pNode, doTranslateExpr, pCxt); + return pCxt->errCode; +} + +static int32_t translateExprList(STranslateContext* pCxt, SNodeList* pList) { + nodesWalkListPostOrder(pList, doTranslateExpr, pCxt); + return pCxt->errCode; +} + +static int32_t translateTable(STranslateContext* pCxt, SNode* pTable) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pTable)) { + case QUERY_NODE_REAL_TABLE: { + SRealTableNode* pRealTable = (SRealTableNode*)pTable; + if ('\0' == pRealTable->table.dbName[0]) { + strcpy(pRealTable->table.dbName, pCxt->pParseCxt->db); + } + if ('\0' == pRealTable->table.tableAlias[0]) { + strcpy(pRealTable->table.tableAlias, pRealTable->table.tableName); + } + SName name; + code = catalogGetTableMeta( + pCxt->pParseCxt->pCatalog, pCxt->pParseCxt->pTransporter, &(pCxt->pParseCxt->mgmtEpSet), toName(pRealTable, &name), &(pRealTable->pMeta)); + if (TSDB_CODE_SUCCESS != code) { + return generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_TABLE_NOT_EXIST, pRealTable->table.tableName); + } + code = addNamespace(pCxt, pRealTable); + break; + } + case QUERY_NODE_TEMP_TABLE: { + STempTableNode* pTempTable = (STempTableNode*)pTable; + code = translateSubquery(pCxt, pTempTable->pSubquery); + if (TSDB_CODE_SUCCESS == code) { + code = addNamespace(pCxt, pTempTable); + } + break; + } + case QUERY_NODE_JOIN_TABLE: { + SJoinTableNode* pJoinTable = (SJoinTableNode*)pTable; + code = translateTable(pCxt, pJoinTable->pLeft); + if (TSDB_CODE_SUCCESS == code) { + code = translateTable(pCxt, pJoinTable->pRight); + } + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, pJoinTable->pOnCond); + } + break; + } + default: + break; + } + return code; +} + +static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool* pIsSelectStar) { + if (NULL == pSelect->pProjectionList) { // select * ... + SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel); + size_t nums = taosArrayGetSize(pTables); + for (size_t i = 0; i < nums; ++i) { + STableNode* pTable = taosArrayGetP(pTables, i); + createColumnNodeByTable(pTable, pSelect->pProjectionList); + } + *pIsSelectStar = true; + } else { + + } +} + +static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) { + int32_t code = TSDB_CODE_SUCCESS; + code = translateTable(pCxt, pSelect->pFromTable); + if (TSDB_CODE_SUCCESS == code) { + code = translateExpr(pCxt, pSelect->pWhere); + } + bool isSelectStar = false; + if (TSDB_CODE_SUCCESS == code) { + code = translateStar(pCxt, pSelect, &isSelectStar); + } + if (TSDB_CODE_SUCCESS == code && !isSelectStar) { + code = translateExprList(pCxt, pSelect->pProjectionList); + } + return code; +} + +static int32_t translateQuery(STranslateContext* pCxt, SNode* pNode) { + int32_t code = TSDB_CODE_SUCCESS; + switch (nodeType(pNode)) { + case QUERY_NODE_SELECT_STMT: + code = translateSelect(pCxt, (SSelectStmt*)pNode); + break; + default: + break; + } + return code; +} + +static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) { + ++(pCxt->currLevel); + int32_t code = translateQuery(pCxt, pNode); + --(pCxt->currLevel); + return code; +} + +int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) { + STranslateContext cxt = { .pParseCxt = pParseCxt, .pNsLevel = taosArrayInit(TARRAY_MIN_SIZE, POINTER_BYTES), .currLevel = 0 }; + return translateQuery(&cxt, pQuery->pRoot); +} diff --git a/source/libs/parser/test/newParserTest.cpp b/source/libs/parser/test/newParserTest.cpp index 706deb443c3c54bddd389d860ed3a6f41af21ae1..0f0fe6ac5d9219a8253de75ade4191cca05bd6a2 100644 --- a/source/libs/parser/test/newParserTest.cpp +++ b/source/libs/parser/test/newParserTest.cpp @@ -71,8 +71,8 @@ private: switch (nodeType(node)) { case QUERY_NODE_REAL_TABLE: { SRealTableNode* realTable = (SRealTableNode*)table; - if ('\0' != realTable->dbName[0]) { - sql.append(realTable->dbName); + if ('\0' != realTable->table.dbName[0]) { + sql.append(realTable->table.dbName); sql.append("."); } sql.append(realTable->table.tableName); diff --git a/source/nodes/src/nodesTraverseFuncs.c b/source/nodes/src/nodesTraverseFuncs.c index ffe40073e65d8f4d08c371676394b88d7ffe4ac1..444ff7cbcf5f21c98c734603343a9eb1938b8d65 100644 --- a/source/nodes/src/nodesTraverseFuncs.c +++ b/source/nodes/src/nodesTraverseFuncs.c @@ -15,68 +15,101 @@ #include "nodes.h" -typedef bool (*FQueryNodeWalker)(SNode* pNode, void* pContext); +typedef enum ETraversalOrder { + TRAVERSAL_PREORDER = 1, + TRAVERSAL_POSTORDER +} ETraversalOrder; -bool nodesWalkNodeList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext) { - SNode* node; - FOREACH(node, pNodeList) { - if (!nodesWalkNode(node, walker, pContext)) { - return false; - } - } - return true; -} +static bool walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext); -bool nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) { +static bool walkNode(SNode* pNode, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) { if (NULL == pNode) { return true; } - if (!walker(pNode, pContext)) { + if (TRAVERSAL_PREORDER == order && !walker(pNode, pContext)) { return false; } + bool res = true; switch (nodeType(pNode)) { case QUERY_NODE_COLUMN: case QUERY_NODE_VALUE: case QUERY_NODE_LIMIT: // these node types with no subnodes - return true; + break; case QUERY_NODE_OPERATOR: { SOperatorNode* pOpNode = (SOperatorNode*)pNode; - if (!nodesWalkNode(pOpNode->pLeft, walker, pContext)) { - return false; + res = walkNode(pOpNode->pLeft, order, walker, pContext); + if (res) { + res = walkNode(pOpNode->pRight, order, walker, pContext); } - return nodesWalkNode(pOpNode->pRight, walker, pContext); + break; } case QUERY_NODE_LOGIC_CONDITION: - return nodesWalkNodeList(((SLogicConditionNode*)pNode)->pParameterList, walker, pContext); + res = walkList(((SLogicConditionNode*)pNode)->pParameterList, order, walker, pContext); + break; case QUERY_NODE_IS_NULL_CONDITION: - return nodesWalkNode(((SIsNullCondNode*)pNode)->pExpr, walker, pContext); + res = walkNode(((SIsNullCondNode*)pNode)->pExpr, order, walker, pContext); + break; case QUERY_NODE_FUNCTION: - return nodesWalkNodeList(((SFunctionNode*)pNode)->pParameterList, walker, pContext); + res = walkList(((SFunctionNode*)pNode)->pParameterList, order, walker, pContext); + break; case QUERY_NODE_REAL_TABLE: case QUERY_NODE_TEMP_TABLE: - return true; // todo + break; // todo case QUERY_NODE_JOIN_TABLE: { SJoinTableNode* pJoinTableNode = (SJoinTableNode*)pNode; - if (!nodesWalkNode(pJoinTableNode->pLeft, walker, pContext)) { - return false; + res = walkNode(pJoinTableNode->pLeft, order, walker, pContext); + if (res) { + res = walkNode(pJoinTableNode->pRight, order, walker, pContext); } - if (!nodesWalkNode(pJoinTableNode->pRight, walker, pContext)) { - return false; + if (res) { + res = walkNode(pJoinTableNode->pOnCond, order, walker, pContext); } - return nodesWalkNode(pJoinTableNode->pOnCond, walker, pContext); + break; } case QUERY_NODE_GROUPING_SET: - return nodesWalkNodeList(((SGroupingSetNode*)pNode)->pParameterList, walker, pContext); + res = walkList(((SGroupingSetNode*)pNode)->pParameterList, order, walker, pContext); + break; case QUERY_NODE_ORDER_BY_EXPR: - return nodesWalkNode(((SOrderByExprNode*)pNode)->pExpr, walker, pContext); + res = walkNode(((SOrderByExprNode*)pNode)->pExpr, order, walker, pContext); + break; default: break; } - return false; + if (res && TRAVERSAL_POSTORDER == order) { + res = walker(pNode, pContext); + } + + return res; +} + +static bool walkList(SNodeList* pNodeList, ETraversalOrder order, FQueryNodeWalker walker, void* pContext) { + SNode* node; + FOREACH(node, pNodeList) { + if (!walkNode(node, order, walker, pContext)) { + return false; + } + } + return true; +} + +void nodesWalkNode(SNode* pNode, FQueryNodeWalker walker, void* pContext) { + (void)walkNode(pNode, TRAVERSAL_PREORDER, walker, pContext); +} + +void nodesWalkList(SNodeList* pNodeList, FQueryNodeWalker walker, void* pContext) { + (void)walkList(pNodeList, TRAVERSAL_PREORDER, walker, pContext); +} + +void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContext) { + (void)walkNode(pNode, TRAVERSAL_POSTORDER, walker, pContext); +} + +void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext) { + (void)walkList(pList, TRAVERSAL_PREORDER, walker, pContext); } bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext) {