From 1e292442009034244fcf7212f494cec76dd7fc26 Mon Sep 17 00:00:00 2001 From: "ramil@mysql.com" <> Date: Tue, 11 Apr 2006 16:13:57 +0500 Subject: [PATCH 1/3] Fix for bug #14360: Date Between Interval Broken. --- mysql-test/r/innodb.result | 9 +++++++++ mysql-test/t/innodb.test | 12 ++++++++++++ sql/item_timefunc.cc | 35 +++++++++++++++++++++++++++++++++++ sql/item_timefunc.h | 1 + 4 files changed, 57 insertions(+) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index c5658d22eb6..9a190557211 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -3232,3 +3232,12 @@ drop trigger t2t; drop trigger t3t; drop trigger t4t; drop table t1, t2, t3, t4, t5; +create table t1(a date) engine=innodb; +create table t2(a date, key(a)) engine=innodb; +insert into t1 values('2005-10-01'); +insert into t2 values('2005-10-01'); +select * from t1, t2 +where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; +a a +2005-10-01 2005-10-01 +drop table t1, t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 832c4635815..b0835cd8419 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2127,3 +2127,15 @@ drop table t1, t2, t3, t4, t5; connection default; disconnect a; disconnect b; + +# +# Bug #14360: problem with intervals +# + +create table t1(a date) engine=innodb; +create table t2(a date, key(a)) engine=innodb; +insert into t1 values('2005-10-01'); +insert into t2 values('2005-10-01'); +select * from t1, t2 + where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; +drop table t1, t2; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index e139eba385e..ee74d30ce53 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -2125,6 +2125,41 @@ longlong Item_date_add_interval::val_int() ((date*100L + ltime.hour)*100L+ ltime.minute)*100L + ltime.second; } + + +bool Item_date_add_interval::eq(const Item *item, bool binary_cmp) const +{ + INTERVAL interval, other_interval; + String val= value; // Because of const + + if (this == item) + return TRUE; + + if ((item->type() != FUNC_ITEM) || + (arg_count != ((Item_func*) item)->arg_count) || + (func_name() != ((Item_func*) item)->func_name())) + return FALSE; + + Item_date_add_interval *other= (Item_date_add_interval*) item; + + if ((int_type != other->int_type) || + (!args[0]->eq(other->args[0], binary_cmp)) || + (get_interval_value(args[1], int_type, &val, &interval))) + return FALSE; + + val= other->value; + + if ((get_interval_value(other->args[1], other->int_type, &val, + &other_interval)) || + ((date_sub_interval ^ interval.neg) ^ + (other->date_sub_interval ^ other_interval.neg))) + return FALSE; + + // Assume comparing same types here due to earlier check + return memcmp(&interval, &other_interval, sizeof(INTERVAL)) == 0; +} + + static const char *interval_names[]= { "year", "quarter", "month", "day", "hour", diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h index 71f595184ec..761faf85e63 100644 --- a/sql/item_timefunc.h +++ b/sql/item_timefunc.h @@ -656,6 +656,7 @@ public: double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); } longlong val_int(); bool get_date(TIME *res, uint fuzzy_date); + bool eq(const Item *item, bool binary_cmp) const; void print(String *str); }; From dfd8f0211c9d9e302544119cb080d3909611884a Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Tue, 11 Apr 2006 10:03:37 -0700 Subject: [PATCH 2/3] Fixed bug #18618. If the second or the third argument of a BETWEEN predicate was a constant expression, like '2005.09.01' - INTERVAL 6 MONTH, while the other two arguments were fields then the predicate was evaluated incorrectly and the query returned a wrong result set. The bug was introduced in 5.0.17 when in the fix for 12612. --- mysql-test/r/func_time.result | 25 +++++++++++++++++++++++++ mysql-test/t/func_time.test | 22 ++++++++++++++++++++++ sql/item_cmpfunc.cc | 12 ++---------- 3 files changed, 49 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index 5d40a0ed01f..fdb4a0c5996 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -847,3 +847,28 @@ timestampdiff(year,'2004-02-28','2005-02-28') select timestampdiff(year,'2004-02-29','2005-02-28'); timestampdiff(year,'2004-02-29','2005-02-28') 0 +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, day date); +CREATE TABLE t2 (id int NOT NULL PRIMARY KEY, day date); +INSERT INTO t1 VALUES +(1, '2005-06-01'), (2, '2005-02-01'), (3, '2005-07-01'); +INSERT INTO t2 VALUES +(1, '2005-08-01'), (2, '2005-06-15'), (3, '2005-07-15'); +SELECT * FROM t1, t2 +WHERE t1.day BETWEEN +'2005.09.01' - INTERVAL 6 MONTH AND t2.day; +id day id day +1 2005-06-01 1 2005-08-01 +3 2005-07-01 1 2005-08-01 +1 2005-06-01 2 2005-06-15 +1 2005-06-01 3 2005-07-15 +3 2005-07-01 3 2005-07-15 +SELECT * FROM t1, t2 +WHERE CAST(t1.day AS DATE) BETWEEN +'2005.09.01' - INTERVAL 6 MONTH AND t2.day; +id day id day +1 2005-06-01 1 2005-08-01 +3 2005-07-01 1 2005-08-01 +1 2005-06-01 2 2005-06-15 +1 2005-06-01 3 2005-07-15 +3 2005-07-01 3 2005-07-15 +DROP TABLE t1,t2; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index c98c1c94609..4e4fb8f777a 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -446,4 +446,26 @@ select timestampdiff(year,'1999-09-11','2001-9-11'); select timestampdiff(year,'2004-02-28','2005-02-28'); select timestampdiff(year,'2004-02-29','2005-02-28'); +# +# Bug #18618: BETWEEN for dates with the second argument being a constant +# expression and the first and the third arguments being fields +# + +CREATE TABLE t1 (id int NOT NULL PRIMARY KEY, day date); +CREATE TABLE t2 (id int NOT NULL PRIMARY KEY, day date); + +INSERT INTO t1 VALUES + (1, '2005-06-01'), (2, '2005-02-01'), (3, '2005-07-01'); +INSERT INTO t2 VALUES + (1, '2005-08-01'), (2, '2005-06-15'), (3, '2005-07-15'); + +SELECT * FROM t1, t2 + WHERE t1.day BETWEEN + '2005.09.01' - INTERVAL 6 MONTH AND t2.day; +SELECT * FROM t1, t2 + WHERE CAST(t1.day AS DATE) BETWEEN + '2005.09.01' - INTERVAL 6 MONTH AND t2.day; + +DROP TABLE t1,t2; + # End of 5.0 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 6e1afd4ef09..590a98777dd 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -52,7 +52,6 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; Field *field= NULL; - bool all_constant= TRUE; /* If the first argument is a FIELD_ITEM, pull out the field. */ if (items[0]->real_item()->type() == Item::FIELD_ITEM) @@ -65,16 +64,9 @@ static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) for (i= 1; i < nitems; i++) { type[0]= item_cmp_type(type[0], items[i]->result_type()); - if (field && !convert_constant_item(thd, field, &items[i])) - all_constant= FALSE; + if (field && convert_constant_item(thd, field, &items[i])) + type[0]= INT_RESULT; } - - /* - If we had a field that can be compared as a longlong, and all constant - items, then the aggregate result will be an INT_RESULT. - */ - if (field && all_constant) - type[0]= INT_RESULT; } From e6ce72fcef4fc4e0f51bfe4b2e743f9083d0835e Mon Sep 17 00:00:00 2001 From: "igor@rurik.mysql.com" <> Date: Wed, 12 Apr 2006 18:15:39 -0700 Subject: [PATCH 3/3] Fixes after manual merge. --- mysql-test/r/innodb.result | 57 +++++++++++++++++++++++++++++++++++--- mysql-test/t/innodb.test | 23 +++++++-------- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 0d76d9fdc7b..0ffcc70ec16 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2924,13 +2924,13 @@ create table t3 (s1 varchar(2) binary,primary key (s1)) engine=innodb; create table t4 (s1 char(2) binary,primary key (s1)) engine=innodb; insert into t1 values (0x41),(0x4120),(0x4100); insert into t2 values (0x41),(0x4120),(0x4100); -ERROR 23000: Duplicate entry 'A' for key 1 +ERROR 23000: Duplicate entry 'A' for key 'PRIMARY' insert into t2 values (0x41),(0x4120); insert into t3 values (0x41),(0x4120),(0x4100); -ERROR 23000: Duplicate entry 'A ' for key 1 +ERROR 23000: Duplicate entry 'A ' for key 'PRIMARY' insert into t3 values (0x41),(0x4100); insert into t4 values (0x41),(0x4120),(0x4100); -ERROR 23000: Duplicate entry 'A' for key 1 +ERROR 23000: Duplicate entry 'A' for key 'PRIMARY' insert into t4 values (0x41),(0x4100); select hex(s1) from t1; hex(s1) @@ -3132,7 +3132,7 @@ ALTER TABLE t2 DROP FOREIGN KEY t2_ibfk_0; SHOW CREATE TABLE t2; Table Create Table t2 CREATE TABLE `t2` ( - `a` int(11) default NULL, + `a` int(11) DEFAULT NULL, KEY `t2_ibfk_0` (`a`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 DROP TABLE t2,t1; @@ -3203,3 +3203,52 @@ where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; a a 2005-10-01 2005-10-01 drop table t1, t2; +CREATE TABLE t1 ( +field1 varchar(8) NOT NULL DEFAULT '', +field2 varchar(8) NOT NULL DEFAULT '', +PRIMARY KEY (field1, field2) +) ENGINE=InnoDB; +CREATE TABLE t2 ( +field1 varchar(8) NOT NULL DEFAULT '' PRIMARY KEY, +FOREIGN KEY (field1) REFERENCES t1 (field1) +ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB; +INSERT INTO t1 VALUES ('old', 'somevalu'); +INSERT INTO t1 VALUES ('other', 'anyvalue'); +INSERT INTO t2 VALUES ('old'); +INSERT INTO t2 VALUES ('other'); +UPDATE t1 SET field1 = 'other' WHERE field2 = 'somevalu'; +ERROR 23000: Upholding foreign key constraints for table 't1', entry 'other-somevalu', key 1 would lead to a duplicate entry +DROP TABLE t2; +DROP TABLE t1; +create table t1 ( +c1 bigint not null, +c2 bigint not null, +primary key (c1), +unique key (c2) +) engine=innodb; +create table t2 ( +c1 bigint not null, +primary key (c1) +) engine=innodb; +alter table t1 add constraint c2_fk foreign key (c2) +references t2(c1) on delete cascade; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) NOT NULL, + `c2` bigint(20) NOT NULL, + PRIMARY KEY (`c1`), + UNIQUE KEY `c2` (`c2`), + CONSTRAINT `c2_fk` FOREIGN KEY (`c2`) REFERENCES `t2` (`c1`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +alter table t1 drop foreign key c2_fk; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `c1` bigint(20) NOT NULL, + `c2` bigint(20) NOT NULL, + PRIMARY KEY (`c1`), + UNIQUE KEY `c2` (`c2`) +) ENGINE=InnoDB DEFAULT CHARSET=latin1 +drop table t1, t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 9c8c54f2b55..83b167def73 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2085,6 +2085,18 @@ connection default; disconnect a; disconnect b; +# +# Bug #14360: problem with intervals +# + +create table t1(a date) engine=innodb; +create table t2(a date, key(a)) engine=innodb; +insert into t1 values('2005-10-01'); +insert into t2 values('2005-10-01'); +select * from t1, t2 + where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; +drop table t1, t2; + # # Test that cascading updates leading to duplicate keys give the correct # error message (bug #9680) @@ -2137,14 +2149,3 @@ alter table t1 drop foreign key c2_fk; show create table t1; # drop table t1, t2; - -# Bug #14360: problem with intervals -# - -create table t1(a date) engine=innodb; -create table t2(a date, key(a)) engine=innodb; -insert into t1 values('2005-10-01'); -insert into t2 values('2005-10-01'); -select * from t1, t2 - where t2.a between t1.a - interval 2 day and t1.a + interval 2 day; -drop table t1, t2;