summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2011-03-17 14:13:03 +0100
committerSergei Golubchik <sergii@pisem.net>2011-03-17 14:13:03 +0100
commit1cda2654578b82da52c29a829d463955f8795cc9 (patch)
treef3a8de34f4bf0c331723a999dedc78e87be4b9bb
parenta169ede155937cba04b01ea104d7904d89f87007 (diff)
downloadmariadb-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.h2
-rw-r--r--mysql-test/r/func_time_hires.result8
-rw-r--r--mysql-test/t/func_time_hires.test6
-rw-r--r--sql-common/my_time.c14
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field_conv.cc12
-rw-r--r--sql/item_timefunc.cc4
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(&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
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(&copy);
- 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,