From 1ccaaf75bda9544e04ba64c5e8ef123fe293fd92 Mon Sep 17 00:00:00 2001 From: Jinqing Kuang Date: Fri, 20 Sep 2024 11:52:43 +0800 Subject: [PATCH] fix(query)[TS-5443]. Fix invalid key in ORDER BY within subqueries Resolved an issue where an ORDER BY alias in subqueries failed to convert to the expected ColumnNode when the corresponding column could be omitted. Updated the conversion logic to handle this case correctly and ensure proper query execution. --- include/libs/nodes/querynodes.h | 1 - source/libs/nodes/src/nodesCloneFuncs.c | 1 - source/libs/nodes/src/nodesUtilFuncs.c | 3 +- source/libs/parser/src/parTranslater.c | 3 - tests/army/query/subquery/subqueryBugs.py | 68 +++++++++++++++++++++++ 5 files changed, 69 insertions(+), 7 deletions(-) diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 1b02203c07..5f9a4a1110 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -57,7 +57,6 @@ typedef struct SExprNode { char aliasName[TSDB_COL_NAME_LEN]; char userAlias[TSDB_COL_NAME_LEN]; SArray* pAssociation; - bool orderAlias; bool asAlias; bool asParam; bool asPosition; diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index d9b72b36b7..5db8863311 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -102,7 +102,6 @@ static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) { COPY_OBJECT_FIELD(resType, sizeof(SDataType)); COPY_CHAR_ARRAY_FIELD(aliasName); COPY_CHAR_ARRAY_FIELD(userAlias); - COPY_SCALAR_FIELD(orderAlias); COPY_SCALAR_FIELD(projIdx); return TSDB_CODE_SUCCESS; } diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 22acf4df45..06adcb4961 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -2443,8 +2443,7 @@ typedef struct SCollectFuncsCxt { static EDealRes collectFuncs(SNode* pNode, void* pContext) { SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext; - if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId) && - !(((SExprNode*)pNode)->orderAlias)) { + if (QUERY_NODE_FUNCTION == nodeType(pNode) && pCxt->classifier(((SFunctionNode*)pNode)->funcId)) { SFunctionNode* pFunc = (SFunctionNode*)pNode; if (FUNCTION_TYPE_TBNAME == pFunc->funcType && pCxt->tableAlias) { SValueNode* pVal = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 473b4f4b1a..8178871cc0 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -6644,7 +6644,6 @@ static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) { pCxt->pTranslateCxt->errCode = code; return DEAL_RES_ERROR; } - ((SExprNode*)pNew)->orderAlias = true; nodesDestroyNode(*pNode); *pNode = pNew; return DEAL_RES_CONTINUE; @@ -6668,7 +6667,6 @@ static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) { pCxt->pTranslateCxt->errCode = code; return DEAL_RES_ERROR; } - ((SExprNode*)pNew)->orderAlias = true; ((SOrderByExprNode*)*pNode)->pExpr = pNew; nodesDestroyNode(pExpr); return DEAL_RES_CONTINUE; @@ -7055,7 +7053,6 @@ static int32_t addOrderByPrimaryKeyToQueryImpl(STranslateContext* pCxt, SNode* p nodesDestroyNode((SNode*)pOrderByExpr); return code; } - ((SExprNode*)pOrderByExpr->pExpr)->orderAlias = true; // NODES_DESTORY_LIST(*pOrderByList); return nodesListMakeStrictAppend(pOrderByList, (SNode*)pOrderByExpr); } diff --git a/tests/army/query/subquery/subqueryBugs.py b/tests/army/query/subquery/subqueryBugs.py index 8442474d40..e208c40abc 100644 --- a/tests/army/query/subquery/subqueryBugs.py +++ b/tests/army/query/subquery/subqueryBugs.py @@ -78,6 +78,72 @@ class TDTestCase(TBase): rows = [row1, row2, row3, row4] tdSql.checkDataMem(sql1, rows) + def ts_5443(self): + tdLog.info("create database ts_5443") + tdSql.execute("create database ts_5443") + tdSql.execute("use ts_5443") + sqls = [ + "CREATE STABLE demo (ts TIMESTAMP, site NCHAR(8), expected BIGINT) TAGS (group_id BIGINT UNSIGNED)", + "CREATE TABLE demo_1 USING demo (group_id) TAGS (1)", + "INSERT INTO demo_1 VALUES ('2022-10-25 16:05:00.000', 'MN-01', 1)", + "CREATE TABLE demo_2 USING demo (group_id) TAGS (2)", + "INSERT INTO demo_2 VALUES ('2022-10-25 16:10:00.000', 'MN-02', 2)", + "CREATE TABLE demo_3 USING demo (group_id) TAGS (3)", + "INSERT INTO demo_3 VALUES ('2022-10-25 16:15:00.000', 'MN-03', 3)", + ] + tdSql.executes(sqls) + # test result of order by in plain query + query = ''' + SELECT _wend, site, SUM(expected) AS check + FROM ts_5443.demo + PARTITION BY site INTERVAL(5m) SLIDING (5m) + ORDER BY 1 DESC, 2, 3 + ''' + tdSql.query(query) + tdSql.checkRows(3) + rows = [ + ['2022-10-25 16:20:00.000', 'MN-03', 3], + ['2022-10-25 16:15:00.000', 'MN-02', 2], + ['2022-10-25 16:10:00.000', 'MN-01', 1], + ] + tdSql.checkDataMem(query, rows) + # test order by position alias within subquery + query = ''' + SELECT COUNT(*) FROM ( + SELECT _wend, site, SUM(expected) AS check + FROM ts_5443.demo + PARTITION BY site INTERVAL(5m) SLIDING (5m) + ORDER BY 1 DESC, 2, 3 + ) WHERE check <> 0 + ''' + tdSql.query(query) + tdSql.checkRows(1) + tdSql.checkData(0, 0, 3) + # test order by target name within subquery + query = ''' + SELECT COUNT(*) FROM ( + SELECT _wend, site, SUM(expected) AS check + FROM ts_5443.demo + PARTITION BY site INTERVAL(5m) SLIDING (5m) + ORDER BY _wend DESC, site, check + ) WHERE check <> 0 + ''' + tdSql.query(query) + tdSql.checkRows(1) + tdSql.checkData(0, 0, 3) + # test having clause within subquery + query = ''' + SELECT COUNT(*) FROM ( + SELECT _wend, site, SUM(expected) AS check + FROM ts_5443.demo + PARTITION BY site INTERVAL(5m) SLIDING (5m) + HAVING _wend > '2022-10-25 16:13:00.000' + ) WHERE check <> 0 + ''' + tdSql.query(query) + tdSql.checkRows(1) + tdSql.checkData(0, 0, 2) + # run def run(self): tdLog.debug(f"start to excute {__file__}") @@ -85,6 +151,8 @@ class TDTestCase(TBase): # TS-30189 self.ts_30189() + # TS-5443 + self.ts_5443() tdLog.success(f"{__file__} successfully executed")