From 29bdba7298ce83b17531c73052e090da97a52795 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Thu, 19 May 2022 14:26:10 +0800 Subject: [PATCH] fix: some problems of parser and planner --- include/libs/function/functionMgt.h | 2 ++ include/libs/nodes/cmdnodes.h | 4 ++-- include/util/taoserror.h | 2 ++ include/util/tdef.h | 4 ++-- source/libs/function/src/functionMgt.c | 4 ++++ source/libs/nodes/src/nodesCodeFuncs.c | 21 ++++++++++++++++++++- source/libs/parser/src/parAstCreater.c | 17 ++++++++++++++--- source/libs/parser/src/parTranslater.c | 13 ++++++++++--- source/libs/parser/src/parUtil.c | 4 ++++ source/libs/planner/src/planSpliter.c | 5 ++++- source/libs/planner/test/planSetOpTest.cpp | 9 +++++++++ source/libs/planner/test/planTestUtil.cpp | 1 + 12 files changed, 74 insertions(+), 12 deletions(-) diff --git a/include/libs/function/functionMgt.h b/include/libs/function/functionMgt.h index aec1476663..89fbc92992 100644 --- a/include/libs/function/functionMgt.h +++ b/include/libs/function/functionMgt.h @@ -142,6 +142,8 @@ void fmFuncMgtDestroy(); int32_t fmGetFuncInfo(SFmGetFuncInfoParam* pParam, SFunctionNode* pFunc); +bool fmIsBuiltinFunc(const char* pFunc); + bool fmIsAggFunc(int32_t funcId); bool fmIsScalarFunc(int32_t funcId); bool fmIsNonstandardSQLFunc(int32_t funcId); diff --git a/include/libs/nodes/cmdnodes.h b/include/libs/nodes/cmdnodes.h index 5e294ae455..82bf4e1f45 100644 --- a/include/libs/nodes/cmdnodes.h +++ b/include/libs/nodes/cmdnodes.h @@ -78,7 +78,7 @@ typedef struct SAlterDatabaseStmt { typedef struct STableOptions { ENodeType type; - char comment[TSDB_STB_COMMENT_LEN]; + char comment[TSDB_TB_COMMENT_LEN]; int32_t delay; float filesFactor; SNodeList* pRollupFuncs; @@ -90,7 +90,7 @@ typedef struct SColumnDefNode { ENodeType type; char colName[TSDB_COL_NAME_LEN]; SDataType dataType; - char comments[TSDB_STB_COMMENT_LEN]; + char comments[TSDB_TB_COMMENT_LEN]; bool sma; } SColumnDefNode; diff --git a/include/util/taoserror.h b/include/util/taoserror.h index be6005d46b..fd3e008e67 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -647,6 +647,8 @@ int32_t* taosGetErrno(); #define TSDB_CODE_PAR_CANNOT_DROP_PRIMARY_KEY TAOS_DEF_ERROR_CODE(0, 0x264A) #define TSDB_CODE_PAR_INVALID_MODIFY_COL TAOS_DEF_ERROR_CODE(0, 0x264B) #define TSDB_CODE_PAR_INVALID_TBNAME TAOS_DEF_ERROR_CODE(0, 0x264C) +#define TSDB_CODE_PAR_INVALID_FUNCTION_NAME TAOS_DEF_ERROR_CODE(0, 0x264D) +#define TSDB_CODE_PAR_COMMENT_TOO_LONG TAOS_DEF_ERROR_CODE(0, 0x264E) //planner #define TSDB_CODE_PLAN_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x2700) diff --git a/include/util/tdef.h b/include/util/tdef.h index f95d96be56..5cc687d7ab 100644 --- a/include/util/tdef.h +++ b/include/util/tdef.h @@ -218,8 +218,8 @@ typedef enum ELogicConditionType { #define TSDB_MAX_SQL_SHOW_LEN 1024 #define TSDB_MAX_ALLOWED_SQL_LEN (1 * 1024 * 1024u) // sql length should be less than 1mb -#define TSDB_APP_NAME_LEN TSDB_UNI_LEN -#define TSDB_STB_COMMENT_LEN 1024 +#define TSDB_APP_NAME_LEN TSDB_UNI_LEN +#define TSDB_TB_COMMENT_LEN 1025 /** * In some scenarios uint16_t (0~65535) is used to store the row len. diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 73ec7f510b..e46cb81561 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -100,6 +100,10 @@ int32_t fmGetFuncInfo(SFmGetFuncInfoParam* pParam, SFunctionNode* pFunc) { return getUdfInfo(pParam, pFunc); } +bool fmIsBuiltinFunc(const char* pFunc) { + return NULL != taosHashGet(gFunMgtService.pFuncNameHashTable, pFunc, strlen(pFunc)); +} + EFuncDataRequired fmFuncDataRequired(SFunctionNode* pFunc, STimeWindow* pTimeWindow) { if (fmIsUserDefinedFunc(pFunc->funcId) || pFunc->funcId < 0 || pFunc->funcId >= funcMgtBuiltinsNum) { return FUNC_DATA_REQUIRED_DATA_LOAD; diff --git a/source/libs/nodes/src/nodesCodeFuncs.c b/source/libs/nodes/src/nodesCodeFuncs.c index 763ccbf7a0..bc49f36afe 100644 --- a/source/libs/nodes/src/nodesCodeFuncs.c +++ b/source/libs/nodes/src/nodesCodeFuncs.c @@ -946,6 +946,23 @@ static int32_t jsonToLogicSubplan(const SJson* pJson, void* pObj) { return code; } +static const char* jkLogicPlanSubplans = "Subplans"; + +static int32_t logicPlanToJson(const void* pObj, SJson* pJson) { + const SQueryLogicPlan* pNode = (const SQueryLogicPlan*)pObj; + return tjsonAddObject(pJson, jkLogicPlanSubplans, nodeToJson, nodesListGetNode(pNode->pTopSubplans, 0)); +} + +static int32_t jsonToLogicPlan(const SJson* pJson, void* pObj) { + SQueryLogicPlan* pNode = (SQueryLogicPlan*)pObj; + SNode* pChild = NULL; + int32_t code = jsonToNodeObject(pJson, jkLogicPlanSubplans, &pChild); + if (TSDB_CODE_SUCCESS == code) { + code = nodesListMakeStrictAppend(&pNode->pTopSubplans, pChild); + } + return code; +} + static const char* jkJoinLogicPlanJoinType = "JoinType"; static const char* jkJoinLogicPlanOnConditions = "OnConditions"; @@ -3029,7 +3046,7 @@ static int32_t specificNodeToJson(const void* pObj, SJson* pJson) { case QUERY_NODE_LOGIC_SUBPLAN: return logicSubplanToJson(pObj, pJson); case QUERY_NODE_LOGIC_PLAN: - break; + return logicPlanToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: return physiTagScanNodeToJson(pObj, pJson); case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: @@ -3126,6 +3143,8 @@ static int32_t jsonToSpecificNode(const SJson* pJson, void* pObj) { return jsonToLogicPartitionNode(pJson, pObj); case QUERY_NODE_LOGIC_SUBPLAN: return jsonToLogicSubplan(pJson, pObj); + case QUERY_NODE_LOGIC_PLAN: + return jsonToLogicPlan(pJson, pObj); case QUERY_NODE_PHYSICAL_PLAN_TAG_SCAN: return jsonToPhysiTagScanNode(pJson, pObj); case QUERY_NODE_PHYSICAL_PLAN_TABLE_SCAN: diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index a438a1e843..9a9a11c7b0 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -196,6 +196,15 @@ static bool checkIndexName(SAstCreateContext* pCxt, SToken* pIndexName) { return true; } +static bool checkComment(SAstCreateContext* pCxt, const SToken* pCommentToken, bool demand) { + if (NULL == pCommentToken) { + pCxt->errCode = demand ? TSDB_CODE_PAR_SYNTAX_ERROR : TSDB_CODE_SUCCESS; + } else if (pCommentToken->n >= (TSDB_TB_COMMENT_LEN + 2)) { + pCxt->errCode = generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_COMMENT_TOO_LONG); + } + return TSDB_CODE_SUCCESS == pCxt->errCode; +} + SNode* createRawExprNode(SAstCreateContext* pCxt, const SToken* pToken, SNode* pNode) { SRawExprNode* target = (SRawExprNode*)nodesMakeNode(QUERY_NODE_RAW_EXPR); CHECK_OUT_OF_MEM(target); @@ -823,8 +832,10 @@ SNode* createAlterTableOptions(SAstCreateContext* pCxt) { SNode* setTableOption(SAstCreateContext* pCxt, SNode* pOptions, ETableOptionType type, void* pVal) { switch (type) { case TABLE_OPTION_COMMENT: - copyStringFormStringToken((SToken*)pVal, ((STableOptions*)pOptions)->comment, - sizeof(((STableOptions*)pOptions)->comment)); + if (checkComment(pCxt, (SToken*)pVal, true)) { + copyStringFormStringToken((SToken*)pVal, ((STableOptions*)pOptions)->comment, + sizeof(((STableOptions*)pOptions)->comment)); + } break; case TABLE_OPTION_DELAY: ((STableOptions*)pOptions)->delay = strtol(((SToken*)pVal)->z, NULL, 10); @@ -848,7 +859,7 @@ SNode* setTableOption(SAstCreateContext* pCxt, SNode* pOptions, ETableOptionType } SNode* createColumnDefNode(SAstCreateContext* pCxt, SToken* pColName, SDataType dataType, const SToken* pComment) { - if (!checkColumnName(pCxt, pColName)) { + if (!checkColumnName(pCxt, pColName) || !checkComment(pCxt, pComment, false)) { return NULL; } SColumnDefNode* pCol = (SColumnDefNode*)nodesMakeNode(QUERY_NODE_COLUMN_DEF); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 18e0843e92..b270e811d9 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -272,6 +272,10 @@ static bool isTimelineFunc(const SNode* pNode) { return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsTimelineFunc(((SFunctionNode*)pNode)->funcId)); } +static bool isScanPseudoColumnFunc(const SNode* pNode) { + return (QUERY_NODE_FUNCTION == nodeType(pNode) && fmIsScanPseudoColumnFunc(((SFunctionNode*)pNode)->funcId)); +} + static bool isDistinctOrderBy(STranslateContext* pCxt) { return (SQL_CLAUSE_ORDER_BY == pCxt->currClause && pCxt->pCurrStmt->isDistinct); } @@ -892,7 +896,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { return DEAL_RES_IGNORE_CHILD; } } - if (QUERY_NODE_COLUMN == nodeType(*pNode)) { + if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { if (pCxt->selectFuncNum > 1) { return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); } else { @@ -930,7 +934,7 @@ static EDealRes rewriteColsToSelectValFuncImpl(SNode** pNode, void* pContext) { if (isAggFunc(*pNode)) { return DEAL_RES_IGNORE_CHILD; } - if (QUERY_NODE_COLUMN == nodeType(*pNode)) { + if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { return rewriteColToSelectValFunc((STranslateContext*)pContext, NULL, pNode); } return DEAL_RES_CONTINUE; @@ -958,7 +962,7 @@ static EDealRes doCheckAggColCoexist(SNode* pNode, void* pContext) { pCxt->existAggFunc = true; return DEAL_RES_IGNORE_CHILD; } - if (QUERY_NODE_COLUMN == nodeType(pNode)) { + if (isScanPseudoColumnFunc(pNode) || QUERY_NODE_COLUMN == nodeType(pNode)) { pCxt->existCol = true; } return DEAL_RES_CONTINUE; @@ -3261,6 +3265,9 @@ static int32_t readFromFile(char* pName, int32_t* len, char** buf) { } static int32_t translateCreateFunction(STranslateContext* pCxt, SCreateFunctionStmt* pStmt) { + if (fmIsBuiltinFunc(pStmt->funcName)) { + return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_INVALID_FUNCTION_NAME); + } SCreateFuncReq req = {0}; strcpy(req.name, pStmt->funcName); req.igExists = pStmt->ignoreExists; diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 1ae066a8c2..7b9147beab 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -160,6 +160,10 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "Only binary/nchar column length could be modified"; case TSDB_CODE_PAR_INVALID_TBNAME: return "Invalid tbname pseudo column"; + case TSDB_CODE_PAR_INVALID_FUNCTION_NAME: + return "Invalid function name"; + case TSDB_CODE_PAR_COMMENT_TOO_LONG: + return "Comment too long"; case TSDB_CODE_OUT_OF_MEMORY: return "Out of memory"; default: diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index d0ac239bcb..fb716af3e5 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -24,6 +24,7 @@ #define SPLIT_FLAG_TEST_MASK(val, mask) (((val) & (mask)) != 0) typedef struct SSplitContext { + int32_t queryId; int32_t groupId; bool split; } SSplitContext; @@ -62,6 +63,7 @@ static SLogicSubplan* splCreateScanSubplan(SSplitContext* pCxt, SScanLogicNode* if (NULL == pSubplan) { return NULL; } + pSubplan->id.queryId = pCxt->queryId; pSubplan->id.groupId = pCxt->groupId; pSubplan->subplanType = SUBPLAN_TYPE_SCAN; pSubplan->pNode = (SLogicNode*)nodesCloneNode(pScan); @@ -242,6 +244,7 @@ static SLogicSubplan* unionCreateSubplan(SSplitContext* pCxt, SLogicNode* pNode) if (NULL == pSubplan) { return NULL; } + pSubplan->id.queryId = pCxt->queryId; pSubplan->id.groupId = pCxt->groupId; pSubplan->subplanType = SUBPLAN_TYPE_SCAN; pSubplan->pNode = pNode; @@ -406,7 +409,7 @@ static const SSplitRule splitRuleSet[] = {{.pName = "SuperTableScan", .splitFunc static const int32_t splitRuleNum = (sizeof(splitRuleSet) / sizeof(SSplitRule)); static int32_t applySplitRule(SLogicSubplan* pSubplan) { - SSplitContext cxt = {.groupId = pSubplan->id.groupId + 1, .split = false}; + SSplitContext cxt = {.queryId = pSubplan->id.queryId, .groupId = pSubplan->id.groupId + 1, .split = false}; do { cxt.split = false; for (int32_t i = 0; i < splitRuleNum; ++i) { diff --git a/source/libs/planner/test/planSetOpTest.cpp b/source/libs/planner/test/planSetOpTest.cpp index 3c7bf9e43a..717384aae6 100644 --- a/source/libs/planner/test/planSetOpTest.cpp +++ b/source/libs/planner/test/planSetOpTest.cpp @@ -32,6 +32,15 @@ TEST_F(PlanSetOpTest, unionAllSubquery) { run("SELECT * FROM (SELECT c1, c2 FROM t1 UNION ALL SELECT c1, c2 FROM t1)"); } +TEST_F(PlanSetOpTest, unionAllWithSubquery) { + useDb("root", "test"); + + // child table + run("SELECT ts FROM (SELECT ts FROM st1s1) UNION ALL SELECT ts FROM (SELECT ts FROM st1s2)"); + // super table + run("SELECT ts FROM (SELECT ts FROM st1) UNION ALL SELECT ts FROM (SELECT ts FROM st1)"); +} + TEST_F(PlanSetOpTest, union) { useDb("root", "test"); diff --git a/source/libs/planner/test/planTestUtil.cpp b/source/libs/planner/test/planTestUtil.cpp index af8ec87158..94a28f46a8 100644 --- a/source/libs/planner/test/planTestUtil.cpp +++ b/source/libs/planner/test/planTestUtil.cpp @@ -322,6 +322,7 @@ class PlannerTestBaseImpl { } void setPlanContext(SQuery* pQuery, SPlanContext* pCxt) { + pCxt->queryId = 1; if (QUERY_NODE_CREATE_TOPIC_STMT == nodeType(pQuery->pRoot)) { pCxt->pAstRoot = ((SCreateTopicStmt*)pQuery->pRoot)->pQuery; pCxt->topicQuery = true; -- GitLab