diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index d5242a46f5..ed8cb6c21f 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -237,33 +237,45 @@ static int32_t translateLength(SFunctionNode* pFunc, char* pErrBuf, int32_t len) return TSDB_CODE_SUCCESS; } -static int32_t translateConcatImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len, int32_t minParaNum, int32_t maxParaNum, int32_t primaryParaNo) { +static int32_t translateConcatImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t len, int32_t minParaNum, int32_t maxParaNum, bool hasSep) { int32_t paraNum = LIST_LENGTH(pFunc->pParameterList); if (paraNum < minParaNum || paraNum > maxParaNum) { return invaildFuncParaNumErrMsg(pErrBuf, len, pFunc->functionName); } - uint8_t resultType = TSDB_DATA_TYPE_NCHAR; + uint8_t resultType = TSDB_DATA_TYPE_BINARY; int32_t resultBytes = 0; int32_t sepBytes = 0; - for (int32_t i = 0; i < LIST_LENGTH(pFunc->pParameterList); ++i) { + + /* For concat/concat_ws function, if params have NCHAR type, promote the final result to NCHAR */ + for (int32_t i = 0; i < paraNum; ++i) { SNode* pPara = nodesListGetNode(pFunc->pParameterList, i); uint8_t paraType = ((SExprNode*)pPara)->resType.type; - int32_t paraBytes = ((SExprNode*)pPara)->resType.bytes; if (!IS_VAR_DATA_TYPE(paraType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } - if (i < primaryParaNo) { - sepBytes = paraBytes; - continue; + if (TSDB_DATA_TYPE_NCHAR == paraType) { + resultType = paraType; } - if (TSDB_DATA_TYPE_BINARY == paraType) { - resultType = TSDB_DATA_TYPE_BINARY; - } - resultBytes += paraBytes; } - if (sepBytes > 0) { - resultBytes += sepBytes * (paraNum - 2); + + for (int32_t i = 0; i < paraNum; ++i) { + SNode* pPara = nodesListGetNode(pFunc->pParameterList, i); + uint8_t paraType = ((SExprNode*)pPara)->resType.type; + int32_t paraBytes = ((SExprNode*)pPara)->resType.bytes; + int32_t factor = 1; + if (TSDB_DATA_TYPE_NCHAR == resultType && TSDB_DATA_TYPE_VARCHAR == paraType) { + factor *= TSDB_NCHAR_SIZE; + } + resultBytes += paraBytes * factor; + + if (i == 0) { + sepBytes = paraBytes * factor; + } + } + + if (hasSep) { + resultBytes += sepBytes * (paraNum - 3); } pFunc->node.resType = (SDataType) { .bytes = resultBytes, .type = resultType }; @@ -271,11 +283,11 @@ static int32_t translateConcatImpl(SFunctionNode* pFunc, char* pErrBuf, int32_t } static int32_t translateConcat(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - return translateConcatImpl(pFunc, pErrBuf, len, 2, 8, 0); + return translateConcatImpl(pFunc, pErrBuf, len, 2, 8, false); } static int32_t translateConcatWs(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { - return translateConcatImpl(pFunc, pErrBuf, len, 3, 9, 1); + return translateConcatImpl(pFunc, pErrBuf, len, 3, 9, true); } static int32_t translateSubstr(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { diff --git a/source/libs/nodes/src/nodesUtilFuncs.c b/source/libs/nodes/src/nodesUtilFuncs.c index 758f9d5d6f..d4457a056e 100644 --- a/source/libs/nodes/src/nodesUtilFuncs.c +++ b/source/libs/nodes/src/nodesUtilFuncs.c @@ -1226,7 +1226,7 @@ void valueNodeToVariant(const SValueNode* pNode, SVariant* pVal) { case TSDB_DATA_TYPE_NCHAR: case TSDB_DATA_TYPE_VARCHAR: case TSDB_DATA_TYPE_VARBINARY: - pVal->pz = pNode->datum.p + VARSTR_HEADER_SIZE; + pVal->pz = pNode->datum.p; break; case TSDB_DATA_TYPE_JSON: case TSDB_DATA_TYPE_DECIMAL: diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index dc71829e3d..4c00dbad34 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -313,8 +313,8 @@ static int32_t doLengthFunction(SScalarParam *pInput, int32_t inputNum, SScalarP return TSDB_CODE_SUCCESS; } -static int32_t concatCopyHelper(const char *input, char *output, bool hasNcharCol, int32_t type, int16_t *dataLen) { - if (hasNcharCol && type == TSDB_DATA_TYPE_VARCHAR) { +static int32_t concatCopyHelper(const char *input, char *output, bool hasNchar, int32_t type, int16_t *dataLen) { + if (hasNchar && type == TSDB_DATA_TYPE_VARCHAR) { TdUcs4 *newBuf = taosMemoryCalloc((varDataLen(input) + 1) * TSDB_NCHAR_SIZE, 1); bool ret = taosMbsToUcs4(varDataVal(input), varDataLen(input), newBuf, (varDataLen(input) + 1) * TSDB_NCHAR_SIZE, NULL); if (!ret) { @@ -345,10 +345,6 @@ static int32_t getNumOfNullEntries(SColumnInfoData *pColumnInfoData, int32_t num } int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - if (inputNum < 2 || inputNum > 8) { // concat accpet 2-8 input strings - return TSDB_CODE_FAILED; - } - SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *)); SColumnInfoData *pOutputData = pOutput->columnData; char **input = taosMemoryCalloc(inputNum, POINTER_BYTES); @@ -356,15 +352,8 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu int32_t inputLen = 0; int32_t numOfRows = 0; - bool hasNcharCol = false; + bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false; for (int32_t i = 0; i < inputNum; ++i) { - int32_t type = GET_PARAM_TYPE(&pInput[i]); - if (!IS_VAR_DATA_TYPE(type)) { - return TSDB_CODE_FAILED; - } - if (type == TSDB_DATA_TYPE_NCHAR) { - hasNcharCol = true; - } if (pInput[i].numOfRows > numOfRows) { numOfRows = pInput[i].numOfRows; } @@ -373,7 +362,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu pInputData[i] = pInput[i].columnData; input[i] = pInputData[i]->pData + pInputData[i]->varmeta.offset[0]; int32_t factor = 1; - if (hasNcharCol && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { + if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { factor = TSDB_NCHAR_SIZE; } @@ -405,7 +394,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu int16_t dataLen = 0; for (int32_t i = 0; i < inputNum; ++i) { - int32_t ret = concatCopyHelper(input[i], output, hasNcharCol, GET_PARAM_TYPE(&pInput[i]), &dataLen); + int32_t ret = concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen); if (ret != TSDB_CODE_SUCCESS) { return ret; } @@ -428,10 +417,6 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { - if (inputNum < 3 || inputNum > 9) { // concat accpet 3-9 input strings including the separator - return TSDB_CODE_FAILED; - } - SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *)); SColumnInfoData *pOutputData = pOutput->columnData; char **input = taosMemoryCalloc(inputNum, POINTER_BYTES); @@ -439,15 +424,8 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p int32_t inputLen = 0; int32_t numOfRows = 0; - bool hasNcharCol = false; + bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false; for (int32_t i = 1; i < inputNum; ++i) { - int32_t type = GET_PARAM_TYPE(&pInput[i]); - if (!IS_VAR_DATA_TYPE(GET_PARAM_TYPE(&pInput[i]))) { - return TSDB_CODE_FAILED; - } - if (type == TSDB_DATA_TYPE_NCHAR) { - hasNcharCol = true; - } if (pInput[i].numOfRows > numOfRows) { numOfRows = pInput[i].numOfRows; } @@ -456,7 +434,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p pInputData[i] = pInput[i].columnData; input[i] = pInputData[i]->pData + pInputData[i]->varmeta.offset[0]; int32_t factor = 1; - if (hasNcharCol && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { + if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { factor = TSDB_NCHAR_SIZE; } @@ -487,7 +465,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p continue; } - int32_t ret = concatCopyHelper(input[i], output, hasNcharCol, GET_PARAM_TYPE(&pInput[i]), &dataLen); + int32_t ret = concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen); if (ret != TSDB_CODE_SUCCESS) { return ret; } @@ -499,7 +477,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p if (i < inputNum - 1) { //insert the separator char *sep = pInputData[0]->pData; - int32_t ret = concatCopyHelper(sep, output, hasNcharCol, GET_PARAM_TYPE(&pInput[0]), &dataLen); + int32_t ret = concatCopyHelper(sep, output, hasNchar, GET_PARAM_TYPE(&pInput[0]), &dataLen); if (ret != TSDB_CODE_SUCCESS) { return ret; }