fix: type overflow

This commit is contained in:
factosea 2024-07-09 14:48:21 +08:00
parent 20f4eda56d
commit 163b31a4ee
7 changed files with 107 additions and 42 deletions

View File

@ -415,7 +415,7 @@ typedef struct SSelectStmt {
int32_t returnRows; // EFuncReturnRows
ETimeLineMode timeLineCurMode;
ETimeLineMode timeLineResMode;
bool hasProcessByRowFunc;
int32_t lastProcessByRowFuncId;
bool timeLineFromOrderBy;
bool isEmptyResult;
bool isSubquery;

View File

@ -831,6 +831,7 @@ int32_t taosGetErrSize();
#define TSDB_CODE_PAR_TBNAME_ERROR TAOS_DEF_ERROR_CODE(0, 0x267D)
#define TSDB_CODE_PAR_TBNAME_DUPLICATED TAOS_DEF_ERROR_CODE(0, 0x267E)
#define TSDB_CODE_PAR_TAG_NAME_DUPLICATED TAOS_DEF_ERROR_CODE(0, 0x267F)
#define TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC TAOS_DEF_ERROR_CODE(0, 0x2680)
#define TSDB_CODE_PAR_INTERNAL_ERROR TAOS_DEF_ERROR_CODE(0, 0x26FF)
//planner

View File

@ -3183,10 +3183,13 @@ static int32_t diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv)
return v < pDiffInfo->prev.i64;
}
case TSDB_DATA_TYPE_TIMESTAMP:
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_UBIGINT:{
uint64_t v = *(uint64_t*)pv;
return v < (uint64_t)pDiffInfo->prev.i64;
}
case TSDB_DATA_TYPE_BIGINT: {
int64_t v = *(int64_t*)pv;
return v - pDiffInfo->prev.i64 < 0;
return v < pDiffInfo->prev.i64;
}
case TSDB_DATA_TYPE_FLOAT: {
float v = *(float*)pv;
@ -3203,9 +3206,13 @@ static int32_t diffIsNegtive(SDiffInfo* pDiffInfo, int32_t type, const char* pv)
return false;
}
static void tryToSetInt64(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
int64_t delta = v - pDiffInfo->prev.i64; // direct previous may be null
if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
static void tryToSetInt64(SDiffInfo* pDiffInfo, int32_t type, SColumnInfoData* pOutput, int64_t v, int32_t pos) {
bool isNegative = v < pDiffInfo->prev.i64;
if(type == TSDB_DATA_TYPE_UBIGINT || type == TSDB_DATA_TYPE_TIMESTAMP){
isNegative = (uint64_t)v < (uint64_t)pDiffInfo->prev.i64;
}
int64_t delta = v - pDiffInfo->prev.i64;
if (isNegative && ignoreNegative(pDiffInfo->ignoreOption)) {
colDataSetNull_f_s(pOutput, pos);
pOutput->hasNull = true;
} else {
@ -3214,6 +3221,16 @@ static void tryToSetInt64(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, int64_
pDiffInfo->prev.i64 = v;
}
static void tryToSetDouble(SDiffInfo* pDiffInfo, SColumnInfoData* pOutput, double v, int32_t pos) {
double delta = v - pDiffInfo->prev.d64;
if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
colDataSetNull_f_s(pOutput, pos);
} else {
colDataSetDouble(pOutput, pos, &delta);
}
pDiffInfo->prev.d64 = v;
}
static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv, SColumnInfoData* pOutput, int32_t pos,
int64_t ts) {
if (!pDiffInfo->hasPrev) {
@ -3224,74 +3241,54 @@ static int32_t doHandleDiff(SDiffInfo* pDiffInfo, int32_t type, const char* pv,
switch (type) {
case TSDB_DATA_TYPE_UINT: {
int64_t v = *(uint32_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_INT: {
int64_t v = *(int32_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_BOOL: {
int64_t v = *(bool*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_UTINYINT: {
int64_t v = *(uint8_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_TINYINT: {
int64_t v = *(int8_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_USMALLINT:{
int64_t v = *(uint16_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_SMALLINT: {
int64_t v = *(int16_t*)pv;
tryToSetInt64(pDiffInfo, pOutput, v, pos);
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_TIMESTAMP:
case TSDB_DATA_TYPE_UBIGINT:
case TSDB_DATA_TYPE_BIGINT: {
int64_t v = *(int64_t*)pv;
int64_t delta = v - pDiffInfo->prev.i64; // direct previous may be null
if (delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) {
colDataSetNull_f_s(pOutput, pos);
} else {
colDataSetInt64(pOutput, pos, &delta);
}
pDiffInfo->prev.i64 = v;
tryToSetInt64(pDiffInfo, type, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_FLOAT: {
double v = *(float*)pv;
double delta = v - pDiffInfo->prev.d64; // direct previous may be null
if ((delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) || isinf(delta) ||
isnan(delta)) { // check for overflow
colDataSetNull_f_s(pOutput, pos);
} else {
colDataSetDouble(pOutput, pos, &delta);
}
pDiffInfo->prev.d64 = v;
tryToSetDouble(pDiffInfo, pOutput, v, pos);
break;
}
case TSDB_DATA_TYPE_DOUBLE: {
double v = *(double*)pv;
double delta = v - pDiffInfo->prev.d64; // direct previous may be null
if ((delta < 0 && ignoreNegative(pDiffInfo->ignoreOption)) || isinf(delta) ||
isnan(delta)) { // check for overflow
colDataSetNull_f_s(pOutput, pos);
} else {
colDataSetDouble(pOutput, pos, &delta);
}
pDiffInfo->prev.d64 = v;
tryToSetDouble(pDiffInfo, pOutput, v, pos);
break;
}
default:

View File

@ -2199,9 +2199,12 @@ static int32_t translateIndefiniteRowsFunc(STranslateContext* pCxt, SFunctionNod
}
if (pSelect->hasIndefiniteRowsFunc &&
(FUNC_RETURN_ROWS_INDEFINITE == pSelect->returnRows || pSelect->returnRows != fmGetFuncReturnRows(pFunc)) &&
(!pSelect->hasProcessByRowFunc || !fmIsProcessByRowFunc(pFunc->funcId))) {
(pSelect->lastProcessByRowFuncId == -1 || !fmIsProcessByRowFunc(pFunc->funcId))) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC);
}
if (pSelect->lastProcessByRowFuncId != -1 && pSelect->lastProcessByRowFuncId != pFunc->funcId) {
return generateSyntaxErrMsg(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC);
}
if (NULL != pSelect->pWindow || NULL != pSelect->pGroupByList) {
return generateSyntaxErrMsgExt(&pCxt->msgBuf, TSDB_CODE_PAR_NOT_ALLOWED_FUNC,
"%s function is not supported in window query or group query", pFunc->functionName);
@ -2466,7 +2469,7 @@ static void setFuncClassification(SNode* pCurrStmt, SFunctionNode* pFunc) {
pSelect->returnRows = fmGetFuncReturnRows(pFunc);
}
if (fmIsProcessByRowFunc(pFunc->funcId)) {
pSelect->hasProcessByRowFunc = true;
pSelect->lastProcessByRowFuncId = pFunc->funcId;
}
pSelect->hasMultiRowsFunc = pSelect->hasMultiRowsFunc ? true : fmIsMultiRowsFunc(pFunc->funcId);
@ -3404,6 +3407,7 @@ static int32_t checkIsEmptyResult(STranslateContext* pCxt, SSelectStmt* pSelect)
static int32_t resetSelectFuncNumWithoutDup(SSelectStmt* pSelect) {
if (pSelect->selectFuncNum <= 1) return TSDB_CODE_SUCCESS;
pSelect->selectFuncNum = 0;
pSelect->lastProcessByRowFuncId = -1;
SNodeList* pNodeList = nodesMakeList();
int32_t code = nodesCollectSelectFuncs(pSelect, SQL_CLAUSE_FROM, NULL, fmIsSelectFunc, pNodeList);
if (TSDB_CODE_SUCCESS != code) {

View File

@ -221,6 +221,8 @@ static char* getSyntaxErrFormat(int32_t errCode) {
return "Table name:%s duplicated";
case TSDB_CODE_PAR_TAG_NAME_DUPLICATED:
return "Tag name:%s duplicated";
case TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC:
return "Some functions cannot appear in the select list at the same time";
default:
return "Unknown error";
}
@ -772,6 +774,7 @@ SNode* createSelectStmtImpl(bool isDistinct, SNodeList* pProjectionList, SNode*
select->onlyHasKeepOrderFunc = true;
select->timeRange = TSWINDOW_INITIALIZER;
select->pHint = pHint;
select->lastProcessByRowFuncId = -1;
return (SNode*)select;
}

View File

@ -678,6 +678,7 @@ TAOS_DEFINE_ERROR(TSDB_CODE_PAR_PRIMARY_KEY_IS_NONE, "Primary key column
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TBNAME_ERROR, "Pseudo tag tbname not set")
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TBNAME_DUPLICATED, "Table name duplicated")
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_TAG_NAME_DUPLICATED, "Tag name duplicated")
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_NOT_ALLOWED_DIFFERENT_BY_ROW_FUNC, "Some functions cannot appear in the select list at the same time")
TAOS_DEFINE_ERROR(TSDB_CODE_PAR_INTERNAL_ERROR, "Parser internal error")
//planner

View File

@ -275,7 +275,7 @@ class TDTestCase:
tdSql.checkRows(2)
def typeOverflowTest(self):
def intOverflowTest(self):
dbname = "db"
ts1 = 1694912400000
@ -284,7 +284,7 @@ class TDTestCase:
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, -2147483648, -32768, 0, 9223372036854775806, 9223372036854775806)" % (ts1 + 1))
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, 2147483647, 32767, 4294967295, 0, 0)" % (ts1 + 2))
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, -10, -10, 0, -9223372036854775806, 9223372036854775806)" % (ts1 + 3))
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, -10, -10, 0, -9223372036854775806, 16223372036854775806)" % (ts1 + 3))
tdSql.query(f"select ts, diff(c1), diff(c2), diff(c3), diff(c4), diff(c5) from {dbname}.stb6_1")
tdSql.checkRows(2)
@ -299,7 +299,6 @@ class TDTestCase:
tdSql.checkData(1, 2, -32777)
tdSql.checkData(1, 3, -4294967295)
tdSql.checkData(1, 4, -9223372036854775806)
tdSql.checkData(1, 5, 9223372036854775806)
tdSql.query(f"select ts, diff(c1, 1), diff(c2) from {dbname}.stb6_1")
tdSql.checkRows(2)
@ -327,6 +326,65 @@ class TDTestCase:
tdSql.checkData(0, 1, 4294967295)
tdSql.checkData(0, 2, 65535)
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, -10, -10, 0, 9223372036854775800, 0)" % (ts1 + 4))
tdSql.execute(f"insert into {dbname}.stb6_1 values(%d, -10, -10, 0, 9223372036854775800, 16223372036854775806)" % (ts1 + 5))
tdSql.query(f"select ts, diff(c4, 0) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.query(f"select ts, diff(c4, 1) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.checkData(2, 1, -10)
tdSql.query(f"select ts, diff(c4, 2) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.query(f"select ts, diff(c4, 3) from {dbname}.stb6_1")
tdSql.checkRows(2)
tdSql.checkData(0, 1, -10)
tdSql.checkData(1, 1, 0)
tdSql.query(f"select ts, diff(c5, 0) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.query(f"select ts, diff(c5, 1) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.checkData(0, 1, None)
tdSql.checkData(1, 0, '2023-09-17 09:00:00.003')
tdSql.checkData(2, 1, None)
tdSql.checkData(3, 0, '2023-09-17 09:00:00.005')
tdSql.query(f"select ts, diff(c5, 2) from {dbname}.stb6_1")
tdSql.checkRows(4)
tdSql.query(f"select ts, diff(c5, 3) from {dbname}.stb6_1")
tdSql.checkRows(2)
tdSql.checkData(0, 0, '2023-09-17 09:00:00.003')
tdSql.checkData(1, 0, '2023-09-17 09:00:00.005')
def doubleOverflowTest(self):
dbname = "db"
ts1 = 1694912400000
tdSql.execute(f'''create table {dbname}.stb7(ts timestamp, c1 float, c2 double) tags(loc nchar(20))''')
tdSql.execute(f"create table {dbname}.stb7_1 using {dbname}.stb7 tags('shanghai')")
tdSql.execute(f"insert into {dbname}.stb7_1 values(%d, 334567777777777777777343434343333333733, 334567777777777777777343434343333333733)" % (ts1 + 1))
tdSql.execute(f"insert into {dbname}.stb7_1 values(%d, -334567777777777777777343434343333333733, -334567777777777777777343434343333333733)" % (ts1 + 2))
tdSql.execute(f"insert into {dbname}.stb7_1 values(%d, 334567777777777777777343434343333333733, 334567777777777777777343434343333333733)" % (ts1 + 3))
tdSql.query(f"select ts, diff(c1), diff(c2) from {dbname}.stb7_1")
tdSql.checkRows(2)
tdSql.query(f"select ts, diff(c1, 1), diff(c2, 1) from {dbname}.stb7_1")
tdSql.checkRows(2)
tdSql.checkData(0, 1, None)
tdSql.checkData(0, 2, None)
tdSql.query(f"select ts, diff(c1, 3), diff(c2, 3) from {dbname}.stb7_1")
tdSql.checkRows(1)
tdSql.checkData(0, 0, '2023-09-17 09:00:00.003')
def run(self):
tdSql.prepare()
dbname = "db"
@ -336,7 +394,8 @@ class TDTestCase:
self.ignoreTest()
self.withPkTest()
self.typeOverflowTest()
self.intOverflowTest()
self.doubleOverflowTest()
tdSql.execute(
f"create table {dbname}.ntb(ts timestamp,c1 int,c2 double,c3 float)")