diff options
author | Sergei Golubchik <sergii@pisem.net> | 2011-03-17 14:13:03 +0100 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2011-03-17 14:13:03 +0100 |
commit | 1cda2654578b82da52c29a829d463955f8795cc9 (patch) | |
tree | f3a8de34f4bf0c331723a999dedc78e87be4b9bb | |
parent | a169ede155937cba04b01ea104d7904d89f87007 (diff) | |
download | mariadb-git-1cda2654578b82da52c29a829d463955f8795cc9.tar.gz |
* 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.
-rw-r--r-- | include/my_time.h | 2 | ||||
-rw-r--r-- | mysql-test/r/func_time_hires.result | 8 | ||||
-rw-r--r-- | mysql-test/t/func_time_hires.test | 6 | ||||
-rw-r--r-- | sql-common/my_time.c | 14 | ||||
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field_conv.cc | 12 | ||||
-rw-r--r-- | sql/item_timefunc.cc | 4 |
7 files changed, 37 insertions, 11 deletions
diff --git a/include/my_time.h b/include/my_time.h index 7d059a03710..db1795eeb6e 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -92,7 +92,7 @@ double TIME_to_double(const MYSQL_TIME *my_time); longlong pack_time(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); uint calc_days_in_year(uint year); diff --git a/mysql-test/r/func_time_hires.result b/mysql-test/r/func_time_hires.result index f96815a6977..4a3dc9b5d5c 100644 --- a/mysql-test/r/func_time_hires.result +++ b/mysql-test/r/func_time_hires.result @@ -158,6 +158,14 @@ select time(f1) from t1 union all select time(f1) from t1; time(f1) 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); select time(f1) from t1; time(f1) diff --git a/mysql-test/t/func_time_hires.test b/mysql-test/t/func_time_hires.test index c651b4aa718..8183f3435e2 100644 --- a/mysql-test/t/func_time_hires.test +++ b/mysql-test/t/func_time_hires.test @@ -86,9 +86,9 @@ create table t1 (f1 timestamp(6)); insert into t1 values ('2002-07-15 21:00:00'); select time(f1) from t1; select time(f1) from t1 union all select time(f1) from t1; -#alter table t1 modify f1 timestamp; -#select time(f1) from t1; -#select time(f1) from t1 union all select time(f1) from t1; +alter table t1 modify f1 timestamp; +select time(f1) from t1; +select time(f1) from t1 union all select time(f1) from t1; # but the effect cannot be eliminated completely: alter table t1 modify f1 varchar(100); select time(f1) from t1; diff --git a/sql-common/my_time.c b/sql-common/my_time.c index 11dd60646ef..f05f1fe835b 100644 --- a/sql-common/my_time.c +++ b/sql-common/my_time.c @@ -654,7 +654,7 @@ fractional: l_time->time_type= MYSQL_TIMESTAMP_TIME; /* 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; /* Check if there is garbage at end of the MYSQL_TIME specification */ @@ -679,6 +679,7 @@ fractional: SYNOPSIS: check_time_range() time pointer to MYSQL_TIME value + uint dec warning set MYSQL_TIME_WARN_OUT_OF_RANGE flag if the value is out of range DESCRIPTION @@ -691,17 +692,24 @@ fractional: 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; + 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) return 1; hour= my_time->hour + (24*my_time->day); + + if (dec == AUTO_SEC_PART_DIGITS) + dec= MAX_SEC_PART_DIGITS; + if (hour <= TIME_MAX_HOUR && (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; my_time->day= 0; diff --git a/sql/field.cc b/sql/field.cc index f32f7d3c214..16b250ed63c 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -5348,7 +5348,7 @@ int Field_time::store_time(MYSQL_TIME *ltime, timestamp_type time_type) Lazy_string_time str(ltime); 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); } diff --git a/sql/field_conv.cc b/sql/field_conv.cc index a4fca6f8ad7..e4da3f114ef 100644 --- a/sql/field_conv.cc +++ b/sql/field_conv.cc @@ -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 from string. @@ -559,7 +567,7 @@ void Copy_field::set(uchar *to,Field *from) /* 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 appears to be: @@ -657,6 +665,8 @@ Copy_field::get_copy_func(Field *to,Field *from) return do_field_int; if (to->result_type() == DECIMAL_RESULT) return do_field_decimal; + if (to->cmp_type() == TIME_RESULT) + return do_field_temporal; // Check if identical fields if (from->result_type() == STRING_RESULT) { diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 1575c1345af..b27e9d72cfc 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2482,7 +2482,7 @@ bool Item_func_add_time::get_date(MYSQL_TIME *ltime, uint fuzzy_date) MYSQL_TIME copy= *ltime; Lazy_string_time str(©); - check_time_range(ltime, &was_cut); + check_time_range(ltime, decimals, &was_cut); if (was_cut) make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, &str, MYSQL_TIMESTAMP_TIME, NullS); @@ -2561,7 +2561,7 @@ bool Item_func_timediff::get_date(MYSQL_TIME *ltime, uint fuzzy_date) goto null_date; *ltime= l_time3; - check_time_range(ltime, &was_cut); + check_time_range(ltime, decimals, &was_cut); if (was_cut) make_truncated_value_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, |