diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c index f4c450f1ce..63156de881 100644 --- a/source/libs/executor/src/aggregateoperator.c +++ b/source/libs/executor/src/aggregateoperator.c @@ -282,7 +282,7 @@ int32_t doAggregateImpl(SOperatorInfo* pOperator, SqlFunctionCtx* pCtx) { } if ((&pCtx[k])->input.pData[0] == NULL) { - code = TSDB_CODE_TDB_INVALID_ACTION; + code = TSDB_CODE_PAR_NOT_SINGLE_GROUP; qError("%s aggregate function error happens, input data is NULL.", GET_TASKID(pOperator->pTaskInfo)); } else { code = pCtx[k].fpSet.process(&pCtx[k]); @@ -570,7 +570,7 @@ void applyAggFunctionOnPartialTuples(SExecTaskInfo* taskInfo, SqlFunctionCtx* pC int32_t code = TSDB_CODE_SUCCESS; if (functionNeedToExecute(&pCtx[k]) && pCtx[k].fpSet.process != NULL) { if ((&pCtx[k])->input.pData[0] == NULL) { - code = TSDB_CODE_TDB_INVALID_ACTION; + code = TSDB_CODE_PAR_NOT_SINGLE_GROUP; qError("%s apply functions error, input data is NULL.", GET_TASKID(taskInfo)); } else { code = pCtx[k].fpSet.process(&pCtx[k]); diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 85da24ab14..1ba48fa0d4 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -2757,7 +2757,7 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) if (!pSelect->isDistinct) { nodesRewriteExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); } - if (1 == pSelect->selectFuncNum && !pSelect->hasOtherVectorFunc) { + if (0 < pSelect->selectFuncNum && !pSelect->hasOtherVectorFunc) { return rewriteColsToSelectValFunc(pCxt, pSelect); } if (cxt.existCol) { @@ -3436,6 +3436,12 @@ static int32_t checkOrderByAggForGroupBy(STranslateContext* pCxt, SSelectStmt* p if (NULL != getGroupByList(pCxt) || NULL != pSelect->pWindow) { return TSDB_CODE_SUCCESS; } + SNode* pProject = NULL; + FOREACH(pProject, pSelect->pProjectionList) { + if(isAggFunc(pProject)) { + return TSDB_CODE_SUCCESS; + } + } SNode* pNode = NULL; WHERE_EACH(pNode, pOrderByList) { SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr; @@ -3501,9 +3507,9 @@ static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { if (TSDB_CODE_SUCCESS == code) { code = checkExprListForGroupBy(pCxt, pSelect, pSelect->pOrderByList); } - // if (other && TSDB_CODE_SUCCESS == code) { - // code = checkOrderByAggForGroupBy(pCxt, pSelect, pSelect->pOrderByList); - // } + if (other && TSDB_CODE_SUCCESS == code) { + code = checkOrderByAggForGroupBy(pCxt, pSelect, pSelect->pOrderByList); + } return code; } @@ -4505,8 +4511,18 @@ static EDealRes replaceOrderByAliasImpl(SNode** pNode, void* pContext) { SNode* pProject = NULL; FOREACH(pProject, pProjectionList) { SExprNode* pExpr = (SExprNode*)pProject; + SNode* activeNode = pProject; if (0 == strcmp(((SColumnRefNode*)*pNode)->colName, pExpr->aliasName)) { - SNode* pNew = nodesCloneNode(pProject); + if(QUERY_NODE_FUNCTION == pProject->type && strcmp(((SFunctionNode*)pProject)->functionName, "_select_value") == 0) { + SNode* paramNode = NULL; + FOREACH(paramNode, ((SFunctionNode*)pProject)->pParameterList) { + SExprNode* pExpr2 = (SExprNode*)pProject; + if (0 == strcmp(((SColumnRefNode*)*pNode)->colName, pExpr2->aliasName)) { + activeNode = paramNode; + } + } + } + SNode* pNew = nodesCloneNode(activeNode); if (NULL == pNew) { pCxt->pTranslateCxt->errCode = TSDB_CODE_OUT_OF_MEMORY; return DEAL_RES_ERROR; diff --git a/source/libs/parser/test/parSelectTest.cpp b/source/libs/parser/test/parSelectTest.cpp index 53d97d0699..dce702f6b6 100644 --- a/source/libs/parser/test/parSelectTest.cpp +++ b/source/libs/parser/test/parSelectTest.cpp @@ -413,6 +413,28 @@ TEST_F(ParserSelectTest, semanticCheck) { run("SELECT c1 FROM t1 order by COUNT(*)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + run("SELECT COUNT(*) FROM t1 order by COUNT(*)"); + + run("SELECT COUNT(*) FROM t1 order by last(c2)"); + + run("SELECT c1 FROM t1 order by last(ts)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + + run("SELECT ts FROM t1 order by last(ts)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + + run("SELECT c2 FROM t1 order by last(ts)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + + run("SELECT * FROM t1 order by last(ts)", TSDB_CODE_PAR_NOT_SINGLE_GROUP); + + run("SELECT last(ts) FROM t1 order by last(ts)"); + + run("SELECT last(ts), ts, c1 FROM t1 order by last(ts)"); + + run("SELECT ts, last(ts) FROM t1 order by last(ts)"); + + run("SELECT first(ts), c2 FROM t1 order by last(c1)"); + + run("SELECT c1 FROM t1 order by concat(c2, 'abc')"); + // TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION run("SELECT distinct c1, c2 FROM t1 WHERE c1 > 0 order by ts", TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION); diff --git a/tests/system-test/2-query/orderBy.py b/tests/system-test/2-query/orderBy.py index fa447cbca4..162a5c6e26 100644 --- a/tests/system-test/2-query/orderBy.py +++ b/tests/system-test/2-query/orderBy.py @@ -276,6 +276,14 @@ class TDTestCase: sql2 = "select count(*) as a, count(c2) as b, max(c2) as c, min(c2) as d, sum(c2) as e from st;" self.queryResultSame(sql1, sql2) + def queryOrderByAgg(self): + + tdSql.error(f"SELECT * FROM t1 order by last(ts)") + + tdSql.query(f"SELECT last(ts) FROM t1 order by last(ts)") + + tdSql.query(f"SELECT last(ts), ts FROM t1 order by last(ts)") + # run def run(self): # prepare env @@ -287,6 +295,9 @@ class TDTestCase: # advance self.queryAdvance() + # agg + self.queryOrderByAgg() + # stop def stop(self):