diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 54c8686161..bb06b65898 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -60,6 +60,7 @@ typedef struct SExprNode { bool orderAlias; bool asAlias; bool asParam; + bool asPosition; } SExprNode; typedef enum EColumnType { diff --git a/source/libs/nodes/src/nodesTraverseFuncs.c b/source/libs/nodes/src/nodesTraverseFuncs.c index 1edfa840e2..927bc6b661 100644 --- a/source/libs/nodes/src/nodesTraverseFuncs.c +++ b/source/libs/nodes/src/nodesTraverseFuncs.c @@ -229,6 +229,9 @@ static void checkParamIsFunc(SFunctionNode* pFunc) { if (nodeType(pPara) == QUERY_NODE_COLUMN) { ((SColumnNode*)pPara)->node.asParam = true; } + if (nodeType(pPara) == QUERY_NODE_VALUE) { + ((SValueNode*)pPara)->node.asParam = true; + } } } diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c old mode 100644 new mode 100755 index cfe1fa4eb3..879f527a85 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1450,6 +1450,8 @@ static EDealRes translateColumnWithoutPrefix(STranslateContext* pCxt, SColumnNod return DEAL_RES_CONTINUE; } +static int32_t getFuncInfo(STranslateContext* pCxt, SFunctionNode* pFunc); + static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** pCol, bool* pFound) { SNodeList* pProjectionList = getProjectListFromCurrStmt(pCxt->pCurrStmt); SNode* pNode; @@ -1470,6 +1472,25 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p } } if (*pFound) { + if (QUERY_NODE_FUNCTION == nodeType(pFoundNode) && (SQL_CLAUSE_GROUP_BY == pCxt->currClause || SQL_CLAUSE_PARTITION_BY == pCxt->currClause)) { + pCxt->errCode = getFuncInfo(pCxt, (SFunctionNode*)pFoundNode); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + if (fmIsVectorFunc(((SFunctionNode*)pFoundNode)->funcId)) { + pCxt->errCode = TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION; + return DEAL_RES_ERROR; + } else if (fmIsPseudoColumnFunc(((SFunctionNode*)pFoundNode)->funcId)) { + if ('\0' != (*pCol)->tableAlias[0]) { + return translateColumnWithPrefix(pCxt, pCol); + } else { + return translateColumnWithoutPrefix(pCxt, pCol); + } + } else { + /* Do nothing and replace old node with found node. */ + } + } else { + return DEAL_RES_ERROR; + } + } SNode* pNew = NULL; int32_t code = nodesCloneNode(pFoundNode, &pNew); if (NULL == pNew) { @@ -1478,6 +1499,13 @@ static EDealRes translateColumnUseAlias(STranslateContext* pCxt, SColumnNode** p } nodesDestroyNode(*(SNode**)pCol); *(SNode**)pCol = (SNode*)pNew; + if (QUERY_NODE_COLUMN == nodeType(pFoundNode)) { + if ('\0' != (*pCol)->tableAlias[0]) { + return translateColumnWithPrefix(pCxt, pCol); + } else { + return translateColumnWithoutPrefix(pCxt, pCol); + } + } } return DEAL_RES_CONTINUE; } @@ -1716,6 +1744,12 @@ int32_t biCheckCreateTableTbnameCol(STranslateContext* pCxt, SCreateTableStmt* p return TSDB_CODE_SUCCESS; } +static bool clauseSupportAlias(ESqlClause clause) { + return SQL_CLAUSE_GROUP_BY == clause || + SQL_CLAUSE_PARTITION_BY == clause || + SQL_CLAUSE_ORDER_BY == clause; +} + static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) { if (NULL == pCxt->pCurrStmt || (isSelectStmt(pCxt->pCurrStmt) && NULL == ((SSelectStmt*)pCxt->pCurrStmt)->pFromTable)) { @@ -1742,7 +1776,8 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) { res = translateColumnWithPrefix(pCxt, pCol); } else { bool found = false; - if (SQL_CLAUSE_ORDER_BY == pCxt->currClause && !(*pCol)->node.asParam) { + if ((clauseSupportAlias(pCxt->currClause)) && + !(*pCol)->node.asParam) { res = translateColumnUseAlias(pCxt, pCol, &found); } if (DEAL_RES_ERROR != res && !found) { @@ -1752,7 +1787,9 @@ static EDealRes translateColumn(STranslateContext* pCxt, SColumnNode** pCol) { res = translateColumnWithoutPrefix(pCxt, pCol); } } - if (SQL_CLAUSE_ORDER_BY == pCxt->currClause && !(*pCol)->node.asParam && res != DEAL_RES_CONTINUE && + if (clauseSupportAlias(pCxt->currClause) && + !(*pCol)->node.asParam && + res != DEAL_RES_CONTINUE && res != DEAL_RES_END) { res = translateColumnUseAlias(pCxt, pCol, &found); } @@ -2954,6 +2991,13 @@ static EDealRes translateFunction(STranslateContext* pCxt, SFunctionNode** pFunc } pCxt->errCode = getFuncInfo(pCxt, *pFunc); + if (TSDB_CODE_SUCCESS == pCxt->errCode) { + if ((SQL_CLAUSE_GROUP_BY == pCxt->currClause || + SQL_CLAUSE_PARTITION_BY == pCxt->currClause) && + fmIsVectorFunc((*pFunc)->funcId)) { + pCxt->errCode = TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION; + } + } if (TSDB_CODE_SUCCESS == pCxt->errCode) { pCxt->errCode = translateFunctionImpl(pCxt, pFunc); } @@ -4940,7 +4984,7 @@ static int32_t getPositionValue(const SValueNode* pVal) { case TSDB_DATA_TYPE_GEOMETRY: return -1; case TSDB_DATA_TYPE_BOOL: - return (pVal->datum.b ? 1 : 0); + return -1; case TSDB_DATA_TYPE_TINYINT: case TSDB_DATA_TYPE_SMALLINT: case TSDB_DATA_TYPE_INT: @@ -4948,7 +4992,7 @@ static int32_t getPositionValue(const SValueNode* pVal) { return pVal->datum.i; case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: - return pVal->datum.d; + return -1; case TSDB_DATA_TYPE_UTINYINT: case TSDB_DATA_TYPE_USMALLINT: case TSDB_DATA_TYPE_UINT: @@ -4960,25 +5004,36 @@ static int32_t getPositionValue(const SValueNode* pVal) { return -1; } -static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pOrderByList, +static int32_t translateClausePosition(STranslateContext* pCxt, SNodeList* pProjectionList, SNodeList* pClauseList, bool* pOther) { *pOther = false; SNode* pNode = NULL; - WHERE_EACH(pNode, pOrderByList) { - SNode* pExpr = ((SOrderByExprNode*)pNode)->pExpr; + WHERE_EACH(pNode, pClauseList) { + SNode* pExpr = NULL; + switch (pNode->type) { + case QUERY_NODE_GROUPING_SET: + pExpr = getGroupByNode(pNode); + break; + case QUERY_NODE_ORDER_BY_EXPR: + pExpr = ((SOrderByExprNode*)pNode)->pExpr; + break; + default: + pExpr = pNode; + break; + } if (QUERY_NODE_VALUE == nodeType(pExpr)) { SValueNode* pVal = (SValueNode*)pExpr; + pVal->node.asPosition = false; if (DEAL_RES_ERROR == translateValue(pCxt, pVal)) { return pCxt->errCode; } int32_t pos = getPositionValue(pVal); if (pos < 0) { - ERASE_NODE(pOrderByList); - continue; + pVal->node.asPosition = false; } else if (0 == pos || pos > LIST_LENGTH(pProjectionList)) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT); } else { - // No longer using SColumnRefNode, processing in replaceOrderByAliasImpl function + pVal->node.asPosition = true; } } else { *pOther = true; @@ -4990,7 +5045,7 @@ static int32_t translateOrderByPosition(STranslateContext* pCxt, SNodeList* pPro static int32_t translateOrderBy(STranslateContext* pCxt, SSelectStmt* pSelect) { bool other; - int32_t code = translateOrderByPosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other); + int32_t code = translateClausePosition(pCxt, pSelect->pProjectionList, pSelect->pOrderByList, &other); if (TSDB_CODE_SUCCESS == code) { if (0 == LIST_LENGTH(pSelect->pOrderByList)) { NODES_DESTORY_LIST(pSelect->pOrderByList); @@ -5121,6 +5176,68 @@ static int32_t translateProjectionList(STranslateContext* pCxt, SSelectStmt* pSe } } +typedef struct SReplaceGroupByAliasCxt { + STranslateContext* pTranslateCxt; + SNodeList* pProjectionList; +} SReplaceGroupByAliasCxt; + +static EDealRes replaceGroupByAliasImpl(SNode** pNode, void* pContext) { + SReplaceGroupByAliasCxt* pCxt = pContext; + SNodeList* pProjectionList = pCxt->pProjectionList; + SNode* pProject = NULL; + if (QUERY_NODE_VALUE == nodeType(*pNode)) { + STranslateContext* pTransCxt = pCxt->pTranslateCxt; + SValueNode* pVal = (SValueNode*) *pNode; + if (DEAL_RES_ERROR == translateValue(pTransCxt, pVal)) { + return DEAL_RES_CONTINUE; + } + if (!pVal->node.asPosition) { + return DEAL_RES_CONTINUE; + } + int32_t pos = getPositionValue(pVal); + if (0 < pos && pos <= LIST_LENGTH(pProjectionList)) { + SNode* pNew = NULL; + int32_t code = nodesCloneNode(nodesListGetNode(pProjectionList, pos - 1), (SNode**)&pNew); + if (TSDB_CODE_SUCCESS != code) { + pCxt->pTranslateCxt->errCode = code; + return DEAL_RES_ERROR; + } + nodesDestroyNode(*pNode); + *pNode = pNew; + return DEAL_RES_CONTINUE; + } else { + return DEAL_RES_CONTINUE; + } + } else if (QUERY_NODE_COLUMN == nodeType(*pNode)) { + STranslateContext* pTransCxt = pCxt->pTranslateCxt; + return translateColumn(pTransCxt, (SColumnNode**)pNode); + } + + return DEAL_RES_CONTINUE; +} + +static int32_t replaceGroupByAlias(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (NULL == pSelect->pGroupByList) { + return TSDB_CODE_SUCCESS; + } + SReplaceGroupByAliasCxt cxt = { + .pTranslateCxt = pCxt, .pProjectionList = pSelect->pProjectionList}; + nodesRewriteExprsPostOrder(pSelect->pGroupByList, replaceGroupByAliasImpl, &cxt); + + return pCxt->errCode; +} + +static int32_t replacePartitionByAlias(STranslateContext* pCxt, SSelectStmt* pSelect) { + if (NULL == pSelect->pPartitionByList) { + return TSDB_CODE_SUCCESS; + } + SReplaceGroupByAliasCxt cxt = { + .pTranslateCxt = pCxt, .pProjectionList = pSelect->pProjectionList}; + nodesRewriteExprsPostOrder(pSelect->pPartitionByList, replaceGroupByAliasImpl, &cxt); + + return pCxt->errCode; +} + static int32_t translateSelectList(STranslateContext* pCxt, SSelectStmt* pSelect) { pCxt->currClause = SQL_CLAUSE_SELECT; int32_t code = translateExprList(pCxt, pSelect->pProjectionList); @@ -5172,9 +5289,21 @@ static int32_t translateGroupBy(STranslateContext* pCxt, SSelectStmt* pSelect) { if (NULL != pSelect->pWindow) { return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_GROUPBY_WINDOW_COEXIST); } - pCxt->currClause = SQL_CLAUSE_GROUP_BY; - pSelect->timeLineResMode = TIME_LINE_NONE; - return translateExprList(pCxt, pSelect->pGroupByList); + bool other; + int32_t code = translateClausePosition(pCxt, pSelect->pProjectionList, pSelect->pGroupByList, &other); + if (TSDB_CODE_SUCCESS == code) { + if (0 == LIST_LENGTH(pSelect->pGroupByList)) { + NODES_DESTORY_LIST(pSelect->pGroupByList); + return TSDB_CODE_SUCCESS; + } + code = replaceGroupByAlias(pCxt, pSelect); + } + if (TSDB_CODE_SUCCESS == code) { + pCxt->currClause = SQL_CLAUSE_GROUP_BY; + pSelect->timeLineResMode = TIME_LINE_NONE; + code = translateExprList(pCxt, pSelect->pGroupByList); + } + return code; } static int32_t getTimeRange(SNode** pPrimaryKeyCond, STimeWindow* pTimeRange, bool* pIsStrict) { @@ -5781,7 +5910,8 @@ static int32_t translatePartitionBy(STranslateContext* pCxt, SSelectStmt* pSelec int32_t code = TSDB_CODE_SUCCESS; if (pSelect->pPartitionByList) { - code = removeConstantValueFromList(&pSelect->pPartitionByList); + bool other; + code = translateClausePosition(pCxt, pSelect->pProjectionList, pSelect->pPartitionByList, &other); } if (TSDB_CODE_SUCCESS == code && pSelect->pPartitionByList) { @@ -5791,8 +5921,10 @@ static int32_t translatePartitionBy(STranslateContext* pCxt, SSelectStmt* pSelec (QUERY_NODE_FUNCTION == nodeType(pPar) && FUNCTION_TYPE_TBNAME == ((SFunctionNode*)pPar)->funcType))) { pSelect->timeLineResMode = TIME_LINE_MULTI; } - - code = translateExprList(pCxt, pSelect->pPartitionByList); + code = replacePartitionByAlias(pCxt, pSelect); + if (TSDB_CODE_SUCCESS == code) { + code = translateExprList(pCxt, pSelect->pPartitionByList); + } } if (TSDB_CODE_SUCCESS == code) { code = translateExprList(pCxt, pSelect->pTags); @@ -6519,7 +6651,11 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect code = removeConstantValueFromList(&pSelect->pPartitionByList); } } - + if (TSDB_CODE_SUCCESS == code) { + if (pSelect->pGroupByList) { + code = removeConstantValueFromList(&pSelect->pGroupByList); + } + } return code; } @@ -6606,7 +6742,7 @@ static int32_t translateSetOperOrderBy(STranslateContext* pCxt, SSetOperator* pS } bool other; - int32_t code = translateOrderByPosition(pCxt, pSetOperator->pProjectionList, pSetOperator->pOrderByList, &other); + int32_t code = translateClausePosition(pCxt, pSetOperator->pProjectionList, pSetOperator->pOrderByList, &other); /* if (TSDB_CODE_SUCCESS == code) { if (other) { diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 35d54ad43c..6a36ea7b85 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -44,7 +44,7 @@ static char* getSyntaxErrFormat(int32_t errCode) { case TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION: return "There mustn't be aggregation"; case TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT: - return "ORDER BY item must be the number of a SELECT-list expression"; + return "ORDER BY / GROUP BY item must be the number of a SELECT-list expression"; case TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION: return "Not a GROUP BY expression"; case TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION: diff --git a/source/util/src/terror.c b/source/util/src/terror.c index 8400675ec6..a0c3b3f766 100644 --- a/source/util/src/terror.c +++ b/source/util/src/terror.c @@ -595,7 +595,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TABLE_NOT_EXIST, "Table does not exist TAOS_DEFINE_ERROR(TSDB_CODE_PAR_AMBIGUOUS_COLUMN, "Column ambiguously defined") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_WRONG_VALUE_TYPE, "Invalid value type") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_ILLEGAL_USE_AGG_FUNCTION, "There mustn't be aggregation") -TAOS_DEFINE_ERROR(TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, "ORDER BY item must be the number of a SELECT-list expression") +TAOS_DEFINE_ERROR(TSDB_CODE_PAR_WRONG_NUMBER_OF_SELECT, "ORDER BY / GROUP BY item must be the number of a SELECT-list expression") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_GROUPBY_LACK_EXPRESSION, "Not a GROUP BY expression") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_SELECTED_EXPRESSION, "Not SELECTed expression") TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_SINGLE_GROUP, "Not a single-group group function") diff --git a/tests/system-test/2-query/distinct.py b/tests/system-test/2-query/distinct.py index 5c07544d5d..5025b39753 100644 --- a/tests/system-test/2-query/distinct.py +++ b/tests/system-test/2-query/distinct.py @@ -144,8 +144,8 @@ class TDTestCase: tdSql.query(f"select distinct c1, c2 from (select c2, c1 from {dbname}.stb1 where c1 > 2 order by ts)") tdSql.query(f"select distinct c1, c2 from (select c2, c1 from {dbname}.t1 where c1 > 2 order by ts)") tdSql.error(f"select distinct c1, c2 from (select c2, c1 from {dbname}.stb1 where c1 > 2 group by c1)") - tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.stb1 group by c1)") - tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.t1 group by c1)") + tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.stb1 group by stb1.c1)") + tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.t1 group by t1.c1)") tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.stb1 )") tdSql.checkRows(1) tdSql.query(f"select distinct c1, c2 from (select max(c1) c1, max(c2) c2 from {dbname}.t1 )") @@ -245,7 +245,7 @@ class TDTestCase: tdSql.query(f"select distinct t1 from (select t0, t1 from {dbname}.stb1 where t0 > 2 ) where t1 < 3") tdSql.checkRows(1) tdSql.error(f"select distinct t1, t0 from (select t1 from {dbname}.stb1 where t0 > 2 ) where t1 < 3") - tdSql.query(f"select distinct t1, t0 from (select max(t1) t1, max(t0) t0 from {dbname}.stb1 group by t1)") + tdSql.query(f"select distinct t1, t0 from (select max(t1) t1, max(t0) t0 from {dbname}.stb1 group by stb1.t1)") tdSql.query(f"select distinct t1, t0 from (select max(t1) t1, max(t0) t0 from {dbname}.stb1)") tdSql.query(f"select distinct t1, t0 from (select t1,t0 from {dbname}.stb1 where t0 > 2 ) where t1 < 3") tdSql.checkRows(1) diff --git a/tests/system-test/2-query/explain.py b/tests/system-test/2-query/explain.py index 92cd28a929..55f484884c 100644 --- a/tests/system-test/2-query/explain.py +++ b/tests/system-test/2-query/explain.py @@ -77,7 +77,7 @@ class TDTestCase: ) query_condition.extend( ( - 1010, + 1010.1, ''' "test1234!@#$%^&*():'>=0") + tdSql.checkRows(check_num) + + # having filter out empty + tdSql.query(f"select tbname, count(*) from {self.dbname}.{self.stable} {keyword} by 1 having count(*) <= 0") + tdSql.checkRows(check_num - nonempty_tb_num) + + ####### by tag + tdSql.query(f"select t2, count(*), count(1), count(c1) from {self.dbname}.{self.stable} {keyword} by 1 ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2, count(*) from {self.dbname}.{self.stable} {keyword} by 1 having count(*) <= 0") + tdSql.checkRows(check_num - nonempty_tb_num) + + # where + tdSql.query(f"select t2, count(*) from {self.dbname}.{self.stable} where ts < now {keyword} by 1 ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2, count(*) from {self.dbname}.{self.stable} where ts > 1737146000000 {keyword} by 1 ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2, count(*) from {self.dbname}.{self.stable} where c1 = 1 {keyword} by 1 ") + tdSql.checkRows(check_num) + + ####### by col + tdSql.query(f"select c1, count(*), count(1), count(c1) from {self.dbname}.{self.stable} {keyword} by 1 ") + num = 0 + if nonempty_tb_num > 0: + num = self.row_nums + tdSql.checkRows(num) + + tdSql.query(f"select ts, count(*) from {self.dbname}.{self.stable} {keyword} by 1 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + # col + tag + tdSql.query(f"select t2, c1, count(*) from {self.dbname}.{self.stable} {keyword} by 1, 2 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2, c1, count(*) from {self.dbname}.{self.stable} {keyword} by 1, c1 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2, c1, count(*) from {self.dbname}.{self.stable} {keyword} by t2, 2 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + tdSql.query(f"select t2, t3, c1, count(*) from {self.dbname}.{self.stable} {keyword} by 1, 2, 3 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2, t3, c1, count(*) from {self.dbname}.{self.stable} {keyword} by t2, 2, 3 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2, t3, c1, count(*) from {self.dbname}.{self.stable} {keyword} by 1, t3, 3 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + tdSql.query(f"select sum(t0.sumc2) from (select c1, sum(c2) as sumc2 from {self.dbname}.{self.stable} {keyword} by 1) t0") + num = 0 + if nonempty_tb_num > 0: + num = 1 + tdSql.checkRows(num) + + tdSql.query(f"select abs(c1), count(*) from {self.dbname}.{self.stable} {keyword} by 1") + num = 0 + if nonempty_tb_num > 0: + num = self.row_nums + tdSql.checkRows(num) + + ####### error case + tdSql.error(f"select c1, count(*) from {self.dbname}.{self.stable} {keyword} by 10") + tdSql.error(f"select c1, count(*) from {self.dbname}.{self.stable} {keyword} by 0") + tdSql.error(f"select c1, c2, count(*) from {self.dbname}.{self.stable} {keyword} by 0, 1") + tdSql.error(f"select c1, count(*) from {self.dbname}.{self.stable} {keyword} by 1.2") + tdSql.error(f"select c1, c2, c3, count(*) from {self.dbname}.{self.stable} {keyword} by 1, 2.2, 3") + tdSql.error(f"select c1, c2, count(*) from {self.dbname}.{self.stable} {keyword} by 1") + tdSql.error(f"select c1, avg(c2), count(*) from {self.dbname}.{self.stable} {keyword} by 1, 2") + + def test_groupby_alias(self, keyword, check_num, nonempty_tb_num): + tdSql.query(f"select t1 as t1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t1_alias ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t1 as t1_alias from {self.dbname}.{self.stable} {keyword} by t1_alias order by count(*)") + tdSql.checkRows(check_num) + + # last + tdSql.query(f"select t1 as t1_alias from {self.dbname}.{self.stable} {keyword} by t1_alias having count(*)>=0") + tdSql.checkRows(check_num) + + # having filter out empty + tdSql.query(f"select t1 as t1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t1_alias having count(*) <= 0") + tdSql.checkRows(check_num - nonempty_tb_num) + + ####### by tag + tdSql.query(f"select t2 as t2_alias, count(*), count(1), count(c1) from {self.dbname}.{self.stable} {keyword} by t2_alias ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2 as t2_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t2_alias having count(*) <= 0") + tdSql.checkRows(check_num - nonempty_tb_num) + + # where + tdSql.query(f"select t2 as t2_alias, count(*) from {self.dbname}.{self.stable} where ts < now {keyword} by t2_alias ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2 as t2_alias, count(*) from {self.dbname}.{self.stable} where ts > 1737146000000 {keyword} by t2_alias ") + tdSql.checkRows(check_num) + + tdSql.query(f"select t2 as t2_alias, count(*) from {self.dbname}.{self.stable} where c1 = 1 {keyword} by t2_alias ") + tdSql.checkRows(check_num) + + ####### by col + tdSql.query(f"select c1 as c1_alias, count(*), count(1), count(c1) from {self.dbname}.{self.stable} {keyword} by c1_alias ") + num = 0 + if nonempty_tb_num > 0: + num = self.row_nums + tdSql.checkRows(num) + + tdSql.query(f"select ts as ts_alias, count(*) from {self.dbname}.{self.stable} {keyword} by ts_alias ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + # col + tag + tdSql.query(f"select t2 as t2_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by 1, 2 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2 as t2_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by 1, c1 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2 as t2_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t2, 2 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + tdSql.query(f"select t2 as t2_alias, t3 as t3_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t2_alias, t3_alias, 3 ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2 as t2_alias, t3 as t3_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t2, t3_alias, c1_alias ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + tdSql.query(f"select t2 as t2_alias, t3 as t3_alias, c1 as c1_alias, count(*) from {self.dbname}.{self.stable} {keyword} by t2_alias, t3, c1_alias ") + tdSql.checkRows(nonempty_tb_num * self.row_nums) + + tdSql.query(f"select sum(t0.sumc2) from (select c1 as c1_alias, sum(c2) as sumc2 from {self.dbname}.{self.stable} {keyword} by c1_alias) t0") + num = 0 + if nonempty_tb_num > 0: + num = 1 + tdSql.checkRows(num) + + tdSql.query(f"select abs(c1) as abs_alias, count(*) from {self.dbname}.{self.stable} {keyword} by abs_alias") + num = 0 + if nonempty_tb_num > 0: + num = self.row_nums + tdSql.checkRows(num) + + ####### error case + tdSql.error(f"select c1, avg(c2) as avg_alias, count(*) from {self.dbname}.{self.stable} {keyword} by 1, avg_alias") + def test_groupby_sub_table(self): for i in range(self.tb_nums): tbname = f"{self.dbname}.sub_{self.stable}_{i}" @@ -276,6 +427,10 @@ class TDTestCase: # empty table only self.test_groupby('group', self.tb_nums, 0) self.test_groupby('partition', self.tb_nums, 0) + self.test_groupby_position('group', self.tb_nums, 0) + self.test_groupby_position('partition', self.tb_nums, 0) + self.test_groupby_alias('group', self.tb_nums, 0) + self.test_groupby_alias('partition', self.tb_nums, 0) self.test_innerSelect(self.tb_nums) self.test_multi_group_key(self.tb_nums, 0) self.test_multi_agg(self.tb_nums, 0) @@ -287,6 +442,10 @@ class TDTestCase: self.test_groupby('group', self.tb_nums, nonempty_tb_num) self.test_groupby('partition', self.tb_nums, nonempty_tb_num) + self.test_groupby_position('group', self.tb_nums, nonempty_tb_num) + self.test_groupby_position('partition', self.tb_nums, nonempty_tb_num) + self.test_groupby_alias('group', self.tb_nums, nonempty_tb_num) + self.test_groupby_alias('partition', self.tb_nums, nonempty_tb_num) self.test_groupby_sub_table() self.test_innerSelect(self.tb_nums) self.test_multi_group_key(self.tb_nums, nonempty_tb_num) diff --git a/tests/system-test/2-query/leastsquares.py b/tests/system-test/2-query/leastsquares.py index 3dfd1f6aca..91cd02bf8f 100644 --- a/tests/system-test/2-query/leastsquares.py +++ b/tests/system-test/2-query/leastsquares.py @@ -77,7 +77,7 @@ class TDTestCase: ) query_condition.extend( ( - 1010, + 1010.1, ''' "test1234!@#$%^&*():'>