diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 6b481fc52e..615ee222a6 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -531,6 +531,7 @@ int32_t nodesCollectColumnsFromNode(SNode* node, const char* pTableAlias, EColle typedef bool (*FFuncClassifier)(int32_t funcId); int32_t nodesCollectFuncs(SSelectStmt* pSelect, ESqlClause clause, char* tableAlias, FFuncClassifier classifier, SNodeList** pFuncs); +int32_t nodesCollectSelectFuncs(SSelectStmt* pSelect, ESqlClause clause, char* tableAlias, FFuncClassifier classifier, SNodeList** pFuncs); int32_t nodesCollectSpecialNodes(SSelectStmt* pSelect, ESqlClause clause, ENodeType type, SNodeList** pNodes); diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 5e28621f7b..0a0502c7f5 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -1477,17 +1477,18 @@ void createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) { SValueNode* pvn = (SValueNode*)p1; pExp->base.pParam[j].type = FUNC_PARAM_TYPE_VALUE; nodesValueNodeToVariant(pvn, &pExp->base.pParam[j].param); - } else if (p1->type == QUERY_NODE_FUNCTION) { - if (strcmp(((SFunctionNode*)p1)->functionName, "_select_value") == 0 && - ((SFunctionNode*)p1)->pParameterList->length == 1 && - ((SFunctionNode*)p1)->pParameterList->pHead->pNode->type == QUERY_NODE_COLUMN) { - SColumnNode* pcn = (SColumnNode*)(((SFunctionNode*)p1)->pParameterList->pHead->pNode); - SValueNode* pvn = (SValueNode*)p1; - pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN; - pExp->base.pParam[j].pCol = - createColumn(pcn->dataBlockId, pcn->slotId, pcn->colId, &pcn->node.resType, pcn->colType); - } - } + } + // else if (p1->type == QUERY_NODE_FUNCTION) { + // if (strcmp(((SFunctionNode*)p1)->functionName, "_select_value") == 0 && + // ((SFunctionNode*)p1)->pParameterList->length == 1 && + // ((SFunctionNode*)p1)->pParameterList->pHead->pNode->type == QUERY_NODE_COLUMN) { + // SColumnNode* pcn = (SColumnNode*)(((SFunctionNode*)p1)->pParameterList->pHead->pNode); + // SValueNode* pvn = (SValueNode*)p1; + // pExp->base.pParam[j].type = FUNC_PARAM_TYPE_COLUMN; + // pExp->base.pParam[j].pCol = + // createColumn(pcn->dataBlockId, pcn->slotId, pcn->colId, &pcn->node.resType, pcn->colType); + // } + // } } } else if (type == QUERY_NODE_OPERATOR) { pExp->pExpr->nodeType = QUERY_NODE_OPERATOR; diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 3675b0b9c4..b13af4f49a 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -2111,6 +2111,34 @@ static EDealRes collectFuncs(SNode* pNode, void* pContext) { FOREACH(pn, pCxt->pFuncs) { if (nodesEqualNode(pn, pNode)) { bFound = true; + break; + } + } + if (!bFound) { + pCxt->errCode = nodesListStrictAppend(pCxt->pFuncs, nodesCloneNode(pNode)); + } + return (TSDB_CODE_SUCCESS == pCxt->errCode ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR); + } + return DEAL_RES_CONTINUE; +} + +static EDealRes collectSelectFuncs(SNode* pNode, void* pContext) { + SCollectFuncsCxt* pCxt = (SCollectFuncsCxt*)pContext; + 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); + if (pVal && strcmp(pVal->literal, pCxt->tableAlias)) { + return DEAL_RES_CONTINUE; + } + } + SExprNode* pExpr = (SExprNode*)pNode; + bool bFound = false; + SNode* pn = NULL; + FOREACH(pn, pCxt->pFuncs) { + if (nodesEqualNode(pn, pNode)) { + bFound = true; + break; } } if (!bFound) { @@ -2133,6 +2161,33 @@ static int32_t funcNodeEqual(const void* pLeft, const void* pRight, size_t len) return nodesEqualNode(*(const SNode**)pLeft, *(const SNode**)pRight) ? 0 : 1; } +int32_t nodesCollectSelectFuncs(SSelectStmt* pSelect, ESqlClause clause, char* tableAlias, FFuncClassifier classifier, SNodeList** pFuncs) { + if (NULL == pSelect || NULL == pFuncs) { + return TSDB_CODE_FAILED; + } + + SCollectFuncsCxt cxt = {.errCode = TSDB_CODE_SUCCESS, + .classifier = classifier, + .tableAlias = tableAlias, + .pFuncs = *pFuncs}; + if (NULL == cxt.pFuncs) { + return TSDB_CODE_OUT_OF_MEMORY; + } + + nodesWalkSelectStmt(pSelect, clause, collectFuncs, &cxt); + if (TSDB_CODE_SUCCESS == cxt.errCode) { + if (LIST_LENGTH(cxt.pFuncs) > 0) { + *pFuncs = cxt.pFuncs; + } else { + nodesDestroyList(cxt.pFuncs); + } + } else { + nodesDestroyList(cxt.pFuncs); + } + + return cxt.errCode; +} + int32_t nodesCollectFuncs(SSelectStmt* pSelect, ESqlClause clause, char* tableAlias, FFuncClassifier classifier, SNodeList** pFuncs) { if (NULL == pSelect || NULL == pFuncs) { return TSDB_CODE_FAILED; @@ -2152,9 +2207,11 @@ int32_t nodesCollectFuncs(SSelectStmt* pSelect, ESqlClause clause, char* tableAl *pFuncs = cxt.pFuncs; } else { nodesDestroyList(cxt.pFuncs); + *pFuncs = NULL; } } else { nodesDestroyList(cxt.pFuncs); + *pFuncs = NULL; } return cxt.errCode; diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 08e794f169..e69fa20cc6 100644 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -2744,6 +2744,24 @@ static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) { return DEAL_RES_CONTINUE; } +static int32_t reCalSelectFuncNum(SSelectStmt* pSelect) { + pSelect->selectFuncNum = 0; + SNodeList* pNodeList = nodesMakeList(); + int32_t code = TSDB_CODE_SUCCESS; + for (ESqlClause clause = SQL_CLAUSE_FROM; clause < SQL_CLAUSE_ORDER_BY; clause++) { + code = nodesCollectSelectFuncs(pSelect, clause, NULL, fmIsSelectFunc, &pNodeList); + if (TSDB_CODE_SUCCESS != code) { + return code; + } + } + SNode* pNode = NULL; + FOREACH(pNode, pNodeList) { + pSelect->selectFuncNum = calcSelectFuncNum((SFunctionNode*)pNode, pSelect->selectFuncNum); + } + nodesDestroyList(pNodeList); + return TSDB_CODE_SUCCESS; +} + static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) { if (NULL != pSelect->pGroupByList || NULL != pSelect->pWindow || (!pSelect->hasAggFuncs && !pSelect->hasIndefiniteRowsFunc && !pSelect->hasInterpFunc)) { @@ -2757,7 +2775,8 @@ static int32_t checkAggColCoexist(STranslateContext* pCxt, SSelectStmt* pSelect) if (!pSelect->isDistinct) { nodesRewriteExprs(pSelect->pOrderByList, doCheckAggColCoexist, &cxt); } - if (0 < pSelect->selectFuncNum && !pSelect->hasOtherVectorFunc) { + if (((!cxt.existCol && 0 < pSelect->selectFuncNum) || (cxt.existCol && 1 == pSelect->selectFuncNum) ) + && !pSelect->hasOtherVectorFunc) { return rewriteColsToSelectValFunc(pCxt, pSelect); } if (cxt.existCol) { @@ -4597,6 +4616,7 @@ static int32_t translateSelectFrom(STranslateContext* pCxt, SSelectStmt* pSelect code = translateOrderBy(pCxt, pSelect); } if (TSDB_CODE_SUCCESS == code) { + reCalSelectFuncNum(pSelect); code = checkAggColCoexist(pCxt, pSelect); } if (TSDB_CODE_SUCCESS == code) {