diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h
index c3c8b5c4ce..69673804fe 100644
--- a/include/libs/function/functionMgt.h
+++ b/include/libs/function/functionMgt.h
@@ -105,7 +105,6 @@ typedef struct SFuncExecEnv {
int32_t calcMemSize;
} SFuncExecEnv;
-typedef void* FuncMgtHandle;
typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo);
typedef void (*FExecProcess)(struct SqlFunctionCtx *pCtx);
@@ -120,9 +119,7 @@ typedef struct SFuncExecFuncs {
int32_t fmFuncMgtInit();
-int32_t fmGetHandle(FuncMgtHandle* pHandle);
-
-int32_t fmGetFuncInfo(FuncMgtHandle handle, const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
+int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
int32_t fmGetFuncResultType(SFunctionNode* pFunc);
@@ -136,7 +133,7 @@ bool fmIsTimeorderFunc(int32_t funcId);
int32_t fmFuncScanType(int32_t funcId);
-int32_t fmGetFuncExecFuncs(FuncMgtHandle handle, int32_t funcId, SFuncExecFuncs* pFpSet);
+int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet);
#ifdef __cplusplus
}
diff --git a/include/libs/nodes/nodes.h b/include/libs/nodes/nodes.h
index 321190d254..068b80cf59 100644
--- a/include/libs/nodes/nodes.h
+++ b/include/libs/nodes/nodes.h
@@ -49,7 +49,6 @@ typedef enum ENodeType {
QUERY_NODE_VALUE,
QUERY_NODE_OPERATOR,
QUERY_NODE_LOGIC_CONDITION,
- QUERY_NODE_IS_NULL_CONDITION,
QUERY_NODE_FUNCTION,
QUERY_NODE_REAL_TABLE,
QUERY_NODE_TEMP_TABLE,
@@ -62,6 +61,7 @@ typedef enum ENodeType {
QUERY_NODE_INTERVAL_WINDOW,
QUERY_NODE_NODE_LIST,
QUERY_NODE_FILL,
+ QUERY_NODE_COLUMN_REF,
// Only be used in parser module.
QUERY_NODE_RAW_EXPR,
@@ -69,7 +69,11 @@ typedef enum ENodeType {
// Statement nodes are used in parser and planner module.
QUERY_NODE_SET_OPERATOR,
QUERY_NODE_SELECT_STMT,
- QUERY_NODE_SHOW_STMT
+ QUERY_NODE_SHOW_STMT,
+
+ QUERY_NODE_LOGIC_PLAN_SCAN,
+ QUERY_NODE_LOGIC_PLAN_FILTER,
+ QUERY_NODE_LOGIC_PLAN_AGG
} ENodeType;
/**
@@ -121,7 +125,8 @@ void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* p
bool nodesEqualNode(const SNode* a, const SNode* b);
-void nodesCloneNode(const SNode* pNode);
+SNode* nodesCloneNode(const SNode* pNode);
+SNodeList* nodesCloneList(const SNodeList* pList);
int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h
index e1b16a7a1a..ea9653e4a8 100644
--- a/include/libs/nodes/querynodes.h
+++ b/include/libs/nodes/querynodes.h
@@ -37,7 +37,7 @@ typedef struct SDataType {
} SDataType;
typedef struct SExprNode {
- ENodeType nodeType;
+ ENodeType type;
SDataType resType;
char aliasName[TSDB_COL_NAME_LEN];
SNodeList* pAssociationList;
@@ -59,6 +59,11 @@ typedef struct SColumnNode {
SNode* pProjectRef;
} SColumnNode;
+typedef struct SColumnRef {
+ ENodeType type;
+ int32_t slotId;
+} SColumnRef;
+
typedef struct SValueNode {
SExprNode node; // QUERY_NODE_VALUE
char* literal;
@@ -80,6 +85,10 @@ typedef enum EOperatorType {
OP_TYPE_DIV,
OP_TYPE_MOD,
+ // bit operator
+ OP_TYPE_BIT_AND,
+ OP_TYPE_BIT_OR,
+
// comparison operator
OP_TYPE_GREATER_THAN,
OP_TYPE_GREATER_EQUAL,
@@ -93,6 +102,8 @@ typedef enum EOperatorType {
OP_TYPE_NOT_LIKE,
OP_TYPE_MATCH,
OP_TYPE_NMATCH,
+ OP_TYPE_IS_NULL,
+ OP_TYPE_IS_NOT_NULL,
// json operator
OP_TYPE_JSON_GET_VALUE,
@@ -118,12 +129,6 @@ typedef struct SLogicConditionNode {
SNodeList* pParameterList;
} SLogicConditionNode;
-typedef struct SIsNullCondNode {
- SExprNode node; // QUERY_NODE_IS_NULL_CONDITION
- SNode* pExpr;
- bool isNull;
-} SIsNullCondNode;
-
typedef struct SNodeListNode {
ENodeType type; // QUERY_NODE_NODE_LIST
SNodeList* pNodeList;
@@ -138,7 +143,7 @@ typedef struct SFunctionNode {
} SFunctionNode;
typedef struct STableNode {
- ENodeType type;
+ SExprNode node;
char dbName[TSDB_DB_NAME_LEN];
char tableName[TSDB_TABLE_NAME_LEN];
char tableAlias[TSDB_TABLE_NAME_LEN];
diff --git a/include/util/taoserror.h b/include/util/taoserror.h
index 0a822927ad..5c12d29b50 100644
--- a/include/util/taoserror.h
+++ b/include/util/taoserror.h
@@ -459,6 +459,7 @@ 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/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c
index 78d2feaa83..887f65a6ea 100644
--- a/source/libs/function/src/functionMgt.c
+++ b/source/libs/function/src/functionMgt.c
@@ -40,14 +40,8 @@ int32_t fmFuncMgtInit() {
return TSDB_CODE_SUCCESS;
}
-int32_t fmGetHandle(FuncMgtHandle* pHandle) {
- *pHandle = &gFunMgtService;
- return TSDB_CODE_SUCCESS;
-}
-
-int32_t fmGetFuncInfo(FuncMgtHandle handle, const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType) {
- SFuncMgtService* pService = (SFuncMgtService*)handle;
- void* pVal = taosHashGet(pService->pFuncNameHashTable, pFuncName, strlen(pFuncName));
+int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType) {
+ void* pVal = taosHashGet(gFunMgtService.pFuncNameHashTable, pFuncName, strlen(pFuncName));
if (NULL == pVal) {
return TSDB_CODE_FAILED;
}
@@ -66,6 +60,17 @@ int32_t fmGetFuncResultType(SFunctionNode* pFunc) {
return funcMgtBuiltins[pFunc->funcId].checkFunc(pFunc);
}
+int32_t fmGetFuncExecFuncs(int32_t funcId, SFuncExecFuncs* pFpSet) {
+ if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
+ return TSDB_CODE_FAILED;
+ }
+ pFpSet->getEnv = funcMgtBuiltins[funcId].getEnvFunc;
+ pFpSet->init = funcMgtBuiltins[funcId].initFunc;
+ pFpSet->process = funcMgtBuiltins[funcId].processFunc;
+ pFpSet->finalize = funcMgtBuiltins[funcId].finalizeFunc;
+ return TSDB_CODE_SUCCESS;
+}
+
bool fmIsAggFunc(int32_t funcId) {
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
return false;
diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c
index 2d0a6483ae..63bb11a821 100644
--- a/source/libs/nodes/src/nodesCloneFuncs.c
+++ b/source/libs/nodes/src/nodesCloneFuncs.c
@@ -13,8 +13,179 @@
* along with this program. If not, see .
*/
-#include "nodes.h"
+#include "querynodes.h"
+#include "taos.h"
-void nodesCloneNode(const SNode* pNode) {
+#define COPY_SCALAR_FIELD(fldname) \
+ do { \
+ (pDst)->fldname = (pSrc)->fldname; \
+ } while (0)
+#define COPY_CHAR_ARRAY_FIELD(fldname) \
+ do { \
+ strcpy((pDst)->fldname, (pSrc)->fldname); \
+ } while (0)
+
+#define COPY_CHAR_POINT_FIELD(fldname) \
+ do { \
+ (pDst)->fldname = strdup((pSrc)->fldname); \
+ } while (0)
+
+#define COPY_NODE_FIELD(fldname) \
+ do { \
+ (pDst)->fldname = nodesCloneNode((pSrc)->fldname); \
+ if (NULL == (pDst)->fldname) { \
+ nodesDestroyNode((SNode*)(pDst)); \
+ return NULL; \
+ } \
+ } while (0)
+
+#define COPY_NODE_LIST_FIELD(fldname) \
+ do { \
+ (pDst)->fldname = nodesCloneList((pSrc)->fldname); \
+ if (NULL == (pDst)->fldname) { \
+ nodesDestroyNode((SNode*)(pDst)); \
+ return NULL; \
+ } \
+ } while (0)
+
+static void dataTypeCopy(const SDataType* pSrc, SDataType* pDst) {
+ COPY_SCALAR_FIELD(type);
+ COPY_SCALAR_FIELD(precision);
+ COPY_SCALAR_FIELD(scale);
+ COPY_SCALAR_FIELD(bytes);
+}
+
+static void exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) {
+ COPY_SCALAR_FIELD(type);
+ dataTypeCopy(&pSrc->resType, &pDst->resType);
+ COPY_CHAR_ARRAY_FIELD(aliasName);
+ // COPY_NODE_LIST_FIELD(pAssociationList);
+}
+
+static SNode* columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) {
+ exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ COPY_SCALAR_FIELD(colId);
+ COPY_SCALAR_FIELD(colType);
+ COPY_CHAR_ARRAY_FIELD(dbName);
+ COPY_CHAR_ARRAY_FIELD(tableName);
+ COPY_CHAR_ARRAY_FIELD(tableAlias);
+ COPY_CHAR_ARRAY_FIELD(colName);
+ // COPY_NODE_FIELD(pProjectRef);
+ return (SNode*)pDst;
+}
+
+static SNode* valueNodeCopy(const SValueNode* pSrc, SValueNode* pDst) {
+ exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ COPY_CHAR_POINT_FIELD(literal);
+ COPY_SCALAR_FIELD(isDuration);
+ switch (pSrc->node.resType.type) {
+ case TSDB_DATA_TYPE_NULL:
+ break;
+ case TSDB_DATA_TYPE_BOOL:
+ COPY_SCALAR_FIELD(datum.b);
+ break;
+ case TSDB_DATA_TYPE_TINYINT:
+ case TSDB_DATA_TYPE_SMALLINT:
+ case TSDB_DATA_TYPE_INT:
+ case TSDB_DATA_TYPE_BIGINT:
+ case TSDB_DATA_TYPE_TIMESTAMP:
+ COPY_SCALAR_FIELD(datum.i);
+ break;
+ case TSDB_DATA_TYPE_UTINYINT:
+ case TSDB_DATA_TYPE_USMALLINT:
+ case TSDB_DATA_TYPE_UINT:
+ case TSDB_DATA_TYPE_UBIGINT:
+ COPY_SCALAR_FIELD(datum.u);
+ break;
+ case TSDB_DATA_TYPE_FLOAT:
+ case TSDB_DATA_TYPE_DOUBLE:
+ COPY_SCALAR_FIELD(datum.d);
+ break;
+ case TSDB_DATA_TYPE_BINARY:
+ case TSDB_DATA_TYPE_NCHAR:
+ case TSDB_DATA_TYPE_VARCHAR:
+ case TSDB_DATA_TYPE_VARBINARY:
+ COPY_CHAR_POINT_FIELD(datum.p);
+ break;
+ case TSDB_DATA_TYPE_JSON:
+ case TSDB_DATA_TYPE_DECIMAL:
+ case TSDB_DATA_TYPE_BLOB:
+ // todo
+ default:
+ break;
+ }
+ return (SNode*)pDst;
+}
+
+static SNode* operatorNodeCopy(const SOperatorNode* pSrc, SOperatorNode* pDst) {
+ exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ COPY_SCALAR_FIELD(opType);
+ COPY_NODE_FIELD(pLeft);
+ COPY_NODE_FIELD(pRight);
+ return (SNode*)pDst;
+}
+
+static SNode* logicConditionNodeCopy(const SLogicConditionNode* pSrc, SLogicConditionNode* pDst) {
+ exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ COPY_SCALAR_FIELD(condType);
+ COPY_NODE_LIST_FIELD(pParameterList);
+ return (SNode*)pDst;
+}
+
+static SNode* functionNodeCopy(const SFunctionNode* pSrc, SFunctionNode* pDst) {
+ exprNodeCopy((const SExprNode*)&pSrc, (SExprNode*)&pDst);
+ COPY_CHAR_ARRAY_FIELD(functionName);
+ COPY_SCALAR_FIELD(funcId);
+ COPY_SCALAR_FIELD(funcType);
+ COPY_NODE_LIST_FIELD(pParameterList);
+ return (SNode*)pDst;
+}
+
+SNode* nodesCloneNode(const SNode* pNode) {
+ if (NULL == pNode) {
+ return NULL;
+ }
+ SNode* pDst = nodesMakeNode(nodeType(pNode));
+ if (NULL == pDst) {
+ return NULL;
+ }
+ switch (nodeType(pNode)) {
+ case QUERY_NODE_COLUMN:
+ return columnNodeCopy((const SColumnNode*)pNode, (SColumnNode*)pDst);
+ case QUERY_NODE_VALUE:
+ return valueNodeCopy((const SValueNode*)pNode, (SValueNode*)pDst);
+ case QUERY_NODE_OPERATOR:
+ return operatorNodeCopy((const SOperatorNode*)pNode, (SOperatorNode*)pDst);
+ case QUERY_NODE_LOGIC_CONDITION:
+ return logicConditionNodeCopy((const SLogicConditionNode*)pNode, (SLogicConditionNode*)pDst);
+ case QUERY_NODE_FUNCTION:
+ return functionNodeCopy((const SFunctionNode*)pNode, (SFunctionNode*)pDst);
+ case QUERY_NODE_REAL_TABLE:
+ case QUERY_NODE_TEMP_TABLE:
+ case QUERY_NODE_JOIN_TABLE:
+ case QUERY_NODE_GROUPING_SET:
+ case QUERY_NODE_ORDER_BY_EXPR:
+ case QUERY_NODE_LIMIT:
+ default:
+ break;
+ }
+ return pDst;
+}
+
+SNodeList* nodesCloneList(const SNodeList* pList) {
+ SNodeList* pDst = nodesMakeList();
+ if (NULL == pDst) {
+ return NULL;
+ }
+ SNode* pNode;
+ FOREACH(pNode, pList) {
+ SNode* pNewNode = nodesCloneNode(pNode);
+ if (NULL == pNewNode) {
+ nodesDestroyList(pDst);
+ return NULL;
+ }
+ nodesListAppend(pDst, pNewNode);
+ }
+ return pDst;
}
diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c
index 959e10fb82..ad83bdbd19 100644
--- a/source/libs/nodes/src/nodesCodeFuncs.c
+++ b/source/libs/nodes/src/nodesCodeFuncs.c
@@ -21,7 +21,6 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
case QUERY_NODE_VALUE:
case QUERY_NODE_OPERATOR:
case QUERY_NODE_LOGIC_CONDITION:
- case QUERY_NODE_IS_NULL_CONDITION:
case QUERY_NODE_FUNCTION:
case QUERY_NODE_REAL_TABLE:
case QUERY_NODE_TEMP_TABLE:
diff --git a/source/libs/nodes/src/nodesEqualFuncs.c b/source/libs/nodes/src/nodesEqualFuncs.c
index 65eb6e9b32..fb2463d350 100644
--- a/source/libs/nodes/src/nodesEqualFuncs.c
+++ b/source/libs/nodes/src/nodesEqualFuncs.c
@@ -89,12 +89,6 @@ static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicCo
return true;
}
-static bool isNullConditionNodeEqual(const SIsNullCondNode* a, const SIsNullCondNode* b) {
- COMPARE_NODE_FIELD(pExpr);
- COMPARE_SCALAR_FIELD(isNull);
- return true;
-}
-
static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
COMPARE_SCALAR_FIELD(funcId);
COMPARE_NODE_LIST_FIELD(pParameterList);
@@ -123,8 +117,6 @@ bool nodesEqualNode(const SNode* a, const SNode* b) {
return operatorNodeEqual((const SOperatorNode*)a, (const SOperatorNode*)b);
case QUERY_NODE_LOGIC_CONDITION:
return logicConditionNodeEqual((const SLogicConditionNode*)a, (const SLogicConditionNode*)b);
- case QUERY_NODE_IS_NULL_CONDITION:
- return isNullConditionNodeEqual((const SIsNullCondNode*)a, (const SIsNullCondNode*)b);
case QUERY_NODE_FUNCTION:
return functionNodeEqual((const SFunctionNode*)a, (const SFunctionNode*)b);
case QUERY_NODE_REAL_TABLE:
diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c
index d1ded390db..b7e7ad6f0b 100644
--- a/source/libs/nodes/src/nodesTraverseFuncs.c
+++ b/source/libs/nodes/src/nodesTraverseFuncs.c
@@ -53,9 +53,6 @@ static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FNodeWalker walker
case QUERY_NODE_LOGIC_CONDITION:
res = walkList(((SLogicConditionNode*)pNode)->pParameterList, order, walker, pContext);
break;
- case QUERY_NODE_IS_NULL_CONDITION:
- res = walkNode(((SIsNullCondNode*)pNode)->pExpr, order, walker, pContext);
- break;
case QUERY_NODE_FUNCTION:
res = walkList(((SFunctionNode*)pNode)->pParameterList, order, walker, pContext);
break;
@@ -179,9 +176,6 @@ static EDealRes rewriteNode(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
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;
diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c
index 5d4ddd0e03..d94ef4d378 100644
--- a/source/libs/nodes/src/nodesUtilFuncs.c
+++ b/source/libs/nodes/src/nodesUtilFuncs.c
@@ -36,8 +36,6 @@ SNode* nodesMakeNode(ENodeType type) {
return makeNode(type, sizeof(SOperatorNode));
case QUERY_NODE_LOGIC_CONDITION:
return makeNode(type, sizeof(SLogicConditionNode));
- case QUERY_NODE_IS_NULL_CONDITION:
- return makeNode(type, sizeof(SIsNullCondNode));
case QUERY_NODE_FUNCTION:
return makeNode(type, sizeof(SFunctionNode));
case QUERY_NODE_REAL_TABLE:
diff --git a/source/libs/parser/inc/astCreateFuncs.h b/source/libs/parser/inc/astCreateFuncs.h
index 43bc5349e4..b44e621704 100644
--- a/source/libs/parser/inc/astCreateFuncs.h
+++ b/source/libs/parser/inc/astCreateFuncs.h
@@ -43,7 +43,6 @@ SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType typ
SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight);
SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft, SNode* pRight);
-SNode* createIsNullCondNode(SAstCreateContext* pCxt, SNode* pExpr, bool isNull);
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList);
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName, const SToken* pTableAlias);
diff --git a/source/libs/parser/inc/new_sql.y b/source/libs/parser/inc/new_sql.y
index c4668a0f9d..065cb95650 100644
--- a/source/libs/parser/inc/new_sql.y
+++ b/source/libs/parser/inc/new_sql.y
@@ -192,12 +192,12 @@ predicate(A) ::= expression(B) NOT BETWEEN expression(C) AND expression(D).
predicate(A) ::= expression(B) IS NULL(C). {
PARSER_TRACE;
SToken s = getTokenFromRawExprNode(pCxt, B);
- A = createRawExprNodeExt(pCxt, &s, &C, createIsNullCondNode(pCxt, releaseRawExprNode(pCxt, B), true));
+ A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, B), NULL));
}
predicate(A) ::= expression(B) IS NOT NULL(C). {
PARSER_TRACE;
SToken s = getTokenFromRawExprNode(pCxt, B);
- A = createRawExprNodeExt(pCxt, &s, &C, createIsNullCondNode(pCxt, releaseRawExprNode(pCxt, B), false));
+ A = createRawExprNodeExt(pCxt, &s, &C, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, B), NULL));
}
predicate(A) ::= expression(B) in_op(C) in_predicate_value(D). {
PARSER_TRACE;
diff --git a/source/libs/parser/inc/parserImpl.h b/source/libs/parser/inc/parserImpl.h
index b55060def7..4f6f0cf387 100644
--- a/source/libs/parser/inc/parserImpl.h
+++ b/source/libs/parser/inc/parserImpl.h
@@ -13,9 +13,6 @@
* along with this program. If not, see .
*/
-#include "querynodes.h"
-#include "parser.h"
-
#ifndef _TD_AST_CREATE_FUNCS_H_
#define _TD_AST_CREATE_FUNCS_H_
@@ -23,9 +20,19 @@
extern "C" {
#endif
+#include "querynodes.h"
+#include "parser.h"
+
+typedef enum EStmtType {
+ STMT_TYPE_CMD = 1,
+ STMT_TYPE_QUERY
+} EStmtType;
+
typedef struct SQuery {
+ EStmtType stmtType;
SNode* pRoot;
- // todo reslut meta
+ int32_t numOfResCols;
+ SSchema* pResSchema;
} SQuery;
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
diff --git a/source/libs/parser/src/astCreateFuncs.c b/source/libs/parser/src/astCreateFuncs.c
index ce2903f6aa..2615aca7f3 100644
--- a/source/libs/parser/src/astCreateFuncs.c
+++ b/source/libs/parser/src/astCreateFuncs.c
@@ -84,6 +84,10 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
}
SToken getTokenFromRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
+ if (NULL == pNode || QUERY_NODE_RAW_EXPR != nodeType(pNode)) {
+ pCxt->valid = false;
+ return nil_token;
+ }
SRawExprNode* target = (SRawExprNode*)pNode;
SToken t = { .type = 0, .z = target->p, .n = target->n};
return t;
@@ -166,14 +170,6 @@ SNode* createNotBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, SNode* pLeft,
createOperatorNode(pCxt, OP_TYPE_LOWER_THAN, pExpr, pLeft), createOperatorNode(pCxt, OP_TYPE_GREATER_THAN, pExpr, pRight));
}
-SNode* createIsNullCondNode(SAstCreateContext* pCxt, SNode* pExpr, bool isNull) {
- SIsNullCondNode* cond = (SIsNullCondNode*)nodesMakeNode(QUERY_NODE_IS_NULL_CONDITION);
- CHECK_OUT_OF_MEM(cond);
- cond->pExpr = pExpr;
- cond->isNull = isNull;
- return (SNode*)cond;
-}
-
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) {
SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
CHECK_OUT_OF_MEM(func);
@@ -292,7 +288,11 @@ SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) {
}
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
- strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, pAlias->n);
+ if (NULL == pNode || !pCxt->valid) {
+ return pNode;
+ }
+ uint32_t maxLen = sizeof(((SExprNode*)pNode)->aliasName);
+ strncpy(((SExprNode*)pNode)->aliasName, pAlias->z, pAlias->n > maxLen ? maxLen : pAlias->n);
return pNode;
}
diff --git a/source/libs/parser/src/new_sql.c b/source/libs/parser/src/new_sql.c
index 2b24448856..2d0c4b7eba 100644
--- a/source/libs/parser/src/new_sql.c
+++ b/source/libs/parser/src/new_sql.c
@@ -1717,7 +1717,7 @@ static YYACTIONTYPE yy_reduce(
{
PARSER_TRACE;
SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56);
- yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createIsNullCondNode(pCxt, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), true));
+ yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NULL, releaseRawExprNode(pCxt, yymsp[-2].minor.yy56), NULL));
}
yymsp[-2].minor.yy56 = yylhsminor.yy56;
break;
@@ -1725,7 +1725,7 @@ static YYACTIONTYPE yy_reduce(
{
PARSER_TRACE;
SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy56);
- yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createIsNullCondNode(pCxt, releaseRawExprNode(pCxt, yymsp[-3].minor.yy56), false));
+ yylhsminor.yy56 = createRawExprNodeExt(pCxt, &s, &yymsp[0].minor.yy0, createOperatorNode(pCxt, OP_TYPE_IS_NOT_NULL, releaseRawExprNode(pCxt, yymsp[-3].minor.yy56), NULL));
}
yymsp[-3].minor.yy56 = yylhsminor.yy56;
break;
diff --git a/source/libs/parser/src/parserImpl.c b/source/libs/parser/src/parserImpl.c
index d503cadd40..a2602c42ee 100644
--- a/source/libs/parser/src/parserImpl.c
+++ b/source/libs/parser/src/parserImpl.c
@@ -174,6 +174,19 @@ static uint32_t getToken(const char* z, uint32_t* tokenId) {
return n;
}
+static EStmtType getStmtType(const SNode* pRootNode) {
+ if (NULL == pRootNode) {
+ return STMT_TYPE_CMD;
+ }
+ switch (nodeType(pRootNode)) {
+ case QUERY_NODE_SELECT_STMT:
+ return STMT_TYPE_QUERY;
+ default:
+ break;
+ }
+ return STMT_TYPE_CMD;
+}
+
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
SAstCreateContext cxt;
createAstCreateContext(pParseCxt, &cxt);
@@ -181,15 +194,12 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
int32_t i = 0;
while (1) {
SToken t0 = {0};
- // printf("===========================\n");
if (cxt.pQueryCxt->pSql[i] == 0) {
NewParse(pParser, 0, t0, &cxt);
goto abort_parse;
}
- // printf("input: [%s]\n", cxt.pQueryCxt->pSql + i);
t0.n = getToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type);
t0.z = (char *)(cxt.pQueryCxt->pSql + i);
- // printf("token : %d %d [%s]\n", t0.type, t0.n, t0.z);
i += t0.n;
switch (t0.type) {
@@ -201,14 +211,12 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
NewParse(pParser, 0, t0, &cxt);
goto abort_parse;
}
-
case TK_QUESTION:
case TK_ILLEGAL: {
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
cxt.valid = false;
goto abort_parse;
}
-
case TK_HEX:
case TK_OCT:
case TK_BIN: {
@@ -216,7 +224,6 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
cxt.valid = false;
goto abort_parse;
}
-
default:
NewParse(pParser, t0.type, t0, &cxt);
// NewParseTrace(stdout, "");
@@ -227,9 +234,9 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
}
abort_parse:
- // printf("doParse completed.\n");
NewParseFree(pParser, free);
destroyAstCreateContext(&cxt);
+ pQuery->stmtType = getStmtType(cxt.pRootNode);
pQuery->pRoot = cxt.pRootNode;
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
}
@@ -255,7 +262,6 @@ static bool beforeHaving(ESqlClause clause) {
typedef struct STranslateContext {
SParseContext* pParseCxt;
- FuncMgtHandle fmgt;
int32_t errCode;
SMsgBuf msgBuf;
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
@@ -292,6 +298,8 @@ 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:
+ return "Out of memory";
default:
return "Unknown error";
}
@@ -376,12 +384,15 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol
pCol->node.resType = pExpr->resType;
}
-static int32_t createColumnNodeByTable(const STableNode* pTable, SNodeList* pList) {
+static int32_t createColumnNodeByTable(STranslateContext* pCxt, 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);
+ if (NULL == pCol) {
+ return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
+ }
setColumnInfoBySchema(pTable, pMeta->schema + i, pCol);
nodesListAppend(pList, (SNode*)pCol);
}
@@ -390,10 +401,14 @@ static int32_t createColumnNodeByTable(const STableNode* pTable, SNodeList* pLis
SNode* pNode;
FOREACH(pNode, pProjectList) {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
+ if (NULL == pCol) {
+ return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
+ }
setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol);
nodesListAppend(pList, (SNode*)pCol);
}
}
+ return TSDB_CODE_SUCCESS;
}
static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
@@ -539,7 +554,7 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
case TSDB_DATA_TYPE_UTINYINT:
case TSDB_DATA_TYPE_USMALLINT:
case TSDB_DATA_TYPE_UINT:
- case TSDB_DATA_TYPE_UBIGINT:{
+ case TSDB_DATA_TYPE_UBIGINT: {
char* endPtr = NULL;
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
break;
@@ -556,12 +571,20 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
case TSDB_DATA_TYPE_VARBINARY: {
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);
+ return DEAL_RES_ERROR;
+ }
trimStringCopy(pVal->literal, n, pVal->datum.p);
break;
}
case TSDB_DATA_TYPE_TIMESTAMP: {
int32_t n = strlen(pVal->literal);
char* tmp = calloc(1, n);
+ if (NULL == tmp) {
+ generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
+ return DEAL_RES_ERROR;
+ }
int32_t len = trimStringCopy(pVal->literal, n, tmp);
if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
tfree(tmp);
@@ -608,7 +631,7 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
}
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
- if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pCxt->fmgt, pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) {
+ if (TSDB_CODE_SUCCESS != fmGetFuncInfo(pFunc->functionName, &pFunc->funcId, &pFunc->funcType)) {
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName);
return DEAL_RES_ERROR;
}
@@ -806,9 +829,15 @@ static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
size_t nums = taosArrayGetSize(pTables);
pSelect->pProjectionList = nodesMakeList();
+ if (NULL == pSelect->pProjectionList) {
+ return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
+ }
for (size_t i = 0; i < nums; ++i) {
STableNode* pTable = taosArrayGetP(pTables, i);
- createColumnNodeByTable(pTable, pSelect->pProjectionList);
+ int32_t code = createColumnNodeByTable(pCxt, pTable, pSelect->pProjectionList);
+ if (TSDB_CODE_SUCCESS != code) {
+ return code;
+ }
}
*pIsSelectStar = true;
} else {
@@ -848,7 +877,7 @@ static int32_t getPositionValue(const SValueNode* pVal) {
return -1;
}
-static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) {
+static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, bool* pOther) {
*pOther = false;
SNode* pNode;
FOREACH(pNode, pOrderByList) {
@@ -856,18 +885,20 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
SValueNode* pVal = (SValueNode*)pExpr;
if (!translateValue(pCxt, pVal)) {
- return false;
+ return pCxt->errCode;
}
- int32_t pos = getPositionValue((SValueNode*)pExpr);
+ int32_t pos = getPositionValue(pVal);
if (pos < 0) {
ERASE_NODE(pOrderByList);
nodesDestroyNode(pNode);
continue;
} else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) {
- generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
- return false;
+ return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
} else {
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
+ if (NULL == pCol) {
+ return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
+ }
setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol);
((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol;
nodesDestroyNode(pExpr);
@@ -876,19 +907,20 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
*pOther = true;
}
}
- return true;
+ return TSDB_CODE_SUCCESS;
}
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
bool other;
- if (!translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other)) {
- return pCxt->errCode;
+ int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other);
+ if (TSDB_CODE_SUCCESS != code) {
+ return code;
}
if (!other) {
return TSDB_CODE_SUCCESS;
}
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
- int32_t code = translateExprList(pCxt, pSelect->pOrderByList);
+ code = translateExprList(pCxt, pSelect->pOrderByList);
if (TSDB_CODE_SUCCESS == code) {
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
}
@@ -945,12 +977,6 @@ static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) {
return translateTable(pCxt, pTable);
}
-// typedef struct SSelectStmt {
-// bool isDistinct;
-// SNode* pLimit;
-// SNode* pSlimit;
-// } SSelectStmt;
-
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
pCxt->pCurrStmt = pSelect;
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
@@ -1004,6 +1030,26 @@ static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
return code;
}
+int32_t setReslutSchema(STranslateContext* pCxt, SQuery* pQuery) {
+ if (QUERY_NODE_SELECT_STMT == nodeType(pQuery->pRoot)) {
+ SSelectStmt* pSelect = (SSelectStmt*)pQuery->pRoot;
+ 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);
+ }
+ SNode* pNode;
+ int32_t index = 0;
+ FOREACH(pNode, pSelect->pProjectionList) {
+ SExprNode* pExpr = (SExprNode*)pNode;
+ pQuery->pResSchema[index].type = pExpr->resType.type;
+ pQuery->pResSchema[index].bytes = pExpr->resType.bytes;
+ strcpy(pQuery->pResSchema[index].name, pExpr->aliasName);
+ }
+ }
+ return TSDB_CODE_SUCCESS;
+}
+
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
STranslateContext cxt = {
.pParseCxt = pParseCxt,
@@ -1014,12 +1060,11 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
.currClause = 0
};
int32_t code = fmFuncMgtInit();
- if (TSDB_CODE_SUCCESS != code) {
- return code;
+ if (TSDB_CODE_SUCCESS == code) {
+ code = translateQuery(&cxt, pQuery->pRoot);
}
- code = fmGetHandle(&cxt.fmgt);
- if (TSDB_CODE_SUCCESS != code) {
- return code;
+ if (TSDB_CODE_SUCCESS == code && STMT_TYPE_QUERY == pQuery->stmtType) {
+ code = setReslutSchema(&cxt, pQuery);
}
- return translateQuery(&cxt, pQuery->pRoot);
+ return code;
}
diff --git a/source/libs/planner/CMakeLists.txt b/source/libs/planner/CMakeLists.txt
index 8d8c148fde..14b4488e6a 100644
--- a/source/libs/planner/CMakeLists.txt
+++ b/source/libs/planner/CMakeLists.txt
@@ -8,7 +8,7 @@ target_include_directories(
target_link_libraries(
planner
- PRIVATE os util catalog cjson parser function qcom
+ PRIVATE os util nodes catalog cjson parser function qcom
PUBLIC transport
)
diff --git a/source/libs/planner/inc/plannerImpl.h b/source/libs/planner/inc/plannerImpl.h
index 050329693c..1f8df990b1 100644
--- a/source/libs/planner/inc/plannerImpl.h
+++ b/source/libs/planner/inc/plannerImpl.h
@@ -20,6 +20,33 @@
extern "C" {
#endif
+#include "querynodes.h"
+#include "planner.h"
+
+typedef struct SLogicNode {
+ ENodeType type;
+ SNodeList* pTargets;
+ SNode* pConditions;
+ SNodeList* pChildren;
+ struct SLogicNode* pParent;
+} SLogicNode;
+
+typedef struct SScanLogicNode {
+ SLogicNode node;
+ SNodeList* pScanCols;
+ struct STableMeta* pMeta;
+} SScanLogicNode;
+
+typedef struct SFilterLogicNode {
+ SLogicNode node;
+} SFilterLogicNode;
+
+typedef struct SAggLogicNode {
+ SLogicNode node;
+ SNodeList* pGroupKeys;
+ SNodeList* pAggFuncs;
+} SAggLogicNode;
+
#ifdef __cplusplus
}
#endif
diff --git a/source/libs/planner/src/plannerImpl.c b/source/libs/planner/src/plannerImpl.c
index 6acb927db9..ddb3023bb3 100644
--- a/source/libs/planner/src/plannerImpl.c
+++ b/source/libs/planner/src/plannerImpl.c
@@ -13,7 +13,192 @@
* along with this program. If not, see .
*/
+#include "plannerImpl.h"
+#include "functionMgt.h"
-// int32_t getPlan(SNode* pRoot, SQueryPlanNode** pQueryPlan) {
+static SLogicNode* createQueryLogicNode(SNode* pStmt);
-// }
\ No newline at end of file
+typedef struct SCollectColumnsCxt {
+ SNodeList* pCols;
+ SHashObj* pColIdHash;
+} SCollectColumnsCxt;
+
+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 SRewriteExprCxt {
+ SNodeList* pTargets;
+} SRewriteExprCxt;
+
+static EDealRes doRewriteExpr(SNode** pNode, void* pContext) {
+ SRewriteExprCxt* pCxt = (SRewriteExprCxt*)pContext;
+ SNode* pTarget;
+ int32_t index = 0;
+ FOREACH(pTarget, pCxt->pTargets) {
+ if (nodesEqualNode(pTarget, *pNode)) {
+ nodesDestroyNode(*pNode);
+ *pNode = nodesMakeNode(QUERY_NODE_COLUMN_REF);
+ ((SColumnRef*)*pNode)->slotId = index;
+ return DEAL_RES_IGNORE_CHILD;
+ }
+ ++index;
+ }
+ 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 SLogicNode* pushLogicNode(SLogicNode* pRoot, SLogicNode* pNode) {
+ if (NULL == pRoot) {
+ return pNode;
+ }
+ if (NULL == pNode) {
+ return pRoot;
+ }
+ pRoot->pParent = pNode;
+ if (NULL == pNode->pChildren) {
+ pNode->pChildren = nodesMakeList();
+ }
+ nodesListAppend(pNode->pChildren, (SNode*)pRoot);
+ return pNode;
+}
+
+static SNodeList* createScanTargets(SNodeList* pCols) {
+
+}
+
+static SLogicNode* createScanLogicNode(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);
+ pScan->pMeta = pRealTable->pMeta;
+ return (SLogicNode*)pScan;
+}
+
+static SLogicNode* createSubqueryLogicNode(SSelectStmt* pSelect, STempTableNode* pTable) {
+ return createQueryLogicNode(pTable->pSubquery);
+}
+
+static SLogicNode* createLogicNodeByTable(SSelectStmt* pSelect, SNode* pTable) {
+ switch (nodeType(pTable)) {
+ case QUERY_NODE_REAL_TABLE:
+ return createScanLogicNode(pSelect, (SRealTableNode*)pTable);
+ case QUERY_NODE_TEMP_TABLE:
+ return createSubqueryLogicNode(pSelect, (STempTableNode*)pTable);
+ case QUERY_NODE_JOIN_TABLE:
+ default:
+ break;
+ }
+ return NULL;
+}
+
+static SLogicNode* createFilterLogicNode(SNode* pWhere) {
+ if (NULL == pWhere) {
+ return NULL;
+ }
+ SFilterLogicNode* pFilter = (SFilterLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_FILTER);
+ pFilter->node.pConditions = nodesCloneNode(pWhere);
+ return (SLogicNode*)pFilter;
+}
+
+static SLogicNode* createAggLogicNode(SSelectStmt* pSelect, SNodeList* pGroupByList, SNode* pHaving) {
+ SNodeList* pAggFuncs = collectAggFuncs(pSelect);
+ if (NULL == pAggFuncs && NULL == pGroupByList) {
+ return NULL;
+ }
+ SAggLogicNode* pAgg = (SAggLogicNode*)nodesMakeNode(QUERY_NODE_LOGIC_PLAN_AGG);
+ pAgg->pGroupKeys = nodesCloneList(pGroupByList);
+ pAgg->pAggFuncs = nodesCloneList(pAggFuncs);
+ pAgg->node.pConditions = nodesCloneNode(pHaving);
+ 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));
+ return pRoot;
+}
+
+static SLogicNode* createQueryLogicNode(SNode* pStmt) {
+ switch (nodeType(pStmt)) {
+ case QUERY_NODE_SELECT_STMT:
+ return createSelectLogicNode((SSelectStmt*)pStmt);
+ default:
+ break;
+ }
+}
+
+int32_t createLogicPlan(SNode* pNode, SLogicNode** pLogicNode) {
+ *pLogicNode = createQueryLogicNode(pNode);
+ return TSDB_CODE_SUCCESS;
+}