Merge pull request #25935 from taosdata/fix/3.0/TD-30188

fix select from union all caused crash
This commit is contained in:
dapan1121 2024-05-30 15:45:44 +08:00 committed by GitHub
commit 4f67ccc5d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 38 additions and 7 deletions

View File

@ -183,6 +183,7 @@ typedef struct SProjectLogicNode {
char stmtName[TSDB_TABLE_NAME_LEN]; char stmtName[TSDB_TABLE_NAME_LEN];
bool ignoreGroupId; bool ignoreGroupId;
bool inputIgnoreGroup; bool inputIgnoreGroup;
bool isSetOpProj;
} SProjectLogicNode; } SProjectLogicNode;
typedef struct SIndefRowsFuncLogicNode { typedef struct SIndefRowsFuncLogicNode {

View File

@ -1587,6 +1587,7 @@ static int32_t createSetOpProjectLogicNode(SLogicPlanContext* pCxt, SSetOperator
TSWAP(pProject->node.pLimit, pSetOperator->pLimit); TSWAP(pProject->node.pLimit, pSetOperator->pLimit);
} }
pProject->ignoreGroupId = true; pProject->ignoreGroupId = true;
pProject->isSetOpProj = true;
int32_t code = TSDB_CODE_SUCCESS; int32_t code = TSDB_CODE_SUCCESS;

View File

@ -3284,9 +3284,23 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
SNodeList* pNewChildTargets = nodesMakeList(); SNodeList* pNewChildTargets = nodesMakeList();
if (NULL == pProjectNode->node.pParent) { if (NULL == pProjectNode->node.pParent) {
SNode* pProjection = NULL; SNode *pProjection = NULL, *pChildTarget = NULL;
bool needOrderMatch = QUERY_NODE_LOGIC_PLAN_PROJECT == nodeType(pChild) && ((SProjectLogicNode*)pChild)->isSetOpProj;
bool orderMatch = true;
if (needOrderMatch) {
// For sql: select ... from (select ... union all select ...);
// When eliminating the outer proj (the outer select), we have to make sure that the outer proj projections and
// union all project targets have same columns in the same order. See detail in TD-30188
FORBOTH(pProjection, pProjectNode->pProjections, pChildTarget, pChild->pTargets) {
if (!pProjection) break;
if (0 != strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) {
orderMatch = false;
break;
}
nodesListAppend(pNewChildTargets, nodesCloneNode(pChildTarget));
}
} else {
FOREACH(pProjection, pProjectNode->pProjections) { FOREACH(pProjection, pProjectNode->pProjections) {
SNode* pChildTarget = NULL;
FOREACH(pChildTarget, pChild->pTargets) { FOREACH(pChildTarget, pChild->pTargets) {
if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) { if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) {
nodesListAppend(pNewChildTargets, nodesCloneNode(pChildTarget)); nodesListAppend(pNewChildTargets, nodesCloneNode(pChildTarget));
@ -3294,8 +3308,10 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan*
} }
} }
} }
}
if (eliminateProjOptCanChildConditionUseChildTargets(pChild, pNewChildTargets)) { if (eliminateProjOptCanChildConditionUseChildTargets(pChild, pNewChildTargets) &&
(!needOrderMatch || (needOrderMatch && orderMatch))) {
nodesDestroyList(pChild->pTargets); nodesDestroyList(pChild->pTargets);
pChild->pTargets = pNewChildTargets; pChild->pTargets = pNewChildTargets;
} else { } else {

View File

@ -240,9 +240,22 @@ class TDTestCase:
tdSql.error( " '' union all select c1 from ct1 " ) tdSql.error( " '' union all select c1 from ct1 " )
# tdSql.error( "select c1 from ct1 union select c1 from ct2 union select c1 from ct4 ") # tdSql.error( "select c1 from ct1 union select c1 from ct2 union select c1 from ct4 ")
def test_select_from_union_all(self):
tdSql.query('select c8, ts from ((select ts, c8,c1 from stb1 order by c1) union all select ts, c8, c1 from stb1 limit 15)')
tdSql.checkRows(15)
tdSql.query('select c8, ts from ((select ts, c8,c1 from stb1 order by c1) union all (select ts, c8, c1 from stb1 order by c8 limit 10) limit 15)')
tdSql.checkRows(15)
tdSql.query('select ts, c1 from ((select ts, c8,c1 from stb1 order by c1) union all (select ts, c8, c1 from stb1 order by c8 limit 10) limit 15)')
tdSql.checkRows(15)
tdSql.query('select ts, c1, c8 from ((select ts, c8,c1 from stb1 order by c1) union all (select ts, c8, c1 from stb1 order by c8 limit 10) limit 15)')
tdSql.checkRows(15)
tdSql.query('select ts, c8, c1, 123 from ((select ts, c8,c1 from stb1 order by c1) union all (select ts, c8, c1 from stb1 order by c8 limit 10) limit 15)')
tdSql.checkRows(15)
def all_test(self): def all_test(self):
self.__test_error() self.__test_error()
self.union_check() self.union_check()
self.test_select_from_union_all()
def __create_tb(self): def __create_tb(self):