Skip to content

Commit

Permalink
fix(tianmu): add the TIME_to_ulonglong_time_round logic, and fix up p…
Browse files Browse the repository at this point in the history
…recision loss problem and value overflow problem (stoneatom#1173)

When converting TIME or DATETIME to ulonglong numeric, the tianmu engine has not the
TIME_to_ulonglong_time_round logic.Which causes the results different from innodb.Furthermore,
i found another bug during processing the issue.When we close the tianmu_insert_delayed parameter,
the TIME or DATETIME or TIMESTAMP type's data will loss precision when executing insert sql.

PR Close stoneatom#1173
  • Loading branch information
Xinqiangxu committed Jun 17, 2023
1 parent 288262f commit c99b8d7
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 26 deletions.
26 changes: 26 additions & 0 deletions mysql-test/suite/tianmu/r/issue1173.result
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
DROP DATABASE IF EXISTS issue1173;
CREATE DATABASE issue1173;
USE issue1173;
CREATE TABLE t1 (a TIME(1) NOT NULL);
INSERT INTO t1 VALUES ('00:00:02.9');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t1;
a a & a a | a a^0 a<<1 a<<0 a>>1 bit_count(a)
00:00:02.9 3 3 3 6 3 1 2
CREATE TABLE t2 (a DATETIME(1) NOT NULL);
INSERT INTO t2 VALUES ('2001-01-01 00:00:02.9');
INSERT INTO t2 VALUES ('2001-01-01 23:59:59.9');
INSERT INTO t2 VALUES ('9999-12-31 23:59:59.9');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t2;
a a & a a | a a^0 a<<1 a<<0 a>>1 bit_count(a)
2001-01-01 00:00:02.9 20010101000003 20010101000003 20010101000003 40020202000006 20010101000003 10005050500001 24
2001-01-01 23:59:59.9 20010102000000 20010102000000 20010102000000 40020204000000 20010102000000 10005051000000 18
9999-12-31 23:59:59.9 99991231000000 99991231000000 99991231000000 199982462000000 99991231000000 49995615500000 24
CREATE TABLE t3 (a VARCHAR(30) NOT NULL);
INSERT INTO t3 VALUES ('18446744073709551610');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t3;
a a & a a | a a^0 a<<1 a<<0 a>>1 bit_count(a)
18446744073709551610 9223372036854775807 9223372036854775807 9223372036854775807 18446744073709551614 9223372036854775807 4611686018427387903 63
DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;
DROP DATABASE issue1173;
26 changes: 26 additions & 0 deletions mysql-test/suite/tianmu/t/issue1173.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
--source include/have_tianmu.inc
--disable_warnings

DROP DATABASE IF EXISTS issue1173;
CREATE DATABASE issue1173;
USE issue1173;

CREATE TABLE t1 (a TIME(1) NOT NULL);
INSERT INTO t1 VALUES ('00:00:02.9');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t1;

CREATE TABLE t2 (a DATETIME(1) NOT NULL);
INSERT INTO t2 VALUES ('2001-01-01 00:00:02.9');
INSERT INTO t2 VALUES ('2001-01-01 23:59:59.9');
INSERT INTO t2 VALUES ('9999-12-31 23:59:59.9');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t2;

CREATE TABLE t3 (a VARCHAR(30) NOT NULL);
INSERT INTO t3 VALUES ('18446744073709551610');
SELECT a, a & a, a | a, a^0, a<<1, a<<0, a>>1, bit_count(a) FROM t3;

DROP TABLE t1;
DROP TABLE t2;
DROP TABLE t3;

DROP DATABASE issue1173;
13 changes: 10 additions & 3 deletions storage/tianmu/core/item_tianmu_field.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -266,8 +266,10 @@ bool Item_tianmudatetime_base::get_time(MYSQL_TIME *ltime) {
}

longlong Item_tianmudatetime::val_int() {
return dt.year * 10000000000LL + dt.month * 100000000 + dt.day * 1000000 + dt.hour * 10000 + dt.minute * 100 +
dt.second;
MYSQL_TIME ltime;
dt.Store(&ltime, MYSQL_TIMESTAMP_DATETIME);
longlong tmp = (longlong)TIME_to_ulonglong_datetime_round(&ltime);
return dt.Neg() ? -tmp : tmp;
}

String *Item_tianmudatetime::val_str(String *s) {
Expand Down Expand Up @@ -317,7 +319,12 @@ bool Item_tianmudate::get_time(MYSQL_TIME *ltime) {
return false;
}

longlong Item_tianmutime::val_int() { return dt.hour * 10000 + dt.minute * 100 + dt.second; }
longlong Item_tianmutime::val_int() {
MYSQL_TIME ltime;
dt.Store(&ltime, MYSQL_TIMESTAMP_TIME);
longlong tmp = (longlong)TIME_to_ulonglong_time_round(&ltime);
return dt.Neg() ? -tmp : tmp;
}
String *Item_tianmutime::val_str(String *s) {
MYSQL_TIME ltime;
get_time(&ltime);
Expand Down
22 changes: 3 additions & 19 deletions storage/tianmu/core/tianmu_table.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -893,13 +893,7 @@ void TianmuTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) {
my_time_t secs_utc = current_txn_->Thd()->variables.time_zone->TIME_to_gmt_sec(&my_time, &myb);
common::GMTSec2GMTTime(&my_time, secs_utc);
}
types::DT dt = {};
dt.year = my_time.year;
dt.month = my_time.month;
dt.day = my_time.day;
dt.hour = my_time.hour;
dt.minute = my_time.minute;
dt.second = my_time.second;
types::DT dt(my_time);

*reinterpret_cast<int64_t *>(vc.Prepare(sizeof(int64_t))) = dt.val;
vc.ExpectedSize(sizeof(int64_t));
Expand All @@ -909,11 +903,7 @@ void TianmuTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) {
MYSQL_TIME my_time;
std::memset(&my_time, 0, sizeof(my_time));
f->get_time(&my_time);
types::DT dt = {};
dt.time_hour = my_time.hour;
dt.minute = my_time.minute;
dt.second = my_time.second;
dt.neg = my_time.neg;
types::DT dt(my_time);

*reinterpret_cast<int64_t *>(vc.Prepare(sizeof(int64_t))) = dt.val;
vc.ExpectedSize(sizeof(int64_t));
Expand All @@ -926,13 +916,7 @@ void TianmuTable::Field2VC(Field *f, loader::ValueCache &vc, size_t col) {
MYSQL_TIME my_time;
std::memset(&my_time, 0, sizeof(my_time));
f->get_time(&my_time);
types::DT dt = {};
dt.year = my_time.year;
dt.month = my_time.month;
dt.day = my_time.day;
dt.hour = my_time.hour;
dt.minute = my_time.minute;
dt.second = my_time.second;
types::DT dt(my_time);

*reinterpret_cast<int64_t *>(vc.Prepare(sizeof(int64_t))) = dt.val;
vc.ExpectedSize(sizeof(int64_t));
Expand Down
14 changes: 10 additions & 4 deletions strings/my_strtoll10.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,16 +204,22 @@ longlong my_strtoll10(const char *nptr, char **endptr, int *error)
if (s != end && (c= (*s-'0')) <= 9)
goto overflow;

li=i*LFACTOR2+ (ulonglong) j*100 + k;

/*Check whether the number overflows*/
if (li > LLONG_MAX || li > (ulonglong) LLONG_MIN)
goto overflow;

/* Check that we didn't get an overflow with the last digit */
if (i > cutoff || (i == cutoff && (j > cutoff2 || (j == cutoff2 &&
k > cutoff3))))
goto overflow;
li=i*LFACTOR2+ (ulonglong) j*100 + k;
return (longlong) li;
return negative ? LLONG_MIN : (longlong) ULLONG_MAX;

return (negative ? -((longlong) li) : (longlong) li);

overflow: /* *endptr is set here */
*error= MY_ERRNO_ERANGE;
return negative ? LLONG_MIN : (longlong) ULLONG_MAX;
return negative ? LLONG_MIN : LLONG_MAX;

end_i:
*endptr= (char*) s;
Expand Down

0 comments on commit c99b8d7

Please sign in to comment.