From a09b9ac2409bb42fde8bc4e858b26f0a1052c670 Mon Sep 17 00:00:00 2001 From: dapan1121 Date: Thu, 30 Nov 2023 20:09:49 +0800 Subject: [PATCH] enh: push down conditions --- include/libs/nodes/plannodes.h | 3 +- source/libs/nodes/src/nodesCloneFuncs.c | 4 + source/libs/planner/src/planLogicCreater.c | 6 +- source/libs/planner/src/planOptimizer.c | 359 ++++++++++++++------- 4 files changed, 262 insertions(+), 110 deletions(-) diff --git a/include/libs/nodes/plannodes.h b/include/libs/nodes/plannodes.h index de8e1edb72..5dbd03354e 100644 --- a/include/libs/nodes/plannodes.h +++ b/include/libs/nodes/plannodes.h @@ -129,9 +129,10 @@ typedef struct SJoinLogicNode { EJoinAlgorithm joinAlgo; SNode* pPrimKeyEqCond; SNode* pColEqCond; + SNode* pColOnCond; SNode* pTagEqCond; SNode* pTagOnCond; - SNode* pFullOnCond; + SNode* pFullOnCond; // except prim eq cond bool isSingleTableJoin; bool hasSubQuery; bool isLowLevelJoin; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index aa4661cf3e..38396af8a5 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -438,9 +438,13 @@ static int32_t logicScanCopy(const SScanLogicNode* pSrc, SScanLogicNode* pDst) { static int32_t logicJoinCopy(const SJoinLogicNode* pSrc, SJoinLogicNode* pDst) { COPY_BASE_OBJECT_FIELD(node, logicNodeCopy); COPY_SCALAR_FIELD(joinType); + COPY_SCALAR_FIELD(subType); COPY_SCALAR_FIELD(joinAlgo); + CLONE_NODE_FIELD(pWindowOffset); + CLONE_NODE_FIELD(pJLimit); CLONE_NODE_FIELD(pPrimKeyEqCond); CLONE_NODE_FIELD(pColEqCond); + CLONE_NODE_FIELD(pColOnCond); CLONE_NODE_FIELD(pTagEqCond); CLONE_NODE_FIELD(pTagOnCond); CLONE_NODE_FIELD(pFullOnCond); diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index bdd8a5f753..bbd2d51273 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -20,6 +20,7 @@ typedef struct SLogicPlanContext { SPlanContext* pPlanCxt; SLogicNode* pCurrRoot; + SSHashObj* pChildTables; bool hasScan; } SLogicPlanContext; @@ -502,8 +503,11 @@ static int32_t createSubqueryLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSe return createQueryLogicNode(pCxt, pTable->pSubquery, pLogicNode); } + + int32_t collectJoinResColumns(SSelectStmt* pSelect, SJoinTableNode* pJoinTable, SNodeList** pCols) { - int32_t code = nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, ((STableNode*)pJoinTable->pLeft)->tableAlias, COLLECT_COL_TYPE_ALL, pCols); + int32_t code = TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { code = nodesCollectColumns(pSelect, SQL_CLAUSE_WHERE, ((STableNode*)pJoinTable->pRight)->tableAlias, COLLECT_COL_TYPE_ALL, pCols); } diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 9fa45efd12..171e7d56ad 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -57,6 +57,14 @@ typedef struct SCpdIsMultiTableCondCxt { bool haveRightCol; } SCpdIsMultiTableCondCxt; +typedef struct SCpdCollectTableColCxt { + SSHashObj* pTables; + SNodeList* pResCols; + SHashObj* pColHash; + int32_t errCode; +} SCpdCollectTableColCxt; + + typedef enum ECondAction { COND_ACTION_STAY = 1, COND_ACTION_PUSH_JOIN, @@ -517,7 +525,15 @@ static bool pdcColBelongThisTable(SNode* pCondCol, SNodeList* pTableCols) { return false; } -static bool pushDownCondOptColInTableList(SNode* pCondCol, SSHashObj* pTables) { +static bool pdcJoinColInTableColList(SNode* pNode, SNodeList* pTableCols) { + if (QUERY_NODE_COLUMN != nodeType(pNode)) { + return false; + } + SColumnNode* pCol = (SColumnNode*)pNode; + return pdcColBelongThisTable(pNode, pTableCols); +} + +static bool pdcJoinColInTableList(SNode* pCondCol, SSHashObj* pTables) { SColumnNode* pTableCol = (SColumnNode*)pCondCol; if (NULL == tSimpleHashGet(pTables, pTableCol->tableAlias, strlen(pTableCol->tableAlias))) { return false; @@ -525,13 +541,12 @@ static bool pushDownCondOptColInTableList(SNode* pCondCol, SSHashObj* pTables) { return true; } - static EDealRes pdcJoinIsCrossTableCond(SNode* pNode, void* pContext) { SCpdIsMultiTableCondCxt* pCxt = pContext; if (QUERY_NODE_COLUMN == nodeType(pNode)) { - if (pushDownCondOptColInTableList(pNode, pCxt->pLeftTbls)) { + if (pdcJoinColInTableList(pNode, pCxt->pLeftTbls)) { pCxt->havaLeftCol = true; - } else if (pushDownCondOptColInTableList(pNode, pCxt->pRightTbls)) { + } else if (pdcJoinColInTableList(pNode, pCxt->pRightTbls)) { pCxt->haveRightCol = true; } return pCxt->havaLeftCol && pCxt->haveRightCol ? DEAL_RES_END : DEAL_RES_CONTINUE; @@ -541,20 +556,38 @@ static EDealRes pdcJoinIsCrossTableCond(SNode* pNode, void* pContext) { static ECondAction pdcJoinGetCondAction(SJoinLogicNode* pJoin, SSHashObj* pLeftTbls, SSHashObj* pRightTbls, SNode* pNode) { - EJoinType t = pJoin->joinType; + EJoinType t = pJoin->joinType; + EJoinSubType s = pJoin->subType; SCpdIsMultiTableCondCxt cxt = { .pLeftTbls = pLeftTbls, .pRightTbls = pRightTbls, .havaLeftCol = false, .haveRightCol = false}; nodesWalkExpr(pNode, pdcJoinIsCrossTableCond, &cxt); - return (JOIN_TYPE_INNER != t - ? COND_ACTION_STAY - : (cxt.havaLeftCol && cxt.haveRightCol - ? COND_ACTION_PUSH_JOIN - : (cxt.havaLeftCol ? COND_ACTION_PUSH_LEFT_CHILD : COND_ACTION_PUSH_RIGHT_CHILD))); + + if (cxt.havaLeftCol) { + if (cxt.haveRightCol) { + if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_ON_COND) { + return COND_ACTION_PUSH_JOIN; + } + return COND_ACTION_STAY; + } + if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_LEFT_FLT) { + return COND_ACTION_PUSH_LEFT_CHILD; + } + return COND_ACTION_STAY; + } + + if (cxt.haveRightCol) { + if (gJoinOpt[t][s].pushDownFlag & PUSH_DOWN_RIGHT_FLT) { + return COND_ACTION_PUSH_RIGHT_CHILD; + } + return COND_ACTION_STAY; + } + + return COND_ACTION_STAY; } -static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond, +static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond, SNode** pRightChildCond) { - SLogicConditionNode* pLogicCond = (SLogicConditionNode*)pJoin->node.pConditions; + SLogicConditionNode* pLogicCond = (SLogicConditionNode*)*pSrcCond; if (LOGIC_COND_TYPE_AND != pLogicCond->condType) { return TSDB_CODE_PLAN_NOT_SUPPORT_JOIN_COND; } @@ -572,7 +605,7 @@ static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNo SNode* pCond = NULL; FOREACH(pCond, pLogicCond->pParameterList) { ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, pCond); - if (COND_ACTION_PUSH_JOIN == condAction) { + if (COND_ACTION_PUSH_JOIN == condAction && NULL != pOnCond) { code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond)); } else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) { code = nodesListMakeAppend(&pLeftChildConds, nodesCloneNode(pCond)); @@ -607,11 +640,13 @@ static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNo } if (TSDB_CODE_SUCCESS == code) { - *pOnCond = pTempOnCond; + if (pOnCond) { + *pOnCond = pTempOnCond; + } *pLeftChildCond = pTempLeftChildCond; *pRightChildCond = pTempRightChildCond; - nodesDestroyNode(pJoin->node.pConditions); - pJoin->node.pConditions = pTempRemainCond; + nodesDestroyNode(*pSrcCond); + *pSrcCond = pTempRemainCond; } else { nodesDestroyList(pOnConds); nodesDestroyList(pLeftChildConds); @@ -626,37 +661,39 @@ static int32_t pdcJoinSplitLogicCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNo return code; } -static int32_t pdcJoinSplitOpCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond, +static int32_t pdcJoinSplitOpCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond, SNode** pRightChildCond) { SSHashObj* pLeftTables = NULL; SSHashObj* pRightTables = NULL; collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pLeftTables); collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pRightTables); - ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, pJoin->node.pConditions); + ECondAction condAction = pdcJoinGetCondAction(pJoin, pLeftTables, pRightTables, *pSrcCond); tSimpleHashCleanup(pLeftTables); tSimpleHashCleanup(pRightTables); - if (COND_ACTION_STAY == condAction) { + if (COND_ACTION_STAY == condAction || (COND_ACTION_PUSH_JOIN == condAction && NULL == pOnCond)) { return TSDB_CODE_SUCCESS; - } else if (COND_ACTION_PUSH_JOIN == condAction) { - *pOnCond = pJoin->node.pConditions; - } else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) { - *pLeftChildCond = pJoin->node.pConditions; - } else if (COND_ACTION_PUSH_RIGHT_CHILD == condAction) { - *pRightChildCond = pJoin->node.pConditions; } - pJoin->node.pConditions = NULL; + + if (COND_ACTION_PUSH_JOIN == condAction) { + *pOnCond = *pSrcCond; + } else if (COND_ACTION_PUSH_LEFT_CHILD == condAction) { + *pLeftChildCond = *pSrcCond; + } else if (COND_ACTION_PUSH_RIGHT_CHILD == condAction) { + *pRightChildCond = *pSrcCond; + } + *pSrcCond = NULL; return TSDB_CODE_SUCCESS; } -static int32_t pdcJoinSplitOrigCond(SJoinLogicNode* pJoin, SNode** pOnCond, SNode** pLeftChildCond, +static int32_t pdcJoinSplitCond(SJoinLogicNode* pJoin, SNode** pSrcCond, SNode** pOnCond, SNode** pLeftChildCond, SNode** pRightChildCond) { - if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->node.pConditions)) { - return pdcJoinSplitLogicCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond); + if (QUERY_NODE_LOGIC_CONDITION == nodeType(*pSrcCond)) { + return pdcJoinSplitLogicCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond); } else { - return pdcJoinSplitOpCond(pJoin, pOnCond, pLeftChildCond, pRightChildCond); + return pdcJoinSplitOpCond(pJoin, pSrcCond, pOnCond, pLeftChildCond, pRightChildCond); } } @@ -668,7 +705,7 @@ static int32_t pdcPushDownCondToChild(SOptimizeContext* pCxt, SLogicNode* pChild return pdcMergeConds(&pChild->pConditions, pCond); } -static bool pushDownCondOptIsPriKey(SNode* pNode, SSHashObj* pTables) { +static bool pdcJoinIsPrim(SNode* pNode, SSHashObj* pTables) { if (QUERY_NODE_COLUMN != nodeType(pNode)) { return false; } @@ -676,7 +713,7 @@ static bool pushDownCondOptIsPriKey(SNode* pNode, SSHashObj* pTables) { if (PRIMARYKEY_TIMESTAMP_COL_ID != pCol->colId || TSDB_SYSTEM_TABLE == pCol->tableType) { return false; } - return pushDownCondOptColInTableList(pNode, pTables); + return pdcJoinColInTableList(pNode, pTables); } static bool pdcJoinIsPrimEqualCond(SJoinLogicNode* pJoin, SNode* pCond) { @@ -695,10 +732,10 @@ static bool pdcJoinIsPrimEqualCond(SJoinLogicNode* pJoin, SNode* pCond) { collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pRightTables); bool res = false; - if (pushDownCondOptIsPriKey(pOper->pLeft, pLeftTables)) { - res = pushDownCondOptIsPriKey(pOper->pRight, pRightTables); - } else if (pushDownCondOptIsPriKey(pOper->pLeft, pRightTables)) { - res = pushDownCondOptIsPriKey(pOper->pRight, pLeftTables); + if (pdcJoinIsPrim(pOper->pLeft, pLeftTables)) { + res = pdcJoinIsPrim(pOper->pRight, pRightTables); + } else if (pdcJoinIsPrim(pOper->pLeft, pRightTables)) { + res = pdcJoinIsPrim(pOper->pRight, pLeftTables); } tSimpleHashCleanup(pLeftTables); @@ -730,7 +767,7 @@ static bool pdcJoinHasPrimEqualCond(SJoinLogicNode* pJoin, SNode* pCond, bool* e } } -static int32_t pushDownCondOptPartJoinOnCondLogicCond(SJoinLogicNode* pJoin, SNode** ppPrimKeyEqCond, SNode** ppOnCond) { +static int32_t pdcJoinSplitPrimInLogicCond(SJoinLogicNode* pJoin, SNode** ppPrimEqCond, SNode** ppOnCond) { SLogicConditionNode* pLogicCond = (SLogicConditionNode*)(pJoin->pFullOnCond); int32_t code = TSDB_CODE_SUCCESS; @@ -738,8 +775,8 @@ static int32_t pushDownCondOptPartJoinOnCondLogicCond(SJoinLogicNode* pJoin, SNo SNode* pCond = NULL; WHERE_EACH(pCond, pLogicCond->pParameterList) { if (pdcJoinIsPrimEqualCond(pJoin, pCond)) { - nodesDestroyNode(*ppPrimKeyEqCond); - *ppPrimKeyEqCond = nodesCloneNode(pCond); + nodesDestroyNode(*ppPrimEqCond); + *ppPrimEqCond = nodesCloneNode(pCond); ERASE_NODE(pLogicCond->pParameterList); } else { code = nodesListMakeAppend(&pOnConds, nodesCloneNode(pCond)); @@ -752,38 +789,38 @@ static int32_t pushDownCondOptPartJoinOnCondLogicCond(SJoinLogicNode* pJoin, SNo code = nodesMergeConds(&pTempOnCond, &pOnConds); } - if (TSDB_CODE_SUCCESS == code && NULL != *ppPrimKeyEqCond) { - *ppOnCond = pTempOnCond; - nodesDestroyNode(pJoin->pFullOnCond); - pJoin->pFullOnCond = NULL; - return TSDB_CODE_SUCCESS; + if (TSDB_CODE_SUCCESS == code) { + if (NULL != *ppPrimEqCond) { + *ppOnCond = pTempOnCond; + nodesDestroyNode(pJoin->pFullOnCond); + pJoin->pFullOnCond = NULL; + return TSDB_CODE_SUCCESS; + } + planError("no primary key equal cond found, condListNum:%d", pLogicCond->pParameterList->length); + return TSDB_CODE_PLAN_INTERNAL_ERROR; } else { nodesDestroyList(pOnConds); nodesDestroyNode(pTempOnCond); - return TSDB_CODE_PLAN_INTERNAL_ERROR; + return code; } } -static int32_t pdcPartJoinPrimCond(SJoinLogicNode* pJoin, SNode** ppPrimKeyEqCond, SNode** ppOnCond) { - if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pFullOnCond) && - LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)(pJoin->pFullOnCond))->condType) { - return pushDownCondOptPartJoinOnCondLogicCond(pJoin, ppPrimKeyEqCond, ppOnCond); - } - - if (pdcJoinIsPrimEqualCond(pJoin, pJoin->pFullOnCond)) { - *ppPrimKeyEqCond = pJoin->pFullOnCond; - *ppOnCond = NULL; - pJoin->pFullOnCond = NULL; - return TSDB_CODE_SUCCESS; - } else { - return TSDB_CODE_PLAN_INTERNAL_ERROR; - } -} - -static int32_t pdcJoinCheckPartPrimOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { +static int32_t pdcJoinSplitPrimEqCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { + int32_t code = TSDB_CODE_SUCCESS; SNode* pPrimKeyEqCond = NULL; SNode* pJoinOnCond = NULL; - int32_t code = pdcPartJoinPrimCond(pJoin, &pPrimKeyEqCond, &pJoinOnCond); + + if (QUERY_NODE_LOGIC_CONDITION == nodeType(pJoin->pFullOnCond) && + LOGIC_COND_TYPE_AND == ((SLogicConditionNode*)(pJoin->pFullOnCond))->condType) { + code = pdcJoinSplitPrimInLogicCond(pJoin, &pPrimKeyEqCond, &pJoinOnCond); + } else if (pdcJoinIsPrimEqualCond(pJoin, pJoin->pFullOnCond)) { + pPrimKeyEqCond = pJoin->pFullOnCond; + pJoinOnCond = NULL; + } else { + planError("unexcepted conds in fullOnCond, type:%s", nodesNodeName(nodeType(pJoin->pFullOnCond))); + code = TSDB_CODE_PLAN_INTERNAL_ERROR; + } + if (TSDB_CODE_SUCCESS == code) { pJoin->pPrimKeyEqCond = pPrimKeyEqCond; pJoin->pFullOnCond = pJoinOnCond; @@ -794,15 +831,7 @@ static int32_t pdcJoinCheckPartPrimOnCond(SOptimizeContext* pCxt, SJoinLogicNode return code; } -static bool pdcIsTableColumn(SNode* pNode, SNodeList* pTableCols) { - if (QUERY_NODE_COLUMN != nodeType(pNode)) { - return false; - } - SColumnNode* pCol = (SColumnNode*)pNode; - return pdcColBelongThisTable(pNode, pTableCols); -} - -static bool pdcIsEqualOnCond(SJoinLogicNode* pJoin, SNode* pCond, bool* allTags) { +static bool pdcJoinIsEqualOnCond(SJoinLogicNode* pJoin, SNode* pCond, bool* allTags) { if (QUERY_NODE_OPERATOR != nodeType(pCond)) { return false; } @@ -826,10 +855,10 @@ static bool pdcIsEqualOnCond(SJoinLogicNode* pJoin, SNode* pCond, bool* allTags) SNodeList* pLeftCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0))->pTargets; SNodeList* pRightCols = ((SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1))->pTargets; bool isEqual = false; - if (pdcIsTableColumn(pOper->pLeft, pLeftCols)) { - isEqual = pdcIsTableColumn(pOper->pRight, pRightCols); - } else if (pdcIsTableColumn(pOper->pLeft, pRightCols)) { - isEqual = pdcIsTableColumn(pOper->pRight, pLeftCols); + if (pdcJoinColInTableColList(pOper->pLeft, pLeftCols)) { + isEqual = pdcJoinColInTableColList(pOper->pRight, pRightCols); + } else if (pdcJoinColInTableColList(pOper->pLeft, pRightCols)) { + isEqual = pdcJoinColInTableColList(pOper->pRight, pLeftCols); } return isEqual; @@ -842,11 +871,12 @@ static int32_t pdcJoinPartLogicEqualOnCond(SJoinLogicNode* pJoin) { SNodeList* pColEqOnConds = NULL; SNodeList* pTagEqOnConds = NULL; SNodeList* pTagOnConds = NULL; + SNodeList* pColOnConds = NULL; SNode* pCond = NULL; bool allTags = false; FOREACH(pCond, pLogicCond->pParameterList) { allTags = false; - if (pdcIsEqualOnCond(pJoin, pCond, &allTags)) { + if (pdcJoinIsEqualOnCond(pJoin, pCond, &allTags)) { if (allTags) { code = nodesListMakeAppend(&pTagEqOnConds, nodesCloneNode(pCond)); } else { @@ -854,7 +884,10 @@ static int32_t pdcJoinPartLogicEqualOnCond(SJoinLogicNode* pJoin) { } } else if (allTags) { code = nodesListMakeAppend(&pTagOnConds, nodesCloneNode(pCond)); + } else { + code = nodesListMakeAppend(&pColOnConds, nodesCloneNode(pCond)); } + if (code) { break; } @@ -863,6 +896,7 @@ static int32_t pdcJoinPartLogicEqualOnCond(SJoinLogicNode* pJoin) { SNode* pTempTagEqCond = NULL; SNode* pTempColEqCond = NULL; SNode* pTempTagOnCond = NULL; + SNode* pTempColOnCond = NULL; if (TSDB_CODE_SUCCESS == code) { code = nodesMergeConds(&pTempColEqCond, &pColEqOnConds); } @@ -872,18 +906,27 @@ static int32_t pdcJoinPartLogicEqualOnCond(SJoinLogicNode* pJoin) { if (TSDB_CODE_SUCCESS == code) { code = nodesMergeConds(&pTempTagOnCond, &pTagOnConds); } + if (TSDB_CODE_SUCCESS == code) { + code = nodesMergeConds(&pTempColOnCond, &pColOnConds); + } if (TSDB_CODE_SUCCESS == code) { pJoin->pColEqCond = pTempColEqCond; + pJoin->pColOnCond = pTempColOnCond; pJoin->pTagEqCond = pTempTagEqCond; pJoin->pTagOnCond = pTempTagOnCond; - return TSDB_CODE_SUCCESS; } else { nodesDestroyList(pColEqOnConds); nodesDestroyList(pTagEqOnConds); - return TSDB_CODE_PLAN_INTERNAL_ERROR; + nodesDestroyList(pColOnConds); + nodesDestroyList(pTagOnConds); + nodesDestroyNode(pTempTagEqCond); + nodesDestroyNode(pTempColEqCond); + nodesDestroyNode(pTempTagOnCond); + nodesDestroyNode(pTempColOnCond); } - return TSDB_CODE_SUCCESS; + + return code; } static int32_t pdcJoinPartEqualOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { @@ -898,7 +941,7 @@ static int32_t pdcJoinPartEqualOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJ } bool allTags = false; - if (pdcIsEqualOnCond(pJoin, pJoin->pFullOnCond, &allTags)) { + if (pdcJoinIsEqualOnCond(pJoin, pJoin->pFullOnCond, &allTags)) { if (allTags) { pJoin->pTagEqCond = nodesCloneNode(pJoin->pFullOnCond); } else { @@ -906,11 +949,114 @@ static int32_t pdcJoinPartEqualOnCond(SOptimizeContext* pCxt, SJoinLogicNode* pJ } } else if (allTags) { pJoin->pTagOnCond = nodesCloneNode(pJoin->pFullOnCond); + } else { + pJoin->pColOnCond = nodesCloneNode(pJoin->pFullOnCond); } return TSDB_CODE_SUCCESS; } +static EDealRes pdcJoinCollectCondCol(SNode* pNode, void* pContext) { + SCpdCollectTableColCxt* pCxt = pContext; + if (QUERY_NODE_COLUMN == nodeType(pNode)) { + if (pdcJoinColInTableList(pNode, pCxt->pTables)) { + SColumnNode* pCol = (SColumnNode*)pNode; + char name[TSDB_TABLE_NAME_LEN + TSDB_COL_NAME_LEN]; + int32_t len = 0; + if ('\0' == pCol->tableAlias[0]) { + len = snprintf(name, sizeof(name), "%s", pCol->colName); + } else { + len = snprintf(name, sizeof(name), "%s.%s", pCol->tableAlias, pCol->colName); + } + if (NULL == taosHashGet(pCxt->pColHash, name, len)) { + pCxt->errCode = taosHashPut(pCxt->pColHash, name, len, NULL, 0); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + pCxt->errCode = nodesListStrictAppend(pCxt->pResCols, nodesCloneNode(pNode)); + } + } + } + } + + return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_CONTINUE : DEAL_RES_ERROR); +} + +static int32_t pdcJoinCollectColsFromParent(SJoinLogicNode* pJoin, SSHashObj* pTables, SNodeList* pCondCols) { + SCpdCollectTableColCxt cxt = { + .errCode = TSDB_CODE_SUCCESS, + .pTables = pTables, + .pResCols = pCondCols, + .pColHash = taosHashInit(128, taosGetDefaultHashFunction(TSDB_DATA_TYPE_BINARY), true, HASH_NO_LOCK) + }; + if (NULL == cxt.pColHash) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + nodesWalkExpr(pJoin->pPrimKeyEqCond, pdcJoinCollectCondCol, &cxt); + if (TSDB_CODE_SUCCESS == cxt.errCode) { + nodesWalkExpr(pJoin->pFullOnCond, pdcJoinCollectCondCol, &cxt); + } + + taosHashCleanup(cxt.pColHash); + return cxt.errCode; +} + +static int32_t pdcJoinAddParentOnColsToTarget(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { + if (NULL == pJoin->node.pParent || QUERY_NODE_LOGIC_PLAN_JOIN != nodeType(pJoin->node.pParent)) { + return TSDB_CODE_SUCCESS; + } + + SNodeList* pTargets = NULL; + int32_t code = TSDB_CODE_SUCCESS; + SNodeList* pCondCols = nodesMakeList(); + if (NULL == pCondCols) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + SSHashObj* pTables = NULL; + collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 0), &pTables); + collectTableAliasFromNodes(nodesListGetNode(pJoin->node.pChildren, 1), &pTables); + + SJoinLogicNode* pTmp = (SJoinLogicNode*)pJoin->node.pParent; + do { + code = pdcJoinCollectColsFromParent(pTmp, pTables, pCondCols); + if (TSDB_CODE_SUCCESS != code) { + break; + } + if (NULL == pTmp->node.pParent || QUERY_NODE_LOGIC_PLAN_JOIN != nodeType(pTmp->node.pParent)) { + break; + } + pTmp = (SJoinLogicNode*)pTmp->node.pParent; + } while (true); + + if (TSDB_CODE_SUCCESS == code) { + code = createColumnByRewriteExprs(pCondCols, &pTargets); + } + + nodesDestroyList(pCondCols); + + if (TSDB_CODE_SUCCESS == code) { + SNode* pNode = NULL; + FOREACH(pNode, pTargets) { + SNode* pTmp = NULL; + bool found = false; + FOREACH(pTmp, pJoin->node.pTargets) { + if (nodesEqualNode(pTmp, pNode)) { + found = true; + break; + } + } + if (!found) { + nodesListStrictAppend(pJoin->node.pTargets, nodesCloneNode(pNode)); + } + } + } + + nodesDestroyList(pTargets); + + return code; +} + + static int32_t pdcJoinAddPreFilterColsToTarget(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { if (NULL == pJoin->pFullOnCond) { return TSDB_CODE_SUCCESS; @@ -986,44 +1132,40 @@ static int32_t pdcDealJoin(SOptimizeContext* pCxt, SJoinLogicNode* pJoin) { SNode* pRightChildCond = NULL; int32_t code = pdcJoinCheckAllCond(pCxt, pJoin); if (TSDB_CODE_SUCCESS == code && NULL != pJoin->node.pConditions && 0 != gJoinOpt[t][s].pushDownFlag) { - code = pdcJoinSplitOrigCond(pJoin, &pOnCond, &pLeftChildCond, &pRightChildCond); - } - if (TSDB_CODE_SUCCESS == code && NULL != pOnCond) { - code = pdcJoinPushDownOnCond(pCxt, pJoin, &pOnCond); - } - if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) { - code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond); - } - if (TSDB_CODE_SUCCESS == code && NULL != pRightChildCond) { - code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1), &pRightChildCond); - } - - - if (NULL == pJoin->node.pConditions) { - int32_t code = pdcJoinCheckPartPrimOnCond(pCxt, pJoin); - if (TSDB_CODE_SUCCESS == code) { - code = pdcJoinPartEqualOnCond(pCxt, pJoin); + code = pdcJoinSplitCond(pJoin, &pJoin->node.pConditions, &pOnCond, &pLeftChildCond, &pRightChildCond); + if (TSDB_CODE_SUCCESS == code && NULL != pOnCond) { + code = pdcJoinPushDownOnCond(pCxt, pJoin, &pOnCond); } - if (TSDB_CODE_SUCCESS == code) { - code = pdcJoinAddPreFilterColsToTarget(pCxt, pJoin); + if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) { + code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond); } - if (TSDB_CODE_SUCCESS == code) { - OPTIMIZE_FLAG_SET_MASK(pJoin->node.optimizedFlag, OPTIMIZE_FLAG_PUSH_DOWN_CONDE); - pCxt->optimized = true; + if (TSDB_CODE_SUCCESS == code && NULL != pRightChildCond) { + code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1), &pRightChildCond); } - return code; } - - if (TSDB_CODE_SUCCESS == code) { - code = pdcJoinCheckPartPrimOnCond(pCxt, pJoin); + code = pdcJoinSplitCond(pJoin, &pJoin->pFullOnCond, NULL, &pLeftChildCond, &pRightChildCond); + if (TSDB_CODE_SUCCESS == code && NULL != pLeftChildCond) { + code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 0), &pLeftChildCond); + } + if (TSDB_CODE_SUCCESS == code && NULL != pRightChildCond) { + code = pdcPushDownCondToChild(pCxt, (SLogicNode*)nodesListGetNode(pJoin->node.pChildren, 1), &pRightChildCond); + } + } + + if (TSDB_CODE_SUCCESS == code) { + code = pdcJoinSplitPrimEqCond(pCxt, pJoin); } if (TSDB_CODE_SUCCESS == code) { code = pdcJoinPartEqualOnCond(pCxt, pJoin); } + if (TSDB_CODE_SUCCESS == code) { + code = pdcJoinAddParentOnColsToTarget(pCxt, pJoin); + } + if (TSDB_CODE_SUCCESS == code) { code = pdcJoinAddPreFilterColsToTarget(pCxt, pJoin); } @@ -3539,7 +3681,7 @@ static bool stbJoinOptShouldBeOptimized(SLogicNode* pNode) { } SJoinLogicNode* pJoin = (SJoinLogicNode*)pNode; - if (pJoin->isSingleTableJoin || NULL == pJoin->pTagEqCond || NULL != pJoin->pTagOnCond || pNode->pChildren->length != 2 + if (pJoin->isSingleTableJoin || NULL == pJoin->pTagEqCond || pNode->pChildren->length != 2 || pJoin->hasSubQuery || pJoin->joinAlgo != JOIN_ALGO_UNKNOWN || pJoin->isLowLevelJoin) { if (pJoin->joinAlgo == JOIN_ALGO_UNKNOWN) { pJoin->joinAlgo = JOIN_ALGO_MERGE; @@ -3644,6 +3786,7 @@ static int32_t stbJoinOptCreateTagHashJoinNode(SLogicNode* pOrig, SNodeList* pCh } pJoin->joinType = pOrigJoin->joinType; + pJoin->subType = pOrigJoin->subType; pJoin->joinAlgo = JOIN_ALGO_HASH; pJoin->isSingleTableJoin = pOrigJoin->isSingleTableJoin; pJoin->hasSubQuery = pOrigJoin->hasSubQuery;