Merge pull request #27776 from taosdata/fix/3.0/TS-5839

fix:[TS-5839] Fix crash when use last function on a column with all null value with partition subclause.
This commit is contained in:
Pan Wei 2024-09-12 09:13:23 +08:00 committed by GitHub
commit c8b087fc2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 56 additions and 16 deletions

View File

@ -110,6 +110,8 @@ typedef struct SFirstLastRes {
int32_t pkBytes;
int8_t pkType;
STuplePos pos;
STuplePos nullTuplePos;
bool nullTupleSaved;
char buf[];
} SFirstLastRes;

View File

@ -152,6 +152,7 @@ int32_t getIrateInfoSize(int32_t pkBytes);
int32_t cachedLastRowFunction(SqlFunctionCtx* pCtx);
bool getFirstLastFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv);
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResultInfo);
int32_t firstFunction(SqlFunctionCtx* pCtx);
int32_t firstFunctionMerge(SqlFunctionCtx* pCtx);
int32_t lastFunction(SqlFunctionCtx* pCtx);

View File

@ -3469,7 +3469,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = {
.translateFunc = translateFirstLast,
.dynDataRequiredFunc = lastDynDataReq,
.getEnvFunc = getFirstLastFuncEnv,
.initFunc = functionSetup,
.initFunc = firstLastFunctionSetup,
.processFunc = lastFunction,
.sprocessFunc = firstLastScalarFunction,
.finalizeFunc = firstLastFinalize,

View File

@ -2617,6 +2617,22 @@ static FORCE_INLINE TSKEY getRowPTs(SColumnInfoData* pTsColInfo, int32_t rowInde
return *(TSKEY*)colDataGetData(pTsColInfo, rowIndex);
}
int32_t firstLastFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) {
if (pResInfo->initialized) {
return TSDB_CODE_SUCCESS;
}
if (TSDB_CODE_SUCCESS != functionSetup(pCtx, pResInfo)) {
return TSDB_CODE_FUNC_SETUP_ERROR;
}
SFirstLastRes * pRes = GET_ROWCELL_INTERBUF(pResInfo);
SInputColumnInfoData* pInput = &pCtx->input;
pRes->nullTupleSaved = false;
pRes->nullTuplePos.pageId = -1;
return TSDB_CODE_SUCCESS;
}
static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
if (pCtx->subsidiaries.rowLen == 0) {
int32_t rowLen = 0;
@ -2635,7 +2651,7 @@ static int32_t prepareBuf(SqlFunctionCtx* pCtx) {
}
static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowIndex, SqlFunctionCtx* pCtx,
SFirstLastRes* pInfo) {
SFirstLastRes* pInfo, bool noElements) {
int32_t code = TSDB_CODE_SUCCESS;
if (pCtx->subsidiaries.num <= 0) {
@ -2643,7 +2659,7 @@ static int32_t firstlastSaveTupleData(const SSDataBlock* pSrcBlock, int32_t rowI
}
if (!pInfo->hasResult) {
code = saveTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
code = saveTupleData(pCtx, rowIndex, pSrcBlock, noElements ? &pInfo->nullTuplePos : &pInfo->pos);
} else {
code = updateTupleData(pCtx, rowIndex, pSrcBlock, &pInfo->pos);
}
@ -2669,7 +2685,7 @@ static int32_t doSaveCurrentVal(SqlFunctionCtx* pCtx, int32_t rowIndex, int64_t
}
pInfo->ts = currentTs;
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
@ -2708,10 +2724,11 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) {
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
pInputCol->hasNull == true) {
// save selectivity value for column consisted of all null values
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pInfo->nullTupleSaved = true;
return TSDB_CODE_SUCCESS;
}
@ -2802,10 +2819,11 @@ int32_t firstFunction(SqlFunctionCtx* pCtx) {
if (numOfElems == 0) {
// save selectivity value for column consisted of all null values
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pInfo->nullTupleSaved = true;
}
SET_VAL(pResInfo, numOfElems, 1);
return TSDB_CODE_SUCCESS;
@ -2841,10 +2859,11 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
if (pInput->colDataSMAIsSet && (pInput->pColumnDataAgg[0]->numOfNull == pInput->totalRows) &&
pInputCol->hasNull == true) {
// save selectivity value for column consisted of all null values
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pInfo->nullTupleSaved = true;
return TSDB_CODE_SUCCESS;
}
@ -2983,10 +3002,11 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) {
// save selectivity value for column consisted of all null values
if (numOfElems == 0) {
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pInfo->nullTupleSaved = true;
}
return TSDB_CODE_SUCCESS;
@ -3031,7 +3051,7 @@ static bool firstLastTransferInfoImpl(SFirstLastRes* pInput, SFirstLastRes* pOut
static int32_t firstLastTransferInfo(SqlFunctionCtx* pCtx, SFirstLastRes* pInput, SFirstLastRes* pOutput, bool isFirst,
int32_t rowIndex) {
if (firstLastTransferInfoImpl(pInput, pOutput, isFirst)) {
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pOutput, pOutput->nullTupleSaved);
if (TSDB_CODE_SUCCESS != code) {
return code;
}
@ -3079,6 +3099,14 @@ static int32_t firstLastFunctionMergeImpl(SqlFunctionCtx* pCtx, bool isFirstQuer
}
}
if (numOfElems == 0) {
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, pInput->startRowIndex, pCtx, pInfo, !pInfo->nullTupleSaved);
if (code != TSDB_CODE_SUCCESS) {
return code;
}
pInfo->nullTupleSaved = true;
}
SET_VAL(GET_RES_INFO(pCtx), numOfElems, 1);
return TSDB_CODE_SUCCESS;
}
@ -3099,6 +3127,11 @@ int32_t firstLastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0;
SFirstLastRes* pRes = GET_ROWCELL_INTERBUF(pResInfo);
if (pResInfo->isNullRes) {
colDataSetNULL(pCol, pBlock->info.rows);
return setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
}
code = colDataSetVal(pCol, pBlock->info.rows, pRes->buf, pRes->isNull || pResInfo->isNullRes);
if (TSDB_CODE_SUCCESS != code) {
return code;
@ -3134,12 +3167,16 @@ int32_t firstLastPartialFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) {
return TSDB_CODE_OUT_OF_RANGE;
}
code = colDataSetVal(pCol, pBlock->info.rows, res, false);
if (TSDB_CODE_SUCCESS != code) {
return TSDB_CODE_OUT_OF_MEMORY;
if (pEntryInfo->numOfRes == 0) {
colDataSetNULL(pCol, pBlock->info.rows);
code = setSelectivityValue(pCtx, pBlock, &pRes->nullTuplePos, pBlock->info.rows);
} else {
code = colDataSetVal(pCol, pBlock->info.rows, res, false);
if (TSDB_CODE_SUCCESS != code) {
return TSDB_CODE_OUT_OF_MEMORY;
}
code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
}
code = setSelectivityValue(pCtx, pBlock, &pRes->pos, pBlock->info.rows);
taosMemoryFree(res);
return code;
}
@ -3185,7 +3222,7 @@ static int32_t doSaveLastrow(SqlFunctionCtx* pCtx, char* pData, int32_t rowIndex
pInfo->pkData = pInfo->buf + pInfo->bytes;
}
pInfo->ts = cts;
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo);
int32_t code = firstlastSaveTupleData(pCtx->pSrcBlock, rowIndex, pCtx, pInfo, false);
if (code != TSDB_CODE_SUCCESS) {
return code;
}

View File

@ -89,7 +89,7 @@ if $data10 != @ -> Merge (columns=3 width=24 input_order=unknown output_order=
return -1
endi
sql explain select count(*), last_row(f1), min(f1) from sta interval(1s);
if $data10 != @ -> Merge (columns=4 width=82 input_order=asc output_order=asc mode=sort)@ then
if $data10 != @ -> Merge (columns=4 width=106 input_order=asc output_order=asc mode=sort)@ then
return -1
endi
sql explain select distinct count(*), last_row(f1), min(f1) from tba1;