diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 9a9e0776ce71b236ef3abe4b1fbeb69815d57904..bc003a3024d53df0acfa05a642236afad1ac5a33 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -225,6 +225,7 @@ typedef struct SUniqueInfo { int32_t numOfPoints; uint8_t colType; int16_t colBytes; + bool hasNull; //null is not hashable, handle separately SHashObj *pHash; char pItems[]; } SUniqueInfo; @@ -3860,6 +3861,7 @@ bool uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) { pInfo->numOfPoints = 0; pInfo->colType = pCtx->resDataInfo.type; pInfo->colBytes = pCtx->resDataInfo.bytes; + pInfo->hasNull = false; if (pInfo->pHash != NULL) { taosHashClear(pInfo->pHash); } else { @@ -3869,8 +3871,22 @@ bool uniqueFunctionSetup(SqlFunctionCtx* pCtx, SResultRowEntryInfo* pResInfo) { } static void doUniqueAdd(SUniqueInfo* pInfo, char *data, TSKEY ts, bool isNull) { - int32_t hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes; + //handle null elements + if (isNull == true) { + int32_t size = sizeof(SUniqueItem) + pInfo->colBytes; + SUniqueItem *pItem = (SUniqueItem *)(pInfo->pItems + pInfo->numOfPoints * size); + if (pInfo->hasNull == false && pItem->isNull == false) { + pItem->timestamp = ts; + pItem->isNull = true; + pInfo->numOfPoints++; + pInfo->hasNull = true; + } else if (pItem->timestamp > ts && pItem->isNull == true) { + pItem->timestamp = ts; + } + return; + } + int32_t hashKeyBytes = IS_VAR_DATA_TYPE(pInfo->colType) ? varDataTLen(data) : pInfo->colBytes; SUniqueItem *pHashItem = taosHashGet(pInfo->pHash, data, hashKeyBytes); if (pHashItem == NULL) { int32_t size = sizeof(SUniqueItem) + pInfo->colBytes; @@ -3884,6 +3900,7 @@ static void doUniqueAdd(SUniqueInfo* pInfo, char *data, TSKEY ts, bool isNull) { pHashItem->timestamp = ts; } + return; } int32_t uniqueFunction(SqlFunctionCtx* pCtx) { @@ -3910,7 +3927,11 @@ int32_t uniqueFunction(SqlFunctionCtx* pCtx) { for (int32_t i = 0; i < pInfo->numOfPoints; ++i) { SUniqueItem *pItem = (SUniqueItem *)(pInfo->pItems + i * (sizeof(SUniqueItem) + pInfo->colBytes)); - colDataAppend(pOutput, i, pItem->data, false); + if (pItem->isNull == true) { + colDataAppendNULL(pOutput, i); + } else { + colDataAppend(pOutput, i, pItem->data, false); + } if (pTsOutput != NULL) { colDataAppendInt64(pTsOutput, i, &pItem->timestamp); }