Commit a25ce5ab authored by Alexander Barkov's avatar Alexander Barkov

MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work...

MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work well on fractional digits
parent fac997fe
......@@ -8559,11 +8559,11 @@ RETURN a = timestamp'2038-01-19 03:14:07.999999'
END
$$
SELECT f1(e) FROM t1;
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30'
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000'
SELECT f2(e) FROM t1;
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30'
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000'
SELECT f3(e) FROM t1;
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30'
ERROR 22007: Truncated incorrect DOUBLE value: '2001-01-01 10:20:30.000000'
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP FUNCTION f3;
......
......@@ -1033,5 +1033,40 @@ CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED);
DROP TABLE t1;
#
# MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work well on fractional digits
#
SET time_zone='+00:00';
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456');
CREATE PROCEDURE p1()
BEGIN
DECLARE ts10 TIMESTAMP(1) DEFAULT NOW();
DECLARE ts16 TIMESTAMP(1) DEFAULT NOW(6);
DECLARE dt10 DATETIME(1) DEFAULT NOW();
DECLARE dt16 DATETIME(1) DEFAULT NOW(6);
DECLARE vts10 VARCHAR(32) DEFAULT ts10;
DECLARE vts16 VARCHAR(32) DEFAULT ts16;
DECLARE vdt10 VARCHAR(32) DEFAULT dt10;
DECLARE vdt16 VARCHAR(32) DEFAULT dt16;
DECLARE tts10 TEXT(32) DEFAULT ts10;
DECLARE tts16 TEXT(32) DEFAULT ts16;
DECLARE tdt10 TEXT(32) DEFAULT dt10;
DECLARE tdt16 TEXT(32) DEFAULT dt16;
SELECT vts10, vts16, vdt10, vdt16;
SELECT tts10, tts16, tdt10, tdt16;
END;
$$
CALL p1;
vts10 2001-01-01 10:20:30.0
vts16 2001-01-01 10:20:30.1
vdt10 2001-01-01 10:20:30.0
vdt16 2001-01-01 10:20:30.1
tts10 2001-01-01 10:20:30.0
tts16 2001-01-01 10:20:30.1
tdt10 2001-01-01 10:20:30.0
tdt16 2001-01-01 10:20:30.1
DROP PROCEDURE p1;
SET timestamp=DEFAULT;
SET time_zone=DEFAULT;
#
# End of 10.4 tests
#
......@@ -625,6 +625,41 @@ CREATE TABLE t1 (a TIMESTAMP);
INSERT INTO t1 SELECT CAST(20010101 AS UNSIGNED);
DROP TABLE t1;
--echo #
--echo # MDEV-17928 Conversion from TIMESTAMP to VARCHAR SP variables does not work well on fractional digits
--echo #
SET time_zone='+00:00';
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30.123456');
DELIMITER $$;
CREATE PROCEDURE p1()
BEGIN
DECLARE ts10 TIMESTAMP(1) DEFAULT NOW();
DECLARE ts16 TIMESTAMP(1) DEFAULT NOW(6);
DECLARE dt10 DATETIME(1) DEFAULT NOW();
DECLARE dt16 DATETIME(1) DEFAULT NOW(6);
DECLARE vts10 VARCHAR(32) DEFAULT ts10;
DECLARE vts16 VARCHAR(32) DEFAULT ts16;
DECLARE vdt10 VARCHAR(32) DEFAULT dt10;
DECLARE vdt16 VARCHAR(32) DEFAULT dt16;
DECLARE tts10 TEXT(32) DEFAULT ts10;
DECLARE tts16 TEXT(32) DEFAULT ts16;
DECLARE tdt10 TEXT(32) DEFAULT dt10;
DECLARE tdt16 TEXT(32) DEFAULT dt16;
SELECT vts10, vts16, vdt10, vdt16;
SELECT tts10, tts16, tdt10, tdt16;
END;
$$
DELIMITER ;$$
--vertical_results
CALL p1;
--horizontal_results
DROP PROCEDURE p1;
SET timestamp=DEFAULT;
SET time_zone=DEFAULT;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -1831,12 +1831,9 @@ int Field::store(const char *to, size_t length, CHARSET_INFO *cs,
}
int Field::store_timestamp(my_time_t ts, ulong sec_part)
int Field::store_timestamp_dec(const timeval &ts, uint dec)
{
MYSQL_TIME ltime;
THD *thd= get_thd();
thd->timestamp_to_TIME(&ltime, ts, sec_part, date_mode_t(0));
return store_time_dec(&ltime, decimals());
return store_time_dec(Datetime(get_thd(), ts).get_mysql_time(), dec);
}
/**
......@@ -5014,7 +5011,7 @@ int Field_timestamp::save_in_field(Field *to)
{
ulong sec_part;
my_time_t ts= get_timestamp(&sec_part);
return to->store_timestamp(ts, sec_part);
return to->store_timestamp_dec(Timeval(ts, sec_part), decimals());
}
my_time_t Field_timestamp::get_timestamp(const uchar *pos,
......@@ -5126,11 +5123,11 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
}
int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part)
int Field_timestamp::store_timestamp_dec(const timeval &ts, uint dec)
{
int warn= 0;
time_round_mode_t mode= Datetime::default_round_mode(get_thd());
store_TIMESTAMP(Timestamp(ts, sec_part).round(decimals(), mode, &warn));
store_TIMESTAMP(Timestamp(ts).round(decimals(), mode, &warn));
if (warn)
{
/*
......@@ -5144,7 +5141,7 @@ int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part)
*/
set_warning(Sql_condition::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
}
if (ts == 0 && sec_part == 0 &&
if (ts.tv_sec == 0 && ts.tv_usec == 0 &&
get_thd()->variables.sql_mode & (ulonglong) TIME_NO_ZERO_DATE)
{
ErrConvString s(
......
......@@ -784,7 +784,12 @@ class Field: public Value_source
virtual int store(longlong nr, bool unsigned_val)=0;
virtual int store_decimal(const my_decimal *d)=0;
virtual int store_time_dec(const MYSQL_TIME *ltime, uint dec);
virtual int store_timestamp(my_time_t timestamp, ulong sec_part);
virtual int store_timestamp_dec(const timeval &ts, uint dec);
int store_timestamp(my_time_t timestamp, ulong sec_part)
{
return store_timestamp_dec(Timeval(timestamp, sec_part),
TIME_SECOND_PART_DIGITS);
}
int store_time(const MYSQL_TIME *ltime)
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
int store(const char *to, size_t length, CHARSET_INFO *cs,
......@@ -2744,7 +2749,7 @@ class Field_timestamp :public Field_temporal {
int store(longlong nr, bool unsigned_val);
int store_time_dec(const MYSQL_TIME *ltime, uint dec);
int store_decimal(const my_decimal *);
int store_timestamp(my_time_t timestamp, ulong sec_part);
int store_timestamp_dec(const timeval &ts, uint dec);
int save_in_field(Field *to);
double val_real(void);
longlong val_int(void);
......
......@@ -7495,7 +7495,8 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
}
else if (part_info->vers_info->interval.is_set())
{
table->field[11]->store_timestamp((my_time_t)part_elem->range_value, 0);
Timeval tv((my_time_t) part_elem->range_value, 0);
table->field[11]->store_timestamp_dec(tv, AUTO_SEC_PART_DIGITS);
table->field[11]->set_notnull();
}
}
......
......@@ -2234,6 +2234,9 @@ class Timestamp: protected Timeval
Timestamp(my_time_t timestamp, ulong sec_part)
:Timeval(timestamp, sec_part)
{ }
explicit Timestamp(const timeval &tv)
:Timeval(tv)
{ }
const struct timeval &tv() const { return *this; }
long fraction_remainder(uint dec) const
{
......
......@@ -853,6 +853,9 @@ class Timeval: public timeval
tv_sec= sec;
tv_usec= usec;
}
explicit Timeval(const timeval &tv)
:timeval(tv)
{ }
};
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment