From 75984e6d1e0a1908f602e79299768e596d744aac Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Thu, 20 Feb 2025 16:29:23 +0800 Subject: [PATCH] fix: group const value --- source/libs/executor/src/executil.c | 3 +- source/libs/function/src/builtinsimpl.c | 16 ++--- source/libs/parser/src/parTranslater.c | 6 +- tests/system-test/2-query/cols_function.py | 82 +++++++++++++++++++--- 4 files changed, 85 insertions(+), 22 deletions(-) diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index c3d21152a8..7a1cf4beb6 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -2127,8 +2127,7 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu for (int32_t i = 0; i < numOfOutput; ++i) { const char* pName = pCtx[i].pExpr->pExpr->_function.functionName; - if ((strcmp(pName, "_select_value") == 0) || (strcmp(pName, "_group_key") == 0) || - (strcmp(pName, "_group_const_value") == 0)) { + if ((strcmp(pName, "_select_value") == 0)) { if (pValCtxArray == NULL) { pValCtx[num++] = &pCtx[i]; } else { diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index c877ca3ae3..eb19c9400c 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -962,12 +962,6 @@ int32_t setSelectivityValue(SqlFunctionCtx* pCtx, SSDataBlock* pBlock, const STu SqlFunctionCtx* pc = pCtx->subsidiaries.pCtx[j]; int32_t dstSlotId = pc->pExpr->base.resSchema.slotId; - // group_key function has its own process function - // do not process there - if (fmIsGroupKeyFunc(pc->functionId)) { - continue; - } - SColumnInfoData* pDstCol = taosArrayGet(pBlock->pDataBlock, dstSlotId); if (NULL == pDstCol) { return TSDB_CODE_OUT_OF_RANGE; @@ -2432,7 +2426,8 @@ int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResIn } SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo); - + pRes->nullTupleSaved = false; + pRes->nullTuplePos.pageId = -1; return TSDB_CODE_SUCCESS; } @@ -2948,6 +2943,7 @@ int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { if (TSDB_CODE_SUCCESS != code) { return code; } + // handle selectivity code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows); @@ -3982,7 +3978,7 @@ int32_t topBotFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t currentRow = pBlock->info.rows; if (pEntryInfo->numOfRes <= 0) { colDataSetNULL(pCol, currentRow); - code = setNullSelectivityValue(pCtx, pBlock, currentRow); + code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, currentRow); return code; } for (int32_t i = 0; i < pEntryInfo->numOfRes; ++i) { @@ -5608,7 +5604,7 @@ int32_t sampleFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t currentRow = pBlock->info.rows; if (pInfo->numSampled == 0) { colDataSetNULL(pCol, currentRow); - code = setNullSelectivityValue(pCtx, pBlock, currentRow); + code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow); return code; } for (int32_t i = 0; i < pInfo->numSampled; ++i) { @@ -6060,7 +6056,7 @@ int32_t modeFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { code = setSelectivityValue(pCtx, pBlock, &resTuplePos, currentRow); } else { colDataSetNULL(pCol, currentRow); - code = setNullSelectivityValue(pCtx, pBlock, currentRow); + code = setSelectivityValue(pCtx, pBlock, &pInfo->nullTuplePos, currentRow); } modeFunctionCleanup(pInfo); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 83ea444912..342d5bdfa1 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -3857,6 +3857,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { if (isVectorFunc(*pNode) && !isDistinctOrderBy(pCxt)) { return DEAL_RES_IGNORE_CHILD; } + bool isSingleTable = fromSingleTable(((SSelectStmt*)pCxt->pCurrStmt)->pFromTable); SNode* pGroupNode = NULL; FOREACH(pGroupNode, getGroupByList(pCxt)) { SNode* pActualNode = getGroupByNode(pGroupNode); @@ -3866,10 +3867,13 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { if (IsEqualTbNameFuncNode(pSelect, pActualNode, *pNode)) { return rewriteExprToGroupKeyFunc(pCxt, pNode); } - if (isTbnameFuction(pActualNode) && QUERY_NODE_COLUMN == nodeType(*pNode) && + if ((isTbnameFuction(pActualNode) || isSingleTable) && QUERY_NODE_COLUMN == nodeType(*pNode) && ((SColumnNode*)*pNode)->colType == COLUMN_TYPE_TAG) { return rewriteExprToSelectTagFunc(pCxt, pNode); } + if(isSingleTable && isTbnameFuction(*pNode)) { + return rewriteExprToSelectTagFunc(pCxt, pNode); + } } SNode* pPartKey = NULL; bool partionByTbname = hasTbnameFunction(pSelect->pPartitionByList); diff --git a/tests/system-test/2-query/cols_function.py b/tests/system-test/2-query/cols_function.py index 8b318cefb1..d311dedf30 100644 --- a/tests/system-test/2-query/cols_function.py +++ b/tests/system-test/2-query/cols_function.py @@ -1022,7 +1022,7 @@ class TDTestCase: self.orderby_test("(select *, tbname from test.long_col_test)", "longcolumntestlongcolumntestlongcolumntestlongcolumntest88888888", True) tdLog.info("long_column_name_test subquery_test: one_cols_multi_output_with_group_test from meters") - def test1(self): + def test_in_interval(self): dbname = "db1" tdSql.execute(f"drop database if exists {dbname} ") tdSql.execute(f"create database {dbname} vgroups 6") @@ -1070,17 +1070,23 @@ class TDTestCase: tdSql.checkData(2, 1, "2022-09-30 15:15:03") tdSql.checkData(2, 2, "2022-09-30 15:15:03") tdSql.checkData(3, 1, "2022-09-30 15:15:04") - tdSql.checkData(3, 2, "2022-09-30 15:15:04") + tdSql.checkData(3, 2, None) - tdSql.query(f'select tbname, last(ts), last(ts) from tba5 interval(1s)') - tdSql.checkData(0, 1, "2022-09-30 15:15:01") + tdSql.query(f'select tbname, last(f1), ts from tba5 interval(1s)') + tdSql.checkRows(3) + tdSql.checkCols(3) + tdSql.checkData(0, 1, 0) tdSql.checkData(0, 2, "2022-09-30 15:15:01") - tdSql.checkData(1, 1, "2022-09-30 15:15:02") + tdSql.checkData(1, 1, 1) tdSql.checkData(1, 2, "2022-09-30 15:15:02") - tdSql.checkData(2, 1, "2022-09-30 15:15:03") + tdSql.checkData(2, 1, 5) tdSql.checkData(2, 2, "2022-09-30 15:15:03") + + tdSql.query(f'select tbname, last(ts) from tba5 interval(1s)') + tdSql.checkData(0, 1, "2022-09-30 15:15:01") + tdSql.checkData(1, 1, "2022-09-30 15:15:02") + tdSql.checkData(2, 1, "2022-09-30 15:15:03") tdSql.checkData(3, 1, "2022-09-30 15:15:04") - tdSql.checkData(3, 2, "2022-09-30 15:15:04") tdSql.query(f'select tbname, cols(last(ts), ts as ts1), cols(last(f1), ts as ts2) from {dbname}.sta group by tbname;') tdSql.checkRows(5) @@ -1154,7 +1160,63 @@ class TDTestCase: tdSql.checkData(1, 0, 'd0') tdSql.checkData(1, 1, 1734574929014) - + def test_null2(self): + dbname = "test_null2" + tdSql.execute(f"drop database if exists {dbname}") + tdSql.execute(f"create database test_null2 vgroups 5") + tdSql.execute(f"use test_null2") + tdSql.execute(f"create stable {dbname}.stb_null1 (ts timestamp, c0 int, c1 int, c2 nchar(30), c3 bool) tags (t1 nchar(30))") + tdSql.execute(f"create table {dbname}.sub_null_1 using {dbname}.stb_null1 tags('st1')") + tdSql.execute(f"create table {dbname}.sub_null_2 using {dbname}.stb_null1 tags('st2')") + + tdSql.execute(f"insert into {dbname}.sub_null_1 values(1734574929000, 1, null, null, null)") + tdSql.execute(f"insert into {dbname}.sub_null_1 values(1734574929001, 2, null, null, null)") + + tdSql.execute(f"insert into {dbname}.sub_null_2 values(1734574929000, 21, null, null, null)") + tdSql.execute(f"insert into {dbname}.sub_null_2 values(1734574929001, 22, null, null, null)") + + tdSql.query(f'select cols(last(ts), ts), cols(last(c2), ts) from {dbname}.stb_null1') + tdSql.checkRows(1) + tdSql.checkCols(2) + tdSql.checkData(0, 0, 1734574929001) + tdSql.checkData(0, 1, None) + + tdSql.query(f'select tbname, cols(last(ts), c0), cols(last(c2), c0) from {dbname}.stb_null1 group by tbname order by tbname') + tdSql.checkRows(2) + tdSql.checkCols(3) + tdSql.checkData(0, 0, 'sub_null_1') + tdSql.checkData(0, 1, 2) + tdSql.checkData(0, 2, None) + tdSql.checkData(1, 0, 'sub_null_2') + tdSql.checkData(1, 1, 22) + tdSql.checkData(1, 2, None) + + tdSql.query(f'select tbname, t1, cols(last(ts), c0), cols(last(c2), c0) from {dbname}.sub_null_1') + tdSql.checkRows(1) + tdSql.checkCols(4) + tdSql.checkData(0, 0, 'sub_null_1') + tdSql.checkData(0, 1, "st1") + tdSql.checkData(0, 2, 2) + tdSql.checkData(0, 3, None) + + tdSql.query(f'select tbname, t1, cols(last(ts), c0), cols(last(c2), ts) from {dbname}.sub_null_2') + tdSql.checkRows(1) + tdSql.checkCols(4) + tdSql.checkData(0, 0, 'sub_null_2') + tdSql.checkData(0, 1, "st2") + tdSql.checkData(0, 2, 22) + tdSql.checkData(0, 3, None) + + tdSql.query(f'select tbname, cols(last(ts), c0), cols(last(c2), c0) from {dbname}.sub_null_1') + tdSql.checkRows(1) + tdSql.checkCols(3) + tdSql.checkData(0, 0, 'sub_null_1') + tdSql.checkData(0, 1, 2) + tdSql.checkData(0, 2, None) + + tdSql.error(f'select tbname, cols(last(ts), c0), cols(last(c2), c0) from {dbname}.stb_null1') + tdSql.error(f'select t1, cols(last(ts), c0), cols(last(c2), c0) from {dbname}.stb_null1') + def run(self): self.funcNestTest() self.funcSupperTableTest() @@ -1166,11 +1228,13 @@ class TDTestCase: self.window_test() self.join_test() self.stream_cols_test() + self.test_in_interval() self.include_null_test() self.long_column_name_test() - self.test1() + self.having_test("test.meters", False) self.having_test("(select tbname, * from test.meters)", True) + self.test_null2() def stop(self):