From e792c1a98662283c9616876432068017030c64d3 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 10 Oct 2024 11:49:26 +0800 Subject: [PATCH 1/4] fix: unitest error --- source/libs/function/src/functionMgt.c | 9 ++++ source/libs/parser/src/parAstCreater.c | 60 +++++++++++++++++++++++++ source/libs/parser/src/parUtil.c | 2 + source/libs/planner/src/planOptimizer.c | 2 + 4 files changed, 73 insertions(+) diff --git a/source/libs/function/src/functionMgt.c b/source/libs/function/src/functionMgt.c index d436925046..1717702df7 100644 --- a/source/libs/function/src/functionMgt.c +++ b/source/libs/function/src/functionMgt.c @@ -232,6 +232,15 @@ bool fmIsInterpFunc(int32_t funcId) { bool fmIsInterpPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_INTERP_PC_FUNC); } +bool fmIsForecastFunc(int32_t funcId) { + if (funcId < 0 || funcId >= funcMgtBuiltinsNum) { + return false; + } + return FUNCTION_TYPE_FORECAST == funcMgtBuiltins[funcId].type; +} + +bool fmIsForecastPseudoColumnFunc(int32_t funcId) { return isSpecificClassifyFunc(funcId, FUNC_MGT_FORECAST_PC_FUNC); } + bool fmIsLastRowFunc(int32_t funcId) { if (funcId < 0 || funcId >= funcMgtBuiltinsNum) { return false; diff --git a/source/libs/parser/src/parAstCreater.c b/source/libs/parser/src/parAstCreater.c index cd3095ede8..684bd24a9c 100644 --- a/source/libs/parser/src/parAstCreater.c +++ b/source/libs/parser/src/parAstCreater.c @@ -1367,6 +1367,25 @@ _err: return NULL; } +SNode* createAnomalyWindowNode(SAstCreateContext* pCxt, SNode* pExpr, const SToken* pFuncOpt) { + SAnomalyWindowNode* pAnomaly = NULL; + CHECK_PARSER_STATUS(pCxt); + pCxt->errCode = nodesMakeNode(QUERY_NODE_ANOMALY_WINDOW, (SNode**)&pAnomaly); + CHECK_MAKE_NODE(pAnomaly); + pAnomaly->pCol = createPrimaryKeyCol(pCxt, NULL); + CHECK_MAKE_NODE(pAnomaly->pCol); + pAnomaly->pExpr = pExpr; + if (pFuncOpt == NULL) { + tstrncpy(pAnomaly->anomalyOpt, "algo=iqr", TSDB_ANAL_ALGO_OPTION_LEN); + } else { + (void)trimString(pFuncOpt->z, pFuncOpt->n, pAnomaly->anomalyOpt, sizeof(pAnomaly->anomalyOpt)); + } + return (SNode*)pAnomaly; +_err: + nodesDestroyNode((SNode*)pAnomaly); + return NULL; +} + SNode* createIntervalWindowNode(SAstCreateContext* pCxt, SNode* pInterval, SNode* pOffset, SNode* pSliding, SNode* pFill) { SIntervalWindowNode* interval = NULL; @@ -2997,6 +3016,47 @@ _err: return NULL; } +SNode* createCreateAnodeStmt(SAstCreateContext* pCxt, const SToken* pUrl) { + CHECK_PARSER_STATUS(pCxt); + SCreateAnodeStmt* pStmt = NULL; + pCxt->errCode = nodesMakeNode(QUERY_NODE_CREATE_ANODE_STMT, (SNode**)&pStmt); + CHECK_MAKE_NODE(pStmt); + (void)trimString(pUrl->z, pUrl->n, pStmt->url, sizeof(pStmt->url)); + return (SNode*)pStmt; +_err: + return NULL; +} + +SNode* createDropAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode) { + CHECK_PARSER_STATUS(pCxt); + SUpdateAnodeStmt* pStmt = NULL; + pCxt->errCode = nodesMakeNode(QUERY_NODE_DROP_ANODE_STMT, (SNode**)&pStmt); + CHECK_MAKE_NODE(pStmt); + if (NULL != pAnode) { + pStmt->anodeId = taosStr2Int32(pAnode->z, NULL, 10); + } else { + pStmt->anodeId = -1; + } + return (SNode*)pStmt; +_err: + return NULL; +} + +SNode* createUpdateAnodeStmt(SAstCreateContext* pCxt, const SToken* pAnode, bool updateAll) { + CHECK_PARSER_STATUS(pCxt); + SUpdateAnodeStmt* pStmt = NULL; + pCxt->errCode = nodesMakeNode(QUERY_NODE_UPDATE_ANODE_STMT, (SNode**)&pStmt); + CHECK_MAKE_NODE(pStmt); + if (NULL != pAnode) { + pStmt->anodeId = taosStr2Int32(pAnode->z, NULL, 10); + } else { + pStmt->anodeId = -1; + } + return (SNode*)pStmt; +_err: + return NULL; +} + SNode* createEncryptKeyStmt(SAstCreateContext* pCxt, const SToken* pValue) { SToken config; config.type = TK_NK_STRING; diff --git a/source/libs/parser/src/parUtil.c b/source/libs/parser/src/parUtil.c index 1ce8b04324..189afdfcd3 100644 --- a/source/libs/parser/src/parUtil.c +++ b/source/libs/parser/src/parUtil.c @@ -185,6 +185,8 @@ static char* getSyntaxErrFormat(int32_t errCode) { return "%s is not supported in system table query"; case TSDB_CODE_PAR_INVALID_INTERP_CLAUSE: return "Invalid usage of RANGE clause, EVERY clause or FILL clause"; + case TSDB_CODE_PAR_INVALID_FORECAST_CLAUSE: + return "Invalid usage of forecast clause"; case TSDB_CODE_PAR_NO_VALID_FUNC_IN_WIN: return "No valid function in window query"; case TSDB_CODE_PAR_INVALID_OPTR_USAGE: diff --git a/source/libs/planner/src/planOptimizer.c b/source/libs/planner/src/planOptimizer.c index 1bcec86385..3b4e835465 100644 --- a/source/libs/planner/src/planOptimizer.c +++ b/source/libs/planner/src/planOptimizer.c @@ -2380,6 +2380,8 @@ static bool sortPriKeyOptHasUnsupportedPkFunc(SLogicNode* pLogicNode, EOrder sor case QUERY_NODE_LOGIC_PLAN_INTERP_FUNC: pFuncList = ((SInterpFuncLogicNode*)pLogicNode)->pFuncs; break; + case QUERY_NODE_LOGIC_PLAN_FORECAST_FUNC: + pFuncList = ((SForecastFuncLogicNode*)pLogicNode)->pFuncs; default: break; } From 3ad2eb939ca965afe68a4712f196eabbaf822bfa Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 10 Oct 2024 11:54:32 +0800 Subject: [PATCH 2/4] fix: unitest error --- source/libs/function/src/builtins.c | 86 ++++++++++++++++++++++++- source/libs/function/src/builtinsimpl.c | 6 ++ 2 files changed, 91 insertions(+), 1 deletion(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 643c4bba82..86f1331e92 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -16,9 +16,10 @@ #include "builtins.h" #include "builtinsimpl.h" #include "cJSON.h" +#include "geomFunc.h" #include "querynodes.h" #include "scalar.h" -#include "geomFunc.h" +#include "tanal.h" #include "taoserror.h" #include "ttime.h" @@ -2078,6 +2079,47 @@ static int32_t translateMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return translateUniqueMode(pFunc, pErrBuf, len, false); } +static int32_t translateForecast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (2 != numOfParams && 1 != numOfParams) { + return invaildFuncParaNumErrMsg(pErrBuf, len, "FORECAST require 1 or 2 parameters"); + } + + uint8_t valType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; + if (!IS_MATHABLE_TYPE(valType)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST only support mathable column"); + } + + if (numOfParams == 2) { + uint8_t optionType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->type; + if (TSDB_DATA_TYPE_BINARY != optionType) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be varchar"); + } + + SNode* pOption = nodesListGetNode(pFunc->pParameterList, 1); + if (QUERY_NODE_VALUE != nodeType(pOption)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be value"); + } + + SValueNode* pValue = (SValueNode*)pOption; + if (!taosAnalGetOptStr(pValue->literal, "algo", NULL, 0) != 0) { + return invaildFuncParaValueErrMsg(pErrBuf, len, "FORECAST option should include algo field"); + } + + pValue->notReserved = true; + } + + pFunc->node.resType = (SDataType){.bytes = tDataTypes[valType].bytes, .type = valType}; + return TSDB_CODE_SUCCESS; +} + +static int32_t translateForecastConf(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_FLOAT].bytes, .type = TSDB_DATA_TYPE_FLOAT}; + return TSDB_CODE_SUCCESS; +} + +static EFuncReturnRows forecastEstReturnRows(SFunctionNode* pFunc) { return FUNC_RETURN_ROWS_N; } + static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); if (numOfParams > 2) { @@ -3623,6 +3665,48 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .estimateReturnRowsFunc = diffEstReturnRows, .processFuncByRow = diffFunctionByRow, }, + { + .name = "forecast", + .type = FUNCTION_TYPE_FORECAST, + .classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | + FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_SYSTABLE_FUNC | FUNC_MGT_KEEP_ORDER_FUNC | FUNC_MGT_PRIMARY_KEY_FUNC, + .translateFunc = translateForecast, + .getEnvFunc = getSelectivityFuncEnv, + .initFunc = functionSetup, + .processFunc = NULL, + .finalizeFunc = NULL, + .estimateReturnRowsFunc = forecastEstReturnRows, + }, + { + .name = "_frowts", + .type = FUNCTION_TYPE_FORECAST_ROWTS, + .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, + .translateFunc = translateTimePseudoColumn, + .getEnvFunc = getTimePseudoFuncEnv, + .initFunc = NULL, + .sprocessFunc = NULL, + .finalizeFunc = NULL + }, + { + .name = "_flow", + .type = FUNCTION_TYPE_FORECAST_LOW, + .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, + .translateFunc = translateForecastConf, + .getEnvFunc = getForecastConfEnv, + .initFunc = NULL, + .sprocessFunc = NULL, + .finalizeFunc = NULL + }, + { + .name = "_fhigh", + .type = FUNCTION_TYPE_FORECAST_HIGH, + .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, + .translateFunc = translateForecastConf, + .getEnvFunc = getForecastConfEnv, + .initFunc = NULL, + .sprocessFunc = NULL, + .finalizeFunc = NULL + }, { .name = "statecount", .type = FUNCTION_TYPE_STATE_COUNT, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 9eda9e5b57..f13685239a 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -18,6 +18,7 @@ #include "function.h" #include "query.h" #include "querynodes.h" +#include "tanal.h" #include "tcompare.h" #include "tdatablock.h" #include "tdigest.h" @@ -3578,6 +3579,11 @@ bool funcInputGetNextRowIndex(SInputColumnInfoData* pInput, int32_t from, bool f } } +bool getForecastConfEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { + pEnv->calcMemSize = sizeof(float); + return true; +} + int32_t diffResultIsNull(SqlFunctionCtx* pCtx, SFuncInputRow* pRow){ SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SDiffInfo* pDiffInfo = GET_ROWCELL_INTERBUF(pResInfo); From 43fa9b4cc776e565bfd0ef94391cf7b07826d792 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 10 Oct 2024 13:04:17 +0800 Subject: [PATCH 3/4] fix: unitest error --- source/libs/function/src/builtins.c | 86 +---------------------------- 1 file changed, 1 insertion(+), 85 deletions(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 86f1331e92..643c4bba82 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -16,10 +16,9 @@ #include "builtins.h" #include "builtinsimpl.h" #include "cJSON.h" -#include "geomFunc.h" #include "querynodes.h" #include "scalar.h" -#include "tanal.h" +#include "geomFunc.h" #include "taoserror.h" #include "ttime.h" @@ -2079,47 +2078,6 @@ static int32_t translateMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return translateUniqueMode(pFunc, pErrBuf, len, false); } -static int32_t translateForecast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); - if (2 != numOfParams && 1 != numOfParams) { - return invaildFuncParaNumErrMsg(pErrBuf, len, "FORECAST require 1 or 2 parameters"); - } - - uint8_t valType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; - if (!IS_MATHABLE_TYPE(valType)) { - return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST only support mathable column"); - } - - if (numOfParams == 2) { - uint8_t optionType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->type; - if (TSDB_DATA_TYPE_BINARY != optionType) { - return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be varchar"); - } - - SNode* pOption = nodesListGetNode(pFunc->pParameterList, 1); - if (QUERY_NODE_VALUE != nodeType(pOption)) { - return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be value"); - } - - SValueNode* pValue = (SValueNode*)pOption; - if (!taosAnalGetOptStr(pValue->literal, "algo", NULL, 0) != 0) { - return invaildFuncParaValueErrMsg(pErrBuf, len, "FORECAST option should include algo field"); - } - - pValue->notReserved = true; - } - - pFunc->node.resType = (SDataType){.bytes = tDataTypes[valType].bytes, .type = valType}; - return TSDB_CODE_SUCCESS; -} - -static int32_t translateForecastConf(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_FLOAT].bytes, .type = TSDB_DATA_TYPE_FLOAT}; - return TSDB_CODE_SUCCESS; -} - -static EFuncReturnRows forecastEstReturnRows(SFunctionNode* pFunc) { return FUNC_RETURN_ROWS_N; } - static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); if (numOfParams > 2) { @@ -3665,48 +3623,6 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .estimateReturnRowsFunc = diffEstReturnRows, .processFuncByRow = diffFunctionByRow, }, - { - .name = "forecast", - .type = FUNCTION_TYPE_FORECAST, - .classification = FUNC_MGT_TIMELINE_FUNC | FUNC_MGT_INTERVAL_INTERPO_FUNC | FUNC_MGT_IMPLICIT_TS_FUNC | - FUNC_MGT_FORBID_STREAM_FUNC | FUNC_MGT_FORBID_SYSTABLE_FUNC | FUNC_MGT_KEEP_ORDER_FUNC | FUNC_MGT_PRIMARY_KEY_FUNC, - .translateFunc = translateForecast, - .getEnvFunc = getSelectivityFuncEnv, - .initFunc = functionSetup, - .processFunc = NULL, - .finalizeFunc = NULL, - .estimateReturnRowsFunc = forecastEstReturnRows, - }, - { - .name = "_frowts", - .type = FUNCTION_TYPE_FORECAST_ROWTS, - .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, - .translateFunc = translateTimePseudoColumn, - .getEnvFunc = getTimePseudoFuncEnv, - .initFunc = NULL, - .sprocessFunc = NULL, - .finalizeFunc = NULL - }, - { - .name = "_flow", - .type = FUNCTION_TYPE_FORECAST_LOW, - .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, - .translateFunc = translateForecastConf, - .getEnvFunc = getForecastConfEnv, - .initFunc = NULL, - .sprocessFunc = NULL, - .finalizeFunc = NULL - }, - { - .name = "_fhigh", - .type = FUNCTION_TYPE_FORECAST_HIGH, - .classification = FUNC_MGT_PSEUDO_COLUMN_FUNC | FUNC_MGT_FORECAST_PC_FUNC | FUNC_MGT_KEEP_ORDER_FUNC, - .translateFunc = translateForecastConf, - .getEnvFunc = getForecastConfEnv, - .initFunc = NULL, - .sprocessFunc = NULL, - .finalizeFunc = NULL - }, { .name = "statecount", .type = FUNCTION_TYPE_STATE_COUNT, From ad61980e40efe27f4659a2c0079aeb8e86e04a08 Mon Sep 17 00:00:00 2001 From: Shengliang Guan Date: Thu, 10 Oct 2024 13:17:24 +0800 Subject: [PATCH 4/4] fix: unitest error --- source/libs/function/src/builtins.c | 44 ++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 643c4bba82..857e472ee0 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -16,9 +16,10 @@ #include "builtins.h" #include "builtinsimpl.h" #include "cJSON.h" +#include "geomFunc.h" #include "querynodes.h" #include "scalar.h" -#include "geomFunc.h" +#include "tanal.h" #include "taoserror.h" #include "ttime.h" @@ -2078,6 +2079,47 @@ static int32_t translateMode(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return translateUniqueMode(pFunc, pErrBuf, len, false); } +static int32_t translateForecast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); + if (2 != numOfParams && 1 != numOfParams) { + return invaildFuncParaNumErrMsg(pErrBuf, len, "FORECAST require 1 or 2 parameters"); + } + + uint8_t valType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; + if (!IS_MATHABLE_TYPE(valType)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST only support mathable column"); + } + + if (numOfParams == 2) { + uint8_t optionType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 1))->type; + if (TSDB_DATA_TYPE_BINARY != optionType) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be varchar"); + } + + SNode* pOption = nodesListGetNode(pFunc->pParameterList, 1); + if (QUERY_NODE_VALUE != nodeType(pOption)) { + return invaildFuncParaTypeErrMsg(pErrBuf, len, "FORECAST option should be value"); + } + + SValueNode* pValue = (SValueNode*)pOption; + if (!taosAnalGetOptStr(pValue->literal, "algo", NULL, 0) != 0) { + return invaildFuncParaValueErrMsg(pErrBuf, len, "FORECAST option should include algo field"); + } + + pValue->notReserved = true; + } + + pFunc->node.resType = (SDataType){.bytes = tDataTypes[valType].bytes, .type = valType}; + return TSDB_CODE_SUCCESS; +} + +static int32_t translateForecastConf(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { + pFunc->node.resType = (SDataType){.bytes = tDataTypes[TSDB_DATA_TYPE_FLOAT].bytes, .type = TSDB_DATA_TYPE_FLOAT}; + return TSDB_CODE_SUCCESS; +} + +static EFuncReturnRows forecastEstReturnRows(SFunctionNode* pFunc) { return FUNC_RETURN_ROWS_N; } + static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { int32_t numOfParams = LIST_LENGTH(pFunc->pParameterList); if (numOfParams > 2) {