diff --git a/include/nodes/nodes.h b/include/nodes/nodes.h index ccb135aa0dcc42f096c1505596ac2d736baf151e..73082825efc9c46bccec06ffae96ba80f0d8ff85 100644 --- a/include/nodes/nodes.h +++ b/include/nodes/nodes.h @@ -54,6 +54,9 @@ typedef enum ENodeType { QUERY_NODE_NODE_LIST, QUERY_NODE_FILL, + // only for parser + QUERY_NODE_TARGET_EXPR, + QUERY_NODE_SET_OPERATOR, QUERY_NODE_SELECT_STMT, QUERY_NODE_SHOW_STMT @@ -78,11 +81,6 @@ typedef struct SNodeList { SListCell* pTail; } SNodeList; -typedef struct SNameStr { - int32_t len; - char* pName; -} SNameStr; - typedef struct SDataType { uint8_t type; uint8_t precision; @@ -114,7 +112,7 @@ typedef struct SColumnNode { } SColumnNode; typedef struct SValueNode { - SExprNode type; // QUERY_NODE_VALUE + SExprNode node; // QUERY_NODE_VALUE char* literal; } SValueNode; @@ -146,7 +144,7 @@ typedef enum EOperatorType { } EOperatorType; typedef struct SOperatorNode { - SExprNode type; // QUERY_NODE_OPERATOR + SExprNode node; // QUERY_NODE_OPERATOR EOperatorType opType; SNode* pLeft; SNode* pRight; @@ -332,6 +330,10 @@ 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 nodesIsArithmeticOp(const SOperatorNode* pOp); +bool nodesIsComparisonOp(const SOperatorNode* pOp); +bool nodesIsJsonOp(const SOperatorNode* pOp); + bool nodesIsTimeorderQuery(const SNode* pQuery); bool nodesIsTimelineQuery(const SNode* pQuery); diff --git a/include/util/taoserror.h b/include/util/taoserror.h index ea8bbb1231a229d6c374a799bfcaa61cf1865da5..b19215c79d973e9221a026ecdc61958b3610bd4e 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -444,6 +444,7 @@ int32_t* taosGetErrno(); #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 +#define TSDB_CODE_PARSER_WRONG_VALUE_TYPE TAOS_DEF_ERROR_CODE(0, 0x2604) //wrong value type #ifdef __cplusplus } diff --git a/source/libs/parser/inc/astCreateContext.h b/source/libs/parser/inc/astCreateContext.h index 5458500a8297646a295d7047fe6e68fdff7c2d24..a0bac9ea7bcb33ce90aaa467ae91a976c39d1282 100644 --- a/source/libs/parser/inc/astCreateContext.h +++ b/source/libs/parser/inc/astCreateContext.h @@ -28,7 +28,6 @@ typedef struct SAstCreateContext { bool notSupport; bool valid; SNode* pRootNode; - SHashObj* pResourceHash; } SAstCreateContext; int32_t createAstCreateContext(SParseContext* pQueryCxt, SAstCreateContext* pCxt); diff --git a/source/libs/parser/inc/astCreateFuncs.h b/source/libs/parser/inc/astCreateFuncs.h index 15f0792d5c15a9e8c44f599329cebcf08524b4b1..7cd7e1932d84b6d1f30a2b17b707ee20fec4676a 100644 --- a/source/libs/parser/inc/astCreateFuncs.h +++ b/source/libs/parser/inc/astCreateFuncs.h @@ -13,11 +13,6 @@ * along with this program. If not, see . */ -#include "nodes.h" -#include "nodesShowStmts.h" -#include "astCreateContext.h" -#include "ttoken.h" - #ifndef _TD_AST_CREATE_FUNCS_H_ #define _TD_AST_CREATE_FUNCS_H_ @@ -25,15 +20,26 @@ extern "C" { #endif +#include "nodes.h" +#include "nodesShowStmts.h" +#include "astCreateContext.h" +#include "ttoken.h" + extern SToken nil_token; +typedef struct STargetExprNode { + ENodeType nodeType; + char* p; + uint32_t n; + SNode* pNode; +} STargetExprNode; + SNodeList* createNodeList(SAstCreateContext* pCxt, SNode* pNode); SNodeList* addNodeToList(SAstCreateContext* pCxt, SNodeList* pList, SNode* pNode); SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableAlias, const SToken* pColumnName); SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral); SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral); -SNode* addMinusSign(SAstCreateContext* pCxt, SNode* pNode); SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias); SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2); SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight); diff --git a/source/libs/parser/src/astCreateFuncs.c b/source/libs/parser/src/astCreateFuncs.c index 6091961ed53e5e4ceabb014a5fa07138ef487d5f..e8b8b42f743f2909cd7480a927837b95f359fbc9 100644 --- a/source/libs/parser/src/astCreateFuncs.c +++ b/source/libs/parser/src/astCreateFuncs.c @@ -76,7 +76,10 @@ SNode* createColumnNode(SAstCreateContext* pCxt, const SToken* pTableAlias, cons SNode* createValueNode(SAstCreateContext* pCxt, int32_t dataType, const SToken* pLiteral) { SValueNode* val = (SValueNode*)nodesMakeNode(QUERY_NODE_VALUE); CHECK_OUT_OF_MEM(val); - // todo + val->literal = strndup(pLiteral->z, pLiteral->n); + CHECK_OUT_OF_MEM(val->literal); + val->node.resType.type = dataType; + val->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; return (SNode*)val; } @@ -87,10 +90,6 @@ SNode* createDurationValueNode(SAstCreateContext* pCxt, const SToken* pLiteral) return (SNode*)val; } -SNode* addMinusSign(SAstCreateContext* pCxt, SNode* pNode) { - // todo -} - SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType type, SNode* pParam1, SNode* pParam2) { SLogicConditionNode* cond = (SLogicConditionNode*)nodesMakeNode(QUERY_NODE_LOGIC_CONDITION); CHECK_OUT_OF_MEM(cond); diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c index 7182bcfedfa13b9eabc94e827cc668148788dd50..1682a1cb9de331020489b758ecfd715fc070c729 100644 --- a/source/libs/parser/src/parserImpl.c +++ b/source/libs/parser/src/parserImpl.c @@ -28,82 +28,11 @@ extern void NewParseFree(void*, FFree); extern void NewParseTrace(FILE*, char*); static uint32_t toNewTokenId(uint32_t tokenId) { -// #define 1 -// #define NEW_TK_AND 2 -// #define NEW_TK_UNION 3 -// #define NEW_TK_ALL 4 -// #define NEW_TK_MINUS 5 -// #define NEW_TK_EXCEPT 6 -// #define NEW_TK_INTERSECT 7 -// #define NEW_TK_NK_PLUS 8 -// #define NEW_TK_NK_MINUS 9 -// #define NEW_TK_NK_STAR 10 -// #define NEW_TK_NK_SLASH 11 -// #define NEW_TK_NK_REM 12 -// #define NEW_TK_SHOW 13 -// #define NEW_TK_DATABASES 14 -// #define NEW_TK_NK_INTEGER 15 -// #define NEW_TK_NK_FLOAT 16 -// #define NEW_TK_NK_STRING 17 -// #define NEW_TK_NK_BOOL 18 -// #define NEW_TK_TIMESTAMP 19 -// #define NEW_TK_NK_VARIABLE 20 -// #define NEW_TK_NK_COMMA 21 -// #define NEW_TK_NK_ID 22 -// #define NEW_TK_NK_LP 23 -// #define NEW_TK_NK_RP 24 -// #define NEW_TK_NK_DOT 25 -// #define NEW_TK_BETWEEN 26 -// #define NEW_TK_NOT 27 -// #define NEW_TK_IS 28 -// #define NEW_TK_NULL 29 -// #define NEW_TK_NK_LT 30 -// #define NEW_TK_NK_GT 31 -// #define NEW_TK_NK_LE 32 -// #define NEW_TK_NK_GE 33 -// #define NEW_TK_NK_NE 34 -// #define 35 -// #define NEW_TK_LIKE 36 -// #define NEW_TK_MATCH 37 -// #define NEW_TK_NMATCH 38 -// #define NEW_TK_IN 39 -// #define NEW_TK_FROM 40 -// #define NEW_TK_AS 41 -// #define NEW_TK_JOIN 42 -// #define NEW_TK_ON 43 -// #define NEW_TK_INNER 44 -// #define NEW_TK_SELECT 45 -// #define NEW_TK_DISTINCT 46 -// #define 47 -// #define NEW_TK_PARTITION 48 -// #define NEW_TK_BY 49 -// #define NEW_TK_SESSION 50 -// #define NEW_TK_STATE_WINDOW 51 -// #define NEW_TK_INTERVAL 52 -// #define NEW_TK_SLIDING 53 -// #define NEW_TK_FILL 54 -// #define NEW_TK_VALUE 55 -// #define NEW_TK_NONE 56 -// #define NEW_TK_PREV 57 -// #define NEW_TK_LINEAR 58 -// #define NEW_TK_NEXT 59 -// #define NEW_TK_GROUP 60 -// #define NEW_TK_HAVING 61 -// #define NEW_TK_ORDER 62 -// #define NEW_TK_SLIMIT 63 -// #define NEW_TK_SOFFSET 64 -// #define NEW_TK_LIMIT 65 -// #define NEW_TK_OFFSET 66 -// #define NEW_TK_NK_LR 67 -// #define NEW_TK_ASC 68 -// #define NEW_TK_DESC 69 -// #define NEW_TK_NULLS 70 -// #define NEW_TK_FIRST 71 -// #define NEW_TK_LAST 72 - switch (tokenId) { case TK_OR: return NEW_TK_OR; + case TK_AND: + return NEW_TK_AND; case TK_UNION: return NEW_TK_UNION; case TK_ALL: @@ -116,22 +45,62 @@ static uint32_t toNewTokenId(uint32_t tokenId) { return NEW_TK_NK_STAR; case TK_SLASH: return NEW_TK_NK_SLASH; + case TK_REM: + return NEW_TK_NK_REM; case TK_SHOW: return NEW_TK_SHOW; case TK_DATABASES: return NEW_TK_DATABASES; + case TK_INTEGER: + return NEW_TK_NK_INTEGER; + case TK_FLOAT: + return NEW_TK_NK_FLOAT; + case TK_STRING: + return NEW_TK_NK_STRING; + case TK_BOOL: + return NEW_TK_NK_BOOL; + case TK_TIMESTAMP: + return NEW_TK_TIMESTAMP; + case TK_VARIABLE: + return NEW_TK_NK_VARIABLE; + case TK_COMMA: + return NEW_TK_NK_COMMA; case TK_ID: return NEW_TK_NK_ID; case TK_LP: return NEW_TK_NK_LP; case TK_RP: return NEW_TK_NK_RP; - case TK_COMMA: - return NEW_TK_NK_COMMA; case TK_DOT: return NEW_TK_NK_DOT; + case TK_BETWEEN: + return NEW_TK_BETWEEN; + case TK_NOT: + return NEW_TK_NOT; + case TK_IS: + return NEW_TK_IS; + case TK_NULL: + return NEW_TK_NULL; + case TK_LT: + return NEW_TK_NK_LT; + case TK_GT: + return NEW_TK_NK_GT; + case TK_LE: + return NEW_TK_NK_LE; + case TK_GE: + return NEW_TK_NK_GE; + case TK_NE: + return NEW_TK_NK_NE; case TK_EQ: return NEW_TK_NK_EQ; + case TK_LIKE: + return NEW_TK_LIKE; + case TK_MATCH: + return NEW_TK_MATCH; + case TK_NMATCH: + return NEW_TK_NMATCH; + case TK_IN: + return NEW_TK_IN; case TK_SELECT: return NEW_TK_SELECT; case TK_DISTINCT: @@ -142,6 +111,38 @@ static uint32_t toNewTokenId(uint32_t tokenId) { return NEW_TK_AS; case TK_FROM: return NEW_TK_FROM; + case TK_JOIN: + return NEW_TK_JOIN; + // case TK_ON: + // return NEW_TK_ON; + // case TK_INNER: + // return NEW_TK_INNER; + // case TK_PARTITION: + // return NEW_TK_PARTITION; + case TK_SESSION: + return NEW_TK_SESSION; + case TK_STATE_WINDOW: + return NEW_TK_STATE_WINDOW; + case TK_INTERVAL: + return NEW_TK_INTERVAL; + case TK_SLIDING: + return NEW_TK_SLIDING; + case TK_FILL: + return NEW_TK_FILL; + // case TK_VALUE: + // return NEW_TK_VALUE; + case TK_NONE: + return NEW_TK_NONE; + case TK_PREV: + return NEW_TK_PREV; + case TK_LINEAR: + return NEW_TK_LINEAR; + // case TK_NEXT: + // return NEW_TK_NEXT; + case TK_GROUP: + return NEW_TK_GROUP; + case TK_HAVING: + return NEW_TK_HAVING; case TK_ORDER: return NEW_TK_ORDER; case TK_BY: @@ -150,6 +151,14 @@ static uint32_t toNewTokenId(uint32_t tokenId) { return NEW_TK_ASC; case TK_DESC: return NEW_TK_DESC; + case TK_SLIMIT: + return NEW_TK_SLIMIT; + case TK_SOFFSET: + return NEW_TK_SOFFSET; + case TK_LIMIT: + return NEW_TK_LIMIT; + case TK_OFFSET: + return NEW_TK_OFFSET; case TK_SPACE: break; default: @@ -224,14 +233,6 @@ abort_parse: 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 enum ESqlClause { SQL_CLAUSE_FROM = 1, SQL_CLAUSE_WHERE @@ -256,6 +257,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Table does not exist : %s"; case TSDB_CODE_PARSER_AMBIGUOUS_COLUMN: return "Column ambiguously defined : %s"; + case TSDB_CODE_PARSER_WRONG_VALUE_TYPE: + return "Invalid value type : %s"; default: return "Unknown error"; } @@ -322,7 +325,8 @@ static void setColumnInfoBySchema(const STableNode* pTable, const SSchema* pColS strcpy(pCol->node.aliasName, pColSchema->name); } pCol->colId = pColSchema->colId; - pCol->colType = pColSchema->type; + // pCol->colType = pColSchema->type; + pCol->node.resType.type = pColSchema->type; pCol->node.resType.bytes = pColSchema->bytes; } @@ -431,6 +435,30 @@ static bool translateValue(STranslateContext* pCxt, SValueNode* pVal) { } static bool translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) { + SDataType ldt = ((SExprNode*)(pOp->pLeft))->resType; + SDataType rdt = ((SExprNode*)(pOp->pRight))->resType; + if (nodesIsArithmeticOp(pOp)) { + if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || + TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { + generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); + return false; + } + pOp->node.resType.type = TSDB_DATA_TYPE_DOUBLE; + pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_DOUBLE].bytes; + return true; + } else if (nodesIsComparisonOp(pOp)) { + if (TSDB_DATA_TYPE_JSON == ldt.type || TSDB_DATA_TYPE_BLOB == ldt.type || + TSDB_DATA_TYPE_JSON == rdt.type || TSDB_DATA_TYPE_BLOB == rdt.type) { + generateSyntaxErrMsg(pCxt, TSDB_CODE_PARSER_WRONG_VALUE_TYPE, ((SExprNode*)(pOp->pRight))->aliasName); + return false; + } + pOp->node.resType.type = TSDB_DATA_TYPE_BOOL; + pOp->node.resType.bytes = tDataTypes[TSDB_DATA_TYPE_BOOL].bytes; + return true; + } else { + // todo json operator + return true; + } return true; } diff --git a/source/libs/parser/test/newParserTest.cpp b/source/libs/parser/test/newParserTest.cpp index 973a6aff1ebaf0a40a4e31473c8758fcf019b4b5..16fd9f26d5b18147ccad57a40724c37232d979f5 100644 --- a/source/libs/parser/test/newParserTest.cpp +++ b/source/libs/parser/test/newParserTest.cpp @@ -55,10 +55,13 @@ protected: return (TSDB_CODE_SUCCESS != translateCode); } if (NULL != query_.pRoot && QUERY_NODE_SELECT_STMT == nodeType(query_.pRoot)) { - string sql; - selectToSql(query_.pRoot, sql); cout << "input sql : [" << cxt_.pSql << "]" << endl; - cout << "output sql : [" << sql << "]" << endl; + // string sql; + // selectToSql(query_.pRoot, sql); + // cout << "output sql : [" << sql << "]" << endl; + string str; + selectToStr(query_.pRoot, str); + cout << "translate str : \n" << str << endl; } return (TSDB_CODE_SUCCESS == translateCode); } @@ -67,6 +70,162 @@ private: static const int max_err_len = 1024; static const int max_sql_len = 1024 * 1024; + string dataTypeToStr(const SDataType& dt) { + switch (dt.type) { + case TSDB_DATA_TYPE_NULL: + return "NULL"; + case TSDB_DATA_TYPE_BOOL: + return "BOOL"; + case TSDB_DATA_TYPE_TINYINT: + return "TINYINT"; + case TSDB_DATA_TYPE_SMALLINT: + return "SMALLINT"; + case TSDB_DATA_TYPE_INT: + return "INT"; + case TSDB_DATA_TYPE_BIGINT: + return "BIGINT"; + case TSDB_DATA_TYPE_FLOAT: + return "FLOAT"; + case TSDB_DATA_TYPE_DOUBLE: + return "DOUBLE"; + case TSDB_DATA_TYPE_BINARY: + return "BINART(" + to_string(dt.bytes) + ")"; + case TSDB_DATA_TYPE_TIMESTAMP: + return "TIMESTAMP"; + case TSDB_DATA_TYPE_NCHAR: + return "NCHAR(" + to_string(dt.bytes) + ")"; + case TSDB_DATA_TYPE_UTINYINT: + return "UTINYINT"; + case TSDB_DATA_TYPE_USMALLINT: + return "USMALLINT"; + case TSDB_DATA_TYPE_UINT: + return "UINT"; + case TSDB_DATA_TYPE_UBIGINT: + return "UBIGINT"; + case TSDB_DATA_TYPE_VARCHAR: + return "VARCHAR(" + to_string(dt.bytes) + ")"; + case TSDB_DATA_TYPE_VARBINARY: + return "VARBINARY(" + to_string(dt.bytes) + ")"; + case TSDB_DATA_TYPE_JSON: + return "JSON"; + case TSDB_DATA_TYPE_DECIMAL: + return "DECIMAL(" + to_string(dt.precision) + ", " + to_string(dt.scale) + ")"; + case TSDB_DATA_TYPE_BLOB: + return "BLOB"; + default: + break; + } + return "Unknown Data Type " + to_string(dt.type); + } + + void nodeToStr(const SNode* node, string& str, bool isProject) { + if (nullptr == node) { + return; + } + + switch (nodeType(node)) { + case QUERY_NODE_COLUMN: { + SColumnNode* pCol = (SColumnNode*)node; + if ('\0' != pCol->dbName[0]) { + str.append(pCol->dbName); + str.append("."); + } + if ('\0' != pCol->tableAlias[0]) { + str.append(pCol->tableAlias); + str.append("."); + } + str.append(pCol->colName); + str.append(" [" + dataTypeToStr(pCol->node.resType) + "]"); + if (isProject) { + str.append(" AS " + string(pCol->node.aliasName)); + } + break; + } + case QUERY_NODE_VALUE: { + SValueNode* pVal = (SValueNode*)node; + str.append(pVal->literal); + str.append(" [" + dataTypeToStr(pVal->node.resType) + "]"); + if (isProject) { + str.append(" AS " + string(pVal->node.aliasName)); + } + break; + } + case QUERY_NODE_OPERATOR: { + SOperatorNode* pOp = (SOperatorNode*)node; + nodeToStr(pOp->pLeft, str, false); + str.append(opTypeToStr(pOp->opType)); + nodeToStr(pOp->pRight, str, false); + str.append(" [" + dataTypeToStr(pOp->node.resType) + "]"); + if (isProject) { + str.append(" AS " + string(pOp->node.aliasName)); + } + break; + } + default: + break; + } + } + + void nodeListToStr(const SNodeList* nodelist, const string& prefix, string& str, bool isProject = false) { + SNode* node = nullptr; + FOREACH(node, nodelist) { + str.append(prefix); + nodeToStr(node, str, isProject); + str.append("\n"); + } + } + + void tableToStr(const SNode* node, const string& prefix, string& str) { + const STableNode* table = (const STableNode*)node; + switch (nodeType(node)) { + case QUERY_NODE_REAL_TABLE: { + SRealTableNode* realTable = (SRealTableNode*)table; + str.append(prefix); + if ('\0' != realTable->table.dbName[0]) { + str.append(realTable->table.dbName); + str.append("."); + } + str.append(realTable->table.tableName); + str.append(string(" ") + realTable->table.tableAlias); + break; + } + case QUERY_NODE_TEMP_TABLE: { + STempTableNode* tempTable = (STempTableNode*)table; + str.append(prefix + "(\n"); + selectToStr(tempTable->pSubquery, str, prefix + "\t"); + str.append("\n"); + str.append(prefix + ") "); + str.append(tempTable->table.tableAlias); + break; + } + case QUERY_NODE_JOIN_TABLE: { + SJoinTableNode* joinTable = (SJoinTableNode*)table; + tableToStr(joinTable->pLeft, prefix, str); + str.append("\n" + prefix + "JOIN\n"); + tableToStr(joinTable->pRight, prefix, str); + if (nullptr != joinTable->pOnCond) { + str.append("\n" + prefix + "\tON "); + nodeToStr(joinTable->pOnCond, str, false); + } + break; + } + default: + break; + } + } + + void selectToStr(const SNode* node, string& str, const string& prefix = "") { + SSelectStmt* select = (SSelectStmt*)node; + str.append(prefix + "SELECT "); + if (select->isDistinct) { + str.append("DISTINCT"); + } + str.append("\n"); + nodeListToStr(select->pProjectionList, prefix + "\t", str, true); + str.append("\n" + prefix + "FROM\n"); + tableToStr(select->pFromTable, prefix + "\t", str); + } + void selectToSql(const SNode* node, string& sql) { SSelectStmt* select = (SSelectStmt*)node; sql.append("SELECT "); @@ -123,7 +282,7 @@ private: } } - string opTypeToSql(EOperatorType type) { + string opTypeToStr(EOperatorType type) { switch (type) { case OP_TYPE_ADD: return " + "; @@ -177,7 +336,7 @@ private: case QUERY_NODE_OPERATOR: { SOperatorNode* pOp = (SOperatorNode*)node; nodeToSql(pOp->pLeft, sql); - sql.append(opTypeToSql(pOp->opType)); + sql.append(opTypeToStr(pOp->opType)); nodeToSql(pOp->pRight, sql); break; } @@ -213,8 +372,7 @@ private: SQuery query_; }; -// SELECT * FROM t1 -TEST_F(NewParserTest, selectStar) { +TEST_F(NewParserTest, selectSimple) { setDatabase("root", "test"); bind("SELECT * FROM t1"); @@ -233,7 +391,14 @@ TEST_F(NewParserTest, selectStar) { ASSERT_TRUE(run()); } -TEST_F(NewParserTest, syntaxError) { +TEST_F(NewParserTest, selectExpression) { + setDatabase("root", "test"); + + bind("SELECT c1 + 10, c2 FROM t1"); + ASSERT_TRUE(run()); +} + +TEST_F(NewParserTest, selectSyntaxError) { setDatabase("root", "test"); bind("SELECTT * FROM t1"); @@ -249,7 +414,7 @@ TEST_F(NewParserTest, syntaxError) { ASSERT_TRUE(run(TSDB_CODE_FAILED)); } -TEST_F(NewParserTest, semanticError) { +TEST_F(NewParserTest, selectSemanticError) { setDatabase("root", "test"); bind("SELECT * FROM t10"); diff --git a/source/nodes/src/nodesTraverseFuncs.c b/source/nodes/src/nodesTraverseFuncs.c index 444ff7cbcf5f21c98c734603343a9eb1938b8d65..0702254b5f664e6f4e2c401dd8921a95daae11db 100644 --- a/source/nodes/src/nodesTraverseFuncs.c +++ b/source/nodes/src/nodesTraverseFuncs.c @@ -109,7 +109,7 @@ void nodesWalkNodePostOrder(SNode* pNode, FQueryNodeWalker walker, void* pContex } void nodesWalkListPostOrder(SNodeList* pList, FQueryNodeWalker walker, void* pContext) { - (void)walkList(pList, TRAVERSAL_PREORDER, walker, pContext); + (void)walkList(pList, TRAVERSAL_POSTORDER, walker, pContext); } bool nodesWalkStmt(SNode* pNode, FQueryNodeWalker walker, void* pContext) { diff --git a/source/nodes/src/nodesUtilFuncs.c b/source/nodes/src/nodesUtilFuncs.c index bf4c4a83ccf4487b40322fd579e4177cdb82bd04..af6cec755d3a5305dc8a684ab51ff7a61009275c 100644 --- a/source/nodes/src/nodesUtilFuncs.c +++ b/source/nodes/src/nodesUtilFuncs.c @@ -70,8 +70,19 @@ SNode* nodesMakeNode(ENodeType type) { return NULL; } -void nodesDestroyNode(SNode* pNode) { +static bool destroyNode(SNode* pNode, void* pContext) { + switch (nodeType(pNode)) { + case QUERY_NODE_VALUE: + tfree(((SValueNode*)pNode)->literal); + break; + default: + break; + } + tfree(pNode); +} +void nodesDestroyNode(SNode* pNode) { + nodesWalkNodePostOrder(pNode, destroyNode, NULL); } SNodeList* nodesMakeList() { @@ -103,13 +114,63 @@ SNodeList* nodesListAppend(SNodeList* pList, SNode* pNode) { } void nodesDestroyList(SNodeList* pList) { + SNode* node; + FOREACH(node, pList) { + nodesDestroyNode(node); + } + tfree(pList); +} + +bool nodesIsArithmeticOp(const SOperatorNode* pOp) { + switch (pOp->opType) { + case OP_TYPE_ADD: + case OP_TYPE_SUB: + case OP_TYPE_MULTI: + case OP_TYPE_DIV: + case OP_TYPE_MOD: + return true; + default: + break; + } + return false; +} +bool nodesIsComparisonOp(const SOperatorNode* pOp) { + switch (pOp->opType) { + case OP_TYPE_GREATER_THAN: + case OP_TYPE_GREATER_EQUAL: + case OP_TYPE_LOWER_THAN: + case OP_TYPE_LOWER_EQUAL: + case OP_TYPE_EQUAL: + case OP_TYPE_NOT_EQUAL: + case OP_TYPE_IN: + case OP_TYPE_NOT_IN: + case OP_TYPE_LIKE: + case OP_TYPE_NOT_LIKE: + case OP_TYPE_MATCH: + case OP_TYPE_NMATCH: + return true; + default: + break; + } + return false; } -bool nodesIsTimeorderQuery(const SNode* pQuery) { +bool nodesIsJsonOp(const SOperatorNode* pOp) { + switch (pOp->opType) { + case OP_TYPE_JSON_GET_VALUE: + case OP_TYPE_JSON_CONTAINS: + return true; + default: + break; + } + return false; +} +bool nodesIsTimeorderQuery(const SNode* pQuery) { + return false; } bool nodesIsTimelineQuery(const SNode* pQuery) { - + return false; } \ No newline at end of file