diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index b9a0b90a9a8bdca9a912719c61b81b051c4959df..bbff34c66f0b99c839d11cc965d7ef7336aac495 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -250,6 +250,7 @@ typedef struct SSelectStmt { SLimitNode* pSlimit; char stmtName[TSDB_TABLE_NAME_LEN]; uint8_t precision; + int32_t selectFuncNum; bool isEmptyResult; bool isTimeLineResult; bool hasAggFuncs; @@ -257,6 +258,7 @@ typedef struct SSelectStmt { bool hasIndefiniteRowsFunc; bool hasSelectFunc; bool hasSelectValFunc; + bool hasOtherVectorFunc; bool hasUniqueFunc; bool hasTailFunc; bool hasInterpFunc; diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index 262adc5d6f76d1fe34b8f41808735b39c585fe79..1da9d4a70f5624f46a5a219df91101f6d21f4626 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -139,7 +139,7 @@ bool fmIsAggFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MG bool fmIsScalarFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SCALAR_FUNC); } -bool fmIsVectorFunc(int32_t funcId) { return !fmIsScalarFunc(funcId); } +bool fmIsVectorFunc(int32_t funcId) { return !fmIsScalarFunc(funcId) && !fmIsScanPseudoColumnFunc(funcId); } bool fmIsSelectFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_SELECT_FUNC); } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 6beb06bf45287540482d73a1edf01bfba4f691da..8e6798dcd2fa0d8f3c13354d75b03510bc747b01 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1186,6 +1186,12 @@ static void setFuncClassification(SNode* pCurrStmt, SFunctionNode* pFunc) { pSelect->hasAggFuncs = pSelect->hasAggFuncs ? true : fmIsAggFunc(pFunc->funcId); pSelect->hasRepeatScanFuncs = pSelect->hasRepeatScanFuncs ? true : fmIsRepeatScanFunc(pFunc->funcId); pSelect->hasIndefiniteRowsFunc = pSelect->hasIndefiniteRowsFunc ? true : fmIsIndefiniteRowsFunc(pFunc->funcId); + if (fmIsSelectFunc(pFunc->funcId)) { + pSelect->hasSelectFunc = true; + ++(pSelect->selectFuncNum); + } else if (fmIsAggFunc(pFunc->funcId) || fmIsIndefiniteRowsFunc(pFunc->funcId)) { + pSelect->hasOtherVectorFunc = true; + } pSelect->hasUniqueFunc = pSelect->hasUniqueFunc ? true : (FUNCTION_TYPE_UNIQUE == pFunc->funcType); pSelect->hasTailFunc = pSelect->hasTailFunc ? true : (FUNCTION_TYPE_TAIL == pFunc->funcType); pSelect->hasInterpFunc = pSelect->hasInterpFunc ? true : (FUNCTION_TYPE_INTERP == pFunc->funcType); @@ -1395,16 +1401,12 @@ static int32_t getGroupByErrorCode(STranslateContext* pCxt) { if (isDistinctOrderBy(pCxt)) { return TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION; } - return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION; + if (isSelectStmt(pCxt->pCurrStmt) && NULL != ((SSelectStmt*)pCxt->pCurrStmt)->pGroupByList) { + return TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION; + } + return TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN; } -typedef struct SCheckExprForGroupByCxt { - STranslateContext* pTranslateCxt; - int32_t selectFuncNum; - bool hasSelectValFunc; - bool hasOtherAggFunc; -} SCheckExprForGroupByCxt; - static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode) { SFunctionNode* pFunc = (SFunctionNode*)nodesMakeNode(QUERY_NODE_FUNCTION); if (NULL == pFunc) { @@ -1445,67 +1447,49 @@ static EDealRes rewriteExprToGroupKeyFunc(STranslateContext* pCxt, SNode** pNode } static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { - SCheckExprForGroupByCxt* pCxt = (SCheckExprForGroupByCxt*)pContext; + STranslateContext* pCxt = (STranslateContext*)pContext; + SSelectStmt* pSelect = (SSelectStmt*)pCxt->pCurrStmt; if (!nodesIsExprNode(*pNode) || isAliasColumn(*pNode)) { return DEAL_RES_CONTINUE; } - if (isSelectFunc(*pNode)) { - ++(pCxt->selectFuncNum); - } else if (isAggFunc(*pNode)) { - pCxt->hasOtherAggFunc = true; - } - if ((pCxt->selectFuncNum > 1 && pCxt->hasSelectValFunc) || (pCxt->hasOtherAggFunc && pCxt->hasSelectValFunc)) { - return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); - } - if (isAggFunc(*pNode) && !isDistinctOrderBy(pCxt->pTranslateCxt)) { + if (isVectorFunc(*pNode) && !isDistinctOrderBy(pCxt)) { return DEAL_RES_IGNORE_CHILD; } SNode* pGroupNode = NULL; - FOREACH(pGroupNode, getGroupByList(pCxt->pTranslateCxt)) { + FOREACH(pGroupNode, getGroupByList(pCxt)) { if (nodesEqualNode(getGroupByNode(pGroupNode), *pNode)) { return DEAL_RES_IGNORE_CHILD; } } SNode* pPartKey = NULL; - FOREACH(pPartKey, ((SSelectStmt*)pCxt->pTranslateCxt->pCurrStmt)->pPartitionByList) { + FOREACH(pPartKey, pSelect->pPartitionByList) { if (nodesEqualNode(pPartKey, *pNode)) { - return rewriteExprToGroupKeyFunc(pCxt->pTranslateCxt, pNode); + return rewriteExprToGroupKeyFunc(pCxt, pNode); } } if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { - if (pCxt->selectFuncNum > 1 || pCxt->hasOtherAggFunc) { - return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); + if (pSelect->selectFuncNum > 1 || pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) { + return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt)); } else { - pCxt->hasSelectValFunc = true; - return rewriteColToSelectValFunc(pCxt->pTranslateCxt, pNode); + return rewriteColToSelectValFunc(pCxt, pNode); } } - if (isAggFunc(*pNode) && isDistinctOrderBy(pCxt->pTranslateCxt)) { - return generateDealNodeErrMsg(pCxt->pTranslateCxt, getGroupByErrorCode(pCxt->pTranslateCxt)); + if (isVectorFunc(*pNode) && isDistinctOrderBy(pCxt)) { + return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt)); } return DEAL_RES_CONTINUE; } static int32_t checkExprForGroupBy(STranslateContext* pCxt, SNode** pNode) { - SCheckExprForGroupByCxt cxt = { - .pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false}; - nodesRewriteExpr(pNode, doCheckExprForGroupBy, &cxt); - if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) { - return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt)); - } + nodesRewriteExpr(pNode, doCheckExprForGroupBy, pCxt); return pCxt->errCode; } -static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SNodeList* pList) { - if (NULL == getGroupByList(pCxt)) { +static int32_t checkExprListForGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect, SNodeList* pList) { + if (NULL == getGroupByList(pCxt) && NULL == pSelect->pWindow) { return TSDB_CODE_SUCCESS; } - SCheckExprForGroupByCxt cxt = { - .pTranslateCxt = pCxt, .selectFuncNum = 0, .hasSelectValFunc = false, .hasOtherAggFunc = false}; - nodesRewriteExprs(pList, doCheckExprForGroupBy, &cxt); - if (cxt.selectFuncNum != 1 && cxt.hasSelectValFunc) { - return generateSyntaxErrMsg(&pCxt->msgBuf, getGroupByErrorCode(pCxt)); - } + nodesRewriteExprs(pList, doCheckExprForGroupBy, pCxt); return pCxt->errCode; } @@ -1529,7 +1513,6 @@ static int32_t rewriteColsToSelectValFunc(STranslateContext* pCxt, SSelectStmt* typedef struct CheckAggColCoexistCxt { STranslateContext* pTranslateCxt; - bool existVectorFunc; bool existCol; int32_t selectFuncNum; bool existOtherVectorFunc; @@ -1537,13 +1520,12 @@ typedef struct CheckAggColCoexistCxt { static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) { CheckAggColCoexistCxt* pCxt = (CheckAggColCoexistCxt*)pContext; - if (isSelectFunc(*pNode)) { - ++(pCxt->selectFuncNum); - } else if (isAggFunc(*pNode)) { - pCxt->existOtherVectorFunc = true; - } if (isVectorFunc(*pNode)) { - pCxt->existVectorFunc = true; + if (isSelectFunc(*pNode)) { + ++(pCxt->selectFuncNum); + } else { + pCxt->existOtherVectorFunc = true; + } return DEAL_RES_IGNORE_CHILD; } SNode* pPartKey = NULL; @@ -1559,14 +1541,12 @@ static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) { } static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) { - if (NULL != pSelect->pGroupByList) { + if (NULL != pSelect->pGroupByList || NULL != pSelect->pWindow || + (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc)) { return TSDB_CODE_SUCCESS; } - CheckAggColCoexistCxt cxt = {.pTranslateCxt = pCxt, - .existVectorFunc = false, - .existCol = false, - .selectFuncNum = 0, - .existOtherVectorFunc = false}; + CheckAggColCoexistCxt cxt = { + .pTranslateCxt = pCxt, .existCol = false, .selectFuncNum = 0, .existOtherVectorFunc = false}; nodesRewriteExprs(pSelect->pProjectionList, doCheckAggColCoexist, &cxt); if (!pSelect->isDistinct) { nodesRewriteExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); @@ -1574,7 +1554,7 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) if (1 == cxt.selectFuncNum && !cxt.existOtherVectorFunc) { return rewriteColsToSelectValFunc(pCxt, pSelect); } - if ((cxt.selectFuncNum > 1 || cxt.existVectorFunc || NULL != pSelect->pWindow) && cxt.existCol) { + if (cxt.existCol) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_SINGLE_GROUP); } return TSDB_CODE_SUCCESS; @@ -2056,7 +2036,7 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { pCxt->currClause = SQL_CLAUSE_ORDER_BY; code = translateExprList(pCxt, pSelect->pOrderByList); if (TSDB_CODE_SUCCESS == code) { - code = checkExprListForGroupBy(pCxt, pSelect->pOrderByList); + code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pOrderByList); } } return code; @@ -2069,7 +2049,7 @@ static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect code = translateStar(pCxt, pSelect); } if (TSDB_CODE_SUCCESS == code) { - code = checkExprListForGroupBy(pCxt, pSelect->pProjectionList); + code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pProjectionList); } return code; } @@ -5264,8 +5244,8 @@ static int32_t serializeVgroupCreateTableBatch(SVgroupCreateTableBatch* pTbBatch } static void destroyCreateTbReqBatch(void* data) { - SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*) data; - size_t size = taosArrayGetSize(pTbBatch->req.pArray); + SVgroupCreateTableBatch* pTbBatch = (SVgroupCreateTableBatch*)data; + size_t size = taosArrayGetSize(pTbBatch->req.pArray); for (int32_t i = 0; i < size; ++i) { SVCreateTbReq* pTableReq = taosArrayGet(pTbBatch->req.pArray, i); taosMemoryFreeClear(pTableReq->name); @@ -5347,10 +5327,10 @@ static int32_t rewriteCreateTable(STranslateContext* pCxt, SQuery* pQuery) { static void addCreateTbReqIntoVgroup(int32_t acctId, SHashObj* pVgroupHashmap, SCreateSubTableClause* pStmt, const STag* pTag, uint64_t suid, SVgroupInfo* pVgInfo) { -// char dbFName[TSDB_DB_FNAME_LEN] = {0}; -// SName name = {.type = TSDB_DB_NAME_T, .acctId = acctId}; -// strcpy(name.dbname, pStmt->dbName); -// tNameGetFullDbName(&name, dbFName); + // char dbFName[TSDB_DB_FNAME_LEN] = {0}; + // SName name = {.type = TSDB_DB_NAME_T, .acctId = acctId}; + // strcpy(name.dbname, pStmt->dbName); + // tNameGetFullDbName(&name, dbFName); struct SVCreateTbReq req = {0}; req.type = TD_CHILD_TABLE; diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp index 4ca2dec29925ab6eee7c7da66a501e0c6fe86a5f..c6d74c5305e6a7c6f02d95833c38f41a56cfe25d 100644 --- a/source/libs/parser/test/parSelectTest.cpp +++ b/source/libs/parser/test/parSelectTest.cpp @@ -144,9 +144,9 @@ TEST_F(ParserSelectTest, IndefiniteRowsFunc) { TEST_F(ParserSelectTest, IndefiniteRowsFuncSemanticCheck) { useDb("root", "test"); - run("SELECT DIFF(c1), c2 FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC); + run("SELECT DIFF(c1), c2 FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP); - run("SELECT DIFF(c1), tbname FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC); + run("SELECT DIFF(c1), tbname FROM t1", TSDB_CODE_PAR_NOT_SINGLE_GROUP); run("SELECT DIFF(c1), count(*) FROM t1", TSDB_CODE_PAR_NOT_ALLOWED_FUNC); @@ -273,7 +273,7 @@ TEST_F(ParserSelectTest, interval) { TEST_F(ParserSelectTest, intervalSemanticCheck) { useDb("root", "test"); - run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + run("SELECT c1 FROM t1 INTERVAL(10s)", TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN); run("SELECT DISTINCT c1, c2 FROM t1 WHERE c1 > 3 INTERVAL(1d) FILL(NEXT)", TSDB_CODE_PAR_INVALID_FILL_TIME_RANGE); run("SELECT HISTOGRAM(c1, 'log_bin', '{\"start\": -33,\"factor\": 55,\"count\": 5,\"infinity\": false}', 1) FROM t1 " "WHERE ts > TIMESTAMP '2022-04-01 00:00:00' and ts < TIMESTAMP '2022-04-30 23:59:59' INTERVAL(10s) FILL(NULL)", diff --git a/source/libs/planner/test/planPartByTest.cpp b/source/libs/planner/test/planPartByTest.cpp index 2abcb44dfdae6217147761cf4e8f75224156c32e..3b71ae3b8880b1f4c3d06f8474d133729f205b6a 100644 --- a/source/libs/planner/test/planPartByTest.cpp +++ b/source/libs/planner/test/planPartByTest.cpp @@ -35,6 +35,8 @@ TEST_F(PlanPartitionByTest, withAggFunc) { run("select count(*) from t1 partition by c1"); + run("select count(*) from st1 partition by c1"); + run("select count(*), c1 from t1 partition by c1"); } diff --git a/tests/system-test/1-insert/time_range_wise.py b/tests/system-test/1-insert/time_range_wise.py index a620a4b51a25682350ed2e5bf6a42678751b489c..2596f824766abaceb8598d9c422c1792cd134217 100644 --- a/tests/system-test/1-insert/time_range_wise.py +++ b/tests/system-test/1-insert/time_range_wise.py @@ -614,12 +614,12 @@ class TDTestCase: self.__insert_data() self.all_test() - tdLog.printNoPrefix("==========step2:create table in rollup database") - tdSql.execute("create database db3 retentions 1s:4m,2s:8m,3s:12m") - tdSql.execute("use db3") + #tdLog.printNoPrefix("==========step2:create table in rollup database") + #tdSql.execute("create database db3 retentions 1s:4m,2s:8m,3s:12m") + #tdSql.execute("use db3") # self.__create_tb() - tdSql.execute(f"create stable stb1 ({PRIMARY_COL} timestamp, {INT_COL} int) tags (tag1 int) rollup(first) watermark 5s max_delay 1m sma({INT_COL}) ") - self.all_test() + #tdSql.execute(f"create stable stb1 ({PRIMARY_COL} timestamp, {INT_COL} int) tags (tag1 int) rollup(first) watermark 5s max_delay 1m sma({INT_COL}) ") + #self.all_test() # self.__insert_data()