diff --git a/source/libs/executor/src/projectoperator.c b/source/libs/executor/src/projectoperator.c index 412a4bfbc00514410df1d69f65d6233af5be55af..1cc377b3ee9320c79e30c34a45d0289936da5918 100644 --- a/source/libs/executor/src/projectoperator.c +++ b/source/libs/executor/src/projectoperator.c @@ -38,7 +38,7 @@ typedef struct SIndefOperatorInfo { SSDataBlock* pNextGroupRes; } SIndefOperatorInfo; -static SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator); +static int32_t doGenerateSourceData(SOperatorInfo* pOperator); static SSDataBlock* doProjectOperation(SOperatorInfo* pOperator); static SSDataBlock* doApplyIndefinitFunction(SOperatorInfo* pOperator); static SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols); @@ -215,7 +215,7 @@ static int32_t setInfoForNewGroup(SSDataBlock* pBlock, SLimitInfo* pLimitInfo, S if (newGroup) { resetLimitInfoForNextGroup(pLimitInfo); } - + return PROJECT_RETRIEVE_CONTINUE; } @@ -267,7 +267,12 @@ SSDataBlock* doProjectOperation(SOperatorInfo* pOperator) { SLimitInfo* pLimitInfo = &pProjectInfo->limitInfo; if (downstream == NULL) { - return doGenerateSourceData(pOperator); + code = doGenerateSourceData(pOperator); + if (code != TSDB_CODE_SUCCESS) { + T_LONG_JMP(pTaskInfo->env, code); + } + + return (pRes->info.rows > 0) ? pRes : NULL; } while (1) { @@ -616,7 +621,7 @@ SArray* setRowTsColumnOutputInfo(SqlFunctionCtx* pCtx, int32_t numOfCols) { return pList; } -SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator) { +int32_t doGenerateSourceData(SOperatorInfo* pOperator) { SProjectOperatorInfo* pProjectInfo = pOperator->info; SExprSupp* pSup = &pOperator->exprSupp; @@ -630,14 +635,45 @@ SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator) { for (int32_t k = 0; k < pSup->numOfExprs; ++k) { int32_t outputSlotId = pExpr[k].base.resSchema.slotId; - ASSERT(pExpr[k].pExpr->nodeType == QUERY_NODE_VALUE); - SColumnInfoData* pColInfoData = taosArrayGet(pRes->pDataBlock, outputSlotId); + if (pExpr[k].pExpr->nodeType == QUERY_NODE_VALUE) { + SColumnInfoData* pColInfoData = taosArrayGet(pRes->pDataBlock, outputSlotId); + + int32_t type = pExpr[k].base.pParam[0].param.nType; + if (TSDB_DATA_TYPE_NULL == type) { + colDataSetNNULL(pColInfoData, 0, 1); + } else { + colDataSetVal(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); + } + } else if (pExpr[k].pExpr->nodeType == QUERY_NODE_FUNCTION) { + SqlFunctionCtx* pfCtx = &pSup->pCtx[k]; + + // UDF scalar functions will be calculated here, for example, select foo(n) from (select 1 n). + // UDF aggregate functions will be handled in agg operator. + if (fmIsScalarFunc(pfCtx->functionId)) { + SArray* pBlockList = taosArrayInit(4, POINTER_BYTES); + taosArrayPush(pBlockList, &pRes); - int32_t type = pExpr[k].base.pParam[0].param.nType; - if (TSDB_DATA_TYPE_NULL == type) { - colDataSetNNULL(pColInfoData, 0, 1); + SColumnInfoData* pResColData = taosArrayGet(pRes->pDataBlock, outputSlotId); + SColumnInfoData idata = {.info = pResColData->info, .hasNull = true}; + + SScalarParam dest = {.columnData = &idata}; + int32_t code = scalarCalculate((SNode*)pExpr[k].pExpr->_function.pFunctNode, pBlockList, &dest); + if (code != TSDB_CODE_SUCCESS) { + taosArrayDestroy(pBlockList); + return code; + } + + int32_t startOffset = pRes->info.rows; + ASSERT(pRes->info.capacity > 0); + colDataAssign(pResColData, &idata, dest.numOfRows, &pRes->info); + colDataDestroy(&idata); + + taosArrayDestroy(pBlockList); + } else { + return TSDB_CODE_OPS_NOT_SUPPORT; + } } else { - colDataSetVal(pColInfoData, 0, taosVariantGet(&pExpr[k].base.pParam[0].param, type), false); + return TSDB_CODE_OPS_NOT_SUPPORT; } } @@ -653,7 +689,7 @@ SSDataBlock* doGenerateSourceData(SOperatorInfo* pOperator) { pOperator->cost.openCost = (taosGetTimestampUs() - st) / 1000.0; } - return (pRes->info.rows > 0) ? pRes : NULL; + return TSDB_CODE_SUCCESS; } static void setPseudoOutputColInfo(SSDataBlock* pResult, SqlFunctionCtx* pCtx, SArray* pPseudoList) { diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index d9295656e8c4b882e5af1d735d7399b7dfb5a332..4eb0f0e1bce3e9f21ce0b4891e7c7c65e3c439cd 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -1694,7 +1694,8 @@ int32_t scalarCalculate(SNode *pNode, SArray *pBlockList, SScalarParam *pDst) { SCL_ERR_JRET(TSDB_CODE_APP_ERROR); } - if (1 == res->numOfRows) { + SSDataBlock *pb = taosArrayGetP(pBlockList, 0); + if (1 == res->numOfRows && pb->info.rows > 0) { SCL_ERR_JRET(sclExtendResRows(pDst, res, pBlockList)); } else { colInfoDataEnsureCapacity(pDst->columnData, res->numOfRows, true); diff --git a/tests/system-test/0-others/udfTest.py b/tests/system-test/0-others/udfTest.py index 78020cb9586e6c59f7c0f84e5aeacdbb596b421c..88d0d420f73f9c06e633ebcf2dbc14a454f6e878 100644 --- a/tests/system-test/0-others/udfTest.py +++ b/tests/system-test/0-others/udfTest.py @@ -234,6 +234,11 @@ class TDTestCase: tdSql.checkData(20,6,88) tdSql.checkData(20,7,1) + tdSql.query("select udf1(1) from (select 1)") + tdSql.checkData(0,0,1) + + tdSql.query("select udf1(n) from (select 1 n)") + tdSql.checkData(0,0,1) # aggregate functions tdSql.query("select udf2(num1) ,udf2(num2), udf2(num3) from tb")