From a4e0bbd34f1bbafe96503ad9d6b5b84576fb3509 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Wed, 14 Dec 2022 20:29:58 +0800 Subject: [PATCH 01/15] fix(query): fixed avg function sum over range --- source/libs/function/inc/builtinsimpl.h | 1 + .../libs/function/src/detail/tavgfunction.c | 102 ++++++++++++++++-- 2 files changed, 93 insertions(+), 10 deletions(-) diff --git a/source/libs/function/inc/builtinsimpl.h b/source/libs/function/inc/builtinsimpl.h index 307a82e256..a7ac53fab6 100644 --- a/source/libs/function/inc/builtinsimpl.h +++ b/source/libs/function/inc/builtinsimpl.h @@ -32,6 +32,7 @@ typedef struct SSumRes { int16_t type; int64_t prevTs; bool isPrevTsSet; + bool overflow; // if overflow is true, dsum to be used for any type; } SSumRes; typedef struct SMinmaxResInfo { diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 60bf30d8ed..98ed7f818d 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -373,7 +373,16 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.isum += plist[i]; + + // check overflow for int + if(pRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pRes->sum.isum <= plist[i] || + pRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pRes->sum.isum >= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pRes->sum.overflow = true; + pRes->sum.dsum = dsum + plist[i]; + } else { + pRes->sum.isum += plist[i]; + } } break; @@ -388,7 +397,16 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.isum += plist[i]; + + // check overflow + if(pRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pRes->sum.isum <= plist[i] || + pRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pRes->sum.isum >= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pRes->sum.overflow = true; + pRes->sum.dsum = dsum + plist[i]; + } else { + pRes->sum.isum += plist[i]; + } } break; } @@ -431,7 +449,16 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.usum += plist[i]; + + // check overflow + if(UINT64_MAX - pRes->sum.usum <= plist[i] ) { + double dsum = (double) pRes->sum.isum; + pRes->sum.overflow = true; + pRes->sum.dsum = dsum + plist[i]; + } else { + pRes->sum.usum += (uint32_t)plist[i]; + } + } break; @@ -446,7 +473,15 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.usum += plist[i]; + + // check overflow + if(UINT64_MAX - pRes->sum.usum <= plist[i] ) { + double dsum = (double) pRes->sum.isum; + pRes->sum.overflow = true; + pRes->sum.dsum = dsum + plist[i]; + } else { + pRes->sum.usum += (uint64_t)plist[i]; + } } break; } @@ -565,9 +600,24 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_INT) { - pAvgRes->sum.isum += plist[i]; + // check overflow for int + if(pAvgRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pAvgRes->sum.isum <= plist[i] || + pAvgRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pAvgRes->sum.isum >= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pAvgRes->sum.overflow = true; + pAvgRes->sum.dsum = dsum + plist[i]; + } else { + pAvgRes->sum.isum += plist[i]; + } } else { - pAvgRes->sum.usum += (uint32_t)plist[i]; + // check overflow for uint + if(UINT64_MAX - pAvgRes->sum.usum <= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pAvgRes->sum.overflow = true; + pAvgRes->sum.dsum = dsum + plist[i]; + } else { + pAvgRes->sum.usum += (uint32_t)plist[i]; + } } } } @@ -584,9 +634,24 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_BIGINT) { - pAvgRes->sum.isum += plist[i]; + // check overflow for int + if(pAvgRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pAvgRes->sum.isum <= plist[i] || + pAvgRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pAvgRes->sum.isum >= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pAvgRes->sum.overflow = true; + pAvgRes->sum.dsum = dsum + plist[i]; + } else { + pAvgRes->sum.isum += plist[i]; + } } else { - pAvgRes->sum.usum += (uint64_t)plist[i]; + // check overflow for uint + if(UINT64_MAX - pAvgRes->sum.usum <= plist[i] ) { + double dsum = (double) pAvgRes->sum.isum; + pAvgRes->sum.overflow = true; + pAvgRes->sum.dsum = dsum + plist[i]; + } else { + pAvgRes->sum.usum += (uint64_t)plist[i]; + } } } } @@ -639,9 +704,26 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { - pOutput->sum.isum += pInput->sum.isum; + int64_t val = pInput->sum.isum; + // check overflow + if(pOutput->sum.isum > 0 && val > 0 && INT64_MAX - pOutput->sum.isum <= val || + pOutput->sum.isum < 0 && val < 0 && INT64_MIN - pOutput->sum.isum >= val ) { + double dsum = (double) pOutput->sum.isum; + pOutput->sum.overflow = true; + pOutput->sum.dsum = dsum + val; + } else { + pOutput->sum.isum += val; + } } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { - pOutput->sum.usum += pInput->sum.usum; + // check overflow + uint64_t val = pInput->sum.usum; + if(UINT64_MAX - pOutput->sum.usum <= val ) { + double dsum = (double) pOutput->sum.isum; + pOutput->sum.overflow = true; + pOutput->sum.dsum = dsum + val; + } else { + pOutput->sum.usum += val; + } } else { pOutput->sum.dsum += pInput->sum.dsum; } From 74cf77643909f47f394cb7522e3d50e52c05cb35 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Wed, 14 Dec 2022 21:34:50 +0800 Subject: [PATCH 02/15] fix(query): avg function sum overflow --- source/libs/function/src/detail/tavgfunction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 98ed7f818d..193922e218 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -377,7 +377,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol // check overflow for int if(pRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pRes->sum.isum <= plist[i] || pRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pRes->sum.isum >= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; + double dsum = (double) pRes->sum.isum; pRes->sum.overflow = true; pRes->sum.dsum = dsum + plist[i]; } else { From 500ee304a6fff8f0197262baaf8d06b5d8e5d92a Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 12:43:28 +0800 Subject: [PATCH 03/15] fix(query): avg sum over range replace with macro --- .../libs/function/src/detail/tavgfunction.c | 154 ++++++------------ 1 file changed, 52 insertions(+), 102 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 193922e218..f3bfa39798 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -41,6 +41,31 @@ } \ } while (0) +// define signed number sum with check overflow +#define CHECK_OVERFLOW_SUM_SIGNED(out, val) \ + if (out->sum.overflow) { \ + out->sum.dsum += val; \ + } else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \ + out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val) { \ + double dsum = (double)out->sum.isum; \ + out->sum.overflow = true; \ + out->sum.dsum = dsum + val; \ + } else { \ + out->sum.isum += val; \ + } + +// define unsigned number sum with check overflow +#define CHECK_OVERFLOW_SUM_UNSIGNED (out, val) \ + if (out->sum.overflow) { \ + out->sum.dsum += val; \ + } else if (UINT64_MAX - out->sum.usum <= val) { \ + double dsum = (double)out->sum.usum; \ + out->sum.overflow = true; \ + out->sum.dsum = dsum + val; \ + } else { \ + out->sum.usum += val; \ + } + typedef struct SAvgRes { double result; SSumRes sum; @@ -344,7 +369,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.isum += plist[i]; + CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]) } break; @@ -359,7 +384,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.isum += plist[i]; + CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]) } break; } @@ -373,16 +398,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - - // check overflow for int - if(pRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pRes->sum.isum <= plist[i] || - pRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pRes->sum.isum >= plist[i] ) { - double dsum = (double) pRes->sum.isum; - pRes->sum.overflow = true; - pRes->sum.dsum = dsum + plist[i]; - } else { - pRes->sum.isum += plist[i]; - } + CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]) } break; @@ -397,16 +413,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - - // check overflow - if(pRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pRes->sum.isum <= plist[i] || - pRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pRes->sum.isum >= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; - pRes->sum.overflow = true; - pRes->sum.dsum = dsum + plist[i]; - } else { - pRes->sum.isum += plist[i]; - } + CHECK_OVERFLOW_SUM_SIGNED(pRes, plist[i]) } break; } @@ -420,7 +427,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.usum += plist[i]; + CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]) } break; @@ -435,7 +442,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - pRes->sum.usum += plist[i]; + CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]) } break; } @@ -449,16 +456,7 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; - - // check overflow - if(UINT64_MAX - pRes->sum.usum <= plist[i] ) { - double dsum = (double) pRes->sum.isum; - pRes->sum.overflow = true; - pRes->sum.dsum = dsum + plist[i]; - } else { - pRes->sum.usum += (uint32_t)plist[i]; - } - + CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]) } break; @@ -473,15 +471,8 @@ static int32_t doAddNumericVector(SColumnInfoData* pCol, int32_t type, SInputCol numOfElems += 1; pRes->count += 1; + CHECK_OVERFLOW_SUM_UNSIGNED(pRes, plist[i]) - // check overflow - if(UINT64_MAX - pRes->sum.usum <= plist[i] ) { - double dsum = (double) pRes->sum.isum; - pRes->sum.overflow = true; - pRes->sum.dsum = dsum + plist[i]; - } else { - pRes->sum.usum += (uint64_t)plist[i]; - } } break; } @@ -563,8 +554,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_TINYINT) { pAvgRes->sum.isum += plist[i]; + CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) } else { - pAvgRes->sum.usum += (uint8_t)plist[i]; + CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint8_t)plist[i]) } } } @@ -581,9 +573,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_SMALLINT) { - pAvgRes->sum.isum += plist[i]; + CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) } else { - pAvgRes->sum.usum += (uint16_t)plist[i]; + CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint16_t)plist[i]) } } } @@ -600,24 +592,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_INT) { - // check overflow for int - if(pAvgRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pAvgRes->sum.isum <= plist[i] || - pAvgRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pAvgRes->sum.isum >= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; - pAvgRes->sum.overflow = true; - pAvgRes->sum.dsum = dsum + plist[i]; - } else { - pAvgRes->sum.isum += plist[i]; - } + CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) } else { - // check overflow for uint - if(UINT64_MAX - pAvgRes->sum.usum <= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; - pAvgRes->sum.overflow = true; - pAvgRes->sum.dsum = dsum + plist[i]; - } else { - pAvgRes->sum.usum += (uint32_t)plist[i]; - } + CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint32_t)plist[i]) } } } @@ -634,24 +611,9 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_BIGINT) { - // check overflow for int - if(pAvgRes->sum.isum > 0 && plist[i] > 0 && INT64_MAX - pAvgRes->sum.isum <= plist[i] || - pAvgRes->sum.isum < 0 && plist[i] < 0 && INT64_MIN - pAvgRes->sum.isum >= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; - pAvgRes->sum.overflow = true; - pAvgRes->sum.dsum = dsum + plist[i]; - } else { - pAvgRes->sum.isum += plist[i]; - } - } else { - // check overflow for uint - if(UINT64_MAX - pAvgRes->sum.usum <= plist[i] ) { - double dsum = (double) pAvgRes->sum.isum; - pAvgRes->sum.overflow = true; - pAvgRes->sum.dsum = dsum + plist[i]; - } else { - pAvgRes->sum.usum += (uint64_t)plist[i]; - } + CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) +\ } else { + CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint64_t)plist[i]) } } } @@ -697,6 +659,8 @@ _over: return TSDB_CODE_SUCCESS; } + + static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { if (IS_NULL_TYPE(pInput->type)) { return; @@ -704,26 +668,9 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { - int64_t val = pInput->sum.isum; - // check overflow - if(pOutput->sum.isum > 0 && val > 0 && INT64_MAX - pOutput->sum.isum <= val || - pOutput->sum.isum < 0 && val < 0 && INT64_MIN - pOutput->sum.isum >= val ) { - double dsum = (double) pOutput->sum.isum; - pOutput->sum.overflow = true; - pOutput->sum.dsum = dsum + val; - } else { - pOutput->sum.isum += val; - } + CHECK_OVERFLOW_SUM_SIGNED(pOutput, pInput->sum.isum) } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { - // check overflow - uint64_t val = pInput->sum.usum; - if(UINT64_MAX - pOutput->sum.usum <= val ) { - double dsum = (double) pOutput->sum.isum; - pOutput->sum.overflow = true; - pOutput->sum.dsum = dsum + val; - } else { - pOutput->sum.usum += val; - } + CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, pInput->sum.usum) } else { pOutput->sum.dsum += pInput->sum.dsum; } @@ -823,9 +770,9 @@ int32_t avgCombine(SqlFunctionCtx* pDestCtx, SqlFunctionCtx* pSourceCtx) { int16_t type = pDBuf->type == TSDB_DATA_TYPE_NULL ? pSBuf->type : pDBuf->type; if (IS_SIGNED_NUMERIC_TYPE(type)) { - pDBuf->sum.isum += pSBuf->sum.isum; + CHECK_OVERFLOW_SUM_SIGNED(pDBuf, pSBuf->sum.isum) } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { - pDBuf->sum.usum += pSBuf->sum.usum; + CHECK_OVERFLOW_SUM_UNSIGNED(pDBuf, pSBuf->sum.usum) } else { pDBuf->sum.dsum += pSBuf->sum.dsum; } @@ -841,7 +788,10 @@ int32_t avgFinalize(SqlFunctionCtx* pCtx, SSDataBlock* pBlock) { int32_t type = pRes->type; if (pRes->count > 0) { - if (IS_SIGNED_NUMERIC_TYPE(type)) { + if(pRes->sum.overflow) { + // overflow flag set , use dsum + pRes->result = pRes->sum.dsum / ((double)pRes->count); + }else if (IS_SIGNED_NUMERIC_TYPE(type)) { pRes->result = pRes->sum.isum / ((double)pRes->count); } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { pRes->result = pRes->sum.usum / ((double)pRes->count); From e9f7572a5491a0fc823a45ba5aeb91ae7f4d35e2 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 14:52:53 +0800 Subject: [PATCH 04/15] fix(query): avg sum operation check range --- source/libs/function/src/detail/tavgfunction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index f3bfa39798..e31db0f360 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -55,7 +55,7 @@ } // define unsigned number sum with check overflow -#define CHECK_OVERFLOW_SUM_UNSIGNED (out, val) \ +#define CHECK_OVERFLOW_SUM_UNSIGNED(out, val) \ if (out->sum.overflow) { \ out->sum.dsum += val; \ } else if (UINT64_MAX - out->sum.usum <= val) { \ From 1ac428ff61c755694233478097fa52e041a44109 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 14:54:22 +0800 Subject: [PATCH 05/15] fix(query): avg sum operation check range build error --- source/libs/function/src/detail/tavgfunction.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index e31db0f360..657320f7ff 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -612,7 +612,7 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_BIGINT) { CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) -\ } else { + } else { CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint64_t)plist[i]) } } From 01309501704226bddf57b84fb84f1ba1b4d88ea0 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 15:32:53 +0800 Subject: [PATCH 06/15] fix(query): avg sum operation check range merge two SAvgRes pointer --- source/libs/function/src/detail/tavgfunction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 657320f7ff..04f5c99d47 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -668,9 +668,9 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_SIGNED(pOutput, pInput->sum.isum) + CHECK_OVERFLOW_SUM_SIGNED(pOutput, pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.isum) } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, pInput->sum.usum) + CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.usum) } else { pOutput->sum.dsum += pInput->sum.dsum; } From 7fa0a2e0b59639bdd2f7c52e2243fe5906867ee4 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 17:10:53 +0800 Subject: [PATCH 07/15] fix(query): avg function check overflow range add case --- tests/system-test/2-query/avg.py | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/tests/system-test/2-query/avg.py b/tests/system-test/2-query/avg.py index 1d4d9a2494..4cad127111 100644 --- a/tests/system-test/2-query/avg.py +++ b/tests/system-test/2-query/avg.py @@ -425,7 +425,35 @@ class TDTestCase: tdSql.checkData(0,4,2.9142856660228804e+37) tdSql.checkData(0,5,None) + # + # test bigint to check overflow + # + def avg_check_overflow(self): + # create db + tdSql.execute(f"drop database if exists db") + tdSql.execute(f"create database if not exists db") + time.sleep(3) + tdSql.execute(f"use db") + tdSql.execute(f"create table st(ts timestamp, ibv bigint, ubv bigint unsigned) tags(area int)") + # insert t1 data + tdSql.execute(f"insert into t1 using st tags(1) values(now,9223372036854775801,18446744073709551611)") + tdSql.execute(f"insert into t1 using st tags(1) values(now,8223372036854775801,17446744073709551611)") + tdSql.execute(f"insert into t1 using st tags(1) values(now,7223372036854775801,16446744073709551611)") + # insert t2 data + tdSql.execute(f"insert into t2 using st tags(2) values(now,9223372036854775801,18446744073709551611)") + tdSql.execute(f"insert into t2 using st tags(2) values(now,8223372036854775801,17446744073709551611)") + tdSql.execute(f"insert into t2 using st tags(2) values(now,7223372036854775801,16446744073709551611)") + + # check single table answer + tdSql.query(f"select avg(ibv), avg(ubv) from t1") + tdSql.checkRows(1) + tdSql.checkData(0, 0,8.223372036854776e+18) + tdSql.checkData(0, 1,1.744674407370955e+19) + tdSql.query(f"select avg(ibv), avg(ubv) from st") + tdSql.checkRows(1) + tdSql.checkData(0, 0,8.223372036854776e+18) + tdSql.checkData(0, 1,1.744674407370955e+19) def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring tdSql.prepare() @@ -455,6 +483,8 @@ class TDTestCase: self.avg_func_filter() self.avg_check_unsigned() + # check avg overflow + self.avg_check_overflow() def stop(self): tdSql.close() tdLog.success(f"{__file__} successfully executed") From 3fb64bf078d565a694a21153f35f4265b15d1e4a Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Thu, 15 Dec 2022 17:58:33 +0800 Subject: [PATCH 08/15] fix(query): avg function check overflow case --- tests/system-test/2-query/avg.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/system-test/2-query/avg.py b/tests/system-test/2-query/avg.py index 4cad127111..29603e63f7 100644 --- a/tests/system-test/2-query/avg.py +++ b/tests/system-test/2-query/avg.py @@ -409,7 +409,7 @@ class TDTestCase: tdSql.query(f"select avg(c1) ,avg(c2) , avg(c3) , avg(c4), avg(c5), avg(c6) from {dbname}.sub1_bound ") tdSql.checkRows(1) tdSql.checkData(0,0,920350133.571428537) - tdSql.checkData(0,1,1.3176245766935393e+18) + tdSql.checkData(0,1,3.952873730080618e+18) tdSql.checkData(0,2,14042.142857143) tdSql.checkData(0,3,53.571428571) tdSql.checkData(0,4,5.828571332045761e+37) From ba31ce80701ac408ebea95a46f21f0dd577bb51e Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sat, 17 Dec 2022 10:46:13 +0800 Subject: [PATCH 09/15] feat(query): avg function check range overflow --- source/libs/function/src/detail/tavgfunction.c | 1 - 1 file changed, 1 deletion(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 04f5c99d47..1473a89bd7 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -553,7 +553,6 @@ int32_t avgFunction(SqlFunctionCtx* pCtx) { } else { for (int32_t i = pInput->startRowIndex; i < pInput->numOfRows + pInput->startRowIndex; ++i) { if (type == TSDB_DATA_TYPE_TINYINT) { - pAvgRes->sum.isum += plist[i]; CHECK_OVERFLOW_SUM_SIGNED(pAvgRes, plist[i]) } else { CHECK_OVERFLOW_SUM_UNSIGNED(pAvgRes, (uint8_t)plist[i]) From 110ed6b4b37ea088e3b1417d5bbb33fd2109e7cd Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sat, 17 Dec 2022 11:40:00 +0800 Subject: [PATCH 10/15] fix(query): avg funciton add case --- tests/system-test/2-query/avg.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/tests/system-test/2-query/avg.py b/tests/system-test/2-query/avg.py index 29603e63f7..3e670232f3 100644 --- a/tests/system-test/2-query/avg.py +++ b/tests/system-test/2-query/avg.py @@ -419,7 +419,7 @@ class TDTestCase: # check + - * / in functions tdSql.query(f" select avg(c1+1) ,avg(c2) , avg(c3*1) , avg(c4/2), avg(c5)/2, avg(c6) from {dbname}.sub1_bound ") tdSql.checkData(0,0,920350134.5714285) - tdSql.checkData(0,1,1.3176245766935393e+18) + tdSql.checkData(0,1,3.952873730080618e+18) tdSql.checkData(0,2,14042.142857143) tdSql.checkData(0,3,26.785714286) tdSql.checkData(0,4,2.9142856660228804e+37) @@ -450,11 +450,26 @@ class TDTestCase: tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) + # check super table tdSql.query(f"select avg(ibv), avg(ubv) from st") tdSql.checkRows(1) tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) + # check child query + tdSql.query(f"select avg(ibv), avg(ubv) from (select * from st)") + tdSql.checkRows(1) + tdSql.checkData(0, 0,8.223372036854776e+18) + tdSql.checkData(0, 1,1.744674407370955e+19) + + # check group by + tdSql.query(f"select avg(ibv), avg(ubv) from st group by tbname") + tdSql.checkRows(2) + tdSql.checkData(0, 0,8.223372036854776e+18) + tdSql.checkData(0, 1,1.744674407370955e+19) + tdSql.checkData(1, 0,8.223372036854776e+18) + tdSql.checkData(1, 1,1.744674407370955e+19) + def run(self): # sourcery skip: extract-duplicate-method, remove-redundant-fstring tdSql.prepare() From 680b7aa090aec54cadef245f74e1104d036948a1 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sat, 17 Dec 2022 16:59:25 +0800 Subject: [PATCH 11/15] fix(query): avg fix case error --- tests/system-test/2-query/avg.py | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/tests/system-test/2-query/avg.py b/tests/system-test/2-query/avg.py index 3e670232f3..dd8b38f9ea 100644 --- a/tests/system-test/2-query/avg.py +++ b/tests/system-test/2-query/avg.py @@ -434,36 +434,36 @@ class TDTestCase: tdSql.execute(f"create database if not exists db") time.sleep(3) tdSql.execute(f"use db") - tdSql.execute(f"create table st(ts timestamp, ibv bigint, ubv bigint unsigned) tags(area int)") + tdSql.execute(f"create table db.st(ts timestamp, ibv bigint, ubv bigint unsigned) tags(area int)") # insert t1 data - tdSql.execute(f"insert into t1 using st tags(1) values(now,9223372036854775801,18446744073709551611)") - tdSql.execute(f"insert into t1 using st tags(1) values(now,8223372036854775801,17446744073709551611)") - tdSql.execute(f"insert into t1 using st tags(1) values(now,7223372036854775801,16446744073709551611)") + tdSql.execute(f"insert into db.t1 using db.st tags(1) values(now,9223372036854775801,18446744073709551611)") + tdSql.execute(f"insert into db.t1 using db.st tags(1) values(now,8223372036854775801,17446744073709551611)") + tdSql.execute(f"insert into db.t1 using db.st tags(1) values(now,7223372036854775801,16446744073709551611)") # insert t2 data - tdSql.execute(f"insert into t2 using st tags(2) values(now,9223372036854775801,18446744073709551611)") - tdSql.execute(f"insert into t2 using st tags(2) values(now,8223372036854775801,17446744073709551611)") - tdSql.execute(f"insert into t2 using st tags(2) values(now,7223372036854775801,16446744073709551611)") + tdSql.execute(f"insert into db.t2 using db.st tags(2) values(now,9223372036854775801,18446744073709551611)") + tdSql.execute(f"insert into db.t2 using db.st tags(2) values(now,8223372036854775801,17446744073709551611)") + tdSql.execute(f"insert into db.t2 using db.st tags(2) values(now,7223372036854775801,16446744073709551611)") # check single table answer - tdSql.query(f"select avg(ibv), avg(ubv) from t1") + tdSql.query(f"select avg(ibv), avg(ubv) from db.t1") tdSql.checkRows(1) tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) # check super table - tdSql.query(f"select avg(ibv), avg(ubv) from st") + tdSql.query(f"select avg(ibv), avg(ubv) from db.st") tdSql.checkRows(1) tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) # check child query - tdSql.query(f"select avg(ibv), avg(ubv) from (select * from st)") + tdSql.query(f"select avg(ibv), avg(ubv) from (select * from db.st)") tdSql.checkRows(1) tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) # check group by - tdSql.query(f"select avg(ibv), avg(ubv) from st group by tbname") + tdSql.query(f"select avg(ibv), avg(ubv) from db.st group by tbname") tdSql.checkRows(2) tdSql.checkData(0, 0,8.223372036854776e+18) tdSql.checkData(0, 1,1.744674407370955e+19) From ea5bf3d31e8f7c607cfb9ae56762333497e4a153 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sat, 17 Dec 2022 17:15:44 +0800 Subject: [PATCH 12/15] fix(query): fix(query): avg check overflow --- source/libs/function/src/detail/tavgfunction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 1473a89bd7..5f1a4675ea 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -344,9 +344,9 @@ static int32_t calculateAvgBySMAInfo(SAvgRes* pRes, int32_t numOfRows, int32_t t pRes->count += numOfElem; if (IS_SIGNED_NUMERIC_TYPE(type)) { - pRes->sum.isum += pAgg->sum; + CHECK_OVERFLOW_SUM_SIGNED(pRes, pAgg->sum); } else if (IS_UNSIGNED_NUMERIC_TYPE(type)) { - pRes->sum.usum += pAgg->sum; + CHECK_OVERFLOW_SUM_UNSIGNED(pRes, pAgg->sum); } else if (IS_FLOAT_TYPE(type)) { pRes->sum.dsum += GET_DOUBLE_VAL((const char*)&(pAgg->sum)); } From 1b8199d98d8cab140f15f958c7a3d2e7c249f6d5 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sat, 17 Dec 2022 20:38:03 +0800 Subject: [PATCH 13/15] fix(query): avg function check overflow mac build --- source/libs/function/src/detail/tavgfunction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index 5f1a4675ea..adc7aae559 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -667,9 +667,9 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_SIGNED(pOutput, pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.isum) + CHECK_OVERFLOW_SUM_SIGNED(pOutput, (pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.isum)) } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.usum) + CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, (pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.usum)) } else { pOutput->sum.dsum += pInput->sum.dsum; } From 1a75e9bb58cb1cb473d8446bd498f3026939e01c Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sun, 18 Dec 2022 15:15:13 +0800 Subject: [PATCH 14/15] feat(query): avg function overflow add big check --- .../libs/function/src/detail/tavgfunction.c | 34 ++++++++++++++++--- 1 file changed, 30 insertions(+), 4 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index adc7aae559..b124678559 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -54,6 +54,20 @@ out->sum.isum += val; \ } +// val is big than INT64_MAX, val come from merge +#define CHECK_OVERFLOW_SUM_SIGNED_BIG(out, val, big) \ + if (out->sum.overflow) { \ + out->sum.dsum += val; \ + } else if (out->sum.isum > 0 && val > 0 && INT64_MAX - out->sum.isum <= val || \ + out->sum.isum < 0 && val < 0 && INT64_MIN - out->sum.isum >= val || \ + big) { \ + double dsum = (double)out->sum.isum; \ + out->sum.overflow = true; \ + out->sum.dsum = dsum + val; \ + } else { \ + out->sum.isum += val; \ + } + // define unsigned number sum with check overflow #define CHECK_OVERFLOW_SUM_UNSIGNED(out, val) \ if (out->sum.overflow) { \ @@ -66,6 +80,18 @@ out->sum.usum += val; \ } +// val is big than UINT64_MAX, val come from merge +#define CHECK_OVERFLOW_SUM_UNSIGNED_BIG(out, val, big) \ + if (out->sum.overflow) { \ + out->sum.dsum += val; \ + } else if (UINT64_MAX - out->sum.usum <= val || big) { \ + double dsum = (double)out->sum.usum; \ + out->sum.overflow = true; \ + out->sum.dsum = dsum + val; \ + } else { \ + out->sum.usum += val; \ + } + typedef struct SAvgRes { double result; SSumRes sum; @@ -658,8 +684,6 @@ _over: return TSDB_CODE_SUCCESS; } - - static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { if (IS_NULL_TYPE(pInput->type)) { return; @@ -667,9 +691,11 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_SIGNED(pOutput, (pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.isum)) + bool overflow = pInput->sum.overflow; + CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, overflow ? pInput->sum.dsum : pInput->sum.isum, overflow); } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { - CHECK_OVERFLOW_SUM_UNSIGNED(pOutput, (pInput->sum.overflow ? pInput->sum.dsum : pInput->sum.usum)) + bool overflow = pInput->sum.overflow; + CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, overflow ? pInput->sum.dsum : pInput->sum.usum, overflow); } else { pOutput->sum.dsum += pInput->sum.dsum; } From 0a5fd77b17e950014d246c3278387d44b4d24729 Mon Sep 17 00:00:00 2001 From: Alex Duan <417921451@qq.com> Date: Sun, 18 Dec 2022 19:04:38 +0800 Subject: [PATCH 15/15] feat(query): avg function overflow mac build --- source/libs/function/src/detail/tavgfunction.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/libs/function/src/detail/tavgfunction.c b/source/libs/function/src/detail/tavgfunction.c index b124678559..8e010181d1 100644 --- a/source/libs/function/src/detail/tavgfunction.c +++ b/source/libs/function/src/detail/tavgfunction.c @@ -692,10 +692,10 @@ static void avgTransferInfo(SAvgRes* pInput, SAvgRes* pOutput) { pOutput->type = pInput->type; if (IS_SIGNED_NUMERIC_TYPE(pOutput->type)) { bool overflow = pInput->sum.overflow; - CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, overflow ? pInput->sum.dsum : pInput->sum.isum, overflow); + CHECK_OVERFLOW_SUM_SIGNED_BIG(pOutput, (overflow ? pInput->sum.dsum : pInput->sum.isum), overflow); } else if (IS_UNSIGNED_NUMERIC_TYPE(pOutput->type)) { bool overflow = pInput->sum.overflow; - CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, overflow ? pInput->sum.dsum : pInput->sum.usum, overflow); + CHECK_OVERFLOW_SUM_UNSIGNED_BIG(pOutput, (overflow ? pInput->sum.dsum : pInput->sum.usum), overflow); } else { pOutput->sum.dsum += pInput->sum.dsum; }