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:
parent
641fccaa93
commit
a3bebe8966
|
@ -860,31 +860,27 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu
|
||||||
int32_t numOfRows = 0;
|
int32_t numOfRows = 0;
|
||||||
bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
|
bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
|
||||||
for (int32_t i = 0; i < inputNum; ++i) {
|
for (int32_t i = 0; i < inputNum; ++i) {
|
||||||
if (pInput[i].numOfRows > numOfRows) {
|
numOfRows = TMAX(pInput[i].numOfRows, numOfRows);
|
||||||
numOfRows = pInput[i].numOfRows;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
int32_t outputLen = VARSTR_HEADER_SIZE;
|
||||||
for (int32_t i = 0; i < inputNum; ++i) {
|
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;
|
pInputData[i] = pInput[i].columnData;
|
||||||
int32_t factor = 1;
|
int32_t factor = 1;
|
||||||
if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
|
if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
|
||||||
factor = TSDB_NCHAR_SIZE;
|
factor = TSDB_NCHAR_SIZE;
|
||||||
}
|
}
|
||||||
|
outputLen += pInputData[i]->info.bytes * factor;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t outputLen = inputLen + numOfRows * VARSTR_HEADER_SIZE;
|
|
||||||
outputBuf = taosMemoryCalloc(outputLen, 1);
|
outputBuf = taosMemoryCalloc(outputLen, 1);
|
||||||
if (NULL == outputBuf) {
|
if (NULL == outputBuf) {
|
||||||
SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
|
SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
char *output = outputBuf;
|
|
||||||
|
|
||||||
for (int32_t k = 0; k < numOfRows; ++k) {
|
for (int32_t k = 0; k < numOfRows; ++k) {
|
||||||
bool hasNull = false;
|
bool hasNull = false;
|
||||||
|
@ -901,6 +897,7 @@ int32_t concatFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOu
|
||||||
}
|
}
|
||||||
|
|
||||||
VarDataLenT dataLen = 0;
|
VarDataLenT dataLen = 0;
|
||||||
|
char *output = outputBuf;
|
||||||
for (int32_t i = 0; i < inputNum; ++i) {
|
for (int32_t i = 0; i < inputNum; ++i) {
|
||||||
int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
|
int32_t rowIdx = (pInput[i].numOfRows == 1) ? 0 : k;
|
||||||
input[i] = colDataGetData(pInputData[i], rowIdx);
|
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));
|
SCL_ERR_JRET(concatCopyHelper(input[i], output, hasNchar, GET_PARAM_TYPE(&pInput[i]), &dataLen));
|
||||||
}
|
}
|
||||||
varDataSetLen(output, dataLen);
|
varDataSetLen(output, dataLen);
|
||||||
SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
|
SCL_ERR_JRET(colDataSetVal(pOutputData, k, outputBuf, false));
|
||||||
output += varDataTLen(output);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pOutput->numOfRows = numOfRows;
|
pOutput->numOfRows = numOfRows;
|
||||||
|
@ -926,51 +922,44 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
|
||||||
int32_t code = TSDB_CODE_SUCCESS;
|
int32_t code = TSDB_CODE_SUCCESS;
|
||||||
SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
|
SColumnInfoData **pInputData = taosMemoryCalloc(inputNum, sizeof(SColumnInfoData *));
|
||||||
SColumnInfoData *pOutputData = pOutput->columnData;
|
SColumnInfoData *pOutputData = pOutput->columnData;
|
||||||
char **input = taosMemoryCalloc(inputNum, POINTER_BYTES);
|
|
||||||
char *outputBuf = NULL;
|
char *outputBuf = NULL;
|
||||||
|
|
||||||
if (NULL == pInputData) {
|
if (NULL == pInputData) {
|
||||||
SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
|
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 inputLen = 0;
|
||||||
int32_t numOfRows = 0;
|
int32_t numOfRows = 0;
|
||||||
bool hasNchar = (GET_PARAM_TYPE(pOutput) == TSDB_DATA_TYPE_NCHAR) ? true : false;
|
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) {
|
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;
|
pInputData[i] = pInput[i].columnData;
|
||||||
int32_t factor = 1;
|
int32_t factor = 1;
|
||||||
if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
|
if (hasNchar && (GET_PARAM_TYPE(&pInput[i]) == TSDB_DATA_TYPE_VARCHAR)) {
|
||||||
factor = TSDB_NCHAR_SIZE;
|
factor = TSDB_NCHAR_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t numOfNulls = getNumOfNullEntries(pInputData[i], pInput[i].numOfRows);
|
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
// calculate required separator space
|
// calculate required separator space
|
||||||
inputLen +=
|
outputLen += pInputData[i]->info.bytes * factor * (inputNum - 2);
|
||||||
(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;
|
|
||||||
} else {
|
} 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);
|
outputBuf = taosMemoryCalloc(outputLen, 1);
|
||||||
if (NULL == outputBuf) {
|
if (NULL == outputBuf) {
|
||||||
SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
|
SCL_ERR_JRET(TSDB_CODE_OUT_OF_MEMORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *output = outputBuf;
|
|
||||||
|
|
||||||
for (int32_t k = 0; k < numOfRows; ++k) {
|
for (int32_t k = 0; k < numOfRows; ++k) {
|
||||||
if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) {
|
if (colDataIsNull_s(pInputData[0], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[0]))) {
|
||||||
colDataSetNULL(pOutputData, k);
|
colDataSetNULL(pOutputData, k);
|
||||||
|
@ -979,6 +968,7 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
|
||||||
|
|
||||||
VarDataLenT dataLen = 0;
|
VarDataLenT dataLen = 0;
|
||||||
bool hasNull = false;
|
bool hasNull = false;
|
||||||
|
char *output = outputBuf;
|
||||||
for (int32_t i = 1; i < inputNum; ++i) {
|
for (int32_t i = 1; i < inputNum; ++i) {
|
||||||
if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
|
if (colDataIsNull_s(pInputData[i], k) || IS_NULL_TYPE(GET_PARAM_TYPE(&pInput[i]))) {
|
||||||
hasNull = true;
|
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;
|
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) {
|
if (i < inputNum - 1) {
|
||||||
// insert the separator
|
// insert the separator
|
||||||
|
@ -1003,14 +992,12 @@ int32_t concatWsFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *p
|
||||||
} else {
|
} else {
|
||||||
varDataSetLen(output, dataLen);
|
varDataSetLen(output, dataLen);
|
||||||
SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
|
SCL_ERR_JRET(colDataSetVal(pOutputData, k, output, false));
|
||||||
output += varDataTLen(output);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pOutput->numOfRows = numOfRows;
|
pOutput->numOfRows = numOfRows;
|
||||||
|
|
||||||
_return:
|
_return:
|
||||||
taosMemoryFree(input);
|
|
||||||
taosMemoryFree(outputBuf);
|
taosMemoryFree(outputBuf);
|
||||||
taosMemoryFree(pInputData);
|
taosMemoryFree(pInputData);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue