fix(query): fix diff function result type to avoid overflow

TD-16068
This commit is contained in:
Ganlin Zhao 2022-05-27 19:43:13 +08:00
parent 1f6c6b119d
commit 266da48c5a
2 changed files with 16 additions and 10 deletions

View File

@ -709,7 +709,13 @@ static int32_t translateDiff(SFunctionNode* pFunc, char* pErrBuf, int32_t len) {
pValue->notReserved = true; pValue->notReserved = true;
} }
pFunc->node.resType = (SDataType){.bytes = tDataTypes[colType].bytes, .type = colType}; uint8_t resType;
if (IS_SIGNED_NUMERIC_TYPE(colType)) {
resType = TSDB_DATA_TYPE_BIGINT;
} else {
resType = TSDB_DATA_TYPE_DOUBLE;
}
pFunc->node.resType = (SDataType){.bytes = tDataTypes[resType].bytes, .type = resType};
return TSDB_CODE_SUCCESS; return TSDB_CODE_SUCCESS;
} }

View File

@ -2299,15 +2299,15 @@ static void doSetPrevVal(SDiffInfo* pDiffInfo, int32_t type, const char* pv) {
} }
static void doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos, int32_t order) { static void doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos, int32_t order) {
int32_t factor = (order == TSDB_ORDER_ASC)? 1:-1; int32_t factor = (order == TSDB_ORDER_ASC)? 1:-1;
switch (type) { switch (type) {
case TSDB_DATA_TYPE_INT: { case TSDB_DATA_TYPE_INT: {
int32_t v = *(int32_t*)pv; int32_t v = *(int32_t*)pv;
int32_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null int64_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null
if (delta < 0 && pDiffInfo->ignoreNegative) { if (delta < 0 && pDiffInfo->ignoreNegative) {
colDataSetNull_f(pOutput->nullbitmap, pos); colDataSetNull_f(pOutput->nullbitmap, pos);
} else { } else {
colDataAppendInt32(pOutput, pos, &delta); colDataAppendInt64(pOutput, pos, &delta);
} }
pDiffInfo->prev.i64 = v; pDiffInfo->prev.i64 = v;
break; break;
@ -2315,22 +2315,22 @@ static void doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SCo
case TSDB_DATA_TYPE_BOOL: case TSDB_DATA_TYPE_BOOL:
case TSDB_DATA_TYPE_TINYINT: { case TSDB_DATA_TYPE_TINYINT: {
int8_t v = *(int8_t*)pv; int8_t v = *(int8_t*)pv;
int8_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null int64_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null
if (delta < 0 && pDiffInfo->ignoreNegative) { if (delta < 0 && pDiffInfo->ignoreNegative) {
colDataSetNull_f(pOutput->nullbitmap, pos); colDataSetNull_f(pOutput->nullbitmap, pos);
} else { } else {
colDataAppendInt8(pOutput, pos, &delta); colDataAppendInt64(pOutput, pos, &delta);
} }
pDiffInfo->prev.i64 = v; pDiffInfo->prev.i64 = v;
break; break;
} }
case TSDB_DATA_TYPE_SMALLINT: { case TSDB_DATA_TYPE_SMALLINT: {
int16_t v = *(int16_t*)pv; int16_t v = *(int16_t*)pv;
int16_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null int64_t delta = factor*(v - pDiffInfo->prev.i64); // direct previous may be null
if (delta < 0 && pDiffInfo->ignoreNegative) { if (delta < 0 && pDiffInfo->ignoreNegative) {
colDataSetNull_f(pOutput->nullbitmap, pos); colDataSetNull_f(pOutput->nullbitmap, pos);
} else { } else {
colDataAppendInt16(pOutput, pos, &delta); colDataAppendInt64(pOutput, pos, &delta);
} }
pDiffInfo->prev.i64 = v; pDiffInfo->prev.i64 = v;
break; break;
@ -2348,11 +2348,11 @@ static void doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SCo
} }
case TSDB_DATA_TYPE_FLOAT: { case TSDB_DATA_TYPE_FLOAT: {
float v = *(float*)pv; float v = *(float*)pv;
float delta = factor*(v - pDiffInfo->prev.d64); // direct previous may be null double delta = factor*(v - pDiffInfo->prev.d64); // direct previous may be null
if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) { //check for overflow if ((delta < 0 && pDiffInfo->ignoreNegative) || isinf(delta) || isnan(delta)) { //check for overflow
colDataSetNull_f(pOutput->nullbitmap, pos); colDataSetNull_f(pOutput->nullbitmap, pos);
} else { } else {
colDataAppendFloat(pOutput, pos, &delta); colDataAppendDouble(pOutput, pos, &delta);
} }
pDiffInfo->prev.d64 = v; pDiffInfo->prev.d64 = v;
break; break;