Merge pull request #10287 from taosdata/feature/3.0_wxy
TD-13495 planner refactoring
This commit is contained in:
commit
ce824cdaa4
|
@ -105,7 +105,6 @@ typedef struct SFuncExecEnv {
|
||||||
int32_t calcMemSize;
|
int32_t calcMemSize;
|
||||||
} SFuncExecEnv;
|
} SFuncExecEnv;
|
||||||
|
|
||||||
typedef void* FuncMgtHandle;
|
|
||||||
typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
typedef bool (*FExecGetEnv)(SFunctionNode* pFunc, SFuncExecEnv* pEnv);
|
||||||
typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo);
|
typedef bool (*FExecInit)(struct SqlFunctionCtx *pCtx, struct SResultRowEntryInfo* pResultCellInfo);
|
||||||
typedef void (*FExecProcess)(struct SqlFunctionCtx *pCtx);
|
typedef void (*FExecProcess)(struct SqlFunctionCtx *pCtx);
|
||||||
|
@ -120,9 +119,7 @@ typedef struct SFuncExecFuncs {
|
||||||
|
|
||||||
int32_t fmFuncMgtInit();
|
int32_t fmFuncMgtInit();
|
||||||
|
|
||||||
int32_t fmGetHandle(FuncMgtHandle* pHandle);
|
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
||||||
|
|
||||||
int32_t fmGetFuncInfo(FuncMgtHandle handle, const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType);
|
|
||||||
|
|
||||||
int32_t fmGetFuncResultType(SFunctionNode* pFunc);
|
int32_t fmGetFuncResultType(SFunctionNode* pFunc);
|
||||||
|
|
||||||
|
@ -136,7 +133,7 @@ bool fmIsTimeorderFunc(int32_t funcId);
|
||||||
|
|
||||||
int32_t fmFuncScanType(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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_VALUE,
|
QUERY_NODE_VALUE,
|
||||||
QUERY_NODE_OPERATOR,
|
QUERY_NODE_OPERATOR,
|
||||||
QUERY_NODE_LOGIC_CONDITION,
|
QUERY_NODE_LOGIC_CONDITION,
|
||||||
QUERY_NODE_IS_NULL_CONDITION,
|
|
||||||
QUERY_NODE_FUNCTION,
|
QUERY_NODE_FUNCTION,
|
||||||
QUERY_NODE_REAL_TABLE,
|
QUERY_NODE_REAL_TABLE,
|
||||||
QUERY_NODE_TEMP_TABLE,
|
QUERY_NODE_TEMP_TABLE,
|
||||||
|
@ -62,6 +61,7 @@ typedef enum ENodeType {
|
||||||
QUERY_NODE_INTERVAL_WINDOW,
|
QUERY_NODE_INTERVAL_WINDOW,
|
||||||
QUERY_NODE_NODE_LIST,
|
QUERY_NODE_NODE_LIST,
|
||||||
QUERY_NODE_FILL,
|
QUERY_NODE_FILL,
|
||||||
|
QUERY_NODE_COLUMN_REF,
|
||||||
|
|
||||||
// Only be used in parser module.
|
// Only be used in parser module.
|
||||||
QUERY_NODE_RAW_EXPR,
|
QUERY_NODE_RAW_EXPR,
|
||||||
|
@ -69,7 +69,11 @@ typedef enum ENodeType {
|
||||||
// Statement nodes are used in parser and planner module.
|
// Statement nodes are used in parser and planner module.
|
||||||
QUERY_NODE_SET_OPERATOR,
|
QUERY_NODE_SET_OPERATOR,
|
||||||
QUERY_NODE_SELECT_STMT,
|
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;
|
} ENodeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -121,7 +125,8 @@ void nodesRewriteListPostOrder(SNodeList* pList, FNodeRewriter rewriter, void* p
|
||||||
|
|
||||||
bool nodesEqualNode(const SNode* a, const SNode* b);
|
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 nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen);
|
||||||
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
int32_t nodesStringToNode(const char* pStr, SNode** pNode);
|
||||||
|
|
|
@ -37,7 +37,7 @@ typedef struct SDataType {
|
||||||
} SDataType;
|
} SDataType;
|
||||||
|
|
||||||
typedef struct SExprNode {
|
typedef struct SExprNode {
|
||||||
ENodeType nodeType;
|
ENodeType type;
|
||||||
SDataType resType;
|
SDataType resType;
|
||||||
char aliasName[TSDB_COL_NAME_LEN];
|
char aliasName[TSDB_COL_NAME_LEN];
|
||||||
SNodeList* pAssociationList;
|
SNodeList* pAssociationList;
|
||||||
|
@ -59,6 +59,11 @@ typedef struct SColumnNode {
|
||||||
SNode* pProjectRef;
|
SNode* pProjectRef;
|
||||||
} SColumnNode;
|
} SColumnNode;
|
||||||
|
|
||||||
|
typedef struct SColumnRef {
|
||||||
|
ENodeType type;
|
||||||
|
int32_t slotId;
|
||||||
|
} SColumnRef;
|
||||||
|
|
||||||
typedef struct SValueNode {
|
typedef struct SValueNode {
|
||||||
SExprNode node; // QUERY_NODE_VALUE
|
SExprNode node; // QUERY_NODE_VALUE
|
||||||
char* literal;
|
char* literal;
|
||||||
|
@ -80,6 +85,10 @@ typedef enum EOperatorType {
|
||||||
OP_TYPE_DIV,
|
OP_TYPE_DIV,
|
||||||
OP_TYPE_MOD,
|
OP_TYPE_MOD,
|
||||||
|
|
||||||
|
// bit operator
|
||||||
|
OP_TYPE_BIT_AND,
|
||||||
|
OP_TYPE_BIT_OR,
|
||||||
|
|
||||||
// comparison operator
|
// comparison operator
|
||||||
OP_TYPE_GREATER_THAN,
|
OP_TYPE_GREATER_THAN,
|
||||||
OP_TYPE_GREATER_EQUAL,
|
OP_TYPE_GREATER_EQUAL,
|
||||||
|
@ -93,6 +102,8 @@ typedef enum EOperatorType {
|
||||||
OP_TYPE_NOT_LIKE,
|
OP_TYPE_NOT_LIKE,
|
||||||
OP_TYPE_MATCH,
|
OP_TYPE_MATCH,
|
||||||
OP_TYPE_NMATCH,
|
OP_TYPE_NMATCH,
|
||||||
|
OP_TYPE_IS_NULL,
|
||||||
|
OP_TYPE_IS_NOT_NULL,
|
||||||
|
|
||||||
// json operator
|
// json operator
|
||||||
OP_TYPE_JSON_GET_VALUE,
|
OP_TYPE_JSON_GET_VALUE,
|
||||||
|
@ -118,12 +129,6 @@ typedef struct SLogicConditionNode {
|
||||||
SNodeList* pParameterList;
|
SNodeList* pParameterList;
|
||||||
} SLogicConditionNode;
|
} SLogicConditionNode;
|
||||||
|
|
||||||
typedef struct SIsNullCondNode {
|
|
||||||
SExprNode node; // QUERY_NODE_IS_NULL_CONDITION
|
|
||||||
SNode* pExpr;
|
|
||||||
bool isNull;
|
|
||||||
} SIsNullCondNode;
|
|
||||||
|
|
||||||
typedef struct SNodeListNode {
|
typedef struct SNodeListNode {
|
||||||
ENodeType type; // QUERY_NODE_NODE_LIST
|
ENodeType type; // QUERY_NODE_NODE_LIST
|
||||||
SNodeList* pNodeList;
|
SNodeList* pNodeList;
|
||||||
|
@ -138,7 +143,7 @@ typedef struct SFunctionNode {
|
||||||
} SFunctionNode;
|
} SFunctionNode;
|
||||||
|
|
||||||
typedef struct STableNode {
|
typedef struct STableNode {
|
||||||
ENodeType type;
|
SExprNode node;
|
||||||
char dbName[TSDB_DB_NAME_LEN];
|
char dbName[TSDB_DB_NAME_LEN];
|
||||||
char tableName[TSDB_TABLE_NAME_LEN];
|
char tableName[TSDB_TABLE_NAME_LEN];
|
||||||
char tableAlias[TSDB_TABLE_NAME_LEN];
|
char tableAlias[TSDB_TABLE_NAME_LEN];
|
||||||
|
|
|
@ -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_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_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_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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,14 +40,8 @@ int32_t fmFuncMgtInit() {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t fmGetHandle(FuncMgtHandle* pHandle) {
|
int32_t fmGetFuncInfo(const char* pFuncName, int32_t* pFuncId, int32_t* pFuncType) {
|
||||||
*pHandle = &gFunMgtService;
|
void* pVal = taosHashGet(gFunMgtService.pFuncNameHashTable, pFuncName, strlen(pFuncName));
|
||||||
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));
|
|
||||||
if (NULL == pVal) {
|
if (NULL == pVal) {
|
||||||
return TSDB_CODE_FAILED;
|
return TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -66,6 +60,17 @@ int32_t fmGetFuncResultType(SFunctionNode* pFunc) {
|
||||||
return funcMgtBuiltins[pFunc->funcId].checkFunc(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) {
|
bool fmIsAggFunc(int32_t funcId) {
|
||||||
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
|
if (funcId < 0 || funcId >= funcMgtBuiltinsNum) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -13,8 +13,179 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ int32_t nodesNodeToString(const SNode* pNode, char** pStr, int32_t* pLen) {
|
||||||
case QUERY_NODE_VALUE:
|
case QUERY_NODE_VALUE:
|
||||||
case QUERY_NODE_OPERATOR:
|
case QUERY_NODE_OPERATOR:
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
case QUERY_NODE_IS_NULL_CONDITION:
|
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
case QUERY_NODE_TEMP_TABLE:
|
case QUERY_NODE_TEMP_TABLE:
|
||||||
|
|
|
@ -89,12 +89,6 @@ static bool logicConditionNodeEqual(const SLogicConditionNode* a, const SLogicCo
|
||||||
return true;
|
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) {
|
static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) {
|
||||||
COMPARE_SCALAR_FIELD(funcId);
|
COMPARE_SCALAR_FIELD(funcId);
|
||||||
COMPARE_NODE_LIST_FIELD(pParameterList);
|
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);
|
return operatorNodeEqual((const SOperatorNode*)a, (const SOperatorNode*)b);
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
return logicConditionNodeEqual((const SLogicConditionNode*)a, (const SLogicConditionNode*)b);
|
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:
|
case QUERY_NODE_FUNCTION:
|
||||||
return functionNodeEqual((const SFunctionNode*)a, (const SFunctionNode*)b);
|
return functionNodeEqual((const SFunctionNode*)a, (const SFunctionNode*)b);
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
|
|
|
@ -53,9 +53,6 @@ static EDealRes walkNode(SNode* pNode, ETraversalOrder order, FNodeWalker walker
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
res = walkList(((SLogicConditionNode*)pNode)->pParameterList, order, walker, pContext);
|
res = walkList(((SLogicConditionNode*)pNode)->pParameterList, order, walker, pContext);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_IS_NULL_CONDITION:
|
|
||||||
res = walkNode(((SIsNullCondNode*)pNode)->pExpr, order, walker, pContext);
|
|
||||||
break;
|
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
res = walkList(((SFunctionNode*)pNode)->pParameterList, order, walker, pContext);
|
res = walkList(((SFunctionNode*)pNode)->pParameterList, order, walker, pContext);
|
||||||
break;
|
break;
|
||||||
|
@ -179,9 +176,6 @@ static EDealRes rewriteNode(SNode** pRawNode, ETraversalOrder order, FNodeRewrit
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
res = rewriteList(((SLogicConditionNode*)pNode)->pParameterList, order, rewriter, pContext);
|
res = rewriteList(((SLogicConditionNode*)pNode)->pParameterList, order, rewriter, pContext);
|
||||||
break;
|
break;
|
||||||
case QUERY_NODE_IS_NULL_CONDITION:
|
|
||||||
res = rewriteNode(&(((SIsNullCondNode*)pNode)->pExpr), order, rewriter, pContext);
|
|
||||||
break;
|
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
res = rewriteList(((SFunctionNode*)pNode)->pParameterList, order, rewriter, pContext);
|
res = rewriteList(((SFunctionNode*)pNode)->pParameterList, order, rewriter, pContext);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -36,8 +36,6 @@ SNode* nodesMakeNode(ENodeType type) {
|
||||||
return makeNode(type, sizeof(SOperatorNode));
|
return makeNode(type, sizeof(SOperatorNode));
|
||||||
case QUERY_NODE_LOGIC_CONDITION:
|
case QUERY_NODE_LOGIC_CONDITION:
|
||||||
return makeNode(type, sizeof(SLogicConditionNode));
|
return makeNode(type, sizeof(SLogicConditionNode));
|
||||||
case QUERY_NODE_IS_NULL_CONDITION:
|
|
||||||
return makeNode(type, sizeof(SIsNullCondNode));
|
|
||||||
case QUERY_NODE_FUNCTION:
|
case QUERY_NODE_FUNCTION:
|
||||||
return makeNode(type, sizeof(SFunctionNode));
|
return makeNode(type, sizeof(SFunctionNode));
|
||||||
case QUERY_NODE_REAL_TABLE:
|
case QUERY_NODE_REAL_TABLE:
|
||||||
|
|
|
@ -43,7 +43,6 @@ SNode* createLogicConditionNode(SAstCreateContext* pCxt, ELogicConditionType typ
|
||||||
SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight);
|
SNode* createOperatorNode(SAstCreateContext* pCxt, EOperatorType type, SNode* pLeft, SNode* pRight);
|
||||||
SNode* createBetweenAnd(SAstCreateContext* pCxt, SNode* pExpr, 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* 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* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList);
|
||||||
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
|
SNode* createNodeListNode(SAstCreateContext* pCxt, SNodeList* pList);
|
||||||
SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName, const SToken* pTableAlias);
|
SNode* createRealTableNode(SAstCreateContext* pCxt, const SToken* pDbName, const SToken* pTableName, const SToken* pTableAlias);
|
||||||
|
|
|
@ -192,12 +192,12 @@ predicate(A) ::= expression(B) NOT BETWEEN expression(C) AND expression(D).
|
||||||
predicate(A) ::= expression(B) IS NULL(C). {
|
predicate(A) ::= expression(B) IS NULL(C). {
|
||||||
PARSER_TRACE;
|
PARSER_TRACE;
|
||||||
SToken s = getTokenFromRawExprNode(pCxt, B);
|
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). {
|
predicate(A) ::= expression(B) IS NOT NULL(C). {
|
||||||
PARSER_TRACE;
|
PARSER_TRACE;
|
||||||
SToken s = getTokenFromRawExprNode(pCxt, B);
|
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). {
|
predicate(A) ::= expression(B) in_op(C) in_predicate_value(D). {
|
||||||
PARSER_TRACE;
|
PARSER_TRACE;
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "querynodes.h"
|
|
||||||
#include "parser.h"
|
|
||||||
|
|
||||||
#ifndef _TD_AST_CREATE_FUNCS_H_
|
#ifndef _TD_AST_CREATE_FUNCS_H_
|
||||||
#define _TD_AST_CREATE_FUNCS_H_
|
#define _TD_AST_CREATE_FUNCS_H_
|
||||||
|
|
||||||
|
@ -23,9 +20,19 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "querynodes.h"
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
typedef enum EStmtType {
|
||||||
|
STMT_TYPE_CMD = 1,
|
||||||
|
STMT_TYPE_QUERY
|
||||||
|
} EStmtType;
|
||||||
|
|
||||||
typedef struct SQuery {
|
typedef struct SQuery {
|
||||||
|
EStmtType stmtType;
|
||||||
SNode* pRoot;
|
SNode* pRoot;
|
||||||
// todo reslut meta
|
int32_t numOfResCols;
|
||||||
|
SSchema* pResSchema;
|
||||||
} SQuery;
|
} SQuery;
|
||||||
|
|
||||||
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
|
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery);
|
||||||
|
|
|
@ -84,6 +84,10 @@ SNode* releaseRawExprNode(SAstCreateContext* pCxt, SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SToken getTokenFromRawExprNode(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;
|
SRawExprNode* target = (SRawExprNode*)pNode;
|
||||||
SToken t = { .type = 0, .z = target->p, .n = target->n};
|
SToken t = { .type = 0, .z = target->p, .n = target->n};
|
||||||
return t;
|
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));
|
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) {
|
SNode* createFunctionNode(SAstCreateContext* pCxt, const SToken* pFuncName, SNodeList* pParameterList) {
|
||||||
SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
SFunctionNode* func = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION);
|
||||||
CHECK_OUT_OF_MEM(func);
|
CHECK_OUT_OF_MEM(func);
|
||||||
|
@ -292,7 +288,11 @@ SNode* createGroupingSetNode(SAstCreateContext* pCxt, SNode* pNode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
SNode* setProjectionAlias(SAstCreateContext* pCxt, SNode* pNode, const SToken* pAlias) {
|
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;
|
return pNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1717,7 +1717,7 @@ static YYACTIONTYPE yy_reduce(
|
||||||
{
|
{
|
||||||
PARSER_TRACE;
|
PARSER_TRACE;
|
||||||
SToken s = getTokenFromRawExprNode(pCxt, yymsp[-2].minor.yy56);
|
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;
|
yymsp[-2].minor.yy56 = yylhsminor.yy56;
|
||||||
break;
|
break;
|
||||||
|
@ -1725,7 +1725,7 @@ static YYACTIONTYPE yy_reduce(
|
||||||
{
|
{
|
||||||
PARSER_TRACE;
|
PARSER_TRACE;
|
||||||
SToken s = getTokenFromRawExprNode(pCxt, yymsp[-3].minor.yy56);
|
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;
|
yymsp[-3].minor.yy56 = yylhsminor.yy56;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -174,6 +174,19 @@ static uint32_t getToken(const char* z, uint32_t* tokenId) {
|
||||||
return n;
|
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) {
|
int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
SAstCreateContext cxt;
|
SAstCreateContext cxt;
|
||||||
createAstCreateContext(pParseCxt, &cxt);
|
createAstCreateContext(pParseCxt, &cxt);
|
||||||
|
@ -181,15 +194,12 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
int32_t i = 0;
|
int32_t i = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
SToken t0 = {0};
|
SToken t0 = {0};
|
||||||
// printf("===========================\n");
|
|
||||||
if (cxt.pQueryCxt->pSql[i] == 0) {
|
if (cxt.pQueryCxt->pSql[i] == 0) {
|
||||||
NewParse(pParser, 0, t0, &cxt);
|
NewParse(pParser, 0, t0, &cxt);
|
||||||
goto abort_parse;
|
goto abort_parse;
|
||||||
}
|
}
|
||||||
// printf("input: [%s]\n", cxt.pQueryCxt->pSql + i);
|
|
||||||
t0.n = getToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type);
|
t0.n = getToken((char *)&cxt.pQueryCxt->pSql[i], &t0.type);
|
||||||
t0.z = (char *)(cxt.pQueryCxt->pSql + i);
|
t0.z = (char *)(cxt.pQueryCxt->pSql + i);
|
||||||
// printf("token : %d %d [%s]\n", t0.type, t0.n, t0.z);
|
|
||||||
i += t0.n;
|
i += t0.n;
|
||||||
|
|
||||||
switch (t0.type) {
|
switch (t0.type) {
|
||||||
|
@ -201,14 +211,12 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
NewParse(pParser, 0, t0, &cxt);
|
NewParse(pParser, 0, t0, &cxt);
|
||||||
goto abort_parse;
|
goto abort_parse;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TK_QUESTION:
|
case TK_QUESTION:
|
||||||
case TK_ILLEGAL: {
|
case TK_ILLEGAL: {
|
||||||
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
|
snprintf(cxt.pQueryCxt->pMsg, cxt.pQueryCxt->msgLen, "unrecognized token: \"%s\"", t0.z);
|
||||||
cxt.valid = false;
|
cxt.valid = false;
|
||||||
goto abort_parse;
|
goto abort_parse;
|
||||||
}
|
}
|
||||||
|
|
||||||
case TK_HEX:
|
case TK_HEX:
|
||||||
case TK_OCT:
|
case TK_OCT:
|
||||||
case TK_BIN: {
|
case TK_BIN: {
|
||||||
|
@ -216,7 +224,6 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
cxt.valid = false;
|
cxt.valid = false;
|
||||||
goto abort_parse;
|
goto abort_parse;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
NewParse(pParser, t0.type, t0, &cxt);
|
NewParse(pParser, t0.type, t0, &cxt);
|
||||||
// NewParseTrace(stdout, "");
|
// NewParseTrace(stdout, "");
|
||||||
|
@ -227,9 +234,9 @@ int32_t doParse(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
}
|
}
|
||||||
|
|
||||||
abort_parse:
|
abort_parse:
|
||||||
// printf("doParse completed.\n");
|
|
||||||
NewParseFree(pParser, free);
|
NewParseFree(pParser, free);
|
||||||
destroyAstCreateContext(&cxt);
|
destroyAstCreateContext(&cxt);
|
||||||
|
pQuery->stmtType = getStmtType(cxt.pRootNode);
|
||||||
pQuery->pRoot = cxt.pRootNode;
|
pQuery->pRoot = cxt.pRootNode;
|
||||||
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
|
return cxt.valid ? TSDB_CODE_SUCCESS : TSDB_CODE_FAILED;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +262,6 @@ static bool beforeHaving(ESqlClause clause) {
|
||||||
|
|
||||||
typedef struct STranslateContext {
|
typedef struct STranslateContext {
|
||||||
SParseContext* pParseCxt;
|
SParseContext* pParseCxt;
|
||||||
FuncMgtHandle fmgt;
|
|
||||||
int32_t errCode;
|
int32_t errCode;
|
||||||
SMsgBuf msgBuf;
|
SMsgBuf msgBuf;
|
||||||
SArray* pNsLevel; // element is SArray*, the element of this subarray is STableNode*
|
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";
|
return "Not SELECTed expression";
|
||||||
case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
|
case TSDB_CODE_PAR_NOT_SINGLE_GROUP:
|
||||||
return "Not a single-group group function";
|
return "Not a single-group group function";
|
||||||
|
case TSDB_CODE_PAR_OUT_OF_MEMORY:
|
||||||
|
return "Out of memory";
|
||||||
default:
|
default:
|
||||||
return "Unknown error";
|
return "Unknown error";
|
||||||
}
|
}
|
||||||
|
@ -376,12 +384,15 @@ static void setColumnInfoByExpr(const STableNode* pTable, SExprNode* pExpr, SCol
|
||||||
pCol->node.resType = pExpr->resType;
|
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)) {
|
if (QUERY_NODE_REAL_TABLE == nodeType(pTable)) {
|
||||||
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
|
const STableMeta* pMeta = ((SRealTableNode*)pTable)->pMeta;
|
||||||
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
int32_t nums = pMeta->tableInfo.numOfTags + pMeta->tableInfo.numOfColumns;
|
||||||
for (int32_t i = 0; i < nums; ++i) {
|
for (int32_t i = 0; i < nums; ++i) {
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
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);
|
setColumnInfoBySchema(pTable, pMeta->schema + i, pCol);
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
}
|
}
|
||||||
|
@ -390,10 +401,14 @@ static int32_t createColumnNodeByTable(const STableNode* pTable, SNodeList* pLis
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
FOREACH(pNode, pProjectList) {
|
FOREACH(pNode, pProjectList) {
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
||||||
|
if (NULL == pCol) {
|
||||||
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol);
|
setColumnInfoByExpr(pTable, (SExprNode*)pNode, pCol);
|
||||||
nodesListAppend(pList, (SNode*)pCol);
|
nodesListAppend(pList, (SNode*)pCol);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool findAndSetColumn(SColumnNode* pCol, const STableNode* pTable) {
|
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_UTINYINT:
|
||||||
case TSDB_DATA_TYPE_USMALLINT:
|
case TSDB_DATA_TYPE_USMALLINT:
|
||||||
case TSDB_DATA_TYPE_UINT:
|
case TSDB_DATA_TYPE_UINT:
|
||||||
case TSDB_DATA_TYPE_UBIGINT:{
|
case TSDB_DATA_TYPE_UBIGINT: {
|
||||||
char* endPtr = NULL;
|
char* endPtr = NULL;
|
||||||
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
|
pVal->datum.u = strtoull(pVal->literal, &endPtr, 10);
|
||||||
break;
|
break;
|
||||||
|
@ -556,12 +571,20 @@ static EDealRes translateValue(STranslateContext* pCxt, SValueNode* pVal) {
|
||||||
case TSDB_DATA_TYPE_VARBINARY: {
|
case TSDB_DATA_TYPE_VARBINARY: {
|
||||||
int32_t n = strlen(pVal->literal);
|
int32_t n = strlen(pVal->literal);
|
||||||
pVal->datum.p = calloc(1, n);
|
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);
|
trimStringCopy(pVal->literal, n, pVal->datum.p);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TSDB_DATA_TYPE_TIMESTAMP: {
|
case TSDB_DATA_TYPE_TIMESTAMP: {
|
||||||
int32_t n = strlen(pVal->literal);
|
int32_t n = strlen(pVal->literal);
|
||||||
char* tmp = calloc(1, n);
|
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);
|
int32_t len = trimStringCopy(pVal->literal, n, tmp);
|
||||||
if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
|
if (taosParseTime(tmp, &pVal->datum.i, len, pVal->node.resType.precision, tsDaylight) != TSDB_CODE_SUCCESS) {
|
||||||
tfree(tmp);
|
tfree(tmp);
|
||||||
|
@ -608,7 +631,7 @@ static EDealRes translateOperator(STranslateContext* pCxt, SOperatorNode* pOp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode* pFunc) {
|
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);
|
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_INVALID_FUNTION, pFunc->functionName);
|
||||||
return DEAL_RES_ERROR;
|
return DEAL_RES_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -806,9 +829,15 @@ static int32_t translateStar(STranslateContext* pCxt, SSelectStmt* pSelect, bool
|
||||||
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
|
SArray* pTables = taosArrayGetP(pCxt->pNsLevel, pCxt->currLevel);
|
||||||
size_t nums = taosArrayGetSize(pTables);
|
size_t nums = taosArrayGetSize(pTables);
|
||||||
pSelect->pProjectionList = nodesMakeList();
|
pSelect->pProjectionList = nodesMakeList();
|
||||||
|
if (NULL == pSelect->pProjectionList) {
|
||||||
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_OUT_OF_MEMORY);
|
||||||
|
}
|
||||||
for (size_t i = 0; i < nums; ++i) {
|
for (size_t i = 0; i < nums; ++i) {
|
||||||
STableNode* pTable = taosArrayGetP(pTables, 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;
|
*pIsSelectStar = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -848,7 +877,7 @@ static int32_t getPositionValue(const SValueNode* pVal) {
|
||||||
return -1;
|
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;
|
*pOther = false;
|
||||||
SNode* pNode;
|
SNode* pNode;
|
||||||
FOREACH(pNode, pOrderByList) {
|
FOREACH(pNode, pOrderByList) {
|
||||||
|
@ -856,18 +885,20 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
|
||||||
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
|
if (QUERY_NODE_VALUE == nodeType(pExpr)) {
|
||||||
SValueNode* pVal = (SValueNode*)pExpr;
|
SValueNode* pVal = (SValueNode*)pExpr;
|
||||||
if (!translateValue(pCxt, pVal)) {
|
if (!translateValue(pCxt, pVal)) {
|
||||||
return false;
|
return pCxt->errCode;
|
||||||
}
|
}
|
||||||
int32_t pos = getPositionValue((SValueNode*)pExpr);
|
int32_t pos = getPositionValue(pVal);
|
||||||
if (pos < 0) {
|
if (pos < 0) {
|
||||||
ERASE_NODE(pOrderByList);
|
ERASE_NODE(pOrderByList);
|
||||||
nodesDestroyNode(pNode);
|
nodesDestroyNode(pNode);
|
||||||
continue;
|
continue;
|
||||||
} else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) {
|
} else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) {
|
||||||
generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
|
return generateSyntaxErrMsg(pCxt, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT);
|
||||||
return false;
|
|
||||||
} else {
|
} else {
|
||||||
SColumnNode* pCol = (SColumnNode*)nodesMakeNode(QUERY_NODE_COLUMN);
|
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);
|
setColumnInfoByExpr(NULL, (SExprNode*)nodesListGetNode(pProjectionList, pos - 1), pCol);
|
||||||
((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol;
|
((SOrderByExprNode*)pNode)->pExpr = (SNode*)pCol;
|
||||||
nodesDestroyNode(pExpr);
|
nodesDestroyNode(pExpr);
|
||||||
|
@ -876,19 +907,20 @@ static bool translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjec
|
||||||
*pOther = true;
|
*pOther = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
bool other;
|
bool other;
|
||||||
if (!translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other)) {
|
int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other);
|
||||||
return pCxt->errCode;
|
if (TSDB_CODE_SUCCESS != code) {
|
||||||
|
return code;
|
||||||
}
|
}
|
||||||
if (!other) {
|
if (!other) {
|
||||||
return TSDB_CODE_SUCCESS;
|
return TSDB_CODE_SUCCESS;
|
||||||
}
|
}
|
||||||
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
|
pCxt->currClause = SQL_CLAUSE_ORDER_BY;
|
||||||
int32_t code = translateExprList(pCxt, pSelect->pOrderByList);
|
code = translateExprList(pCxt, pSelect->pOrderByList);
|
||||||
if (TSDB_CODE_SUCCESS == code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
|
code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList);
|
||||||
}
|
}
|
||||||
|
@ -945,12 +977,6 @@ static int32_t translateFrom(STranslateContext* pCxt, SNode* pTable) {
|
||||||
return translateTable(pCxt, pTable);
|
return translateTable(pCxt, pTable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// typedef struct SSelectStmt {
|
|
||||||
// bool isDistinct;
|
|
||||||
// SNode* pLimit;
|
|
||||||
// SNode* pSlimit;
|
|
||||||
// } SSelectStmt;
|
|
||||||
|
|
||||||
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
static int32_t translateSelect(STranslateContext* pCxt, SSelectStmt* pSelect) {
|
||||||
pCxt->pCurrStmt = pSelect;
|
pCxt->pCurrStmt = pSelect;
|
||||||
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
|
int32_t code = translateFrom(pCxt, pSelect->pFromTable);
|
||||||
|
@ -1004,6 +1030,26 @@ static int32_t translateSubquery(STranslateContext* pCxt, SNode* pNode) {
|
||||||
return code;
|
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) {
|
int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
STranslateContext cxt = {
|
STranslateContext cxt = {
|
||||||
.pParseCxt = pParseCxt,
|
.pParseCxt = pParseCxt,
|
||||||
|
@ -1014,12 +1060,11 @@ int32_t doTranslate(SParseContext* pParseCxt, SQuery* pQuery) {
|
||||||
.currClause = 0
|
.currClause = 0
|
||||||
};
|
};
|
||||||
int32_t code = fmFuncMgtInit();
|
int32_t code = fmFuncMgtInit();
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
if (TSDB_CODE_SUCCESS == code) {
|
||||||
return code;
|
code = translateQuery(&cxt, pQuery->pRoot);
|
||||||
}
|
}
|
||||||
code = fmGetHandle(&cxt.fmgt);
|
if (TSDB_CODE_SUCCESS == code && STMT_TYPE_QUERY == pQuery->stmtType) {
|
||||||
if (TSDB_CODE_SUCCESS != code) {
|
code = setReslutSchema(&cxt, pQuery);
|
||||||
return code;
|
|
||||||
}
|
}
|
||||||
return translateQuery(&cxt, pQuery->pRoot);
|
return code;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@ target_include_directories(
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
planner
|
planner
|
||||||
PRIVATE os util catalog cjson parser function qcom
|
PRIVATE os util nodes catalog cjson parser function qcom
|
||||||
PUBLIC transport
|
PUBLIC transport
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,33 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -13,7 +13,192 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "plannerImpl.h"
|
||||||
|
#include "functionMgt.h"
|
||||||
|
|
||||||
// int32_t getPlan(SNode* pRoot, SQueryPlanNode** pQueryPlan) {
|
static SLogicNode* createQueryLogicNode(SNode* pStmt);
|
||||||
|
|
||||||
// }
|
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;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue