fix:[TD-30730] Modify precision rules for input parameters of function timetruncate and add test.
This commit is contained in:
parent
5685346d78
commit
4601583361
|
@ -1343,9 +1343,6 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
|
|||
GET_TYPED_DATA(timePrec, int64_t, GET_PARAM_TYPE(&pInput[timePrecIdx]), pInput[timePrecIdx].columnData->pData);
|
||||
memcpy(timezone, varDataVal(pInput[timeZoneIdx].columnData->pData), varDataLen(pInput[timeZoneIdx].columnData->pData));
|
||||
|
||||
int64_t factor = TSDB_TICK_PER_SECOND(timePrec);
|
||||
int64_t unit = timeUnit * 1000 / factor;
|
||||
|
||||
for (int32_t i = 0; i < pInput[0].numOfRows; ++i) {
|
||||
if (colDataIsNull_s(pInput[0].columnData, i)) {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
|
@ -1355,201 +1352,27 @@ int32_t timeTruncateFunction(SScalarParam *pInput, int32_t inputNum, SScalarPara
|
|||
char *input = colDataGetData(pInput[0].columnData, i);
|
||||
|
||||
if (IS_VAR_DATA_TYPE(type)) { /* datetime format strings */
|
||||
int32_t ret = convertStringToTimestamp(type, input, TSDB_TIME_PRECISION_NANO, &timeVal);
|
||||
int32_t ret = convertStringToTimestamp(type, input, timePrec, &timeVal);
|
||||
if (ret != TSDB_CODE_SUCCESS) {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
// If converted value is less than 10digits in second, use value in second instead
|
||||
int64_t timeValSec = timeVal / 1000000000;
|
||||
if (timeValSec < 1000000000) {
|
||||
timeVal = timeValSec;
|
||||
}
|
||||
} else if (type == TSDB_DATA_TYPE_BIGINT) { /* unix timestamp */
|
||||
GET_TYPED_DATA(timeVal, int64_t, type, input);
|
||||
} else if (type == TSDB_DATA_TYPE_TIMESTAMP) { /* timestamp column*/
|
||||
GET_TYPED_DATA(timeVal, int64_t, type, input);
|
||||
int64_t timeValSec = timeVal / factor;
|
||||
if (timeValSec < 1000000000) {
|
||||
timeVal = timeValSec;
|
||||
}
|
||||
}
|
||||
|
||||
char buf[20] = {0};
|
||||
NUM_TO_STRING(TSDB_DATA_TYPE_BIGINT, &timeVal, sizeof(buf), buf);
|
||||
int32_t tsDigits = (int32_t)strlen(buf);
|
||||
|
||||
switch (unit) {
|
||||
case 0: { /* 1u or 1b */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
if (timePrec == TSDB_TIME_PRECISION_NANO && timeUnit == 1) {
|
||||
timeVal = timeVal * 1;
|
||||
} else {
|
||||
timeVal = timeVal / 1000 * 1000;
|
||||
}
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
timeVal = timeVal * factor;
|
||||
} else {
|
||||
timeVal = timeVal * 1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1: { /* 1a */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal * 1;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal / 1000 * 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000000 * 1000000;
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
timeVal = timeVal * factor;
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 1000: { /* 1s */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal / 1000 * 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal / 1000000 * 1000000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000000000 * 1000000000;
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
timeVal = timeVal * factor;
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 60000: { /* 1m */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal / 1000 / 60 * 60 * 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal / 1000000 / 60 * 60 * 1000000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000000000 / 60 * 60 * 1000000000;
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
timeVal = timeVal * factor / factor / 60 * 60 * factor;
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 3600000: { /* 1h */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal / 1000 / 3600 * 3600 * 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal / 1000000 / 3600 * 3600 * 1000000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000000000 / 3600 * 3600 * 1000000000;
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
timeVal = timeVal * factor / factor / 3600 * 3600 * factor;
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 86400000: { /* 1d */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000)) % (((int64_t)86400) * 1000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000 / 86400 * 86400 * 1000;
|
||||
}
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000)) % (((int64_t)86400) * 1000000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000000 / 86400 * 86400 * 1000000;
|
||||
}
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000000)) % (((int64_t)86400) * 1000000000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000000000 / 86400 * 86400 * 1000000000;
|
||||
}
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = (timeVal - (timeVal + offsetFromTz(timezone, 1)) % (86400L)) * factor;
|
||||
} else {
|
||||
timeVal = timeVal * factor / factor / 86400 * 86400 * factor;
|
||||
}
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 604800000: { /* 1w */
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000)) % (((int64_t)604800) * 1000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000 / 604800 * 604800 * 1000;
|
||||
}
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000)) % (((int64_t)604800) * 1000000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000000 / 604800 * 604800 * 1000000;
|
||||
}
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1000000000)) % (((int64_t)604800) * 1000000000);
|
||||
} else {
|
||||
timeVal = timeVal / 1000000000 / 604800 * 604800 * 1000000000;
|
||||
}
|
||||
} else if (tsDigits <= TSDB_TIME_PRECISION_SEC_DIGITS) {
|
||||
if (ignoreTz) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, 1)) % (((int64_t)604800L) * factor);
|
||||
} else {
|
||||
timeVal = timeVal * factor / factor / 604800 * 604800 * factor;
|
||||
}
|
||||
} else {
|
||||
colDataSetNULL(pOutput->columnData, i);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
timeVal = timeVal * 1;
|
||||
break;
|
||||
}
|
||||
// truncate the timestamp to time_unit precision
|
||||
int64_t seconds = timeUnit / TSDB_TICK_PER_SECOND(timePrec);
|
||||
if (ignoreTz && (seconds == 604800 || seconds == 86400)) {
|
||||
timeVal = timeVal - (timeVal + offsetFromTz(timezone, TSDB_TICK_PER_SECOND(timePrec))) % (((int64_t)seconds) * TSDB_TICK_PER_SECOND(timePrec));;
|
||||
} else {
|
||||
timeVal = timeVal / timeUnit * timeUnit;
|
||||
}
|
||||
|
||||
// truncate the timestamp to db precision
|
||||
switch (timePrec) {
|
||||
case TSDB_TIME_PRECISION_MILLI: {
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal / 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_TIME_PRECISION_MICRO: {
|
||||
if (tsDigits == TSDB_TIME_PRECISION_NANO_DIGITS) {
|
||||
timeVal = timeVal / 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal * 1000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case TSDB_TIME_PRECISION_NANO: {
|
||||
if (tsDigits == TSDB_TIME_PRECISION_MICRO_DIGITS) {
|
||||
timeVal = timeVal * 1000;
|
||||
} else if (tsDigits == TSDB_TIME_PRECISION_MILLI_DIGITS) {
|
||||
timeVal = timeVal * 1000000;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colDataSetVal(pOutput->columnData, i, (char *)&timeVal, false);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ class TDTestCase:
|
|||
'2020-4-1 00:00:00.001002',
|
||||
'2020-5-1 00:00:00.001002001'
|
||||
]
|
||||
self.unix_ts = ['1','1111','1111111','1111111111','1111111111111']
|
||||
self.db_param_precision = ['ms','us','ns']
|
||||
self.time_unit = ['1w','1d','1h','1m','1s','1a','1u','1b']
|
||||
self.error_unit = ['2w','2d','2h','2m','2s','2a','2u','1c','#1']
|
||||
|
@ -134,7 +135,7 @@ class TDTestCase:
|
|||
tdSql.checkEqual(tdSql.queryResult[i][0],int(date_time[i]*1000/1000/1000/1000/1000/60/60/24)*24*60*60*1000*1000*1000 )
|
||||
else:
|
||||
# assuming the client timezone is UTC+0800
|
||||
tdSql.checkEqual(tdSql.queryResult[i][0],int(date_time[i] - (date_time[i] + 8 * 3600 * 1000000) % (86400 * 1000000)))
|
||||
tdSql.checkEqual(tdSql.queryResult[i][0],int(date_time[i] - (date_time[i] + 8 * 3600 * 1000000000) % (86400 * 1000000000)))
|
||||
elif unit.lower() == '1w':
|
||||
for i in range(len(self.ts_str)):
|
||||
if self.rest_tag != 'rest':
|
||||
|
@ -167,16 +168,49 @@ class TDTestCase:
|
|||
self.check_tb_type(unit,tb_type,ignore_tz)
|
||||
tdSql.checkRows(len(self.ts_str))
|
||||
self.check_ms_timestamp(unit,date_time,ignore_tz)
|
||||
for uts in self.unix_ts:
|
||||
ans_time = []
|
||||
if tb_type.lower() == 'ntb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ntbname}')
|
||||
elif tb_type.lower() == 'ctb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ctbname}')
|
||||
elif tb_type.lower() == 'stb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.stbname}')
|
||||
for i in range(len(self.ts_str)):
|
||||
ans_time.append(int(uts))
|
||||
self.check_ms_timestamp(unit, ans_time, ignore_tz)
|
||||
elif precision.lower() == 'us':
|
||||
for ignore_tz in tz_options:
|
||||
self.check_tb_type(unit,tb_type,ignore_tz)
|
||||
tdSql.checkRows(len(self.ts_str))
|
||||
self.check_us_timestamp(unit,date_time,ignore_tz)
|
||||
for uts in self.unix_ts:
|
||||
ans_time = []
|
||||
if tb_type.lower() == 'ntb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ntbname}')
|
||||
elif tb_type.lower() == 'ctb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ctbname}')
|
||||
elif tb_type.lower() == 'stb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.stbname}')
|
||||
for i in range(len(self.ts_str)):
|
||||
ans_time.append(int(uts))
|
||||
self.check_us_timestamp(unit, ans_time, ignore_tz)
|
||||
elif precision.lower() == 'ns':
|
||||
for ignore_tz in tz_options:
|
||||
self.check_tb_type(unit,tb_type, ignore_tz)
|
||||
tdSql.checkRows(len(self.ts_str))
|
||||
self.check_ns_timestamp(unit,date_time,ignore_tz)
|
||||
for uts in self.unix_ts:
|
||||
ans_time = []
|
||||
if tb_type.lower() == 'ntb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ntbname}')
|
||||
elif tb_type.lower() == 'ctb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.ctbname}')
|
||||
elif tb_type.lower() == 'stb':
|
||||
tdSql.query(f'select timetruncate({uts},{unit},{ignore_tz}) from {self.stbname}')
|
||||
for i in range(len(self.ts_str)):
|
||||
ans_time.append(int(uts))
|
||||
self.check_ns_timestamp(unit, ans_time, ignore_tz)
|
||||
for unit in self.error_unit:
|
||||
if tb_type.lower() == 'ntb':
|
||||
tdSql.error(f'select timetruncate(ts,{unit}) from {self.ntbname}')
|
||||
|
|
Loading…
Reference in New Issue