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)