From 26c618e5ad0b6d9b20c9e43a7e82ec87be365602 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 18 May 2022 16:03:59 +0800 Subject: [PATCH 1/5] enh(query): support sum(NULL), max(NULL), min(NULL) --- include/common/ttypes.h | 2 ++ source/common/src/tdatablock.c | 4 +++- source/libs/function/src/builtins.c | 9 ++++++--- source/libs/function/src/builtinsimpl.c | 24 +++++++++++++++++++----- 4 files changed, 30 insertions(+), 9 deletions(-) diff --git a/include/common/ttypes.h b/include/common/ttypes.h index cab429d136..14428bfc43 100644 --- a/include/common/ttypes.h +++ b/include/common/ttypes.h @@ -179,6 +179,8 @@ typedef struct { } \ } while (0) +//TODO: use varchar(0) to represent NULL type +#define IS_NULL_TYPE(_t) ((_t) == TSDB_DATA_TYPE_NULL) #define IS_SIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_TINYINT && (_t) <= TSDB_DATA_TYPE_BIGINT) #define IS_UNSIGNED_NUMERIC_TYPE(_t) ((_t) >= TSDB_DATA_TYPE_UTINYINT && (_t) <= TSDB_DATA_TYPE_UBIGINT) #define IS_FLOAT_TYPE(_t) ((_t) == TSDB_DATA_TYPE_FLOAT || (_t) == TSDB_DATA_TYPE_DOUBLE) diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index 43dcf2dfa9..f239b04f55 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -322,7 +322,9 @@ int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* p } pColumnInfoData->pData = tmp; - memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows); + if (pColumnInfoData->info.type != TSDB_DATA_TYPE_NULL) { + memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows); + } } pColumnInfoData->hasNull = pSource->hasNull; diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 24d6c1ade9..d58df3e876 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -46,8 +46,10 @@ static int32_t translateInOutNum(SFunctionNode* pFunc, char* pErrBuf, int32_t le } uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_NUMERIC_TYPE(paraType)) { + if (!IS_NUMERIC_TYPE(paraType) && !IS_NULL_TYPE(paraType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); + } else if (IS_NULL_TYPE(paraType)) { + paraType = TSDB_DATA_TYPE_BIGINT; } pFunc->node.resType = (SDataType){.bytes = tDataTypes[paraType].bytes, .type = paraType}; @@ -114,18 +116,19 @@ static int32_t translateSum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { } uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_NUMERIC_TYPE(paraType)) { + if (!IS_NUMERIC_TYPE(paraType) && !IS_NULL_TYPE(paraType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } uint8_t resType = 0; - if (IS_SIGNED_NUMERIC_TYPE(paraType) || paraType == TSDB_DATA_TYPE_BOOL) { + if (IS_SIGNED_NUMERIC_TYPE(paraType) || TSDB_DATA_TYPE_BOOL == paraType || IS_NULL_TYPE(paraType)) { resType = TSDB_DATA_TYPE_BIGINT; } else if (IS_UNSIGNED_NUMERIC_TYPE(paraType)) { resType = TSDB_DATA_TYPE_UBIGINT; } else if (IS_FLOAT_TYPE(paraType)) { resType = TSDB_DATA_TYPE_DOUBLE; } + pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType}; return TSDB_CODE_SUCCESS; } diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 4ab1a52897..d8d7a2f62e 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -255,7 +255,7 @@ int32_t functionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); - pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; + //pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; char* in = GET_ROWCELL_INTERBUF(pResInfo); colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes); @@ -377,11 +377,17 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) { // Only the pre-computing information loaded and actual data does not loaded SInputColumnInfoData* pInput = &pCtx->input; - SColumnDataAgg* pAgg = pInput->pColumnDataAgg[0]; - int32_t type = pInput->pData[0]->info.type; + SColumnDataAgg* pAgg = pInput->pColumnDataAgg[0]; + int32_t type = pInput->pData[0]->info.type; SSumRes* pSumRes = GET_ROWCELL_INTERBUF(GET_RES_INFO(pCtx)); + if (IS_NULL_TYPE(type)) { + GET_RES_INFO(pCtx)->isNullRes = 1; + numOfElem = 1; + goto _sum_over; + } + if (pInput->colDataAggIsSet) { numOfElem = pInput->numOfRows - pAgg->numOfNull; ASSERT(numOfElem >= 0); @@ -426,6 +432,7 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) { } } +_sum_over: // data in the check operation are all null, not output SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1); return TSDB_CODE_SUCCESS; @@ -782,6 +789,12 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); SMinmaxResInfo *pBuf = GET_ROWCELL_INTERBUF(pResInfo); + if (IS_NULL_TYPE(type)) { + GET_RES_INFO(pCtx)->isNullRes = 1; + numOfElems = 1; + goto _min_max_over; + } + // data in current data block are qualified to the query if (pInput->colDataAggIsSet) { numOfElems = pInput->numOfRows - pAgg->numOfNull; @@ -1202,6 +1215,7 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc) { } } +_min_max_over: return numOfElems; } @@ -1234,9 +1248,9 @@ int32_t minmaxFunctionFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { if (pCol->info.type == TSDB_DATA_TYPE_FLOAT) { float v = *(double*) &pRes->v; - colDataAppend(pCol, currentRow, (const char*)&v, false); + colDataAppend(pCol, currentRow, (const char*)&v, pEntryInfo->isNullRes); } else { - colDataAppend(pCol, currentRow, (const char*)&pRes->v, false); + colDataAppend(pCol, currentRow, (const char*)&pRes->v, pEntryInfo->isNullRes); } setSelectivityValue(pCtx, pBlock, &pRes->tuplePos, currentRow); From a52e0027cf6508a562a4ed04ba30c90763c46fe4 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 18 May 2022 16:03:59 +0800 Subject: [PATCH 2/5] enh(query): support count(NULL) = 0 --- source/libs/function/src/builtinsimpl.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index d8d7a2f62e..77126225bf 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -330,8 +330,18 @@ static FORCE_INLINE int32_t getNumofElem(SqlFunctionCtx* pCtx) { int32_t countFunction(SqlFunctionCtx* pCtx) { int32_t numOfElem = getNumofElem(pCtx); SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); - char* buf = GET_ROWCELL_INTERBUF(pResInfo); - *((int64_t*)buf) += numOfElem; + + SInputColumnInfoData* pInput = &pCtx->input; + int32_t type = pInput->pData[0]->info.type; + + char* buf = GET_ROWCELL_INTERBUF(pResInfo); + if (IS_NULL_TYPE(type)) { + //select count(NULL) returns 0 + numOfElem = 1; + *((int64_t*)buf) = 0; + } else { + *((int64_t*)buf) += numOfElem; + } SET_VAL(pResInfo, numOfElem, 1); return TSDB_CODE_SUCCESS; From e948d5a2483f3d6da8ee822d6b66cba51a2f6ab7 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 18 May 2022 16:35:13 +0800 Subject: [PATCH 3/5] enh(query): support avg(NULL), stddev(NULL) --- source/libs/function/src/builtins.c | 2 +- source/libs/function/src/builtinsimpl.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index d58df3e876..306b438344 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -63,7 +63,7 @@ static int32_t translateInNumOutDou(SFunctionNode* pFunc, char* pErrBuf, int32_t } uint8_t paraType = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.type; - if (!IS_NUMERIC_TYPE(paraType)) { + if (!IS_NUMERIC_TYPE(paraType) && !IS_NULL_TYPE(paraType)) { return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName); } diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 77126225bf..90632256b2 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -542,6 +542,12 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { int32_t start = pInput->startRowIndex; int32_t numOfRows = pInput->numOfRows; + if (IS_NULL_TYPE(type)) { + GET_RES_INFO(pCtx)->isNullRes = 1; + numOfElem = 1; + goto _avg_over; + } + switch (type) { case TSDB_DATA_TYPE_TINYINT: { int8_t* plist = (int8_t*)pCol->pData; @@ -633,6 +639,7 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { break; } +_avg_over: // data in the check operation are all null, not output SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1); return TSDB_CODE_SUCCESS; @@ -1330,6 +1337,12 @@ int32_t stddevFunction(SqlFunctionCtx* pCtx) { int32_t start = pInput->startRowIndex; int32_t numOfRows = pInput->numOfRows; + if (IS_NULL_TYPE(type)) { + GET_RES_INFO(pCtx)->isNullRes = 1; + numOfElem = 1; + goto _stddev_over; + } + switch (type) { case TSDB_DATA_TYPE_TINYINT: { int8_t* plist = (int8_t*)pCol->pData; @@ -1427,6 +1440,7 @@ int32_t stddevFunction(SqlFunctionCtx* pCtx) { break; } +_stddev_over: // data in the check operation are all null, not output SET_VAL(GET_RES_INFO(pCtx), numOfElem, 1); return TSDB_CODE_SUCCESS; From dbe43425f172eb855d5c52a32944c1d0fb5a34e1 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 18 May 2022 16:53:17 +0800 Subject: [PATCH 4/5] fix(query): fix error --- source/common/src/tdatablock.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/source/common/src/tdatablock.c b/source/common/src/tdatablock.c index f239b04f55..43dcf2dfa9 100644 --- a/source/common/src/tdatablock.c +++ b/source/common/src/tdatablock.c @@ -322,9 +322,7 @@ int32_t colDataAssign(SColumnInfoData* pColumnInfoData, const SColumnInfoData* p } pColumnInfoData->pData = tmp; - if (pColumnInfoData->info.type != TSDB_DATA_TYPE_NULL) { - memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows); - } + memcpy(pColumnInfoData->pData, pSource->pData, pSource->info.bytes * numOfRows); } pColumnInfoData->hasNull = pSource->hasNull; From 8daaea58de512252bc8091644d830fe632a55dd3 Mon Sep 17 00:00:00 2001 From: Ganlin Zhao Date: Wed, 18 May 2022 18:51:40 +0800 Subject: [PATCH 5/5] feat(query): fix ci --- source/libs/function/inc/builtinsimpl.h | 1 + source/libs/function/src/builtins.c | 2 +- source/libs/function/src/builtinsimpl.c | 13 +++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index 748fb60ef9..a20d0e4718 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -74,6 +74,7 @@ int32_t diffFunction(SqlFunctionCtx *pCtx); bool getFirstLastFuncEnv(struct SFunctionNode* pFunc, SFuncExecEnv* pEnv); int32_t firstFunction(SqlFunctionCtx *pCtx); int32_t lastFunction(SqlFunctionCtx *pCtx); +int32_t lastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock); bool getTopBotFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv); int32_t topFunction(SqlFunctionCtx *pCtx); diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 4672105841..5358930df0 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -875,7 +875,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .getEnvFunc = getFirstLastFuncEnv, .initFunc = functionSetup, .processFunc = lastFunction, - .finalizeFunc = functionFinalize + .finalizeFunc = lastFinalize }, { .name = "diff", diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index ca10d3513e..d54cc96611 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -1981,6 +1981,19 @@ int32_t lastFunction(SqlFunctionCtx* pCtx) { return TSDB_CODE_SUCCESS; } +int32_t lastFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { + int32_t slotId = pCtx->pExpr->base.resSchema.slotId; + SColumnInfoData* pCol = taosArrayGet(pBlock->pDataBlock, slotId); + + SResultRowEntryInfo* pResInfo = GET_RES_INFO(pCtx); + pResInfo->isNullRes = (pResInfo->numOfRes == 0) ? 1 : 0; + + char* in = GET_ROWCELL_INTERBUF(pResInfo); + colDataAppend(pCol, pBlock->info.rows, in, pResInfo->isNullRes); + + return pResInfo->numOfRes; +} + bool getDiffFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { pEnv->calcMemSize = sizeof(SDiffInfo); return true;