fix:precision problems in time conversion
This commit is contained in:
parent
bdcaa3e1f3
commit
37e10aca29
|
@ -714,25 +714,31 @@ static bool smlIsNchar(const char *pVal, uint16_t len) {
|
||||||
|
|
||||||
static int64_t smlGetTimeValue(const char *value, int32_t len, int8_t type) {
|
static int64_t smlGetTimeValue(const char *value, int32_t len, int8_t type) {
|
||||||
char *endPtr = NULL;
|
char *endPtr = NULL;
|
||||||
double ts = (double)strtoll(value, &endPtr, 10);
|
int64_t tsInt64 = strtoll(value, &endPtr, 10);
|
||||||
if(value + len != endPtr){
|
if(value + len != endPtr){
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
double ts = tsInt64;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TSDB_TIME_PRECISION_HOURS:
|
case TSDB_TIME_PRECISION_HOURS:
|
||||||
ts *= (3600 * 1e9);
|
ts *= (3600 * 1e9);
|
||||||
|
tsInt64 *= (3600 * 1e9);
|
||||||
break;
|
break;
|
||||||
case TSDB_TIME_PRECISION_MINUTES:
|
case TSDB_TIME_PRECISION_MINUTES:
|
||||||
ts *= (60 * 1e9);
|
ts *= (60 * 1e9);
|
||||||
|
tsInt64 *= (60 * 1e9);
|
||||||
break;
|
break;
|
||||||
case TSDB_TIME_PRECISION_SECONDS:
|
case TSDB_TIME_PRECISION_SECONDS:
|
||||||
ts *= (1e9);
|
ts *= (1e9);
|
||||||
|
tsInt64 *= (1e9);
|
||||||
break;
|
break;
|
||||||
case TSDB_TIME_PRECISION_MILLI:
|
case TSDB_TIME_PRECISION_MILLI:
|
||||||
ts *= (1e6);
|
ts *= (1e6);
|
||||||
|
tsInt64 *= (1e6);
|
||||||
break;
|
break;
|
||||||
case TSDB_TIME_PRECISION_MICRO:
|
case TSDB_TIME_PRECISION_MICRO:
|
||||||
ts *= (1e3);
|
ts *= (1e3);
|
||||||
|
tsInt64 *= (1e3);
|
||||||
break;
|
break;
|
||||||
case TSDB_TIME_PRECISION_NANO:
|
case TSDB_TIME_PRECISION_NANO:
|
||||||
break;
|
break;
|
||||||
|
@ -743,7 +749,7 @@ static int64_t smlGetTimeValue(const char *value, int32_t len, int8_t type) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (int64_t)ts;
|
return tsInt64;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t smlGetTimeNow(int8_t precision) {
|
static int64_t smlGetTimeNow(int8_t precision) {
|
||||||
|
|
|
@ -1188,3 +1188,36 @@ TEST(testCase, smlParseTelnetLine_diff_json_type2_Test) {
|
||||||
destroyRequest(request);
|
destroyRequest(request);
|
||||||
smlDestroyInfo(info);
|
smlDestroyInfo(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(testCase, sml_TD15662_Test) {
|
||||||
|
TAOS *taos = taos_connect("localhost", "root", "taosdata", NULL, 0);
|
||||||
|
ASSERT_NE(taos, nullptr);
|
||||||
|
|
||||||
|
TAOS_RES *pRes = taos_query(taos, "create database if not exists db_15662 precision 'ns'");
|
||||||
|
taos_free_result(pRes);
|
||||||
|
|
||||||
|
pRes = taos_query(taos, "use db_15662");
|
||||||
|
taos_free_result(pRes);
|
||||||
|
|
||||||
|
SRequestObj *request = (SRequestObj *)createRequest((STscObj *)taos, NULL, NULL, TSDB_SQL_INSERT);
|
||||||
|
ASSERT_NE(request, nullptr);
|
||||||
|
|
||||||
|
SSmlHandle *info = smlBuildSmlInfo(taos, request, TSDB_SML_LINE_PROTOCOL, TSDB_SML_TIMESTAMP_NANO_SECONDS);
|
||||||
|
ASSERT_NE(info, nullptr);
|
||||||
|
|
||||||
|
const char *sql[] = {
|
||||||
|
"iyyyje,id=iyyyje_41943_1303,t0=t,t1=127i8,t2=32767i16,t3=2147483647i32,t4=9223372036854775807i64,t5=11.12345f32,t6=22.123456789f64,t7=\"binaryTagValue\",t8=L\"ncharTagValue\" c0=false,c1=127i8,c2=32767i16,c3=2147483647i32,c4=9223372036854775807i64,c5=11.12345f32,c6=22.123456789f64,c7=\"binaryColValue\",c8=L\"ncharColValue\",c9=7u64 1626006833639000000",
|
||||||
|
};
|
||||||
|
int ret = smlProcess(info, (char **)sql, sizeof(sql) / sizeof(sql[0]));
|
||||||
|
ASSERT_EQ(ret, 0);
|
||||||
|
|
||||||
|
// case 1
|
||||||
|
TAOS_RES *res = taos_query(taos, "select * from t_a5615048edae55218a22a149edebdc82");
|
||||||
|
ASSERT_NE(res, nullptr);
|
||||||
|
|
||||||
|
TAOS_ROW row = taos_fetch_row(res);
|
||||||
|
int64_t ts = *(int64_t*)row[0];
|
||||||
|
ASSERT_EQ(ts, 1626006833639000000);
|
||||||
|
|
||||||
|
taos_free_result(res);
|
||||||
|
}
|
|
@ -374,39 +374,133 @@ char getPrecisionUnit(int32_t precision) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision) {
|
int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision) {
|
||||||
assert(fromPrecision == TSDB_TIME_PRECISION_MILLI || fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
assert(fromPrecision == TSDB_TIME_PRECISION_MILLI ||
|
||||||
|
fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||||
fromPrecision == TSDB_TIME_PRECISION_NANO);
|
fromPrecision == TSDB_TIME_PRECISION_NANO);
|
||||||
assert(toPrecision == TSDB_TIME_PRECISION_MILLI || toPrecision == TSDB_TIME_PRECISION_MICRO ||
|
assert(toPrecision == TSDB_TIME_PRECISION_MILLI ||
|
||||||
|
toPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||||
toPrecision == TSDB_TIME_PRECISION_NANO);
|
toPrecision == TSDB_TIME_PRECISION_NANO);
|
||||||
static double factors[3][3] = {{1., 1000., 1000000.}, {1.0 / 1000, 1., 1000.}, {1.0 / 1000000, 1.0 / 1000, 1.}};
|
double tempResult = (double)time;
|
||||||
return (int64_t)((double)time * factors[fromPrecision][toPrecision]);
|
switch(fromPrecision) {
|
||||||
|
case TSDB_TIME_PRECISION_MILLI: {
|
||||||
|
switch (toPrecision) {
|
||||||
|
case TSDB_TIME_PRECISION_MILLI:
|
||||||
|
return time;
|
||||||
|
case TSDB_TIME_PRECISION_MICRO:
|
||||||
|
tempResult *= 1000;
|
||||||
|
time *= 1000;
|
||||||
|
goto end_;
|
||||||
|
case TSDB_TIME_PRECISION_NANO:
|
||||||
|
tempResult *= 1000000;
|
||||||
|
time *= 1000000;
|
||||||
|
goto end_;
|
||||||
|
}
|
||||||
|
} // end from milli
|
||||||
|
case TSDB_TIME_PRECISION_MICRO: {
|
||||||
|
switch (toPrecision) {
|
||||||
|
case TSDB_TIME_PRECISION_MILLI:
|
||||||
|
return time / 1000;
|
||||||
|
case TSDB_TIME_PRECISION_MICRO:
|
||||||
|
return time;
|
||||||
|
case TSDB_TIME_PRECISION_NANO:
|
||||||
|
tempResult *= 1000;
|
||||||
|
time *= 1000;
|
||||||
|
goto end_;
|
||||||
|
}
|
||||||
|
} //end from micro
|
||||||
|
case TSDB_TIME_PRECISION_NANO: {
|
||||||
|
switch (toPrecision) {
|
||||||
|
case TSDB_TIME_PRECISION_MILLI:
|
||||||
|
return time / 1000000;
|
||||||
|
case TSDB_TIME_PRECISION_MICRO:
|
||||||
|
return time / 1000;
|
||||||
|
case TSDB_TIME_PRECISION_NANO:
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
} //end from nano
|
||||||
|
default: {
|
||||||
|
assert(0);
|
||||||
|
return time; // only to pass windows compilation
|
||||||
|
}
|
||||||
|
} //end switch fromPrecision
|
||||||
|
end_:
|
||||||
|
if (tempResult >= (double)INT64_MAX) return INT64_MAX;
|
||||||
|
if (tempResult <= (double)INT64_MIN) return INT64_MIN; // INT64_MIN means NULL
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// !!!!notice:there are precision problems, double lose precison if time is too large, for example: 1626006833631000000*1.0 = double = 1626006833631000064
|
||||||
|
//int64_t convertTimePrecision(int64_t time, int32_t fromPrecision, int32_t toPrecision) {
|
||||||
|
// assert(fromPrecision == TSDB_TIME_PRECISION_MILLI || fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||||
|
// fromPrecision == TSDB_TIME_PRECISION_NANO);
|
||||||
|
// assert(toPrecision == TSDB_TIME_PRECISION_MILLI || toPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||||
|
// toPrecision == TSDB_TIME_PRECISION_NANO);
|
||||||
|
// static double factors[3][3] = {{1., 1000., 1000000.}, {1.0 / 1000, 1., 1000.}, {1.0 / 1000000, 1.0 / 1000, 1.}};
|
||||||
|
// ((double)time * factors[fromPrecision][toPrecision]);
|
||||||
|
//}
|
||||||
|
|
||||||
int64_t convertTimeFromPrecisionToUnit(int64_t time, int32_t fromPrecision, char toUnit) {
|
int64_t convertTimeFromPrecisionToUnit(int64_t time, int32_t fromPrecision, char toUnit) {
|
||||||
assert(fromPrecision == TSDB_TIME_PRECISION_MILLI || fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
assert(fromPrecision == TSDB_TIME_PRECISION_MILLI || fromPrecision == TSDB_TIME_PRECISION_MICRO ||
|
||||||
fromPrecision == TSDB_TIME_PRECISION_NANO);
|
fromPrecision == TSDB_TIME_PRECISION_NANO);
|
||||||
static double factors[3] = {1000000., 1000., 1.};
|
int64_t factors[3] = {NANOSECOND_PER_MSEC, NANOSECOND_PER_USEC, 1};
|
||||||
|
double tmp = time;
|
||||||
switch (toUnit) {
|
switch (toUnit) {
|
||||||
case 's':
|
case 's':{
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_SEC;
|
tmp *= (NANOSECOND_PER_SEC/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_SEC/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'm':
|
case 'm':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_MINUTE;
|
tmp *= (NANOSECOND_PER_MINUTE/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_MINUTE/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_HOUR;
|
tmp *= (NANOSECOND_PER_HOUR/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_HOUR/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
case 'd':
|
case 'd':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_DAY;
|
tmp *= (NANOSECOND_PER_DAY/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_DAY/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
case 'w':
|
case 'w':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_WEEK;
|
tmp *= (NANOSECOND_PER_WEEK/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_WEEK/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
case 'a':
|
case 'a':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_MSEC;
|
tmp *= (NANOSECOND_PER_MSEC/factors[fromPrecision]); // the result of division is an integer
|
||||||
|
time *= (NANOSECOND_PER_MSEC/factors[fromPrecision]);
|
||||||
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
return time * factors[fromPrecision] / NANOSECOND_PER_USEC;
|
// the result of (NANOSECOND_PER_USEC/(double)factors[fromPrecision]) maybe a double
|
||||||
|
switch (fromPrecision) {
|
||||||
|
case TSDB_TIME_PRECISION_MILLI:{
|
||||||
|
tmp /= 1000;
|
||||||
|
time /= 1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_TIME_PRECISION_MICRO:{
|
||||||
|
tmp /= 1;
|
||||||
|
time /= 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case TSDB_TIME_PRECISION_NANO:{
|
||||||
|
tmp *= 1000;
|
||||||
|
time *= 1000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case 'b':
|
case 'b':
|
||||||
return time * factors[fromPrecision];
|
tmp *= factors[fromPrecision];
|
||||||
|
time *= factors[fromPrecision];
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (tmp >= (double)INT64_MAX) return INT64_MAX;
|
||||||
|
if (tmp <= (double)INT64_MIN) return INT64_MIN;
|
||||||
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t convertStringToTimestamp(int16_t type, char *inputData, int64_t timePrec, int64_t *timeVal) {
|
int32_t convertStringToTimestamp(int16_t type, char *inputData, int64_t timePrec, int64_t *timeVal) {
|
||||||
|
|
Loading…
Reference in New Issue