From 11028921b6e83e61c28585434b8f67c1e0d2a9d6 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 19 Apr 2022 18:16:29 +0800 Subject: [PATCH 1/4] refactor(query): refactor cast function TD-14837 TD-14843 TD-14904 --- include/util/taoserror.h | 1 + source/libs/function/src/builtins.c | 15 ++++++++++++--- source/libs/scalar/src/scalar.c | 3 +++ source/libs/scalar/src/sclfunc.c | 12 ++++++------ 4 files changed, 22 insertions(+), 9 deletions(-) diff --git a/include/util/taoserror.h b/include/util/taoserror.h index c5b477343d..6c5e006671 100644 --- a/include/util/taoserror.h +++ b/include/util/taoserror.h @@ -617,6 +617,7 @@ int32_t* taosGetErrno(); #define TSDB_CODE_FUNC_FUNTION_ERROR TAOS_DEF_ERROR_CODE(0, 0x2800) #define TSDB_CODE_FUNC_FUNTION_PARA_NUM TAOS_DEF_ERROR_CODE(0, 0x2801) #define TSDB_CODE_FUNC_FUNTION_PARA_TYPE TAOS_DEF_ERROR_CODE(0, 0x2802) +#define TSDB_CODE_FUNC_FUNTION_PARA_VALUE TAOS_DEF_ERROR_CODE(0, 0x2803) #ifdef __cplusplus } diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 78dec26be5..5ba0cee53e 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -28,13 +28,17 @@ static int32_t buildFuncErrMsg(char* pErrBuf, int32_t len, int32_t errCode, cons } static int32_t invaildFuncParaNumErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) { - return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_NUM, "Invalid number of arguments : %s", pFuncName); + return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_NUM, "Invalid number of parameters : %s", pFuncName); } static int32_t invaildFuncParaTypeErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) { return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_TYPE, "Inconsistent datatypes : %s", pFuncName); } +static int32_t invaildFuncParaValueErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) { + return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_VALUE, "Invalid parameter value : %s", pFuncName); +} + // There is only one parameter of numeric type, and the return type is parameter type static int32_t translateInOutNum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { if (1 != LIST_LENGTH(pFunc->pParameterList)) { @@ -317,10 +321,15 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { uint8_t para1Type = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; // The function return type has been set during syntax parsing uint8_t para2Type = pFunc->node.resType.type; - if ((TSDB_DATA_TYPE_JSON == para1Type || TSDB_DATA_TYPE_BLOB == para1Type || TSDB_DATA_TYPE_MEDIUMBLOB == para1Type) || - (TSDB_DATA_TYPE_JSON == para2Type || TSDB_DATA_TYPE_BLOB == para2Type || TSDB_DATA_TYPE_MEDIUMBLOB == para2Type)) { + if (para2Type != TSDB_DATA_TYPE_BIGINT && para2Type != TSDB_DATA_TYPE_UBIGINT && + para2Type != TSDB_DATA_TYPE_VARCHAR && para2Type != TSDB_DATA_TYPE_NCHAR && + para2Type != TSDB_DATA_TYPE_TIMESTAMP) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } + int32_t para2Bytes = pFunc->node.resType.bytes; + if (para2Bytes < 0) { //negative value or overflow + return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName); + } return TSDB_CODE_SUCCESS; } diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index 0432ae1df8..e6de165ab5 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -444,6 +444,9 @@ EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) { res->node.resType.type = TSDB_DATA_TYPE_NULL; } else { res->node.resType = node->node.resType; + if (res->node.resType.type == TSDB_DATA_TYPE_NCHAR) { + res->node.resType.bytes *= TSDB_NCHAR_SIZE; + } int32_t type = output.columnData->info.type; if (IS_VAR_DATA_TYPE(type)) { res->datum.p = output.columnData->pData; diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index e7ff0bde91..995d38e9b7 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -646,13 +646,13 @@ int32_t substrFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { int16_t inputType = pInput[0].columnData->info.type; int16_t outputType = pOutput[0].columnData->info.type; - if (outputType != TSDB_DATA_TYPE_BIGINT && outputType != TSDB_DATA_TYPE_UBIGINT && - outputType != TSDB_DATA_TYPE_VARCHAR && outputType != TSDB_DATA_TYPE_NCHAR && - outputType != TSDB_DATA_TYPE_TIMESTAMP) { - return TSDB_CODE_FAILED; - } int64_t outputLen = pOutput[0].columnData->info.bytes; + if (IS_VAR_DATA_TYPE(outputType)) { + int32_t factor = (TSDB_DATA_TYPE_NCHAR == outputType) ? TSDB_NCHAR_SIZE : 1; + outputLen = outputLen * factor + VARSTR_HEADER_SIZE; + } + char *input = NULL; char *outputBuf = taosMemoryCalloc(outputLen * pInput[0].numOfRows, 1); char *output = outputBuf; @@ -723,7 +723,7 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp } else if (inputType == TSDB_DATA_TYPE_BINARY) { int32_t len = sprintf(varDataVal(output), "%.*s", (int32_t)(outputLen - VARSTR_HEADER_SIZE), varDataVal(input)); varDataSetLen(output, len); - } else if (inputType == TSDB_DATA_TYPE_BINARY || inputType == TSDB_DATA_TYPE_NCHAR) { + } else if (inputType == TSDB_DATA_TYPE_NCHAR) { //not support return TSDB_CODE_FAILED; } else { From 482afcf2880413d903495080ceb43564aef9feda Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 19 Apr 2022 18:16:29 +0800 Subject: [PATCH 2/4] refactor(query): refactor cast function TD-14837 TD-14843 TD-14904 --- source/libs/scalar/src/scalar.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/source/libs/scalar/src/scalar.c b/source/libs/scalar/src/scalar.c index e6de165ab5..0432ae1df8 100644 --- a/source/libs/scalar/src/scalar.c +++ b/source/libs/scalar/src/scalar.c @@ -444,9 +444,6 @@ EDealRes sclRewriteFunction(SNode** pNode, SScalarCtx *ctx) { res->node.resType.type = TSDB_DATA_TYPE_NULL; } else { res->node.resType = node->node.resType; - if (res->node.resType.type == TSDB_DATA_TYPE_NCHAR) { - res->node.resType.bytes *= TSDB_NCHAR_SIZE; - } int32_t type = output.columnData->info.type; if (IS_VAR_DATA_TYPE(type)) { res->datum.p = output.columnData->pData; From f9947be46f603b323763c815bc445cb33e02146c Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 19 Apr 2022 18:16:29 +0800 Subject: [PATCH 3/4] refactor(query): refactor cast function TD-14837 TD-14843 TD-14904 --- source/libs/function/src/builtins.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 5ba0cee53e..4403ff1540 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -32,7 +32,7 @@ static int32_t invaildFuncParaNumErrMsg(char* pErrBuf, int32_t len, const char* } static int32_t invaildFuncParaTypeErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) { - return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_TYPE, "Inconsistent datatypes : %s", pFuncName); + return buildFuncErrMsg(pErrBuf, len, TSDB_CODE_FUNC_FUNTION_PARA_TYPE, "Invalid datatypes : %s", pFuncName); } static int32_t invaildFuncParaValueErrMsg(char* pErrBuf, int32_t len, const char* pFuncName) { @@ -327,7 +327,7 @@ static int32_t translateCast(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } int32_t para2Bytes = pFunc->node.resType.bytes; - if (para2Bytes < 0) { //negative value or overflow + if (para2Bytes <= 0) { //non-positive value or overflow return invaildFuncParaValueErrMsg(pErrBuf, len, pFunc->functionName); } return TSDB_CODE_SUCCESS; From f53db3d3b97d7ca5ad9e00124574d795c5a98cc3 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Tue, 19 Apr 2022 20:40:45 +0800 Subject: [PATCH 4/4] fix(query): fix cast function NULL value handling logic --- source/libs/scalar/src/sclfunc.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 995d38e9b7..baa99b7c1e 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -653,20 +653,15 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp outputLen = outputLen * factor + VARSTR_HEADER_SIZE; } - char *input = NULL; char *outputBuf = taosMemoryCalloc(outputLen * pInput[0].numOfRows, 1); char *output = outputBuf; - if (IS_VAR_DATA_TYPE(inputType)) { - input = pInput[0].columnData->pData + pInput[0].columnData->varmeta.offset[0]; - } else { - input = pInput[0].columnData->pData; - } for (int32_t i = 0; i < pInput[0].numOfRows; ++i) { if (colDataIsNull_s(pInput[0].columnData, i)) { colDataAppendNULL(pOutput->columnData, i); continue; } + char *input = colDataGetData(pInput[0].columnData, i); switch(outputType) { case TSDB_DATA_TYPE_BIGINT: { @@ -776,11 +771,6 @@ int32_t castFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutp } colDataAppend(pOutput->columnData, i, output, false); - if (IS_VAR_DATA_TYPE(inputType)) { - input += varDataTLen(input); - } else { - input += tDataTypes[inputType].bytes; - } if (IS_VAR_DATA_TYPE(outputType)) { output += varDataTLen(output); } else {