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.
This commit is contained in:
sima 2024-08-21 10:01:32 +08:00 committed by Jing Sima
parent 641fccaa93
commit a3bebe8966
1 changed files with 23 additions and 36 deletions

View File

@ -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);