Commit 1cda2654 authored by Sergei Golubchik's avatar Sergei Golubchik

* fix for ALTER TABLE ... MODIFY timestamp->timestamp.

  Use dedicated  do_field_temporal() for Copy_field.
* check_time_range() needs to know TIME's precision to use the
  correct max value.
parent a169ede1
...@@ -92,7 +92,7 @@ double TIME_to_double(const MYSQL_TIME *my_time); ...@@ -92,7 +92,7 @@ double TIME_to_double(const MYSQL_TIME *my_time);
longlong pack_time(MYSQL_TIME *my_time); longlong pack_time(MYSQL_TIME *my_time);
MYSQL_TIME *unpack_time(longlong packed, MYSQL_TIME *my_time); MYSQL_TIME *unpack_time(longlong packed, MYSQL_TIME *my_time);
int check_time_range(struct st_mysql_time *, int *warning); int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning);
long calc_daynr(uint year,uint month,uint day); long calc_daynr(uint year,uint month,uint day);
uint calc_days_in_year(uint year); uint calc_days_in_year(uint year);
......
...@@ -158,6 +158,14 @@ select time(f1) from t1 union all select time(f1) from t1; ...@@ -158,6 +158,14 @@ select time(f1) from t1 union all select time(f1) from t1;
time(f1) time(f1)
21:00:00.000000 21:00:00.000000
21:00:00.000000 21:00:00.000000
alter table t1 modify f1 timestamp;
select time(f1) from t1;
time(f1)
21:00:00
select time(f1) from t1 union all select time(f1) from t1;
time(f1)
21:00:00
21:00:00
alter table t1 modify f1 varchar(100); alter table t1 modify f1 varchar(100);
select time(f1) from t1; select time(f1) from t1;
time(f1) time(f1)
......
...@@ -86,9 +86,9 @@ create table t1 (f1 timestamp(6)); ...@@ -86,9 +86,9 @@ create table t1 (f1 timestamp(6));
insert into t1 values ('2002-07-15 21:00:00'); insert into t1 values ('2002-07-15 21:00:00');
select time(f1) from t1; select time(f1) from t1;
select time(f1) from t1 union all select time(f1) from t1; select time(f1) from t1 union all select time(f1) from t1;
#alter table t1 modify f1 timestamp; alter table t1 modify f1 timestamp;
#select time(f1) from t1; select time(f1) from t1;
#select time(f1) from t1 union all select time(f1) from t1; select time(f1) from t1 union all select time(f1) from t1;
# but the effect cannot be eliminated completely: # but the effect cannot be eliminated completely:
alter table t1 modify f1 varchar(100); alter table t1 modify f1 varchar(100);
select time(f1) from t1; select time(f1) from t1;
......
...@@ -654,7 +654,7 @@ fractional: ...@@ -654,7 +654,7 @@ fractional:
l_time->time_type= MYSQL_TIMESTAMP_TIME; l_time->time_type= MYSQL_TIMESTAMP_TIME;
/* Check if the value is valid and fits into MYSQL_TIME range */ /* Check if the value is valid and fits into MYSQL_TIME range */
if (check_time_range(l_time, warning)) if (check_time_range(l_time, 6, warning))
return MYSQL_TIMESTAMP_ERROR; return MYSQL_TIMESTAMP_ERROR;
/* Check if there is garbage at end of the MYSQL_TIME specification */ /* Check if there is garbage at end of the MYSQL_TIME specification */
...@@ -679,6 +679,7 @@ fractional: ...@@ -679,6 +679,7 @@ fractional:
SYNOPSIS: SYNOPSIS:
check_time_range() check_time_range()
time pointer to MYSQL_TIME value time pointer to MYSQL_TIME value
uint dec
warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range
DESCRIPTION DESCRIPTION
...@@ -691,17 +692,24 @@ fractional: ...@@ -691,17 +692,24 @@ fractional:
1 time value is invalid 1 time value is invalid
*/ */
int check_time_range(struct st_mysql_time *my_time, int *warning) int check_time_range(struct st_mysql_time *my_time, uint dec, int *warning)
{ {
longlong hour; longlong hour;
static ulong max_sec_part[MAX_SEC_PART_DIGITS+1]= {000000, 900000, 990000,
999000, 999900, 999990, 999999};
if (my_time->minute >= 60 || my_time->second >= 60) if (my_time->minute >= 60 || my_time->second >= 60)
return 1; return 1;
hour= my_time->hour + (24*my_time->day); hour= my_time->hour + (24*my_time->day);
if (dec == AUTO_SEC_PART_DIGITS)
dec= MAX_SEC_PART_DIGITS;
if (hour <= TIME_MAX_HOUR && if (hour <= TIME_MAX_HOUR &&
(hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE || (hour != TIME_MAX_HOUR || my_time->minute != TIME_MAX_MINUTE ||
my_time->second != TIME_MAX_SECOND || !my_time->second_part)) my_time->second != TIME_MAX_SECOND ||
my_time->second_part <= max_sec_part[dec]))
return 0; return 0;
my_time->day= 0; my_time->day= 0;
......
...@@ -5348,7 +5348,7 @@ int Field_time::store_time(MYSQL_TIME *ltime, timestamp_type time_type) ...@@ -5348,7 +5348,7 @@ int Field_time::store_time(MYSQL_TIME *ltime, timestamp_type time_type)
Lazy_string_time str(ltime); Lazy_string_time str(ltime);
int was_cut= 0; int was_cut= 0;
int have_smth_to_conv= !check_time_range(&l_time, &was_cut); int have_smth_to_conv= !check_time_range(&l_time, decimals(), &was_cut);
return store_TIME_with_warning(&l_time, &str, was_cut, have_smth_to_conv); return store_TIME_with_warning(&l_time, &str, was_cut, have_smth_to_conv);
} }
......
...@@ -365,6 +365,14 @@ static void do_field_decimal(Copy_field *copy) ...@@ -365,6 +365,14 @@ static void do_field_decimal(Copy_field *copy)
} }
static void do_field_temporal(Copy_field *copy)
{
MYSQL_TIME ltime;
copy->from_field->get_date(&ltime, TIME_FUZZY_DATE);
copy->to_field->store_time(&ltime, ltime.time_type);
}
/** /**
string copy for single byte characters set when to string is shorter than string copy for single byte characters set when to string is shorter than
from string. from string.
...@@ -559,7 +567,7 @@ void Copy_field::set(uchar *to,Field *from) ...@@ -559,7 +567,7 @@ void Copy_field::set(uchar *to,Field *from)
/* /*
To do: To do:
If 'save\ is set to true and the 'from' is a blob field, do_copy is set to If 'save' is set to true and the 'from' is a blob field, do_copy is set to
do_save_blob rather than do_conv_blob. The only differences between them do_save_blob rather than do_conv_blob. The only differences between them
appears to be: appears to be:
...@@ -657,6 +665,8 @@ Copy_field::get_copy_func(Field *to,Field *from) ...@@ -657,6 +665,8 @@ Copy_field::get_copy_func(Field *to,Field *from)
return do_field_int; return do_field_int;
if (to->result_type() == DECIMAL_RESULT) if (to->result_type() == DECIMAL_RESULT)
return do_field_decimal; return do_field_decimal;
if (to->cmp_type() == TIME_RESULT)
return do_field_temporal;
// Check if identical fields // Check if identical fields
if (from->result_type() == STRING_RESULT) if (from->result_type() == STRING_RESULT)
{ {
......
...@@ -2482,7 +2482,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, uint fuzzy_date) ...@@ -2482,7 +2482,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
MYSQL_TIME copy= *ltime; MYSQL_TIME copy= *ltime;
Lazy_string_time str(&copy); Lazy_string_time str(&copy);
check_time_range(ltime, &was_cut); check_time_range(ltime, decimals, &was_cut);
if (was_cut) if (was_cut)
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
&str, MYSQL_TIMESTAMP_TIME, NullS); &str, MYSQL_TIMESTAMP_TIME, NullS);
...@@ -2561,7 +2561,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, uint fuzzy_date) ...@@ -2561,7 +2561,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
goto null_date; goto null_date;
*ltime= l_time3; *ltime= l_time3;
check_time_range(ltime, &was_cut); check_time_range(ltime, decimals, &was_cut);
if (was_cut) if (was_cut)
make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
......
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