diff --git a/include/common/tcommon.h b/include/common/tcommon.h index a6857aa683..96bc4a1a59 100644 --- a/include/common/tcommon.h +++ b/include/common/tcommon.h @@ -166,14 +166,32 @@ typedef enum EStreamType { #pragma pack(push, 1) typedef struct SColumnDataAgg { - int16_t colId; + int32_t colId; int16_t numOfNull; - int64_t sum; - int64_t max; - int64_t min; + union { + struct { + int64_t sum; + int64_t max; + int64_t min; + }; + struct { + uint64_t decimal128Sum[2]; + uint64_t decimal128Max[2]; + uint64_t decimal128Min[2]; + }; + }; } SColumnDataAgg; #pragma pack(pop) +#define COL_AGG_GET_SUM_PTR(pAggs, dataType) \ + (dataType != TSDB_DATA_TYPE_DECIMAL ? (void*)&pAggs->sum : (void*)pAggs->decimal128Sum) + +#define COL_AGG_GET_MAX_PTR(pAggs, dataType) \ + (dataType != TSDB_DATA_TYPE_DECIMAL ? (void*)&pAggs->max : (void*)pAggs->decimal128Max) + +#define COL_AGG_GET_MIN_PTR(pAggs, dataType) \ + (dataType != TSDB_DATA_TYPE_DECIMAL ? (void*)&pAggs->min : (void*)pAggs->decimal128Min) + typedef struct SBlockID { // The uid of table, from which current data block comes. And it is always 0, if current block is the // result of calculation. diff --git a/include/common/tdataformat.h b/include/common/tdataformat.h index 0a28f7782c..c1c3846690 100644 --- a/include/common/tdataformat.h +++ b/include/common/tdataformat.h @@ -43,6 +43,8 @@ typedef struct SColData SColData; typedef struct SRowKey SRowKey; typedef struct SValueColumn SValueColumn; +struct SColumnDataAgg; +typedef struct SColumnDataAgg* SColumnDataAggPtr; #define HAS_NONE ((uint8_t)0x1) #define HAS_NULL ((uint8_t)0x2) @@ -187,7 +189,7 @@ uint8_t tColDataGetBitValue(const SColData *pColData, int32_t iVal); int32_t tColDataCopy(SColData *pColDataFrom, SColData *pColData, xMallocFn xMalloc, void *arg); void tColDataArrGetRowKey(SColData *aColData, int32_t nColData, int32_t iRow, SRowKey *key); -extern void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, int16_t *numOfNull); +extern void (*tColDataCalcSMA[])(SColData *pColData, SColumnDataAggPtr pAggs); int32_t tColDataCompress(SColData *colData, SColDataCompressInfo *info, SBuffer *output, SBuffer *assist); int32_t tColDataDecompress(void *input, SColDataCompressInfo *info, SColData *colData, SBuffer *assist); diff --git a/include/libs/decimal/decimal.h b/include/libs/decimal/decimal.h index 0211e1da5b..a9d845eb13 100644 --- a/include/libs/decimal/decimal.h +++ b/include/libs/decimal/decimal.h @@ -32,8 +32,13 @@ typedef struct Decimal64 { #define DECIMAL64_GET_VALUE(pDec) (int64_t)((pDec)->words[0]) #define DECIMAL64_SET_VALUE(pDec, val) (*(int64_t*)((pDec)->words)) = (int64_t)(val) #define DECIMAL64_CLONE(pDst, pFrom) ((Decimal64*)(pDst))->words[0] = ((Decimal64*)(pFrom))->words[0] -#define DECIMAL64_MAX 999999999999999999LL -#define DECIMAL64_MIN -999999999999999999LL + +static const Decimal64 decimal64Zero = {0}; +static const Decimal64 decimal64Min = {(uint64_t)-999999999999999999LL}; +static const Decimal64 decimal64Max = {(uint64_t)999999999999999999LL}; +#define DECIMAL64_ZERO decimal64Zero +#define DECIMAL64_MAX decimal64Max +#define DECIMAL64_MIN decimal64Min typedef struct Decimal128 { DecimalWord words[2]; // do not touch it directly, use DECIMAL128_HIGH_WORD/DECIMAL128_LOW_WORD @@ -43,6 +48,23 @@ typedef struct Decimal128 { #define decimalFromStr decimal128FromStr #define makeDecimal makeDecimal128 +// TODO wjm handle endian problem +#define DEFINE_DECIMAL128(lo, hi) {lo, hi} +static const Decimal128 decimal128Zero = DEFINE_DECIMAL128(0, 0); +static const Decimal128 decimal128Two = DEFINE_DECIMAL128(2, 0); +static const Decimal128 decimal128Max = DEFINE_DECIMAL128(687399551400673280ULL - 1, 5421010862427522170LL); +static const Decimal128 decimal128Min = DEFINE_DECIMAL128(17759344522308878337ULL, 13025733211282029445ULL); +// TODO wjm handle endian problem +#define DECIMAL128_LOW_WORD(pDec) (uint64_t)((pDec)->words[0]) +#define DECIMAL128_SET_LOW_WORD(pDec, val) (pDec)->words[0] = val +#define DECIMAL128_HIGH_WORD(pDec) (int64_t)((pDec)->words[1]) +#define DECIMAL128_SET_HIGH_WORD(pDec, val) *(int64_t*)((pDec)->words + 1) = val + +#define DECIMAL128_ZERO decimal128Zero +#define DECIMAL128_MAX decimal128Max +#define DECIMAL128_MIN decimal128Min +#define DECIMAL128_CLONE(pDst, pFrom) makeDecimal128(pDst, DECIMAL128_HIGH_WORD(pFrom), DECIMAL128_LOW_WORD(pFrom)) + typedef struct SDecimalCompareCtx { void* pData; int8_t type; diff --git a/include/util/tcompare.h b/include/util/tcompare.h index 7d5f73e5f5..41bedc1a19 100644 --- a/include/util/tcompare.h +++ b/include/util/tcompare.h @@ -91,6 +91,9 @@ int32_t compareLenBinaryVal(const void *pLeft, const void *pRight); int32_t compareDecimal64(const void* pleft, const void* pright); int32_t compareDecimal128(const void* pleft, const void* pright); +int32_t compareDecimal64SameScale(const void* pleft, const void* pright); +int32_t compareDecimal128SameScale(const void* pleft, const void* pright); + int32_t comparestrRegexMatch(const void *pLeft, const void *pRight); int32_t comparestrRegexNMatch(const void *pLeft, const void *pRight); diff --git a/source/common/src/tdataformat.c b/source/common/src/tdataformat.c index 370895871e..5171b956c9 100644 --- a/source/common/src/tdataformat.c +++ b/source/common/src/tdataformat.c @@ -18,6 +18,7 @@ #include "tRealloc.h" #include "tdatablock.h" #include "tlog.h" +#include "decimal.h" static int32_t (*tColDataAppendValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData); static int32_t (*tColDataUpdateValueImpl[8][3])(SColData *pColData, uint8_t *pData, uint32_t nData, bool forward); @@ -3832,8 +3833,9 @@ int32_t tDecodeRow(SDecoder *pDecoder, SRow **ppRow) { if ((MIN) > (VAL)) (MIN) = (VAL); \ } while (0) -static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t*numOfNull = &pAggs->numOfNull; *sum = 0; *max = 0; *min = 1; @@ -3863,8 +3865,9 @@ static FORCE_INLINE void tColDataCalcSMABool(SColData *pColData, int64_t *sum, i } } -static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *sum = 0; *max = INT8_MIN; *min = INT8_MAX; @@ -3894,8 +3897,9 @@ static FORCE_INLINE void tColDataCalcSMATinyInt(SColData *pColData, int64_t *sum } } -static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *sum = 0; *max = INT16_MIN; *min = INT16_MAX; @@ -3925,8 +3929,9 @@ static FORCE_INLINE void tColDataCalcSMATinySmallInt(SColData *pColData, int64_t } } -static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *sum = 0; *max = INT32_MIN; *min = INT32_MAX; @@ -3956,8 +3961,9 @@ static FORCE_INLINE void tColDataCalcSMAInt(SColData *pColData, int64_t *sum, in } } -static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *sum = 0; *max = INT64_MIN; *min = INT64_MAX; @@ -3987,8 +3993,9 @@ static FORCE_INLINE void tColDataCalcSMABigInt(SColData *pColData, int64_t *sum, } } -static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(double *)sum = 0; *(double *)max = -FLT_MAX; *(double *)min = FLT_MAX; @@ -4018,8 +4025,9 @@ static FORCE_INLINE void tColDataCalcSMAFloat(SColData *pColData, int64_t *sum, } } -static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(double *)sum = 0; *(double *)max = -DBL_MAX; *(double *)min = DBL_MAX; @@ -4049,8 +4057,9 @@ static FORCE_INLINE void tColDataCalcSMADouble(SColData *pColData, int64_t *sum, } } -static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(uint64_t *)sum = 0; *(uint64_t *)max = 0; *(uint64_t *)min = UINT8_MAX; @@ -4080,8 +4089,9 @@ static FORCE_INLINE void tColDataCalcSMAUTinyInt(SColData *pColData, int64_t *su } } -static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(uint64_t *)sum = 0; *(uint64_t *)max = 0; *(uint64_t *)min = UINT16_MAX; @@ -4111,8 +4121,9 @@ static FORCE_INLINE void tColDataCalcSMATinyUSmallInt(SColData *pColData, int64_ } } -static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(uint64_t *)sum = 0; *(uint64_t *)max = 0; *(uint64_t *)min = UINT32_MAX; @@ -4142,8 +4153,9 @@ static FORCE_INLINE void tColDataCalcSMAUInt(SColData *pColData, int64_t *sum, i } } -static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(uint64_t *)sum = 0; *(uint64_t *)max = 0; *(uint64_t *)min = UINT64_MAX; @@ -4173,8 +4185,9 @@ static FORCE_INLINE void tColDataCalcSMAUBigInt(SColData *pColData, int64_t *sum } } -static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, - int16_t *numOfNull) { +static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, SColumnDataAgg* pAggs) { + int64_t *sum = &pAggs->sum, *max = &pAggs->max, *min = &pAggs->min; + int16_t *numOfNull = &pAggs->numOfNull; *(uint64_t *)sum = 0; *(uint64_t *)max = 0; *(uint64_t *)min = 0; @@ -4209,7 +4222,76 @@ static FORCE_INLINE void tColDataCalcSMAVarType(SColData *pColData, int64_t *sum } } -void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_t *min, int16_t *numOfNull) = { +#define CALC_DECIMAL_SUM_MAX_MIN(TYPE, pOps, pColData, pSum, pMax, pMin) \ + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { \ + pVal = ((TYPE *)pColData->pData) + iVal; \ + pOps->add(pSum, pVal, WORD_NUM(TYPE)); \ + if (pOps->gt(pVal, pMax, WORD_NUM(TYPE))) { \ + *(pMax) = *pVal; \ + } \ + if (pOps->lt(pVal, pMin, WORD_NUM(TYPE))) { \ + *(pMin) = *pVal; \ + } \ + } + +static FORCE_INLINE void tColDataCalcSMADecimal64Type(SColData* pColData, SColumnDataAgg* pAggs) { + Decimal64* pSum = (Decimal64*)&pAggs->sum, *pMax = (Decimal64*)&pAggs->max, *pMin = (Decimal64*)&pAggs->min; + *pSum = DECIMAL64_ZERO; + *pMax = DECIMAL64_MIN; + *pMin = DECIMAL64_MAX; + pAggs->numOfNull = 0; + + Decimal64 *pVal = NULL; + SDecimalOps *pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); + if (HAS_VALUE == pColData->flag) { + CALC_DECIMAL_SUM_MAX_MIN(Decimal64, pOps, pColData, pSum, pMax, pMin); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + switch (tColDataGetBitValue(pColData, iVal)) { + case 0: + case 1: + pAggs->numOfNull++; + break; + case 2: + CALC_DECIMAL_SUM_MAX_MIN(Decimal64, pOps, pColData, pSum, pMax, pMin); + break; + default: + break; + } + } + } +} + +static FORCE_INLINE void tColDataCalcSMADecimal128Type(SColData* pColData, SColumnDataAgg* pAggs) { + Decimal128* pSum = (Decimal128*)pAggs->decimal128Sum, *pMax = (Decimal128*)pAggs->decimal128Max, *pMin = (Decimal128*)pAggs->decimal128Min; + *pSum = DECIMAL128_ZERO; + *pMax = DECIMAL128_MIN; + *pMin = DECIMAL128_MAX; + pAggs->numOfNull = 0; + pAggs->colId |= 0x80000000; // TODO wjm define it + + Decimal128 *pVal = NULL; + SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); + if (HAS_VALUE == pColData->flag) { + CALC_DECIMAL_SUM_MAX_MIN(Decimal128, pOps, pColData, pSum, pMax, pMin); + } else { + for (int32_t iVal = 0; iVal < pColData->nVal; ++iVal) { + switch (tColDataGetBitValue(pColData, iVal)) { + case 0: + case 1: + pAggs->numOfNull++; + break; + case 2: + CALC_DECIMAL_SUM_MAX_MIN(Decimal128, pOps, pColData, pSum, pMax, pMin); + break; + default: + break; + } + } + } +} + +void (*tColDataCalcSMA[])(SColData *pColData, SColumnDataAgg* pAggs) = { NULL, tColDataCalcSMABool, // TSDB_DATA_TYPE_BOOL tColDataCalcSMATinyInt, // TSDB_DATA_TYPE_TINYINT @@ -4227,10 +4309,11 @@ void (*tColDataCalcSMA[])(SColData *pColData, int64_t *sum, int64_t *max, int64_ tColDataCalcSMAUBigInt, // TSDB_DATA_TYPE_UBIGINT tColDataCalcSMAVarType, // TSDB_DATA_TYPE_JSON tColDataCalcSMAVarType, // TSDB_DATA_TYPE_VARBINARY - tColDataCalcSMAVarType, // TSDB_DATA_TYPE_DECIMAL + tColDataCalcSMADecimal128Type, // TSDB_DATA_TYPE_DECIMAL tColDataCalcSMAVarType, // TSDB_DATA_TYPE_BLOB NULL, // TSDB_DATA_TYPE_MEDIUMBLOB - tColDataCalcSMAVarType // TSDB_DATA_TYPE_GEOMETRY + tColDataCalcSMAVarType, // TSDB_DATA_TYPE_GEOMETRY + tColDataCalcSMADecimal64Type, // TSDB_DATA_TYPE_DECIMAL64 }; // SValueColumn ================================ diff --git a/source/dnode/vnode/src/tsdb/tsdbDataFileRW.c b/source/dnode/vnode/src/tsdb/tsdbDataFileRW.c index 3b187323b5..6c1e016e24 100644 --- a/source/dnode/vnode/src/tsdb/tsdbDataFileRW.c +++ b/source/dnode/vnode/src/tsdb/tsdbDataFileRW.c @@ -1069,7 +1069,7 @@ static int32_t tsdbDataFileDoWriteBlockData(SDataFileWriter *writer, SBlockData if ((colData->cflag & COL_SMA_ON) == 0 || ((colData->flag & HAS_VALUE) == 0)) continue; SColumnDataAgg sma[1] = {{.colId = colData->cid}}; - tColDataCalcSMA[colData->type](colData, &sma->sum, &sma->max, &sma->min, &sma->numOfNull); + tColDataCalcSMA[colData->type](colData, sma); TAOS_CHECK_GOTO(tPutColumnDataAgg(&buffers[0], sma), &lino, _exit); } diff --git a/source/dnode/vnode/src/tsdb/tsdbUtil.c b/source/dnode/vnode/src/tsdb/tsdbUtil.c index 94db115af6..51c7a5049c 100644 --- a/source/dnode/vnode/src/tsdb/tsdbUtil.c +++ b/source/dnode/vnode/src/tsdb/tsdbUtil.c @@ -1574,11 +1574,22 @@ int32_t tGetDiskDataHdr(SBufferReader *br, SDiskDataHdr *pHdr) { int32_t tPutColumnDataAgg(SBuffer *buffer, SColumnDataAgg *pColAgg) { int32_t code; - if ((code = tBufferPutI16v(buffer, pColAgg->colId))) return code; - if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code; - if ((code = tBufferPutI64(buffer, pColAgg->sum))) return code; - if ((code = tBufferPutI64(buffer, pColAgg->max))) return code; - if ((code = tBufferPutI64(buffer, pColAgg->min))) return code; + if (pColAgg->colId & 0x80000000) { + if ((code = tBufferPutI32v(buffer, pColAgg->colId))) return code; + if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Sum[0]))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Sum[1]))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Max[0]))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Max[1]))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Min[0]))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->decimal128Min[1]))) return code; + } else { + if ((code = tBufferPutI32v(buffer, pColAgg->colId))) return code; + if ((code = tBufferPutI16v(buffer, pColAgg->numOfNull))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->sum))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->max))) return code; + if ((code = tBufferPutI64(buffer, pColAgg->min))) return code; + } return 0; } @@ -1586,11 +1597,21 @@ int32_t tPutColumnDataAgg(SBuffer *buffer, SColumnDataAgg *pColAgg) { int32_t tGetColumnDataAgg(SBufferReader *br, SColumnDataAgg *pColAgg) { int32_t code; - if ((code = tBufferGetI16v(br, &pColAgg->colId))) return code; + if ((code = tBufferGetI32v(br, &pColAgg->colId))) return code; if ((code = tBufferGetI16v(br, &pColAgg->numOfNull))) return code; - if ((code = tBufferGetI64(br, &pColAgg->sum))) return code; - if ((code = tBufferGetI64(br, &pColAgg->max))) return code; - if ((code = tBufferGetI64(br, &pColAgg->min))) return code; + if (pColAgg->colId & 0x80000000) { + pColAgg->colId &= 0xFFFF; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Sum[0]))) return code; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Sum[1]))) return code; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Max[0]))) return code; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Max[1]))) return code; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Min[0]))) return code; + if ((code = tBufferGetI64(br, &pColAgg->decimal128Min[1]))) return code; + } else { + if ((code = tBufferGetI64(br, &pColAgg->sum))) return code; + if ((code = tBufferGetI64(br, &pColAgg->max))) return code; + if ((code = tBufferGetI64(br, &pColAgg->min))) return code; + } return 0; } diff --git a/source/libs/decimal/src/decimal.c b/source/libs/decimal/src/decimal.c index 9a4f598145..3a3b632dc2 100644 --- a/source/libs/decimal/src/decimal.c +++ b/source/libs/decimal/src/decimal.c @@ -234,10 +234,7 @@ static Decimal64 SCALE_MULTIPLIER_64[TSDB_DECIMAL64_MAX_PRECISION + 1] = {1LL, 10000000000000000LL, 100000000000000000LL, 1000000000000000000LL}; - -static const Decimal64 decimal64Zero = {0}; #define DECIMAL64_ONE SCALE_MULTIPLIER_64[0] -#define DECIMAL64_ZERO decimal64Zero #define DECIMAL64_GET_MAX(precision, pMax) \ do { \ @@ -339,6 +336,7 @@ static SDecimalOps* getDecimalOpsImp(DecimalInternalType t) { return NULL; } } +// TODO wjm const?? SDecimalOps* getDecimalOps(int8_t dataType) { return getDecimalOpsImp(DECIMAL_GET_INTERNAL_TYPE(dataType)); } void makeDecimal64(Decimal64* pDec64, int64_t w) { DECIMAL64_SET_VALUE(pDec64, w); } @@ -431,17 +429,9 @@ int32_t decimal64ToStr(const DecimalType* pInt, uint8_t scale, char* pBuf, int32 return 0; } -// TODO wjm handle endian problem -#define DECIMAL128_LOW_WORD(pDec) (uint64_t)((pDec)->words[0]) -#define DECIMAL128_SET_LOW_WORD(pDec, val) (pDec)->words[0] = val -#define DECIMAL128_HIGH_WORD(pDec) (int64_t)((pDec)->words[1]) -#define DECIMAL128_SET_HIGH_WORD(pDec, val) *(int64_t*)((pDec)->words + 1) = val // return 1 if positive or zero, else return -1 #define DECIMAL128_SIGN(pDec) (1 | (DECIMAL128_HIGH_WORD(pDec) >> 63)) -// TODO wjm handle endian problem -#define DEFINE_DECIMAL128(lo, hi) {lo, hi} - static const Decimal128 SCALE_MULTIPLIER_128[TSDB_DECIMAL128_MAX_PRECISION + 1] = { DEFINE_DECIMAL128(1LL, 0), DEFINE_DECIMAL128(10LL, 0), @@ -497,12 +487,6 @@ static double getDoubleScaleMultiplier(uint8_t scale) { return SCALE_MULTIPLIER_DOUBLE[scale]; }; -static const Decimal128 decimal128Zero = DEFINE_DECIMAL128(0, 0); -static const Decimal128 decimal128Two = DEFINE_DECIMAL128(2, 0); -static const Decimal128 decimal128Max = DEFINE_DECIMAL128(687399551400673280ULL - 1, 5421010862427522170LL); - -#define DECIMAL128_ZERO decimal128Zero -#define DECIMAL128_MAX decimal128Max #define DECIMAL128_ONE SCALE_MULTIPLIER_128[0] #define DECIMAL128_TEN SCALE_MULTIPLIER_128[1] @@ -1013,7 +997,28 @@ static int32_t decimal64FromUint64(DecimalType* pDec, uint8_t prec, uint8_t scal return 0; } -static int32_t decimal64FromDouble(DecimalType* pDec, uint8_t prec, uint8_t scale, double val) { return 0; } +static int32_t decimal64FromDouble(DecimalType* pDec, uint8_t prec, uint8_t scale, double val) { + double unscaled = val * getDoubleScaleMultiplier(scale); + if (isnan(unscaled)) { + goto _OVERFLOW; + } + unscaled = round(unscaled); + + bool negative = unscaled < 0 ? true : false; + double abs = TABS(unscaled); + if (abs > ldexp(1.0, 63) - 1) { + goto _OVERFLOW; + } + + uint64_t result = (uint64_t)abs; + makeDecimal64(pDec, result); + if (negative) decimal64Negate(pDec); + return 0; + +_OVERFLOW: + makeDecimal64(pDec, 0); + return TSDB_CODE_DECIMAL_OVERFLOW; +} static int32_t decimal64FromDecimal128(DecimalType* pDec, uint8_t prec, uint8_t scale, const DecimalType* pVal, uint8_t valPrec, uint8_t valScale) { diff --git a/source/libs/decimal/test/decimalTest.cpp b/source/libs/decimal/test/decimalTest.cpp index ab54254bc4..4babb489a0 100644 --- a/source/libs/decimal/test/decimalTest.cpp +++ b/source/libs/decimal/test/decimalTest.cpp @@ -178,6 +178,7 @@ class Numeric { } Numeric(const Numeric& o) = default; ~Numeric() = default; + Numeric& operator=(const Numeric& o) = default; SDataType getRetType(EOperatorType op, const SDataType& lt, const SDataType& rt) const { SDataType ot = {0}; @@ -424,6 +425,23 @@ TEST(decimal, numeric) { ASSERT_EQ(os.toStringTrimTailingZeros(), "0.0000000100270361075880117"); double dv = dec4 / 123123.123; + + Numeric<128> max{38, 0, "99999999999999999999999999999999999999.000"}; + ASSERT_EQ(max.toString(), "99999999999999999999999999999999999999"); + Numeric<128> zero{38, 0, "0"}; + auto min = zero - max; + ASSERT_EQ(min.toString(), "-99999999999999999999999999999999999999"); + + dec = 123.456; + ASSERT_EQ(dec.toString(), "123.4560"); + + dec = 47563.36; + dec128 = 0; + o = dec128 + dec; // (37, 10) + (10, 4) = (38, 10) + ASSERT_EQ(o.toString(), "47563.3600000000"); + dec = 3749.00; + o = o + dec;// (38, 10) + (10, 4) = (38, 9) + ASSERT_EQ(o.toString(), "51312.360000000"); } TEST(decimal, decimalFromType) { diff --git a/source/libs/function/inc/functionResInfoInt.h b/source/libs/function/inc/functionResInfoInt.h index 5c134f0d9b..a8cef86046 100644 --- a/source/libs/function/inc/functionResInfoInt.h +++ b/source/libs/function/inc/functionResInfoInt.h @@ -25,6 +25,7 @@ extern "C" { #include "tdigest.h" #include "functionResInfo.h" #include "tpercentile.h" +#include "decimal.h" #define USE_ARRAYLIST @@ -39,6 +40,7 @@ typedef struct SSumRes { int64_t isum; uint64_t usum; double dsum; + void* pData; // for decimal128 }; int16_t type; int64_t prevTs; @@ -46,6 +48,16 @@ typedef struct SSumRes { bool overflow; // if overflow is true, dsum to be used for any type; } SSumRes; +typedef struct SDecimalSumRes { + int64_t flag; // currently not used + // TODO wjm use same struct for the following four fields as SSumRes + int16_t type; + int64_t prevTs; + bool isPrevTsSet; + bool overflow; // if overflow is true, dsum to be used for any type; + Decimal128 sum; +} SDecimalSumRes; + typedef struct SMinmaxResInfo { bool assign; // assign the first value or not int64_t v; diff --git a/source/libs/function/src/builtins.c b/source/libs/function/src/builtins.c index 97b83dbbc7..3ba55c850b 100644 --- a/source/libs/function/src/builtins.c +++ b/source/libs/function/src/builtins.c @@ -412,6 +412,7 @@ static bool paramSupportGeometry(uint64_t typeFlag) { static bool paramSupportDecimal(uint64_t typeFlag) { return FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_DECIMAL_TYPE) || + FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_NUMERIC_TYPE) || FUNC_MGT_TEST_MASK(typeFlag, FUNC_PARAM_SUPPORT_ALL_TYPE); } @@ -1025,15 +1026,20 @@ static int32_t translateSum(SFunctionNode* pFunc, char* pErrBuf, int32_t len) { uint8_t paraType = getSDataTypeFromNode(nodesListGetNode(pFunc->pParameterList, 0))->type; uint8_t resType = 0; + uint8_t prec = 0, scale = 0; 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; + } else if (IS_DECIMAL_TYPE(paraType)) { + resType = TSDB_DATA_TYPE_DECIMAL; + prec = TSDB_DECIMAL_MAX_PRECISION; + scale = ((SExprNode*)nodesListGetNode(pFunc->pParameterList, 0))->resType.scale; } - pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType}; + pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType, .precision = prec, .scale = scale}; return TSDB_CODE_SUCCESS; } @@ -1859,7 +1865,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, - .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_BIGINT_TYPE | FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_UBIGINT_TYPE}}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_BIGINT_TYPE | FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_UBIGINT_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE}}, .translateFunc = translateSum, .dataRequiredFunc = statisDataRequired, .getEnvFunc = getSumFuncEnv, @@ -1885,7 +1891,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .inputParaInfo[0][0] = {.isLastParam = true, .startParam = 1, .endParam = 1, - .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE, + .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, @@ -1912,7 +1918,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .inputParaInfo[0][0] = {.isLastParam = true, .startParam = 1, .endParam = 1, - .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE |FUNC_PARAM_SUPPORT_DECIMAL_TYPE, + .validDataType = FUNC_PARAM_SUPPORT_NUMERIC_TYPE | FUNC_PARAM_SUPPORT_STRING_TYPE | FUNC_PARAM_SUPPORT_NULL_TYPE, .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, @@ -2057,7 +2063,7 @@ const SBuiltinFuncDefinition funcMgtBuiltins[] = { .validNodeType = FUNC_PARAM_SUPPORT_EXPR_NODE, .paramAttribute = FUNC_PARAM_NO_SPECIFIC_ATTRIBUTE, .valueRangeFlag = FUNC_PARAM_NO_SPECIFIC_VALUE,}, - .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_DOUBLE_TYPE}}, + .outputParaInfo = {.validDataType = FUNC_PARAM_SUPPORT_DOUBLE_TYPE | FUNC_PARAM_SUPPORT_DECIMAL_TYPE}}, .translateFunc = translateOutDouble, .dataRequiredFunc = statisDataRequired, .getEnvFunc = getAvgFuncEnv, diff --git a/source/libs/function/src/builtinsimpl.c b/source/libs/function/src/builtinsimpl.c index 9965d30367..bc375e6a51 100644 --- a/source/libs/function/src/builtinsimpl.c +++ b/source/libs/function/src/builtinsimpl.c @@ -15,6 +15,7 @@ #include "builtinsimpl.h" #include "cJSON.h" +#include "decimal.h" #include "function.h" #include "functionResInfoInt.h" #include "query.h" @@ -105,6 +106,19 @@ typedef enum { } \ } while (0) +#define LIST_ADD_DECIMAL_N(_res, _col, _start, _rows, _t, numOfElem) \ + do { \ + _t* d = (_t*)(_col->pData); \ + const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); \ + for (int32_t i = (_start); i < (_rows) + (_start); ++i) { \ + if (((_col)->hasNull) && colDataIsNull_f((_col)->nullbitmap, i)) { \ + continue; \ + }; \ + pOps->add(_res, d + i, WORD_NUM(_t)); \ + (numOfElem)++; \ + } \ + } while (0) + #define LIST_SUB_N(_res, _col, _start, _rows, _t, numOfElem) \ do { \ _t* d = (_t*)(_col->pData); \ @@ -635,6 +649,15 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) { pSumRes->usum += pAgg->sum; } else if (IS_FLOAT_TYPE(type)) { pSumRes->dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum)); + } else if (IS_DECIMAL_TYPE(type)) { + SDecimalSumRes* pDecimalSum = (SDecimalSumRes*)pSumRes; + pDecimalSum->type = TSDB_DATA_TYPE_DECIMAL; + const SDecimalOps* pOps = getDecimalOps(type); + if (TSDB_DATA_TYPE_DECIMAL64 == type) { + pOps->add(&pDecimalSum->sum, &pAgg->sum, WORD_NUM(Decimal64)); + } else if (TSDB_DATA_TYPE_DECIMAL == type) { + pOps->add(&pDecimalSum->sum, pAgg->decimal128Sum, WORD_NUM(Decimal)); + } } } else { // computing based on the true data block SColumnInfoData* pCol = pInput->pData[0]; @@ -666,6 +689,15 @@ int32_t sumFunction(SqlFunctionCtx* pCtx) { LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, double, numOfElem); } else if (type == TSDB_DATA_TYPE_FLOAT) { LIST_ADD_N(pSumRes->dsum, pCol, start, numOfRows, float, numOfElem); + } else if (IS_DECIMAL_TYPE(type)) { + SDecimalSumRes* pDecimalSum = (SDecimalSumRes*)pSumRes; + pSumRes->type = TSDB_DATA_TYPE_DECIMAL; + if (TSDB_DATA_TYPE_DECIMAL64 == type) { + LIST_ADD_DECIMAL_N(&pDecimalSum->sum, pCol, start, numOfRows, Decimal64, numOfElem); + } else if (TSDB_DATA_TYPE_DECIMAL == type) { + LIST_ADD_DECIMAL_N(&pDecimalSum->sum, pCol, start, numOfRows, Decimal128, numOfElem); + } + // TODO wjm check overflow } } @@ -766,8 +798,11 @@ int32_t sumCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) { return TSDB_CODE_SUCCESS; } -bool getSumFuncEnv(SFunctionNode* UNUSED_PARAM(pFunc), SFuncExecEnv* pEnv) { - pEnv->calcMemSize = sizeof(SSumRes); +bool getSumFuncEnv(SFunctionNode* pFunc, SFuncExecEnv* pEnv) { + if (pFunc->node.resType.type == TSDB_DATA_TYPE_DECIMAL) + pEnv->calcMemSize = sizeof(SDecimalSumRes); + else + pEnv->calcMemSize = sizeof(SSumRes); return true; } diff --git a/source/libs/function/src/detail/tminmax.c b/source/libs/function/src/detail/tminmax.c index 0911ec4e64..c79c6b7553 100644 --- a/source/libs/function/src/detail/tminmax.c +++ b/source/libs/function/src/detail/tminmax.c @@ -396,6 +396,40 @@ static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFu } break; } + case TSDB_DATA_TYPE_DECIMAL64: { + const Decimal64* pData = (const Decimal64*)pCol->pData; + const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); + int32_t code = 0; + for (; i < end; ++i) { + if (colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + if (pOps->gt(&pBuf->v, &pData[i], WORD_NUM(Decimal64))) { + pBuf->v = DECIMAL64_GET_VALUE(&pData[i]); + if (pCtx->subsidiaries.num > 0) { + code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos); + if (TSDB_CODE_SUCCESS != code) return code; + } + } + } + } break; + case TSDB_DATA_TYPE_DECIMAL: { + int32_t code = 0; + const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); + const Decimal128* pData = (const Decimal128*)pCol->pData; + for (; i < end; ++i) { + if (colDataIsNull_f(pCol->nullbitmap, i)) { + continue; + } + if (pOps->gt(pBuf->str, &pData[i], WORD_NUM(Decimal128))) { + memcpy(pBuf->str, pData + i, pCol->info.bytes); + if (pCtx->subsidiaries.num > 0) { + code = updateTupleData(pCtx, i, pCtx->pSrcBlock, &pBuf->tuplePos); + if (TSDB_CODE_SUCCESS != code) return code; + } + } + } + } break; } } else { switch (pCol->info.type) { @@ -459,7 +493,7 @@ static int32_t doExtractVal(SColumnInfoData* pCol, int32_t i, int32_t end, SqlFu __COMPARE_ACQUIRED_MAX(i, end, pCol->nullbitmap, pData, pCtx, *(double*)&(pBuf->v), &pBuf->tuplePos) break; } - case TSDB_DATA_TYPE_DECIMAL64: {// TODO wjm merge decimal64 and decimal + case TSDB_DATA_TYPE_DECIMAL64: { const Decimal64* pData = (const Decimal64*)pCol->pData; const SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); int32_t code = 0; @@ -584,11 +618,20 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems) } int16_t index = 0; - void* tval = (isMinFunc) ? &pInput->pColumnDataAgg[0]->min : &pInput->pColumnDataAgg[0]->max; + void* tval = NULL; + if (type == TSDB_DATA_TYPE_DECIMAL) { + tval = isMinFunc ? pInput->pColumnDataAgg[0]->decimal128Min : pInput->pColumnDataAgg[0]->decimal128Max; + } else { + tval = (isMinFunc) ? &pInput->pColumnDataAgg[0]->min : &pInput->pColumnDataAgg[0]->max; + } if (!pBuf->assign) { if (type == TSDB_DATA_TYPE_FLOAT) { GET_FLOAT_VAL(&pBuf->v) = GET_DOUBLE_VAL(tval); + } else if (type == TSDB_DATA_TYPE_DECIMAL) { + pBuf->str = taosMemoryCalloc(1, pCol->info.bytes); + if (!pBuf->str) return terrno; + memcpy(pBuf->str, tval, pCol->info.bytes); } else { pBuf->v = GET_INT64_VAL(tval); } @@ -631,6 +674,18 @@ int32_t doMinMaxHelper(SqlFunctionCtx* pCtx, int32_t isMinFunc, int32_t* nElems) GET_FLOAT_VAL(&pBuf->v) = val; code = saveRelatedTupleTag(pCtx, pInput, tval); } + } else if (type == TSDB_DATA_TYPE_DECIMAL64) { + SDecimalOps* pOps = getDecimalOps(type); + if (pOps->lt(&pBuf->v, tval, WORD_NUM(Decimal64)) ^ isMinFunc) { + DECIMAL64_SET_VALUE((Decimal64*)&pBuf->v, *(int64_t*)tval); + code =saveRelatedTupleTag(pCtx, pInput, tval); + } + } else if (type == TSDB_DATA_TYPE_DECIMAL) { + SDecimalOps* pOps = getDecimalOps(type); + if (pOps->lt(pBuf->str, tval, WORD_NUM(Decimal128)) ^ isMinFunc) { + DECIMAL128_CLONE((Decimal128*)pBuf->str, (Decimal128*)tval); + code =saveRelatedTupleTag(pCtx, pInput, tval); + } } } diff --git a/source/libs/scalar/src/filter.c b/source/libs/scalar/src/filter.c index 6f34e2e3c2..4c070ef447 100644 --- a/source/libs/scalar/src/filter.c +++ b/source/libs/scalar/src/filter.c @@ -13,6 +13,7 @@ * along with this program. If not, see . */ #include +#include "decimal.h" #include "nodes.h" #include "os.h" #include "tglobal.h" @@ -3922,6 +3923,8 @@ typedef enum { FLT_SCL_DATUM_KIND_FLOAT64, FLT_SCL_DATUM_KIND_VARCHAR, FLT_SCL_DATUM_KIND_NCHAR, + FLT_SCL_DATUM_KIND_DECIMAL64, + FLT_SCL_DATUM_KIND_DECIMAL, FLT_SCL_DATUM_KIND_MAX, } SFltSclDatumKind; @@ -4009,6 +4012,12 @@ int32_t fltSclCompareDatum(SFltSclDatum *val1, SFltSclDatum *val2) { case FLT_SCL_DATUM_KIND_FLOAT64: { return fltSclCompareWithFloat64(val1, val2); } + case FLT_SCL_DATUM_KIND_DECIMAL64: { + return compareDecimal64SameScale(&val1->i, &val2->i); + } + case FLT_SCL_DATUM_KIND_DECIMAL: { + return compareDecimal128SameScale(val1->pData, val2->pData); + } // TODO: varchar/nchar default: qError("not supported kind when compare datum. kind2 : %d", val2->kind); @@ -4157,7 +4166,61 @@ int32_t fltSclGetOrCreateColumnRange(SColumnNode *colNode, SArray *colRangeList, return TSDB_CODE_SUCCESS; } -int32_t fltSclBuildDatumFromValueNode(SFltSclDatum *datum, SValueNode *valNode) { +static int32_t fltSclBuildDecimalDatumFromValueNode(SFltSclDatum* datum, SColumnNode* pColNode, SValueNode* valNode) { + datum->type = pColNode->node.resType; + if (valNode->isNull) { + datum->kind = FLT_SCL_DATUM_KIND_NULL; + } else { + void* pInput = NULL; + switch (valNode->node.resType.type) { + case TSDB_DATA_TYPE_NULL: + datum->kind = FLT_SCL_DATUM_KIND_NULL; + FLT_RET(0); + case TSDB_DATA_TYPE_BOOL: + pInput = &valNode->datum.b; + break; + case TSDB_DATA_TYPE_TINYINT: + case TSDB_DATA_TYPE_SMALLINT: + case TSDB_DATA_TYPE_INT: + case TSDB_DATA_TYPE_BIGINT: + case TSDB_DATA_TYPE_TIMESTAMP: + pInput = &valNode->datum.i; + break; + case TSDB_DATA_TYPE_UTINYINT: + case TSDB_DATA_TYPE_USMALLINT: + case TSDB_DATA_TYPE_UINT: + case TSDB_DATA_TYPE_UBIGINT: + pInput = &valNode->datum.u; + break; + case TSDB_DATA_TYPE_FLOAT: + case TSDB_DATA_TYPE_DOUBLE: + pInput = &valNode->datum.d; + break; + default: + qError("not supported type %d when build decimal datum from value node", valNode->node.resType.type); + return TSDB_CODE_INVALID_PARA; + } + + void *pData = NULL; + if (datum->type.type == TSDB_DATA_TYPE_DECIMAL64) { + pData = &datum->i; // TODO wjm set kind + } else if (datum->type.type == TSDB_DATA_TYPE_DECIMAL) { + pData = taosMemoryCalloc(1, pColNode->node.resType.bytes); + if (!pData) FLT_ERR_RET(terrno); + datum->pData = pData; + datum->kind = FLT_SCL_DATUM_KIND_DECIMAL; + } + int32_t code = convertToDecimal(pInput, &valNode->node.resType, pData, &datum->type); + if (TSDB_CODE_SUCCESS != code) return code; // TODO wjm handle overflow error + valNode->node.resType = datum->type; + } + FLT_RET(0); +} + +int32_t fltSclBuildDatumFromValueNode(SFltSclDatum *datum, SColumnNode* pColNode, SValueNode *valNode) { + if (IS_DECIMAL_TYPE(pColNode->node.resType.type)) { + return fltSclBuildDecimalDatumFromValueNode(datum, pColNode, valNode); + } datum->type = valNode->node.resType; if (valNode->isNull) { @@ -4206,7 +4269,7 @@ int32_t fltSclBuildDatumFromValueNode(SFltSclDatum *datum, SValueNode *valNode) return TSDB_CODE_SUCCESS; } -int32_t fltSclBuildDatumFromBlockSmaValue(SFltSclDatum *datum, uint8_t type, int64_t val) { +int32_t fltSclBuildDatumFromBlockSmaValue(SFltSclDatum *datum, uint8_t type, void* val) { switch (type) { case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_TINYINT: @@ -4215,7 +4278,7 @@ int32_t fltSclBuildDatumFromBlockSmaValue(SFltSclDatum *datum, uint8_t type, int case TSDB_DATA_TYPE_BIGINT: case TSDB_DATA_TYPE_TIMESTAMP: { datum->kind = FLT_SCL_DATUM_KIND_INT64; - datum->i = val; + datum->i = *(int64_t*)val; break; } case TSDB_DATA_TYPE_UTINYINT: @@ -4223,15 +4286,25 @@ int32_t fltSclBuildDatumFromBlockSmaValue(SFltSclDatum *datum, uint8_t type, int case TSDB_DATA_TYPE_UINT: case TSDB_DATA_TYPE_UBIGINT: { datum->kind = FLT_SCL_DATUM_KIND_UINT64; - datum->u = *(uint64_t *)&val; + datum->u = *(uint64_t *)val; break; } case TSDB_DATA_TYPE_FLOAT: case TSDB_DATA_TYPE_DOUBLE: { datum->kind = FLT_SCL_DATUM_KIND_FLOAT64; - datum->d = *(double *)&val; + datum->d = *(double *)val; break; } + case TSDB_DATA_TYPE_DECIMAL64: + datum->kind = FLT_SCL_DATUM_KIND_DECIMAL; + datum->u = *(uint64_t *)val; + break; + case TSDB_DATA_TYPE_DECIMAL: + datum->kind = FLT_SCL_DATUM_KIND_DECIMAL; + datum->pData = taosMemoryCalloc(1, tDataTypes[type].bytes); + memcpy(datum->pData, val, tDataTypes[type].bytes); + break; + // TODO:varchar/nchar/json default: { datum->kind = FLT_SCL_DATUM_KIND_NULL; @@ -4268,11 +4341,14 @@ int32_t fltSclBuildRangeFromBlockSma(SFltSclColumnRange *colRange, SColumnDataAg FLT_ERR_RET(terrno); } } + int8_t type = colRange->colNode->node.resType.type; SFltSclDatum min = {0}; - FLT_ERR_RET(fltSclBuildDatumFromBlockSmaValue(&min, colRange->colNode->node.resType.type, pAgg->min)); + min.type = colRange->colNode->node.resType; + FLT_ERR_RET(fltSclBuildDatumFromBlockSmaValue(&min, type, COL_AGG_GET_MIN_PTR(pAgg, type))); SFltSclPoint minPt = {.excl = false, .start = true, .val = min}; SFltSclDatum max = {0}; - FLT_ERR_RET(fltSclBuildDatumFromBlockSmaValue(&max, colRange->colNode->node.resType.type, pAgg->max)); + max.type = min.type; + FLT_ERR_RET(fltSclBuildDatumFromBlockSmaValue(&max, type, COL_AGG_GET_MAX_PTR(pAgg, type))); SFltSclPoint maxPt = {.excl = false, .start = false, .val = max}; if (NULL == taosArrayPush(points, &minPt)) { FLT_ERR_RET(terrno); @@ -4917,11 +4993,66 @@ _return: FLT_RET(code); } +// TODO wjm start from here, check why 这里将double赋值给整数????? +static int32_t fltSclBuildRangePointsForInOper(SFltSclOperator* oper, SArray* points) { + SNodeListNode *listNode = (SNodeListNode *)oper->valNode; + SFltSclDatum minDatum = {.kind = FLT_SCL_DATUM_KIND_INT64, .i = INT64_MAX, .type = oper->colNode->node.resType}; + SFltSclDatum maxDatum = {.kind = FLT_SCL_DATUM_KIND_INT64, .i = INT64_MIN, .type = oper->colNode->node.resType}; + SNode* nodeItem = NULL; + FOREACH(nodeItem, listNode->pNodeList) { + SValueNode *valueNode = (SValueNode *)nodeItem; + SFltSclDatum valDatum; + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, oper->colNode, valueNode)); + if(valueNode->node.resType.type == TSDB_DATA_TYPE_FLOAT || valueNode->node.resType.type == TSDB_DATA_TYPE_DOUBLE) { + minDatum.i = TMIN(minDatum.i, valDatum.d); + maxDatum.i = TMAX(maxDatum.i, valDatum.d); + } else if (IS_DECIMAL_TYPE(valueNode->node.resType.type)) { + // TODO wjm test it, looks like we cannot assign double or decimal values to int64, what if in (0, 1.9), and there is a block with all col range in 1.1-1.8. + SDecimalOps* pOps = getDecimalOps(valueNode->node.resType.type); + if (valueNode->node.resType.type == TSDB_DATA_TYPE_DECIMAL64) { + // TODO wjm do i need to convert precision and scale??? + if (pOps->gt(&minDatum.i, &valDatum.i, WORD_NUM(Decimal64))) minDatum.i = valDatum.i; + if (pOps->lt(&maxDatum.i, &valDatum.i, WORD_NUM(Decimal64))) maxDatum.i = valDatum.i; + maxDatum.kind = minDatum.kind = FLT_SCL_DATUM_KIND_DECIMAL64; + } else if (valueNode->node.resType.type == TSDB_DATA_TYPE_DECIMAL) { + if (listNode->pNodeList->pHead->pNode == nodeItem) { + // first node in list, set min/max datum + minDatum.pData = taosMemoryCalloc(1, sizeof(Decimal)); + if (!minDatum.pData) return terrno; + maxDatum.pData = taosMemoryCalloc(1, sizeof(Decimal)); + if (!maxDatum.pData) { + taosMemoryFreeClear(minDatum.pData); + return terrno; + } + DECIMAL128_CLONE((Decimal*)minDatum.pData, &decimal128Max); + DECIMAL128_CLONE((Decimal*)maxDatum.pData, &decimal128Min); + } + if (pOps->gt(minDatum.pData, valDatum.pData, WORD_NUM(Decimal))) DECIMAL128_CLONE((Decimal*)minDatum.pData, (Decimal*)valDatum.pData); + + if (pOps->lt(maxDatum.pData, valDatum.pData, WORD_NUM(Decimal))) DECIMAL128_CLONE((Decimal*)maxDatum.pData, (Decimal*)valDatum.pData); + maxDatum.kind = minDatum.kind = FLT_SCL_DATUM_KIND_DECIMAL; + } + } else { + minDatum.i = TMIN(minDatum.i, valDatum.i); + maxDatum.i = TMAX(maxDatum.i, valDatum.i); + } + } + SFltSclPoint startPt = {.start = true, .excl = false, .val = minDatum}; + SFltSclPoint endPt = {.start = false, .excl = false, .val = maxDatum}; + if (NULL == taosArrayPush(points, &startPt)) { + FLT_ERR_RET(terrno); + } + if (NULL == taosArrayPush(points, &endPt)) { + FLT_ERR_RET(terrno); + } + FLT_RET(0); +} + int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { switch (oper->type) { case OP_TYPE_GREATER_THAN: { SFltSclDatum start; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&start, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&start, oper->colNode, oper->valNode)); SFltSclPoint startPt = {.start = true, .excl = true, .val = start}; SFltSclDatum end = {.kind = FLT_SCL_DATUM_KIND_MAX, .type = oper->colNode->node.resType}; SFltSclPoint endPt = {.start = false, .excl = false, .val = end}; @@ -4935,7 +5066,7 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { } case OP_TYPE_GREATER_EQUAL: { SFltSclDatum start; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&start, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&start, oper->colNode, oper->valNode)); SFltSclPoint startPt = {.start = true, .excl = false, .val = start}; SFltSclDatum end = {.kind = FLT_SCL_DATUM_KIND_MAX, .type = oper->colNode->node.resType}; SFltSclPoint endPt = {.start = false, .excl = false, .val = end}; @@ -4949,7 +5080,7 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { } case OP_TYPE_LOWER_THAN: { SFltSclDatum end; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&end, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&end, oper->colNode, oper->valNode)); SFltSclPoint endPt = {.start = false, .excl = true, .val = end}; SFltSclDatum start = {.kind = FLT_SCL_DATUM_KIND_MIN, .type = oper->colNode->node.resType}; SFltSclPoint startPt = {.start = true, .excl = false, .val = start}; @@ -4963,7 +5094,7 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { } case OP_TYPE_LOWER_EQUAL: { SFltSclDatum end; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&end, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&end, oper->colNode, oper->valNode)); SFltSclPoint endPt = {.start = false, .excl = false, .val = end}; SFltSclDatum start = {.kind = FLT_SCL_DATUM_KIND_MIN, .type = oper->colNode->node.resType}; SFltSclPoint startPt = {.start = true, .excl = false, .val = start}; @@ -4977,7 +5108,7 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { } case OP_TYPE_EQUAL: { SFltSclDatum valDatum; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, oper->colNode, oper->valNode)); SFltSclPoint startPt = {.start = true, .excl = false, .val = valDatum}; SFltSclPoint endPt = {.start = false, .excl = false, .val = valDatum}; if (NULL == taosArrayPush(points, &startPt)) { @@ -4990,7 +5121,7 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { } case OP_TYPE_NOT_EQUAL: { SFltSclDatum valDatum; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, oper->valNode)); + FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, oper->colNode, oper->valNode)); { SFltSclDatum start = {.kind = FLT_SCL_DATUM_KIND_MIN, .type = oper->colNode->node.resType}; SFltSclPoint startPt = {.start = true, .excl = false, .val = start}; @@ -5041,31 +5172,8 @@ int32_t fltSclBuildRangePoints(SFltSclOperator *oper, SArray *points) { break; } case OP_TYPE_IN: { - SNodeListNode *listNode = (SNodeListNode *)oper->valNode; - SFltSclDatum minDatum = {.kind = FLT_SCL_DATUM_KIND_INT64, .i = INT64_MAX, .type = oper->colNode->node.resType}; - SFltSclDatum maxDatum = {.kind = FLT_SCL_DATUM_KIND_INT64, .i = INT64_MIN, .type = oper->colNode->node.resType}; - SNode* nodeItem = NULL; - FOREACH(nodeItem, listNode->pNodeList) { - SValueNode *valueNode = (SValueNode *)nodeItem; - SFltSclDatum valDatum; - FLT_ERR_RET(fltSclBuildDatumFromValueNode(&valDatum, valueNode)); - if(valueNode->node.resType.type == TSDB_DATA_TYPE_FLOAT || valueNode->node.resType.type == TSDB_DATA_TYPE_DOUBLE) { - minDatum.i = TMIN(minDatum.i, valDatum.d); - maxDatum.i = TMAX(maxDatum.i, valDatum.d); - } else { - minDatum.i = TMIN(minDatum.i, valDatum.i); - maxDatum.i = TMAX(maxDatum.i, valDatum.i); - } - } - SFltSclPoint startPt = {.start = true, .excl = false, .val = minDatum}; - SFltSclPoint endPt = {.start = false, .excl = false, .val = maxDatum}; - if (NULL == taosArrayPush(points, &startPt)) { - FLT_ERR_RET(terrno); - } - if (NULL == taosArrayPush(points, &endPt)) { - FLT_ERR_RET(terrno); - } - break; + FLT_ERR_RET(fltSclBuildRangePointsForInOper(oper, points)); + break; } default: { qError("not supported operator type : %d when build range points", oper->type); diff --git a/source/libs/scalar/src/sclfunc.c b/source/libs/scalar/src/sclfunc.c index 87aefd0d4a..38ab814d87 100644 --- a/source/libs/scalar/src/sclfunc.c +++ b/source/libs/scalar/src/sclfunc.c @@ -3260,6 +3260,7 @@ int32_t countScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam return TSDB_CODE_SUCCESS; } +// TODO wjm what is sum scalar function??? int32_t sumScalarFunction(SScalarParam *pInput, int32_t inputNum, SScalarParam *pOutput) { SColumnInfoData *pInputData = pInput->columnData; SColumnInfoData *pOutputData = pOutput->columnData; diff --git a/source/util/CMakeLists.txt b/source/util/CMakeLists.txt index 207c005bee..934c356c64 100644 --- a/source/util/CMakeLists.txt +++ b/source/util/CMakeLists.txt @@ -47,7 +47,7 @@ else() util PUBLIC os common PUBLIC lz4_static pcre2-8 - PUBLIC api cjson geos_c TSZ + PUBLIC api cjson geos_c TSZ decimal ) endif() diff --git a/source/util/src/tcompare.c b/source/util/src/tcompare.c index 14f848ec26..b0ccc12e4e 100644 --- a/source/util/src/tcompare.c +++ b/source/util/src/tcompare.c @@ -1056,6 +1056,20 @@ int32_t compareDecimal128(const void* pleft, const void* pright) { return 0; } +int32_t compareDecimal64SameScale(const void* pleft, const void* pright) { + SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL64); + if (pOps->gt(pleft, pright, WORD_NUM(Decimal64))) return 1; + if (pOps->lt(pleft, pright, WORD_NUM(Decimal64))) return -1; + return 0; +} + +int32_t compareDecimal128SameScale(const void* pleft, const void* pright) { + SDecimalOps* pOps = getDecimalOps(TSDB_DATA_TYPE_DECIMAL); + if (pOps->gt(pleft, pright, WORD_NUM(Decimal))) return 1; + if (pOps->lt(pleft, pright, WORD_NUM(Decimal))) return -1; + return 0; +} + int32_t compareJsonValDesc(const void *pLeft, const void *pRight) { return compareJsonVal(pRight, pLeft); } /* diff --git a/tests/system-test/2-query/decimal.py b/tests/system-test/2-query/decimal.py index f7568826a5..a75cd6974e 100644 --- a/tests/system-test/2-query/decimal.py +++ b/tests/system-test/2-query/decimal.py @@ -227,7 +227,7 @@ class TableInserter: self.tags_types = tags_types self.columns_types = columns_types - def insert(self, rows: int, start_ts: int, step: int): + def insert(self, rows: int, start_ts: int, step: int, flush_database: bool = False): pre_insert = f"insert into {self.dbName}.{self.tbName} values" sql = pre_insert for i in range(rows): @@ -242,12 +242,17 @@ class TableInserter: sql += ")" if i != rows - 1: sql += ", " + local_flush_database = i % 5000 == 0; if len(sql) > 1000: tdLog.debug(f"insert into with sql{sql}") + if flush_database and local_flush_database: + self.conn.execute(f"flush database {self.dbName}", queryTimes=1) self.conn.execute(sql, queryTimes=1) sql = pre_insert if len(sql) > len(pre_insert): tdLog.debug(f"insert into with sql{sql}") + if flush_database: + self.conn.execute(f"flush database {self.dbName}", queryTimes=1) self.conn.execute(sql, queryTimes=1) class TDTestCase: @@ -461,7 +466,7 @@ class TDTestCase: pass #TableInserter(tdSql, self.db_name, f"{self.c_table_prefix}{i}", self.columns, self.tags).insert(1, 1537146000000, 500) - TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(100, 1537146000000, 500) + TableInserter(tdSql, self.db_name, self.norm_table_name, self.columns).insert(100000, 1537146000000, 500, flush_database=True) ## insert null/None for decimal type @@ -478,7 +483,7 @@ class TDTestCase: DataType(TypeEnum.VARCHAR, 255), ] DecimalColumnTableCreater(tdSql, self.db_name, "tt", columns, []).create() - TableInserter(tdSql, self.db_name, 'tt', columns).insert(1, 1537146000000, 500) + TableInserter(tdSql, self.db_name, 'tt', columns).insert(100000, 1537146000000, 500, flush_database=True) def test_decimal_ddl(self): tdSql.execute("create database test", queryTimes=1)