From 241b3856535ffbb5d6fa81e7769624ae71a2ce0b Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Fri, 22 Jul 2022 20:05:30 +0800 Subject: [PATCH 1/3] fix: plan problem when functions that requires a timeline is used in a partition by query --- source/libs/planner/src/planLogicCreater.c | 12 +++++++++++- source/libs/planner/src/planSpliter.c | 20 ++++++++++++++++++-- 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index de9f16f171..6a30f32f2b 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -787,6 +787,14 @@ static int32_t createFillLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect return code; } +static bool isPrimaryKeySort(SNodeList* pOrderByList) { + SNode* pExpr = ((SOrderByExprNode*)nodesListGetNode(pOrderByList, 0))->pExpr; + if (QUERY_NODE_COLUMN != nodeType(pExpr)) { + return false; + } + return PRIMARYKEY_TIMESTAMP_COL_ID == ((SColumnNode*)pExpr)->colId; +} + static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { if (NULL == pSelect->pOrderByList) { return TSDB_CODE_SUCCESS; @@ -800,7 +808,9 @@ static int32_t createSortLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect pSort->groupSort = pSelect->groupSort; pSort->node.groupAction = pSort->groupSort ? GROUP_ACTION_KEEP : GROUP_ACTION_CLEAR; pSort->node.requireDataOrder = DATA_ORDER_LEVEL_NONE; - pSort->node.resultDataOrder = pSort->groupSort ? DATA_ORDER_LEVEL_IN_GROUP : DATA_ORDER_LEVEL_GLOBAL; + pSort->node.resultDataOrder = isPrimaryKeySort(pSelect->pOrderByList) + ? (pSort->groupSort ? DATA_ORDER_LEVEL_IN_GROUP : DATA_ORDER_LEVEL_GLOBAL) + : DATA_ORDER_LEVEL_NONE; int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_ORDER_BY, NULL, COLLECT_COL_TYPE_ALL, &pSort->node.pTargets); if (TSDB_CODE_SUCCESS == code && NULL == pSort->node.pTargets) { diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index 9e844dd6a2..45fc45336c 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -215,6 +215,14 @@ static bool stbSplHasMultiTbScan(bool streamQuery, SLogicNode* pNode) { return (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pChild) && stbSplIsMultiTbScan(streamQuery, (SScanLogicNode*)pChild)); } +static bool stbSplIsMultiTbScanChild(bool streamQuery, SLogicNode* pNode) { + if (1 != LIST_LENGTH(pNode->pChildren)) { + return false; + } + SNode* pChild = nodesListGetNode(pNode->pChildren, 0); + return (QUERY_NODE_LOGIC_PLAN_SCAN == nodeType(pChild) && stbSplIsMultiTbScan(streamQuery, (SScanLogicNode*)pChild)); +} + static bool stbSplNeedSplitWindow(bool streamQuery, SLogicNode* pNode) { SWindowLogicNode* pWindow = (SWindowLogicNode*)pNode; if (WINDOW_TYPE_INTERVAL == pWindow->winType) { @@ -247,7 +255,7 @@ static bool stbSplNeedSplit(bool streamQuery, SLogicNode* pNode) { case QUERY_NODE_LOGIC_PLAN_JOIN: return !(((SJoinLogicNode*)pNode)->isSingleTableJoin); case QUERY_NODE_LOGIC_PLAN_PARTITION: - return stbSplHasMultiTbScan(streamQuery, pNode); + return stbSplIsMultiTbScanChild(streamQuery, pNode); case QUERY_NODE_LOGIC_PLAN_AGG: return !stbSplHasGatherExecFunc(((SAggLogicNode*)pNode)->pAggFuncs) && stbSplHasMultiTbScan(streamQuery, pNode); case QUERY_NODE_LOGIC_PLAN_WINDOW: @@ -970,7 +978,15 @@ static int32_t stbSplSplitJoinNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) } static int32_t stbSplSplitPartitionNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) { - int32_t code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, NULL, pInfo->pSplitNode, true); + int32_t code = TSDB_CODE_SUCCESS; + SNodeList* pMergeKeys = NULL; + if (pInfo->pSplitNode->requireDataOrder >= DATA_ORDER_LEVEL_IN_GROUP) { + code = stbSplCreateMergeKeysByPrimaryKey( + stbSplFindPrimaryKeyFromScan((SScanLogicNode*)nodesListGetNode(pInfo->pSplitNode->pChildren, 0)), &pMergeKeys); + } + if (TSDB_CODE_SUCCESS == code) { + code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, pMergeKeys, pInfo->pSplitNode, true); + } if (TSDB_CODE_SUCCESS == code) { code = nodesListMakeStrictAppend(&pInfo->pSubplan->pChildren, (SNode*)splCreateScanSubplan(pCxt, pInfo->pSplitNode, SPLIT_FLAG_STABLE_SPLIT)); From 27c71155cc554b76a2cf73e919c09a21f1b0888e Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Fri, 22 Jul 2022 20:29:52 +0800 Subject: [PATCH 2/3] fix: plan problem when functions that requires a timeline is used in a partition by query --- source/libs/function/src/builtinsimpl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index bb4467cf34..64e0c86644 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -3880,11 +3880,11 @@ int32_t elapsedFunction(SqlFunctionCtx* pCtx) { if (pCtx->end.key != INT64_MIN) { pInfo->min = pCtx->end.key; } else { - pInfo->min = ptsList[0]; + pInfo->min = ptsList[start]; } } else { if (pCtx->start.key == INT64_MIN) { - pInfo->min = (pInfo->min > ptsList[0]) ? ptsList[0] : pInfo->min; + pInfo->min = (pInfo->min > ptsList[start]) ? ptsList[start] : pInfo->min; } else { pInfo->min = pCtx->start.key; } From 3b6837598cedf716b5999b1a9e1d84a58e0f03d2 Mon Sep 17 00:00:00 2001 From: Xiaoyu Wang Date: Fri, 22 Jul 2022 21:06:20 +0800 Subject: [PATCH 3/3] fix: plan problem when functions that requires a timeline is used in a partition by query --- source/libs/planner/src/planSpliter.c | 16 ++++++++++++++-- source/libs/planner/test/planPartByTest.cpp | 2 ++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/source/libs/planner/src/planSpliter.c b/source/libs/planner/src/planSpliter.c index 45fc45336c..8586234b7e 100644 --- a/source/libs/planner/src/planSpliter.c +++ b/source/libs/planner/src/planSpliter.c @@ -977,12 +977,24 @@ static int32_t stbSplSplitJoinNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) return code; } +static int32_t stbSplCreateMergeKeysForPartitionNode(SLogicNode* pPart, SNodeList** pMergeKeys) { + SNode* pPrimaryKey = + nodesCloneNode(stbSplFindPrimaryKeyFromScan((SScanLogicNode*)nodesListGetNode(pPart->pChildren, 0))); + if (NULL == pPrimaryKey) { + return TSDB_CODE_OUT_OF_MEMORY; + } + int32_t code = nodesListAppend(pPart->pTargets, pPrimaryKey); + if (TSDB_CODE_SUCCESS == code) { + code = stbSplCreateMergeKeysByPrimaryKey(pPrimaryKey, pMergeKeys); + } + return code; +} + static int32_t stbSplSplitPartitionNode(SSplitContext* pCxt, SStableSplitInfo* pInfo) { int32_t code = TSDB_CODE_SUCCESS; SNodeList* pMergeKeys = NULL; if (pInfo->pSplitNode->requireDataOrder >= DATA_ORDER_LEVEL_IN_GROUP) { - code = stbSplCreateMergeKeysByPrimaryKey( - stbSplFindPrimaryKeyFromScan((SScanLogicNode*)nodesListGetNode(pInfo->pSplitNode->pChildren, 0)), &pMergeKeys); + code = stbSplCreateMergeKeysForPartitionNode(pInfo->pSplitNode, &pMergeKeys); } if (TSDB_CODE_SUCCESS == code) { code = stbSplCreateMergeNode(pCxt, pInfo->pSubplan, pInfo->pSplitNode, pMergeKeys, pInfo->pSplitNode, true); diff --git a/source/libs/planner/test/planPartByTest.cpp b/source/libs/planner/test/planPartByTest.cpp index 256960a15e..48ab1e1ac2 100644 --- a/source/libs/planner/test/planPartByTest.cpp +++ b/source/libs/planner/test/planPartByTest.cpp @@ -67,6 +67,8 @@ TEST_F(PlanPartitionByTest, withTimeLineFunc) { useDb("root", "test"); run("SELECT TWA(c1) FROM st1 PARTITION BY c1"); + + run("SELECT MAVG(c1, 2) FROM st1 PARTITION BY c1"); } TEST_F(PlanPartitionByTest, withSlimit) {