mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
* 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.
This commit is contained in:
@@ -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;
|
|||||||
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));
|
|||||||
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:
|
|||||||
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:
|
|||||||
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:
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void do_field_temporal(Copy_field *copy)
|
||||||
|
{
|
||||||
|
MYSQL_TIME ltime;
|
||||||
|
copy->from_field->get_date(<ime, TIME_FUZZY_DATE);
|
||||||
|
copy->to_field->store_time(<ime, 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)
|
|||||||
/*
|
/*
|
||||||
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)
|
|||||||
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)
|
|||||||
MYSQL_TIME copy= *ltime;
|
MYSQL_TIME copy= *ltime;
|
||||||
Lazy_string_time str(©);
|
Lazy_string_time str(©);
|
||||||
|
|
||||||
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)
|
|||||||
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,
|
||||||
|
Reference in New Issue
Block a user