Commit 5e71afcb authored by unknown's avatar unknown

Bug#21811 Odd casting with date + INTERVAL arithmetic

- Type casting was not consequent, thus when adding a DATE type with
  a WEEK interval the result type was DATETIME and not DATE as is the
  norm.
- By changing the order of the date internal enumerations the deviant
  type casting is resolved (Item_date_add_interval::fix_length_and_dec()
  which determines result type for this operation assumes that addition
  of any interval with value <= INTERVAL_DAY to date value will result
  in date). There are two independant places to change:
  interval_names[] and interval_type.


mysql-test/r/func_date_add.result:
  Updated result file for type casting test
mysql-test/r/func_time.result:
  Updated result file for type casting test
mysql-test/t/func_date_add.test:
  Added test for type casting when adding intervals to date.
sql/item_timefunc.cc:
  Changed order of "week" key word to match the date interval enumeration.
sql/item_timefunc.h:
  Changed the order of the enumeration to better follow interval sizes.
parent a4b16953
...@@ -71,3 +71,17 @@ NULL ...@@ -71,3 +71,17 @@ NULL
NULL NULL
NULL NULL
drop table t1; drop table t1;
End of 4.1 tests
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY
2006-09-27
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH
2006-10-26
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR
2007-09-26
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK
2006-10-03
End of 5.0 tests
...@@ -612,7 +612,7 @@ date_add(date,INTERVAL "1 1:1:1" DAY_SECOND) ...@@ -612,7 +612,7 @@ date_add(date,INTERVAL "1 1:1:1" DAY_SECOND)
2003-01-03 01:01:01 2003-01-03 01:01:01
select date_add(date,INTERVAL "1" WEEK) from t1; select date_add(date,INTERVAL "1" WEEK) from t1;
date_add(date,INTERVAL "1" WEEK) date_add(date,INTERVAL "1" WEEK)
2003-01-09 00:00:00 2003-01-09
select date_add(date,INTERVAL "1" QUARTER) from t1; select date_add(date,INTERVAL "1" QUARTER) from t1;
date_add(date,INTERVAL "1" QUARTER) date_add(date,INTERVAL "1" QUARTER)
2003-04-02 2003-04-02
...@@ -621,7 +621,7 @@ timestampadd(MINUTE, 1, date) ...@@ -621,7 +621,7 @@ timestampadd(MINUTE, 1, date)
2003-01-02 00:01:00 2003-01-02 00:01:00
select timestampadd(WEEK, 1, date) from t1; select timestampadd(WEEK, 1, date) from t1;
timestampadd(WEEK, 1, date) timestampadd(WEEK, 1, date)
2003-01-09 00:00:00 2003-01-09
select timestampadd(SQL_TSI_SECOND, 1, date) from t1; select timestampadd(SQL_TSI_SECOND, 1, date) from t1;
timestampadd(SQL_TSI_SECOND, 1, date) timestampadd(SQL_TSI_SECOND, 1, date)
2003-01-02 00:00:01 2003-01-02 00:00:01
......
...@@ -64,4 +64,17 @@ insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY)); ...@@ -64,4 +64,17 @@ insert into t1 values (date_add('2000-01-04', INTERVAL NULL DAY));
select * from t1; select * from t1;
drop table t1; drop table t1;
# End of 4.1 tests --echo End of 4.1 tests
#
# Bug#21811
#
# Make sure we end up with an appropriate
# date format (DATE) after addition operation
#
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 DAY;
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 MONTH;
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 YEAR;
SELECT CAST('2006-09-26' AS DATE) + INTERVAL 1 WEEK;
--echo End of 5.0 tests
...@@ -2151,11 +2151,15 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const ...@@ -2151,11 +2151,15 @@ bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const
(date_sub_interval == other->date_sub_interval)); (date_sub_interval == other->date_sub_interval));
} }
/*
'interval_names' reflects the order of the enumeration interval_type.
See item_timefunc.h
*/
static const char *interval_names[]= static const char *interval_names[]=
{ {
"year", "quarter", "month", "day", "hour", "year", "quarter", "month", "week", "day",
"minute", "week", "second", "microsecond", "hour", "minute", "second", "microsecond",
"year_month", "day_hour", "day_minute", "year_month", "day_hour", "day_minute",
"day_second", "hour_minute", "hour_second", "day_second", "hour_minute", "hour_second",
"minute_second", "day_microsecond", "minute_second", "day_microsecond",
......
...@@ -630,18 +630,21 @@ public: ...@@ -630,18 +630,21 @@ public:
}; };
/* /*
The following must be sorted so that simple intervals comes first. 'interval_type' must be sorted so that simple intervals comes first,
(get_interval_value() depends on this) ie year, quarter, month, week, day, hour, etc. The order based on
interval size is also important and the intervals should be kept in a
large to smaller order. (get_interval_value() depends on this)
*/ */
enum interval_type enum interval_type
{ {
INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_YEAR, INTERVAL_QUARTER, INTERVAL_MONTH, INTERVAL_WEEK,
INTERVAL_MINUTE, INTERVAL_WEEK, INTERVAL_SECOND, INTERVAL_MICROSECOND , INTERVAL_DAY, INTERVAL_HOUR, INTERVAL_MINUTE, INTERVAL_SECOND,
INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_MICROSECOND, INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR,
INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE,
INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND,
INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND INTERVAL_HOUR_MICROSECOND, INTERVAL_MINUTE_MICROSECOND,
INTERVAL_SECOND_MICROSECOND
}; };
class Item_date_add_interval :public Item_date_func class Item_date_add_interval :public Item_date_func
......
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