提交 d2f1e633 编写于 作者: X Xiaoyu Wang

TD-13338 SELECT statement translate code

上级 13c9aa55
......@@ -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);
......
......@@ -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
}
......
......@@ -28,7 +28,6 @@ typedef struct SAstCreateContext {
bool notSupport;
bool valid;
SNode* pRootNode;
SHashObj* pResourceHash;
} SAstCreateContext;
int32_t createAstCreateContext(SParseContext* pQueryCxt, SAstCreateContext* pCxt);
......
......@@ -13,11 +13,6 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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);
......
......@@ -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);
......
......@@ -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;
}
......
......@@ -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");
......
......@@ -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) {
......
......@@ -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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册