fix subquery with same name caused data error

This commit is contained in:
wangjiaming0909 2024-08-28 16:19:57 +08:00
parent 2dffbe488b
commit 9713094bb2
8 changed files with 71 additions and 8 deletions

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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) {

View File

@ -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);

View File

@ -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);
}