fix:[TD-30730] Modify precision rules for input parameters of function to_iso8601 and add test.
This commit is contained in:
parent
aa7d4c1180
commit
5685346d78
|
@ -2166,15 +2166,6 @@ static int32_t translateToIso8601(SFunctionNode* pFunc, char* pErrBuf, int32_t l
|
||||||
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
return invaildFuncParaTypeErrMsg(pErrBuf, len, pFunc->functionName);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QUERY_NODE_VALUE == nodeType(nodesListGetNode(pFunc->pParameterList, 0))) {
|
|
||||||
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 0);
|
|
||||||
|
|
||||||
if (!validateTimestampDigits(pValue)) {
|
|
||||||
pFunc->node.resType = (SDataType){.bytes = 0, .type = TSDB_DATA_TYPE_BINARY};
|
|
||||||
return TSDB_CODE_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// param1
|
// param1
|
||||||
if (numOfParams == 2) {
|
if (numOfParams == 2) {
|
||||||
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
|
SValueNode* pValue = (SValueNode*)nodesListGetNode(pFunc->pParameterList, 1);
|
||||||
|
|
|
@ -1095,24 +1095,45 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *
|
||||||
char fraction[20] = {0};
|
char fraction[20] = {0};
|
||||||
bool hasFraction = false;
|
bool hasFraction = false;
|
||||||
NUM_TO_STRING(type, input, sizeof(fraction), fraction);
|
NUM_TO_STRING(type, input, sizeof(fraction), fraction);
|
||||||
int32_t tsDigits = (int32_t)strlen(fraction);
|
int32_t fractionLen;
|
||||||
|
|
||||||
char buf[64] = {0};
|
char buf[64] = {0};
|
||||||
int64_t timeVal;
|
int64_t timeVal;
|
||||||
|
char* format = NULL;
|
||||||
|
int64_t quot = 0;
|
||||||
|
long mod = 0;
|
||||||
|
|
||||||
GET_TYPED_DATA(timeVal, int64_t, type, input);
|
GET_TYPED_DATA(timeVal, int64_t, type, input);
|
||||||
if (tsDigits > TSDB_TIME_PRECISION_SEC_DIGITS) {
|
|
||||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
switch (pInput->columnData[0].info.precision) {
|
||||||
timeVal = timeVal / 1000;
|
case TSDB_TIME_PRECISION_MILLI: {
|
||||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
quot = timeVal / 1000;
|
||||||
timeVal = timeVal / ((int64_t)(1000 * 1000));
|
fractionLen = 5;
|
||||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
format = ".%03" PRId64;
|
||||||
timeVal = timeVal / ((int64_t)(1000 * 1000 * 1000));
|
mod = timeVal % 1000;
|
||||||
} else {
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_TIME_PRECISION_MICRO: {
|
||||||
|
quot = timeVal / 1000000;
|
||||||
|
fractionLen = 8;
|
||||||
|
format = ".%06" PRId64;
|
||||||
|
mod = timeVal % 1000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case TSDB_TIME_PRECISION_NANO: {
|
||||||
|
quot = timeVal / 1000000000;
|
||||||
|
fractionLen = 11;
|
||||||
|
format = ".%09" PRId64;
|
||||||
|
mod = timeVal % 1000000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default: {
|
||||||
colDataSetNULL(pOutput->columnData, i);
|
colDataSetNULL(pOutput->columnData, i);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
hasFraction = true;
|
|
||||||
memmove(fraction, fraction + TSDB_TIME_PRECISION_SEC_DIGITS, TSDB_TIME_PRECISION_SEC_DIGITS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// trans current timezone's unix ts to dest timezone
|
// trans current timezone's unix ts to dest timezone
|
||||||
|
@ -1122,18 +1143,19 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *
|
||||||
if (0 != offsetOfTimezone(tz, &offset)) {
|
if (0 != offsetOfTimezone(tz, &offset)) {
|
||||||
goto _end;
|
goto _end;
|
||||||
}
|
}
|
||||||
timeVal -= offset + 3600 * ((int64_t)tsTimezone);
|
quot -= offset + 3600 * ((int64_t)tsTimezone);
|
||||||
|
|
||||||
struct tm tmInfo;
|
struct tm tmInfo;
|
||||||
int32_t len = 0;
|
int32_t len = 0;
|
||||||
|
|
||||||
if (taosLocalTime((const time_t *)&timeVal, &tmInfo, buf) == NULL) {
|
if (taosLocalTime((const time_t *)", &tmInfo, buf) == NULL) {
|
||||||
len = (int32_t)strlen(buf);
|
len = (int32_t)strlen(buf);
|
||||||
goto _end;
|
goto _end;
|
||||||
}
|
}
|
||||||
|
|
||||||
strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
|
len = (int32_t)strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%S", &tmInfo);
|
||||||
len = (int32_t)strlen(buf);
|
|
||||||
|
len += snprintf(buf + len, fractionLen, format, mod);
|
||||||
|
|
||||||
// add timezone string
|
// add timezone string
|
||||||
if (tzLen > 0) {
|
if (tzLen > 0) {
|
||||||
|
@ -1141,32 +1163,6 @@ int32_t toISO8601Function(SScalarParam *pInput, int32_t inputNum, SScalarParam *
|
||||||
len += tzLen;
|
len += tzLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hasFraction) {
|
|
||||||
int32_t fracLen = (int32_t)strlen(fraction) + 1;
|
|
||||||
|
|
||||||
char *tzInfo;
|
|
||||||
if (buf[len - 1] == 'z' || buf[len - 1] == 'Z') {
|
|
||||||
tzInfo = &buf[len - 1];
|
|
||||||
memmove(tzInfo + fracLen, tzInfo, strlen(tzInfo));
|
|
||||||
} else {
|
|
||||||
tzInfo = strchr(buf, '+');
|
|
||||||
if (tzInfo) {
|
|
||||||
memmove(tzInfo + fracLen, tzInfo, strlen(tzInfo));
|
|
||||||
} else {
|
|
||||||
// search '-' backwards
|
|
||||||
tzInfo = strrchr(buf, '-');
|
|
||||||
if (tzInfo) {
|
|
||||||
memmove(tzInfo + fracLen, tzInfo, strlen(tzInfo));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
char tmp[32] = {0};
|
|
||||||
sprintf(tmp, ".%s", fraction);
|
|
||||||
memcpy(tzInfo, tmp, fracLen);
|
|
||||||
len += fracLen;
|
|
||||||
}
|
|
||||||
|
|
||||||
_end:
|
_end:
|
||||||
memmove(buf + VARSTR_HEADER_SIZE, buf, len);
|
memmove(buf + VARSTR_HEADER_SIZE, buf, len);
|
||||||
varDataSetLen(buf, len);
|
varDataSetLen(buf, len);
|
||||||
|
|
|
@ -19,6 +19,61 @@ class TDTestCase:
|
||||||
self.dbname = 'db'
|
self.dbname = 'db'
|
||||||
self.stbname = f'{self.dbname}.stb'
|
self.stbname = f'{self.dbname}.stb'
|
||||||
self.ntbname = f'{self.dbname}.ntb'
|
self.ntbname = f'{self.dbname}.ntb'
|
||||||
|
def check_timestamp_precision(self):
|
||||||
|
time_zone = time.strftime('%z')
|
||||||
|
tdSql.execute(f'drop database if exists {self.dbname}')
|
||||||
|
tdSql.execute(f'create database {self.dbname} precision "us"')
|
||||||
|
tdSql.execute(f'use {self.dbname}')
|
||||||
|
tdSql.execute(f'create table if not exists {self.ntbname}(ts timestamp, c1 int, c2 timestamp)')
|
||||||
|
tdSql.execute(f'insert into {self.ntbname} values(now,1,today())')
|
||||||
|
ts_list = ['1', '11', '111', '1111', '11111', '111111', '1111111', '11111111', '111111111', '1111111111',
|
||||||
|
'11111111111','111111111111','1111111111111','11111111111111','111111111111111','1111111111111111',
|
||||||
|
'11111111111111111','111111111111111111','1111111111111111111']
|
||||||
|
res_list_ms = ['1970-01-01T08:00:00.001+0800', '1970-01-01T08:00:00.011+0800', '1970-01-01T08:00:00.111+0800',
|
||||||
|
'1970-01-01T08:00:01.111+0800', '1970-01-01T08:00:11.111+0800', '1970-01-01T08:01:51.111+0800',
|
||||||
|
'1970-01-01T08:18:31.111+0800', '1970-01-01T11:05:11.111+0800', '1970-01-02T14:51:51.111+0800',
|
||||||
|
'1970-01-14T04:38:31.111+0800', '1970-05-09T22:25:11.111+0800', '1973-07-10T08:11:51.111+0800',
|
||||||
|
'2005-03-18T09:58:31.111+0800', '2322-02-06T03:45:11.111+0800', '5490-12-21T13:31:51.111+0800',
|
||||||
|
'37179-09-17T15:18:31.111+0800', '354067-02-04T09:05:11.111+0800',
|
||||||
|
'3522940-12-11T18:51:51.111+0800', '35211679-06-14T20:38:31.111+0800']
|
||||||
|
res_list_us = ['1970-01-01T08:00:00.000001+0800', '1970-01-01T08:00:00.000011+0800',
|
||||||
|
'1970-01-01T08:00:00.000111+0800', '1970-01-01T08:00:00.001111+0800',
|
||||||
|
'1970-01-01T08:00:00.011111+0800', '1970-01-01T08:00:00.111111+0800',
|
||||||
|
'1970-01-01T08:00:01.111111+0800', '1970-01-01T08:00:11.111111+0800',
|
||||||
|
'1970-01-01T08:01:51.111111+0800', '1970-01-01T08:18:31.111111+0800',
|
||||||
|
'1970-01-01T11:05:11.111111+0800', '1970-01-02T14:51:51.111111+0800',
|
||||||
|
'1970-01-14T04:38:31.111111+0800', '1970-05-09T22:25:11.111111+0800',
|
||||||
|
'1973-07-10T08:11:51.111111+0800', '2005-03-18T09:58:31.111111+0800',
|
||||||
|
'2322-02-06T03:45:11.111111+0800', '5490-12-21T13:31:51.111111+0800',
|
||||||
|
'37179-09-17T15:18:31.111111+0800']
|
||||||
|
res_list_ns = ['1970-01-01T08:00:00.000000001+0800', '1970-01-01T08:00:00.000000011+0800',
|
||||||
|
'1970-01-01T08:00:00.000000111+0800', '1970-01-01T08:00:00.000001111+0800',
|
||||||
|
'1970-01-01T08:00:00.000011111+0800', '1970-01-01T08:00:00.000111111+0800',
|
||||||
|
'1970-01-01T08:00:00.001111111+0800', '1970-01-01T08:00:00.011111111+0800',
|
||||||
|
'1970-01-01T08:00:00.111111111+0800', '1970-01-01T08:00:01.111111111+0800',
|
||||||
|
'1970-01-01T08:00:11.111111111+0800', '1970-01-01T08:01:51.111111111+0800',
|
||||||
|
'1970-01-01T08:18:31.111111111+0800', '1970-01-01T11:05:11.111111111+0800',
|
||||||
|
'1970-01-02T14:51:51.111111111+0800', '1970-01-14T04:38:31.111111111+0800',
|
||||||
|
'1970-05-09T22:25:11.111111111+0800', '1973-07-10T08:11:51.111111111+0800',
|
||||||
|
'2005-03-18T09:58:31.111111111+0800']
|
||||||
|
# test to_iso8601's precision with default precision 'ms'
|
||||||
|
for i in range(len(ts_list)):
|
||||||
|
tdSql.query(f'select to_iso8601({ts_list[i]})')
|
||||||
|
tdSql.checkEqual(tdSql.queryResult[0][0],res_list_ms[i])
|
||||||
|
# test to_iso8601's precision with table's precision 'us'
|
||||||
|
for i in range(len(ts_list)):
|
||||||
|
tdSql.query(f'select to_iso8601({ts_list[i]}) from {self.ntbname}')
|
||||||
|
tdSql.checkEqual(tdSql.queryResult[0][0],res_list_us[i])
|
||||||
|
|
||||||
|
tdSql.execute(f'drop database if exists {self.dbname}')
|
||||||
|
tdSql.execute(f'create database {self.dbname} precision "ns"')
|
||||||
|
tdSql.execute(f'use {self.dbname}')
|
||||||
|
tdSql.execute(f'create table if not exists {self.ntbname}(ts timestamp, c1 int, c2 timestamp)')
|
||||||
|
tdSql.execute(f'insert into {self.ntbname} values(now,1,today())')
|
||||||
|
# test to_iso8601's precision with table's precision 'ns'
|
||||||
|
for i in range(len(ts_list)):
|
||||||
|
tdSql.query(f'select to_iso8601({ts_list[i]}) from {self.ntbname}')
|
||||||
|
tdSql.checkEqual(tdSql.queryResult[0][0],res_list_ns[i])
|
||||||
def check_customize_param_ms(self):
|
def check_customize_param_ms(self):
|
||||||
time_zone = time.strftime('%z')
|
time_zone = time.strftime('%z')
|
||||||
tdSql.execute(f'drop database if exists {self.dbname}')
|
tdSql.execute(f'drop database if exists {self.dbname}')
|
||||||
|
@ -65,7 +120,7 @@ class TDTestCase:
|
||||||
tdSql.checkRows(1)
|
tdSql.checkRows(1)
|
||||||
for i in range(0,3):
|
for i in range(0,3):
|
||||||
tdSql.query("select to_iso8601(1) from db.ntb")
|
tdSql.query("select to_iso8601(1) from db.ntb")
|
||||||
tdSql.checkData(i,0,"1970-01-01T08:00:01+0800")
|
tdSql.checkData(i,0,"1970-01-01T08:00:00.001+0800")
|
||||||
tdSql.checkRows(3)
|
tdSql.checkRows(3)
|
||||||
tdSql.query("select to_iso8601(ts) from db.ntb")
|
tdSql.query("select to_iso8601(ts) from db.ntb")
|
||||||
tdSql.checkRows(3)
|
tdSql.checkRows(3)
|
||||||
|
@ -97,7 +152,7 @@ class TDTestCase:
|
||||||
tdSql.checkRows(3)
|
tdSql.checkRows(3)
|
||||||
tdSql.query("select to_iso8601(1) from db.stb")
|
tdSql.query("select to_iso8601(1) from db.stb")
|
||||||
for i in range(0,3):
|
for i in range(0,3):
|
||||||
tdSql.checkData(i,0,"1970-01-01T08:00:01+0800")
|
tdSql.checkData(i,0,"1970-01-01T08:00:00.001+0800")
|
||||||
tdSql.checkRows(3)
|
tdSql.checkRows(3)
|
||||||
tdSql.query("select to_iso8601(ts) from db.stb")
|
tdSql.query("select to_iso8601(ts) from db.stb")
|
||||||
tdSql.checkRows(3)
|
tdSql.checkRows(3)
|
||||||
|
@ -113,6 +168,7 @@ class TDTestCase:
|
||||||
def run(self): # sourcery skip: extract-duplicate-method
|
def run(self): # sourcery skip: extract-duplicate-method
|
||||||
self.check_base_function()
|
self.check_base_function()
|
||||||
self.check_customize_param_ms()
|
self.check_customize_param_ms()
|
||||||
|
self.check_timestamp_precision()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
tdSql.close()
|
tdSql.close()
|
||||||
|
|
Loading…
Reference in New Issue