From c4cc51b583162bbca8ce4e9aa80c2f5f3acb9a92 Mon Sep 17 00:00:00 2001 From: facetosea <285808407@qq.com> Date: Sun, 16 Feb 2025 01:15:12 +0800 Subject: [PATCH] cols: use aggfunc --- include/libs/function/function.h | 4 +-- include/libs/nodes/querynodes.h | 5 +-- source/libs/executor/src/aggregateoperator.c | 2 +- source/libs/executor/src/executil.c | 10 +++--- source/libs/function/src/functionMgt.c | 4 +-- source/libs/nodes/src/nodesCloneFuncs.c | 4 +-- source/libs/nodes/src/nodesEqualFuncs.c | 4 +-- source/libs/nodes/src/nodesMsgFuncs.c | 16 ++++----- source/libs/nodes/src/nodesUtilFuncs.c | 4 +++ source/libs/parser/src/parTranslater.c | 38 ++++++++++---------- source/libs/planner/src/planLogicCreater.c | 11 +++--- source/libs/planner/src/planOptimizer.c | 3 +- source/libs/planner/src/planUtil.c | 3 +- tests/system-test/2-query/cols_function.py | 9 ++++- 14 files changed, 61 insertions(+), 56 deletions(-) diff --git a/include/libs/function/function.h b/include/libs/function/function.h index 8c299d2c8c..b2bde42463 100644 --- a/include/libs/function/function.h +++ b/include/libs/function/function.h @@ -276,14 +276,14 @@ typedef struct tExprNode { int32_t num; struct SFunctionNode *pFunctNode; int32_t functionType; - int32_t bindTupleFuncIdx; + int32_t bindExprID; } _function; struct { struct SNode *pRootNode; } _optrRoot; }; - int32_t tupleFuncIdx; + int32_t relatedTo; } tExprNode; struct SScalarParam { diff --git a/include/libs/nodes/querynodes.h b/include/libs/nodes/querynodes.h index 9a118bdeab..5fae336d22 100644 --- a/include/libs/nodes/querynodes.h +++ b/include/libs/nodes/querynodes.h @@ -62,8 +62,8 @@ typedef struct SExprNode { bool asParam; bool asPosition; int32_t projIdx; - int32_t bindTupleFuncIdx; - int32_t tupleFuncIdx; + int32_t relatedTo; + int32_t bindExprID; } SExprNode; typedef enum EColumnType { @@ -701,6 +701,7 @@ char* getFullJoinTypeString(EJoinType type, EJoinSubType stype); int32_t mergeJoinConds(SNode** ppDst, SNode** ppSrc); int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num); +bool isRelatedToOtherExpr(SExprNode* pExpr); #ifdef __cplusplus } diff --git a/source/libs/executor/src/aggregateoperator.c b/source/libs/executor/src/aggregateoperator.c index bec8bf7f6f..bd4eb2e61d 100644 --- a/source/libs/executor/src/aggregateoperator.c +++ b/source/libs/executor/src/aggregateoperator.c @@ -397,7 +397,7 @@ static int32_t createDataBlockForEmptyInput(SOperatorInfo* pOperator, SSDataBloc // if the last expression is a tuple function, we don't need to create a empty data block int32_t lastExprIndex = pOperator->exprSupp.numOfExprs - 1; - if(pOperator->exprSupp.pExprInfo[lastExprIndex].pExpr->tupleFuncIdx > 0) { + if(pOperator->exprSupp.pExprInfo[lastExprIndex].pExpr->_function.bindExprID > 0) { return TSDB_CODE_SUCCESS; } diff --git a/source/libs/executor/src/executil.c b/source/libs/executor/src/executil.c index 95e76e8599..c2baf75881 100644 --- a/source/libs/executor/src/executil.c +++ b/source/libs/executor/src/executil.c @@ -1992,10 +1992,10 @@ int32_t createExprFromOneNode(SExprInfo* pExp, SNode* pNode, int16_t slotId) { code = TSDB_CODE_QRY_EXECUTOR_INTERNAL_ERROR; QUERY_CHECK_CODE(code, lino, _end); } - if(type == QUERY_NODE_FUNCTION) { - pExp->pExpr->_function.bindTupleFuncIdx = ((SExprNode*)pNode)->bindTupleFuncIdx; + if (type == QUERY_NODE_FUNCTION) { + pExp->pExpr->_function.bindExprID = ((SExprNode*)pNode)->bindExprID; } - pExp->pExpr->tupleFuncIdx = ((SExprNode*)pNode)->tupleFuncIdx; + pExp->pExpr->relatedTo = ((SExprNode*)pNode)->relatedTo; _end: if (code != TSDB_CODE_SUCCESS) { qError("%s failed at line %d since %s", __func__, lino, tstrerror(code)); @@ -2091,7 +2091,7 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu SArray* pValCtxArray = NULL; for (int32_t i = numOfOutput - 1; i > 0; --i) { // select Func is at the end of the list - int32_t funcIdx = pCtx[i].pExpr->pExpr->tupleFuncIdx; + int32_t funcIdx = pCtx[i].pExpr->pExpr->_function.bindExprID; if (funcIdx > 0) { if (pValCtxArray == NULL) { // the end of the list is the select function of biggest index @@ -2134,7 +2134,7 @@ static int32_t setSelectValueColumnInfo(SqlFunctionCtx* pCtx, int32_t numOfOutpu if (pValCtxArray == NULL) { pValCtx[num++] = &pCtx[i]; } else { - int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->_function.bindTupleFuncIdx; // start from index 1; + int32_t bindFuncIndex = pCtx[i].pExpr->pExpr->relatedTo; // start from index 1; if (bindFuncIndex > 0) { // 0 is default index related to the select function bindFuncIndex -= 1; } diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index a88bee48fa..03935bf1a0 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -443,8 +443,8 @@ int32_t createFunctionWithSrcFunc(const char* pName, const SFunctionNode* pSrcFu return code; } resetOutputChangedFunc(*ppFunc, pSrcFunc); - (*ppFunc)->node.bindTupleFuncIdx = pSrcFunc->node.bindTupleFuncIdx; - (*ppFunc)->node.tupleFuncIdx = pSrcFunc->node.tupleFuncIdx; + (*ppFunc)->node.relatedTo = pSrcFunc->node.relatedTo; + (*ppFunc)->node.bindExprID = pSrcFunc->node.bindExprID; return code; } diff --git a/source/libs/nodes/src/nodesCloneFuncs.c b/source/libs/nodes/src/nodesCloneFuncs.c index 11c9b322d2..c27f4a4859 100644 --- a/source/libs/nodes/src/nodesCloneFuncs.c +++ b/source/libs/nodes/src/nodesCloneFuncs.c @@ -106,8 +106,8 @@ static int32_t exprNodeCopy(const SExprNode* pSrc, SExprNode* pDst) { COPY_SCALAR_FIELD(asParam); COPY_SCALAR_FIELD(asPosition); COPY_SCALAR_FIELD(projIdx); - COPY_SCALAR_FIELD(bindTupleFuncIdx); - COPY_SCALAR_FIELD(tupleFuncIdx); + COPY_SCALAR_FIELD(relatedTo); + COPY_SCALAR_FIELD(bindExprID); return TSDB_CODE_SUCCESS; } diff --git a/source/libs/nodes/src/nodesEqualFuncs.c b/source/libs/nodes/src/nodesEqualFuncs.c index e1c17f5c35..fa15c9f2fa 100644 --- a/source/libs/nodes/src/nodesEqualFuncs.c +++ b/source/libs/nodes/src/nodesEqualFuncs.c @@ -139,10 +139,10 @@ static bool functionNodeEqual(const SFunctionNode* a, const SFunctionNode* b) { COMPARE_STRING_FIELD(functionName); COMPARE_NODE_LIST_FIELD(pParameterList); if (a->funcType == FUNCTION_TYPE_SELECT_VALUE) { - if ((a->node.bindTupleFuncIdx != b->node.bindTupleFuncIdx)) return false; + if ((a->node.relatedTo != b->node.relatedTo)) return false; } else { // select cols(cols(first(c0), ts), first(c0) from meters; - if ((a->node.tupleFuncIdx != b->node.tupleFuncIdx)) { + if ((a->node.bindExprID != b->node.bindExprID)) { return false; } } diff --git a/source/libs/nodes/src/nodesMsgFuncs.c b/source/libs/nodes/src/nodesMsgFuncs.c index 5bd773796f..d6348f4184 100644 --- a/source/libs/nodes/src/nodesMsgFuncs.c +++ b/source/libs/nodes/src/nodesMsgFuncs.c @@ -670,10 +670,10 @@ static int32_t exprNodeToMsg(const void* pObj, STlvEncoder* pEncoder) { const SExprNode* pNode = (const SExprNode*)pObj; int32_t code = tlvEncodeObj(pEncoder, EXPR_CODE_RES_TYPE, dataTypeToMsg, &pNode->resType); if (TSDB_CODE_SUCCESS == code) { - code = tlvEncodeI32(pEncoder, EXPR_CODE_BIND_TUPLE_FUNC_IDX, pNode->bindTupleFuncIdx); + code = tlvEncodeI32(pEncoder, EXPR_CODE_BIND_TUPLE_FUNC_IDX, pNode->relatedTo); } if (TSDB_CODE_SUCCESS == code) { - code = tlvEncodeI32(pEncoder, EXPR_CODE_TUPLE_FUNC_IDX, pNode->tupleFuncIdx); + code = tlvEncodeI32(pEncoder, EXPR_CODE_TUPLE_FUNC_IDX, pNode->bindExprID); } return code; } @@ -689,10 +689,10 @@ static int32_t msgToExprNode(STlvDecoder* pDecoder, void* pObj) { code = tlvDecodeObjFromTlv(pTlv, msgToDataType, &pNode->resType); break; case EXPR_CODE_BIND_TUPLE_FUNC_IDX: - code = tlvDecodeI32(pTlv, &pNode->bindTupleFuncIdx); + code = tlvDecodeI32(pTlv, &pNode->relatedTo); break; case EXPR_CODE_TUPLE_FUNC_IDX: - code = tlvDecodeI32(pTlv, &pNode->tupleFuncIdx); + code = tlvDecodeI32(pTlv, &pNode->bindExprID); break; default: break; @@ -709,10 +709,10 @@ static int32_t columnNodeInlineToMsg(const void* pObj, STlvEncoder* pEncoder) { int32_t code = dataTypeInlineToMsg(&pNode->node.resType, pEncoder); if (TSDB_CODE_SUCCESS == code) { - code = tlvEncodeValueI32(pEncoder, pNode->node.bindTupleFuncIdx); + code = tlvEncodeValueI32(pEncoder, pNode->node.relatedTo); } if (TSDB_CODE_SUCCESS == code) { - code = tlvEncodeValueI32(pEncoder, pNode->node.tupleFuncIdx); + code = tlvEncodeValueI32(pEncoder, pNode->node.bindExprID); } if (TSDB_CODE_SUCCESS == code) { code = tlvEncodeValueU64(pEncoder, pNode->tableId); @@ -765,10 +765,10 @@ static int32_t msgToColumnNodeInline(STlvDecoder* pDecoder, void* pObj) { int32_t code = msgToDataTypeInline(pDecoder, &pNode->node.resType); if (TSDB_CODE_SUCCESS == code) { - code = tlvDecodeValueI32(pDecoder, &pNode->node.bindTupleFuncIdx); + code = tlvDecodeValueI32(pDecoder, &pNode->node.relatedTo); } if (TSDB_CODE_SUCCESS == code) { - code = tlvDecodeValueI32(pDecoder, &pNode->node.tupleFuncIdx); + code = tlvDecodeValueI32(pDecoder, &pNode->node.bindExprID); } if (TSDB_CODE_SUCCESS == code) { code = tlvDecodeValueU64(pDecoder, &pNode->tableId); diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index e0dfe69eb7..b96a1d3a12 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -3243,3 +3243,7 @@ int32_t nodesListDeduplicate(SNodeList** ppList) { int32_t rewriteExprAliasName(SExprNode* pNode, int64_t num) { return tsnprintf(pNode->aliasName, TSDB_COL_NAME_LEN, "expr_%ld", num); } + +bool isRelatedToOtherExpr(SExprNode* pExpr) { + return pExpr->relatedTo != 0; +} diff --git a/source/libs/parser/src/parTranslater.c b/source/libs/parser/src/parTranslater.c index 342b2dba79..b0be691240 100755 --- a/source/libs/parser/src/parTranslater.c +++ b/source/libs/parser/src/parTranslater.c @@ -1105,11 +1105,11 @@ static bool isForecastPseudoColumnFunc(const SNode* pNode) { } static bool isColsFunctionResult(const SNode* pNode) { - return ((nodesIsExprNode(pNode)) && ((SExprNode*)pNode)->bindTupleFuncIdx > 0); + return ((nodesIsExprNode(pNode)) && ((SExprNode*)pNode)->relatedTo > 0); } static bool isInvalidColsBindFunction(const SFunctionNode* pFunc) { - return (!fmIsSelectFunc(pFunc->funcId) && pFunc->node.tupleFuncIdx != 0); + return (!fmIsSelectFunc(pFunc->funcId) && pFunc->node.bindExprID != 0); } #ifdef BUILD_NO_CALL @@ -3582,8 +3582,8 @@ static EDealRes rewriteColToSelectValFunc(STranslateContext* pCxt, SNode** pNode tstrncpy(pFunc->functionName, "_select_value", TSDB_FUNC_NAME_LEN); tstrncpy(pFunc->node.aliasName, ((SExprNode*)*pNode)->aliasName, TSDB_COL_NAME_LEN); tstrncpy(pFunc->node.userAlias, ((SExprNode*)*pNode)->userAlias, TSDB_COL_NAME_LEN); - pFunc->node.bindTupleFuncIdx = ((SExprNode*)*pNode)->bindTupleFuncIdx; - pFunc->node.tupleFuncIdx = ((SExprNode*)*pNode)->tupleFuncIdx; + pFunc->node.relatedTo = ((SExprNode*)*pNode)->relatedTo; + pFunc->node.bindExprID = ((SExprNode*)*pNode)->bindExprID; pCxt->errCode = nodesListMakeAppend(&pFunc->pParameterList, *pNode); if (TSDB_CODE_SUCCESS == pCxt->errCode) { pCxt->errCode = getFuncInfo(pCxt, pFunc); @@ -3894,7 +3894,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { if (isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) { if ((pSelect->selectFuncNum > 1 || (isDistinctOrderBy(pCxt) && pCxt->currClause == SQL_CLAUSE_ORDER_BY)) && - ((SExprNode*)*pNode)->bindTupleFuncIdx == 0) { + !isRelatedToOtherExpr((SExprNode*)*pNode)) { return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias); } if (isWindowJoinStmt(pSelect) && @@ -3903,7 +3903,7 @@ static EDealRes doCheckExprForGroupBy(SNode** pNode, void* pContext) { return rewriteExprToGroupKeyFunc(pCxt, pNode); } - if ((pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) && ((SExprNode*)*pNode)->bindTupleFuncIdx == 0) { + if ((pSelect->hasOtherVectorFunc || !pSelect->hasSelectFunc) && !isRelatedToOtherExpr((SExprNode*)*pNode)) { return generateDealNodeErrMsg(pCxt, getGroupByErrorCode(pCxt), ((SExprNode*)(*pNode))->userAlias); } @@ -3983,7 +3983,7 @@ static EDealRes doCheckAggColCoexist(SNode** pNode, void* pContext) { return rewriteExprToSelectTagFunc(pCxt->pTranslateCxt, pNode); } if ((isScanPseudoColumnFunc(*pNode) || QUERY_NODE_COLUMN == nodeType(*pNode)) && - ((!nodesIsExprNode(*pNode) || ((SExprNode*)*pNode)->bindTupleFuncIdx == 0))) { + ((!nodesIsExprNode(*pNode) || !isRelatedToOtherExpr((SExprNode*)*pNode)))) { pCxt->existCol = true; } return DEAL_RES_CONTINUE; @@ -5466,16 +5466,18 @@ static int32_t prepareColumnExpansion(STranslateContext* pCxt, ESqlClause clause int32_t code = TSDB_CODE_SUCCESS; if (clause == SQL_CLAUSE_SELECT) { code = rewriteColsFunction(pCxt, &pSelect->pProjectionList, &pSelect->pProjectionBindList); - code = translateExprList(pCxt, pSelect->pProjectionBindList); } else if (clause == SQL_CLAUSE_ORDER_BY) { code = rewriteColsFunction(pCxt, &pSelect->pOrderByList, &pSelect->pProjectionBindList); - if (TSDB_CODE_SUCCESS == code) { - code = translateExprList(pCxt, pSelect->pProjectionBindList); - } } else { code = generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_WRONG_VALUE_TYPE, "Invalid clause for column expansion"); } + if (TSDB_CODE_SUCCESS == code) { + code = translateExprList(pCxt, pSelect->pProjectionBindList); + } + if (pSelect->pProjectionBindList != NULL) { + pSelect->hasAggFuncs = true; + } return code; } @@ -7391,19 +7393,19 @@ static bool isMultiColsFuncNode(SNode* pNode) { } typedef struct SBindTupleFuncCxt { - int32_t bindTupleFuncIdx; + int32_t bindExprID; } SBindTupleFuncCxt; static EDealRes pushDownBindSelectFunc(SNode** pNode, void* pContext) { SBindTupleFuncCxt* pCxt = pContext; if (nodesIsExprNode(*pNode)) { - ((SExprNode*)*pNode)->bindTupleFuncIdx = pCxt->bindTupleFuncIdx; + ((SExprNode*)*pNode)->relatedTo = pCxt->bindExprID; int32_t len = strlen(((SExprNode*)*pNode)->aliasName); if (len + TSDB_COL_NAME_EXLEN >= TSDB_COL_NAME_LEN) { parserError("%s The alias name is too long, the extra part will be truncated", __func__); return DEAL_RES_ERROR; } else { - tsnprintf(((SExprNode*)*pNode)->aliasName + len, TSDB_COL_NAME_EXLEN, ".%d", pCxt->bindTupleFuncIdx); + tsnprintf(((SExprNode*)*pNode)->aliasName + len, TSDB_COL_NAME_EXLEN, ".%d", pCxt->bindExprID); } SFunctionNode* pFunc = (SFunctionNode*)*pNode; } @@ -7512,7 +7514,7 @@ static EDealRes rewriteSingleColsFunc(SNode** pNode, void* pContext) { selectFuncIndex = selectFuncCount; SNode* pNewNode = NULL; code = nodesCloneNode(pSelectFunc, &pNewNode); - ((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex; + ((SExprNode*)pNewNode)->bindExprID = selectFuncIndex; nodesListMakeStrictAppend(pCxt->selectFuncList, pNewNode); } @@ -7595,7 +7597,7 @@ static int32_t rewriteColsFunction(STranslateContext* pCxt, SNodeList** nodeList ++selectFuncCount; selectFuncIndex = selectFuncCount; code = nodesCloneNode(pSelectFunc, &pNewNode); - ((SExprNode*)pNewNode)->tupleFuncIdx = selectFuncIndex; + ((SExprNode*)pNewNode)->bindExprID = selectFuncIndex; nodesListMakeStrictAppend(selectFuncList, pNewNode); } // start from index 1, because the first parameter is select function which needn't to output. @@ -13905,10 +13907,6 @@ static int32_t extractQueryResultSchema(const SNodeList* pProjections, int32_t* int32_t index = 0; FOREACH(pNode, pProjections) { SExprNode* pExpr = (SExprNode*)pNode; - if(pExpr->tupleFuncIdx != 0) { - *numOfCols -= 1; - continue; - } if (TSDB_DATA_TYPE_NULL == pExpr->resType.type) { (*pSchema)[index].type = TSDB_DATA_TYPE_VARCHAR; (*pSchema)[index].bytes = VARSTR_HEADER_SIZE; diff --git a/source/libs/planner/src/planLogicCreater.c b/source/libs/planner/src/planLogicCreater.c index cd0355008a..2fd8d863fb 100644 --- a/source/libs/planner/src/planLogicCreater.c +++ b/source/libs/planner/src/planLogicCreater.c @@ -123,8 +123,8 @@ static EDealRes doRewriteExpr(SNode** pNode, void* pContext) { tstrncpy(pCol->node.userAlias, ((SExprNode*)pExpr)->userAlias, TSDB_COL_NAME_LEN); tstrncpy(pCol->colName, ((SExprNode*)pExpr)->aliasName, TSDB_COL_NAME_LEN); pCol->node.projIdx = ((SExprNode*)(*pNode))->projIdx; - pCol->node.bindTupleFuncIdx = ((SExprNode*)(*pNode))->bindTupleFuncIdx; - pCol->node.tupleFuncIdx = ((SExprNode*)(*pNode))->tupleFuncIdx; + pCol->node.relatedTo = ((SExprNode*)(*pNode))->relatedTo; + //pCol->node.bindExprID = ((SExprNode*)(*pNode))->bindExprID; if (QUERY_NODE_FUNCTION == nodeType(pExpr)) { setColumnInfo((SFunctionNode*)pExpr, pCol, pCxt->isPartitionBy); } @@ -712,7 +712,7 @@ static SColumnNode* createColumnByExpr(const char* pStmtName, SExprNode* pExpr) if (NULL != pStmtName) { snprintf(pCol->tableAlias, sizeof(pCol->tableAlias), "%s", pStmtName); } - pCol->node.bindTupleFuncIdx = pExpr->bindTupleFuncIdx; + pCol->node.relatedTo = pExpr->relatedTo; return pCol; } @@ -818,7 +818,7 @@ static int32_t addWinJoinPrimKeyToAggFuncs(SSelectStmt* pSelect, SNodeList** pLi } static int32_t createAggLogicNode(SLogicPlanContext* pCxt, SSelectStmt* pSelect, SLogicNode** pLogicNode) { - if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList && !pSelect->pProjectionBindList) { + if (!pSelect->hasAggFuncs && NULL == pSelect->pGroupByList) { return TSDB_CODE_SUCCESS; } @@ -1598,9 +1598,6 @@ static int32_t createColumnByProjections(SLogicPlanContext* pCxt, const char* pS SNode* pNode; int32_t projIdx = 1; FOREACH(pNode, pExprs) { - if (((SExprNode*)pNode)->tupleFuncIdx != 0) { - continue; - } SColumnNode* pCol = createColumnByExpr(pStmtName, (SExprNode*)pNode); if (TSDB_CODE_SUCCESS != (code = nodesListStrictAppend(pList, (SNode*)pCol))) { nodesDestroyList(pList); diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 8dec06137c..f3a80af168 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -3606,8 +3606,7 @@ static int32_t eliminateProjOptimizeImpl(SOptimizeContext* pCxt, SLogicSubplan* } else { FOREACH(pProjection, pProjectNode->pProjections) { FOREACH(pChildTarget, pChild->pTargets) { - if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName) - && ((SColumnNode*)pProjection)->node.tupleFuncIdx == 0) { + if (0 == strcmp(((SColumnNode*)pProjection)->colName, ((SColumnNode*)pChildTarget)->colName)) { SNode* pNew = NULL; code = nodesCloneNode(pChildTarget, &pNew); if (TSDB_CODE_SUCCESS == code) { diff --git a/source/libs/planner/src/planUtil.c b/source/libs/planner/src/planUtil.c index 49559719a7..4cac6ae1a8 100644 --- a/source/libs/planner/src/planUtil.c +++ b/source/libs/planner/src/planUtil.c @@ -79,8 +79,7 @@ static EDealRes doCreateColumn(SNode* pNode, void* pContext) { } } } - pCol->node.bindTupleFuncIdx = pExpr->bindTupleFuncIdx; - pCol->node.tupleFuncIdx = pExpr->tupleFuncIdx; + pCol->node.relatedTo = pExpr->relatedTo; return (TSDB_CODE_SUCCESS == nodesListStrictAppend(pCxt->pList, (SNode*)pCol) ? DEAL_RES_IGNORE_CHILD : DEAL_RES_ERROR); } diff --git a/tests/system-test/2-query/cols_function.py b/tests/system-test/2-query/cols_function.py index a418e1f8a5..29ca667e3a 100644 --- a/tests/system-test/2-query/cols_function.py +++ b/tests/system-test/2-query/cols_function.py @@ -522,6 +522,12 @@ class TDTestCase: tdSql.checkCols(2) tdSql.checkData(0, 0, 3) tdSql.checkData(0, 1, 1) + tdSql.query(f'select * from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1 c21), first(c0) from test.meters where c0 < 4)') + tdSql.checkRows(1) + tdSql.checkCols(5) + tdSql.checkData(0, 1, 3) + tdSql.checkData(0, 3, 1) + tdSql.checkData(0, 4, 1) tdSql.error(f'select c1 from (select cols(last_row(c0), ts as t1, c1), cols(first(c0), ts as t2, c1), first(c0) from test.meters where c0 < 4)') # cols on system table @@ -966,11 +972,12 @@ class TDTestCase: self.one_cols_1output_test() self.multi_cols_output_test() self.subquery_test() - #self.window_test() + self.window_test() self.join_test() self.stream_cols_test() self.include_null_test() + def stop(self): tdSql.close() tdLog.success("%s successfully executed" % __file__)