From a3bebe896650b238ae0bc00295476771ed1f6d55 Mon Sep 17 00:00:00 2001 From: sima Date: Wed, 21 Aug 2024 10:01:32 +0800 Subject: [PATCH] fix:[TD-31571] fix CONCAT function to return NULL when all input parameters are NULL Previously, the CONCAT function did not correctly handle cases where all input parameters were NULL, resulting in an unexpected output. This commit ensures that CONCAT returns NULL when all input arguments are NULL, aligning with expected SQL behavior. --- source/libs/scalar/src/sclfunc.c | 59 +++++++++++++------------------- 1 file changed, 23 insertions(+), 36 deletions(-) diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 12f0137fc5..477a768ccf 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -860,31 +860,27 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu int32_t numOfRows = 0; bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false; for (int32_t i = 0; i < inputNum; ++i) { - if (pInput[i].numOfRows > numOfRows) { - numOfRows = pInput[i].numOfRows; - } + numOfRows = TMAX(pInput[i].numOfRows, numOfRows); } + int32_t outputLen = VARSTR_HEADER_SIZE; for (int32_t i = 0; i < inputNum; ++i) { + if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) { + colDataSetNNULL(pOutputData, 0, numOfRows); + pOutput->numOfRows = numOfRows; + goto _return; + } pInputData[i] = pInput[i].columnData; int32_t factor = 1; if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { factor = TSDB_NCHAR_SIZE; } - - int32_t numOfNulls = getNumOfNullEntries(pInputData[i], pInput[i].numOfRows); - if (pInput[i].numOfRows == 1) { - inputLen += (pInputData[i]->varmeta.length - VARSTR_HEADER_SIZE) * factor * (numOfRows - numOfNulls); - } else { - inputLen += (pInputData[i]->varmeta.length - (numOfRows - numOfNulls) * VARSTR_HEADER_SIZE) * factor; - } + outputLen += pInputData[i]->info.bytes * factor; } - int32_t outputLen = inputLen + numOfRows * VARSTR_HEADER_SIZE; outputBuf = taosMemoryCalloc(outputLen, 1); if (NULL == outputBuf) { SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } - char *output = outputBuf; for (int32_t k = 0; k < numOfRows; ++k) { bool hasNull = false; @@ -901,6 +897,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu } VarDataLenT dataLen = 0; + char *output = outputBuf; for (int32_t i = 0; i < inputNum; ++i) { int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k; input[i] = colDataGetData(pInputData[i], rowIdx); @@ -908,8 +905,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu SCL_ERR_JRET(concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen)); } varDataSetLen(output, dataLen); - SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false)); - output += varDataTLen(output); + SCL_ERR_JRET(colDataSetVal(pOutputData, k, outputBuf, false)); } pOutput->numOfRows = numOfRows; @@ -926,51 +922,44 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p int32_t code = TSDB_CODE_SUCCESS; SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *)); SColumnInfoData *pOutputData = pOutput->columnData; - char **input = taosMemoryCalloc(inputNum, POINTER_BYTES); char *outputBuf = NULL; if (NULL == pInputData) { SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } - if (NULL == input) { - SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); - } int32_t inputLen = 0; int32_t numOfRows = 0; bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false; - for (int32_t i = 1; i < inputNum; ++i) { - if (pInput[i].numOfRows > numOfRows) { - numOfRows = pInput[i].numOfRows; - } - } for (int32_t i = 0; i < inputNum; ++i) { + numOfRows = TMAX(pInput[i].numOfRows, numOfRows); + } + int32_t outputLen = VARSTR_HEADER_SIZE; + for (int32_t i = 0; i < inputNum; ++i) { + if (IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) { + colDataSetNNULL(pOutputData, 0, numOfRows); + pOutput->numOfRows = numOfRows; + goto _return; + } pInputData[i] = pInput[i].columnData; int32_t factor = 1; if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) { factor = TSDB_NCHAR_SIZE; } - int32_t numOfNulls = getNumOfNullEntries(pInputData[i], pInput[i].numOfRows); if (i == 0) { // calculate required separator space - inputLen += - (pInputData[0]->varmeta.length - VARSTR_HEADER_SIZE) * (numOfRows - numOfNulls) * (inputNum - 2) * factor; - } else if (pInput[i].numOfRows == 1) { - inputLen += (pInputData[i]->varmeta.length - VARSTR_HEADER_SIZE) * (numOfRows - numOfNulls) * factor; + outputLen += pInputData[i]->info.bytes * factor * (inputNum - 2); } else { - inputLen += (pInputData[i]->varmeta.length - (numOfRows - numOfNulls) * VARSTR_HEADER_SIZE) * factor; + outputLen += pInputData[i]->info.bytes * factor; } } - int32_t outputLen = inputLen + numOfRows * VARSTR_HEADER_SIZE; outputBuf = taosMemoryCalloc(outputLen, 1); if (NULL == outputBuf) { SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY); } - char *output = outputBuf; - for (int32_t k = 0; k < numOfRows; ++k) { if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) { colDataSetNULL(pOutputData, k); @@ -979,6 +968,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p VarDataLenT dataLen = 0; bool hasNull = false; + char *output = outputBuf; for (int32_t i = 1; i < inputNum; ++i) { if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) { hasNull = true; @@ -986,9 +976,8 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k; - input[i] = colDataGetData(pInputData[i], rowIdx); - SCL_ERR_JRET(concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen)); + SCL_ERR_JRET(concatCopyHelper(colDataGetData(pInputData[i], rowIdx), output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen)); if (i < inputNum - 1) { // insert the separator @@ -1003,14 +992,12 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p } else { varDataSetLen(output, dataLen); SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false)); - output += varDataTLen(output); } } pOutput->numOfRows = numOfRows; _return: - taosMemoryFree(input); taosMemoryFree(outputBuf); taosMemoryFree(pInputData);