Commit 68d1a598 authored by Sergei Golubchik's avatar Sergei Golubchik

bugfix: copy timestamps correctly in INSERT...SELECT

Implement Field_timestamp::save_in_field(timestamp_field)
that stores timestamp values without converting them to MYSQL_TIME
and back, because this conversion is lossy around DST change time.
This fixes main.old-mode test.

This is 10.2 version of f8a800be
parent a5e1f60b
......@@ -1808,6 +1808,33 @@ int Field::store(const char *to, uint length, CHARSET_INFO *cs,
}
static int timestamp_to_TIME(THD *thd, MYSQL_TIME *ltime, my_time_t ts,
ulong sec_part, ulonglong fuzzydate)
{
thd->time_zone_used= 1;
if (ts == 0 && sec_part == 0)
{
if (fuzzydate & TIME_NO_ZERO_DATE)
return 1;
set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME);
}
else
{
thd->variables.time_zone->gmt_sec_to_TIME(ltime, ts);
ltime->second_part= sec_part;
}
return 0;
}
int Field::store_timestamp(my_time_t ts, ulong sec_part)
{
MYSQL_TIME ltime;
THD *thd= get_thd();
timestamp_to_TIME(thd, &ltime, ts, sec_part, 0);
return store_time_dec(&ltime, decimals());
}
/**
Pack the field into a format suitable for storage and transfer.
......@@ -4966,6 +4993,13 @@ Field_timestamp::Field_timestamp(uchar *ptr_arg, uint32 len_arg,
}
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);
}
my_time_t Field_timestamp::get_timestamp(const uchar *pos,
ulong *sec_part) const
{
......@@ -5092,6 +5126,22 @@ int Field_timestamp::store(longlong nr, bool unsigned_val)
}
int Field_timestamp::store_timestamp(my_time_t ts, ulong sec_part)
{
store_TIME(ts, sec_part);
if (ts == 0 && sec_part == 0 &&
get_thd()->variables.sql_mode & TIME_NO_ZERO_DATE)
{
ErrConvString s(
STRING_WITH_LEN("0000-00-00 00:00:00.000000") - (decimals() ? 6 - decimals() : 7),
system_charset_info);
set_datetime_warning(WARN_DATA_TRUNCATED, &s, MYSQL_TIMESTAMP_DATETIME, 1);
return 1;
}
return 0;
}
double Field_timestamp::val_real(void)
{
return (double) Field_timestamp::val_int();
......@@ -5195,22 +5245,9 @@ Field_timestamp::validate_value_in_record(THD *thd, const uchar *record) const
bool Field_timestamp::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
THD *thd= get_thd();
thd->time_zone_used= 1;
ulong sec_part;
my_time_t temp= get_timestamp(&sec_part);
if (temp == 0 && sec_part == 0)
{ /* Zero time is "000000" */
if (fuzzydate & TIME_NO_ZERO_DATE)
return 1;
set_zero_time(ltime, MYSQL_TIMESTAMP_DATETIME);
}
else
{
thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)temp);
ltime->second_part= sec_part;
}
return 0;
my_time_t ts= get_timestamp(&sec_part);
return timestamp_to_TIME(get_thd(), ltime, ts, sec_part, fuzzydate);
}
......
......@@ -842,6 +842,7 @@ 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(MYSQL_TIME *ltime, uint dec);
virtual int store_timestamp(my_time_t timestamp, ulong sec_part);
int store_time(MYSQL_TIME *ltime)
{ return store_time_dec(ltime, TIME_SECOND_PART_DIGITS); }
int store(const char *to, uint length, CHARSET_INFO *cs,
......@@ -2395,6 +2396,8 @@ class Field_timestamp :public Field_temporal {
int store(longlong nr, bool unsigned_val);
int store_time_dec(MYSQL_TIME *ltime, uint dec);
int store_decimal(const my_decimal *);
int store_timestamp(my_time_t timestamp, ulong sec_part);
int save_in_field(Field *to);
double val_real(void);
longlong val_int(void);
String *val_str(String*,String *);
......
......@@ -419,11 +419,8 @@ void Field::do_field_decimal(Copy_field *copy)
void Field::do_field_timestamp(Copy_field *copy)
{
Field_timestamp *f= static_cast<Field_timestamp*>(copy->from_field);
Field_timestamp *t= static_cast<Field_timestamp*>(copy->to_field);
ulong sec_part;
my_time_t ts= f->get_timestamp(&sec_part);
t->store_TIME(ts, sec_part);
// XXX why couldn't we do it everywhere?
copy->from_field->save_in_field(copy->to_field);
}
......
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