diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 4bf0663def..fce2aece05 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -61,6 +61,7 @@ typedef struct SExprNode { bool asAlias; bool asParam; bool asPosition; + int32_t projIdx; } SExprNode; typedef enum EColumnType { @@ -91,6 +92,7 @@ typedef struct SColumnNode { int16_t numOfPKs; bool tableHasPk; bool isPk; + int32_t projRefIdx; } SColumnNode; typedef struct SColumnRefNode { diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 78cf78f6db..709bdff374 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -103,6 +103,7 @@ static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) { COPY_CHAR_ARRAY_FIELD(aliasName); COPY_CHAR_ARRAY_FIELD(userAlias); COPY_SCALAR_FIELD(orderAlias); + COPY_SCALAR_FIELD(projIdx); return TSDB_CODE_SUCCESS; } @@ -124,6 +125,7 @@ static int32_t columnNodeCopy(const SColumnNode* pSrc, SColumnNode* pDst) { COPY_SCALAR_FIELD(tableHasPk); COPY_SCALAR_FIELD(isPk); COPY_SCALAR_FIELD(numOfPKs); + COPY_SCALAR_FIELD(projRefIdx); return TSDB_CODE_SUCCESS; } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 7e84ef8482..8a7b9a15b0 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1305,7 +1305,11 @@ static int32_t createColumnsByTable(STranslateContext* pCxt, const STableNode* p SListCell* pCell = nodesListGetCell(pList, LIST_LENGTH(pList) - 1); code = setColumnInfoByExpr(pTempTable, (SExprNode*)pNode, (SColumnNode**)&pCell->pNode); } - if (TSDB_CODE_SUCCESS != code) break; + if (TSDB_CODE_SUCCESS == code) { + pCol->projRefIdx = ((SExprNode*)pNode)->projIdx; + } else { + break; + } } } return code; @@ -5174,6 +5178,11 @@ static int32_t translateProjectionList(STranslateContext* pCxt, SSelectStmt* pSe if (!pSelect->isSubquery) { return rewriteProjectAlias(pSelect->pProjectionList); } else { + SNode* pNode; + int32_t projIdx = 1; + FOREACH(pNode, pSelect->pProjectionList) { + ((SExprNode*)pNode)->projIdx = projIdx++; + } return TSDB_CODE_SUCCESS; } } diff --git a/source/libs/planner/inc/planInt.h b/source/libs/planner/inc/planInt.h index 090071ee7f..9435955a3e 100644 --- a/source/libs/planner/inc/planInt.h +++ b/source/libs/planner/inc/planInt.h @@ -68,6 +68,7 @@ int32_t tagScanSetExecutionMode(SScanLogicNode* pScan); int32_t cloneLimit(SLogicNode* pParent, SLogicNode* pChild, uint8_t cloneWhat, bool* pCloned); int32_t sortPriKeyOptGetSequencingNodesImpl(SLogicNode* pNode, bool groupSort, SSortLogicNode* pSort, bool* pNotOptimize, SNodeList** pSequencingNodes, bool* keepSort); +bool isColRefExpr(const SColumnNode* pCol, const SExprNode* pExpr); #ifdef __cplusplus diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index d5ee5c51df..d1a7a67057 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -1390,11 +1390,14 @@ static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pS } SNode* pNode; + int32_t projIdx = 1; FOREACH(pNode, pExprs) { - if (TSDB_CODE_SUCCESS != (code = nodesListStrictAppend(pList, (SNode*)createColumnByExpr(pStmtName, (SExprNode*)pNode)))) { + SColumnNode* pCol = createColumnByExpr(pStmtName, (SExprNode*)pNode); + if (TSDB_CODE_SUCCESS != (code = nodesListStrictAppend(pList, (SNode*)pCol))) { nodesDestroyList(pList); return code; } + pCol->projRefIdx = ((SExprNode*)pNode)->projIdx; } *pCols = pList; diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index d48871fd70..5d218d3aad 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -4883,13 +4883,41 @@ typedef struct SMergeProjectionsContext { int32_t errCode; } SMergeProjectionsContext; +static EDealRes mergeProjectionsExpr2(SNode** pNode, void* pContext) { + SMergeProjectionsContext* pCxt = pContext; + SProjectLogicNode* pChildProj = pCxt->pChildProj; + if (QUERY_NODE_COLUMN == nodeType(*pNode)) { + SColumnNode* pProjCol = (SColumnNode*)(*pNode); + SNode* pProjection; + int32_t projIdx = 1; + FOREACH(pProjection, pChildProj->pProjections) { + if (isColRefExpr(pProjCol, (SExprNode*)pProjection)) { + + //} + //if (0 == strcmp(((SColumnNode*)(*pNode))->colName, ((SExprNode*)pProjection)->aliasName)) { + SNode* pExpr = NULL; + pCxt->errCode = nodesCloneNode(pProjection, &pExpr); + if (pExpr == NULL) { + return DEAL_RES_ERROR; + } + snprintf(((SExprNode*)pExpr)->aliasName, sizeof(((SExprNode*)pExpr)->aliasName), "%s", + ((SExprNode*)*pNode)->aliasName);// 保留外层project的aliasname, 外层project的aliasName是被改写过的. + nodesDestroyNode(*pNode); + *pNode = pExpr; + return DEAL_RES_IGNORE_CHILD; + } + } + } + return DEAL_RES_CONTINUE; +} + static EDealRes mergeProjectionsExpr(SNode** pNode, void* pContext) { SMergeProjectionsContext* pCxt = pContext; SProjectLogicNode* pChildProj = pCxt->pChildProj; if (QUERY_NODE_COLUMN == nodeType(*pNode)) { SNode* pTarget; FOREACH(pTarget, ((SLogicNode*)pChildProj)->pTargets) { - if (nodesEqualNode(pTarget, *pNode)) { + if (nodesEqualNode(pTarget, *pNode)) { // pNode是projectlist里的, aliasName被改写成了expr_#, 而pTarget是根据childProject的projectlist生成的, node里面啥都没有 SNode* pProjection; FOREACH(pProjection, pChildProj->pProjections) { if (0 == strcmp(((SColumnNode*)pTarget)->colName, ((SExprNode*)pProjection)->aliasName)) { @@ -4917,7 +4945,7 @@ static int32_t mergeProjectsOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* ((SProjectLogicNode*)pSelfNode)->inputIgnoreGroup = true; } SMergeProjectionsContext cxt = {.pChildProj = (SProjectLogicNode*)pChild, .errCode = TSDB_CODE_SUCCESS}; - nodesRewriteExprs(((SProjectLogicNode*)pSelfNode)->pProjections, mergeProjectionsExpr, &cxt); + nodesRewriteExprs(((SProjectLogicNode*)pSelfNode)->pProjections, mergeProjectionsExpr2, &cxt); int32_t code = cxt.errCode; if (TSDB_CODE_SUCCESS == code) { diff --git a/source/libs/planner/src/planPhysiCreater.c b/source/libs/planner/src/planPhysiCreater.c index e50e574f01..f3a4331562 100644 --- a/source/libs/planner/src/planPhysiCreater.c +++ b/source/libs/planner/src/planPhysiCreater.c @@ -166,6 +166,7 @@ static int32_t createTarget(SNode* pNode, int16_t dataBlockId, int16_t slotId, S } static int32_t putSlotToHashImpl(int16_t dataBlockId, int16_t slotId, const char* pName, int32_t len, SHashObj* pHash) { + qInfo("wjm put slot into hash: %p, name: %s, slotId: %d", pHash, pName, slotId); SSlotIndex* pIndex = taosHashGet(pHash, pName, len); if (NULL != pIndex) { SSlotIdInfo info = {.slotId = slotId, .set = false}; @@ -223,8 +224,16 @@ static int32_t buildDataBlockSlots(SPhysiPlanContext* pCxt, SNodeList* pList, SD code = nodesListStrictAppend(pDataBlockDesc->pSlots, createSlotDesc(pCxt, name, pNode, slotId, true, false)); } if (TSDB_CODE_SUCCESS == code) { + qInfo("wjm append slot name: %s, slotId: %d, aliasName: %s", name, slotId, ((SExprNode*)pNode)->aliasName); code = putSlotToHash(name, len, pDataBlockDesc->dataBlockId, slotId, pNode, pHash); } + if (TSDB_CODE_SUCCESS == code) { + if (nodeType(pNode) == QUERY_NODE_COLUMN && ((SColumnNode*)pNode)->projRefIdx > 0) { + sprintf(name + strlen(name), "%d", ((SColumnNode*)pNode)->projRefIdx); + } + qInfo("wjm append slot name: %s, slotId: %d, aliasName: %s", name, slotId, ((SExprNode*)pNode)->aliasName); + code = putSlotToHash(name, strlen(name), pDataBlockDesc->dataBlockId, slotId, pNode, pHash); + } taosMemoryFree(name); if (TSDB_CODE_SUCCESS == code) { pDataBlockDesc->totalRowSize += ((SExprNode*)pNode)->resType.bytes; @@ -306,6 +315,7 @@ static int32_t addDataBlockSlotsImpl(SPhysiPlanContext* pCxt, SNodeList* pList, } } + qInfo("wjm add datablock slots for: %s id: %d, aliasName: %s", name, slotId, ((SExprNode*)pNode)->aliasName); taosMemoryFree(name); if (TSDB_CODE_SUCCESS == code) { SNode* pTarget = NULL; @@ -383,9 +393,12 @@ static EDealRes doSetSlotId(SNode* pNode, void* pContext) { if (TSDB_CODE_SUCCESS != pCxt->errCode) { return DEAL_RES_ERROR; } - SSlotIndex* pIndex = taosHashGet(pCxt->pLeftHash, name, len); + if (((SColumnNode*)pNode)->projRefIdx > 0) { + sprintf(name + strlen(name), "%d", ((SColumnNode*)pNode)->projRefIdx); + } + SSlotIndex* pIndex = taosHashGet(pCxt->pLeftHash, name, strlen(name)); if (NULL == pIndex) { - pIndex = taosHashGet(pCxt->pRightHash, name, len); + pIndex = taosHashGet(pCxt->pRightHash, name, strlen(name)); } // pIndex is definitely not NULL, otherwise it is a bug if (NULL == pIndex) { @@ -396,9 +409,10 @@ static EDealRes doSetSlotId(SNode* pNode, void* pContext) { taosMemoryFree(name); return DEAL_RES_ERROR; } - taosMemoryFree(name); ((SColumnNode*)pNode)->dataBlockId = pIndex->dataBlockId; ((SColumnNode*)pNode)->slotId = ((SSlotIdInfo*)taosArrayGet(pIndex->pSlotIdsInfo, 0))->slotId; + qInfo("wjm set slotId for %s, slotId: %d, aliasName: %s", name, ((SColumnNode*)pNode)->slotId, ((SExprNode*)pNode)->aliasName); + taosMemoryFree(name); return DEAL_RES_IGNORE_CHILD; } return DEAL_RES_CONTINUE; @@ -462,6 +476,7 @@ static SPhysiNode* makePhysiNode(SPhysiPlanContext* pCxt, SLogicNode* pLogicNode terrno = code; return NULL; } + qInfo("wjm create node: %s", nodesNodeName(type)); TSWAP(pPhysiNode->pLimit, pLogicNode->pLimit); TSWAP(pPhysiNode->pSlimit, pLogicNode->pSlimit); diff --git a/source/libs/planner/src/planUtil.c b/source/libs/planner/src/planUtil.c index e1e98f221f..8c319baa77 100644 --- a/source/libs/planner/src/planUtil.c +++ b/source/libs/planner/src/planUtil.c @@ -716,5 +716,8 @@ int32_t tagScanSetExecutionMode(SScanLogicNode* pScan) { return TSDB_CODE_SUCCESS; } +bool isColRefExpr(const SColumnNode* pCol, const SExprNode* pExpr) { + if (pCol->projRefIdx > 0) return pCol->projRefIdx == pExpr->projIdx; - + return 0 == strcmp(pCol->colName, pExpr->aliasName); +}