summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Glukhov <Sergey.Glukhov@sun.com>2010-03-19 10:21:37 +0400
committerSergey Glukhov <Sergey.Glukhov@sun.com>2010-03-19 10:21:37 +0400
commitd1c2e8508fcc795eb5aeafe1af492929ec13ee97 (patch)
treebac600074d72d2769dd262757434eebbacb45fcf
parentcaa1ccb0c324bca664112a5562f174f603e0a0b7 (diff)
downloadmariadb-git-d1c2e8508fcc795eb5aeafe1af492929ec13ee97.tar.gz
Bug#51598 Inconsistent behaviour with a COALESCE statement inside an IN comparison
Optimizer erroneously translated LEFT JOIN into INNER JOIN. It leads to cutting rows with NULL right side. It happens because Item_row uses not_null_tables() method form the base(Item) class and does not calculate 'null tables' properly. The fix is adding calculation of 'not null tables' to Item_row. mysql-test/r/join_outer.result: test result mysql-test/t/join_outer.test: test case sql/item_row.cc: adding calculation of 'not null tables' to Item_row. sql/item_row.h: adding calculation of 'not null tables' to Item_row.
-rw-r--r--mysql-test/r/join_outer.result20
-rw-r--r--mysql-test/t/join_outer.test18
-rw-r--r--sql/item_row.cc4
-rw-r--r--sql/item_row.h4
4 files changed, 44 insertions, 2 deletions
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 083be3737f7..4543446e807 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -1289,3 +1289,23 @@ a COUNT( t2.b ) SUM( t2.b ) MAX( t2.b )
1 3 6 3
NULL 3 6 3
DROP TABLE t1, t2;
+#
+# Bug#51598 Inconsistent behaviour with a COALESCE statement inside an IN comparison
+#
+CREATE TABLE t1(f1 INT, f2 INT, f3 INT);
+INSERT INTO t1 VALUES (1, NULL, 3);
+CREATE TABLE t2(f1 INT, f2 INT);
+INSERT INTO t2 VALUES (2, 1);
+EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
+WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
+id select_type table type possible_keys key key_len ref rows filtered Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1 100.00
+1 SIMPLE t2 system NULL NULL NULL NULL 1 100.00
+Warnings:
+Note 1003 select '1' AS `f1`,NULL AS `f2`,'3' AS `f3`,NULL AS `f1`,NULL AS `f2` from `test`.`t1` left join `test`.`t2` on(multiple equal(NULL)) where ((coalesce('1',NULL),'3') in ((1,3),(2,2)))
+SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
+WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
+f1 f2 f3 f1 f2
+1 NULL 3 NULL NULL
+DROP TABLE t1, t2;
+End of 5.1 tests
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index aeaa69657c6..e3d68d71603 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -896,3 +896,21 @@ FROM t1 JOIN t2 USING( a )
GROUP BY t1.a WITH ROLLUP;
DROP TABLE t1, t2;
+
+--echo #
+--echo # Bug#51598 Inconsistent behaviour with a COALESCE statement inside an IN comparison
+--echo #
+CREATE TABLE t1(f1 INT, f2 INT, f3 INT);
+INSERT INTO t1 VALUES (1, NULL, 3);
+CREATE TABLE t2(f1 INT, f2 INT);
+INSERT INTO t2 VALUES (2, 1);
+
+EXPLAIN EXTENDED SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
+WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
+
+SELECT * FROM t1 LEFT JOIN t2 ON t1.f2 = t2.f2
+WHERE (COALESCE(t1.f1, t2.f1), f3) IN ((1, 3), (2, 2));
+
+DROP TABLE t1, t2;
+
+--echo End of 5.1 tests
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 29b37eb2bc0..7535c1fa80b 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -30,7 +30,8 @@
*/
Item_row::Item_row(List<Item> &arg):
- Item(), used_tables_cache(0), const_item_cache(1), with_null(0)
+ Item(), used_tables_cache(0), not_null_tables_cache(0),
+ const_item_cache(1), with_null(0)
{
//TODO: think placing 2-3 component items in item (as it done for function)
@@ -71,6 +72,7 @@ bool Item_row::fix_fields(THD *thd, Item **ref)
Item *item= *arg;
used_tables_cache |= item->used_tables();
const_item_cache&= item->const_item() && !with_null;
+ not_null_tables_cache|= item->not_null_tables();
/*
Some subqueries transformations aren't done in the view_prepare_mode thus
is_null() will fail. So we skip is_null() calculation for CREATE VIEW as
diff --git a/sql/item_row.h b/sql/item_row.h
index 67441f49603..76d1c875e7d 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -16,7 +16,7 @@
class Item_row: public Item
{
Item **items;
- table_map used_tables_cache;
+ table_map used_tables_cache, not_null_tables_cache;
uint arg_count;
bool const_item_cache;
bool with_null;
@@ -26,6 +26,7 @@ public:
Item(),
items(item->items),
used_tables_cache(item->used_tables_cache),
+ not_null_tables_cache(0),
arg_count(item->arg_count),
const_item_cache(item->const_item_cache),
with_null(0)
@@ -65,6 +66,7 @@ public:
bool const_item() const { return const_item_cache; };
enum Item_result result_type() const { return ROW_RESULT; }
void update_used_tables();
+ table_map not_null_tables() const { return not_null_tables_cache; }
virtual void print(String *str, enum_query_type query_type);
bool walk(Item_processor processor, bool walk_subquery, uchar *arg);