summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Glukhov <Sergey.Glukhov@sun.com>2010-02-26 15:39:25 +0400
committerSergey Glukhov <Sergey.Glukhov@sun.com>2010-02-26 15:39:25 +0400
commit9245ed4a12ce25214d60f93cbf20882cb2b78741 (patch)
tree86ad600c103f19ca2727b788b2ae1cd8df029f49
parent936ed6ca86633a91976fd6fcd931683ec007f440 (diff)
downloadmariadb-git-9245ed4a12ce25214d60f93cbf20882cb2b78741.tar.gz
Bug#50995 Having clause on subquery result produces incorrect results.
The problem is that cond->fix_fields(thd, 0) breaks condition(cuts off 'having'). The reason of that is that NULL valued Item pointer is present in the middle of Item list and it breaks the Item processing loop. mysql-test/r/having.result: test case mysql-test/t/having.test: test case sql/item_cmpfunc.h: added ASSERT to make sure that we do not add NULL valued Item pointer sql/sql_select.cc: skip adding an item to condition if Item pointer is NULL. skip adding a list to condition if this list is empty.
-rw-r--r--mysql-test/r/having.result20
-rw-r--r--mysql-test/t/having.test26
-rw-r--r--sql/item_cmpfunc.h18
-rw-r--r--sql/sql_select.cc8
4 files changed, 66 insertions, 6 deletions
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 9c3cc8fc89e..68ba34e353c 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
b COUNT(DISTINCT a)
NULL 1
DROP TABLE t1;
+#
+# Bug#50995 Having clause on subquery result produces incorrect results.
+#
+CREATE TABLE t1
+(
+id1 INT,
+id2 INT NOT NULL,
+INDEX id1(id2)
+);
+INSERT INTO t1 SET id1=1, id2=1;
+INSERT INTO t1 SET id1=2, id2=1;
+INSERT INTO t1 SET id1=3, id2=1;
+SELECT t1.id1,
+(SELECT 0 FROM DUAL
+WHERE t1.id1=t1.id1) AS amount FROM t1
+WHERE t1.id2 = 1
+HAVING amount > 0
+ORDER BY t1.id1;
+id1 amount
+DROP TABLE t1;
End of 5.0 tests
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index af9af4fe1fc..185ca4bdddb 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL);
SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
DROP TABLE t1;
+
+--echo #
+--echo # Bug#50995 Having clause on subquery result produces incorrect results.
+--echo #
+
+CREATE TABLE t1
+(
+ id1 INT,
+ id2 INT NOT NULL,
+ INDEX id1(id2)
+);
+
+INSERT INTO t1 SET id1=1, id2=1;
+INSERT INTO t1 SET id1=2, id2=1;
+INSERT INTO t1 SET id1=3, id2=1;
+
+SELECT t1.id1,
+(SELECT 0 FROM DUAL
+ WHERE t1.id1=t1.id1) AS amount FROM t1
+WHERE t1.id2 = 1
+HAVING amount > 0
+ORDER BY t1.id1;
+
+DROP TABLE t1;
+
+
--echo End of 5.0 tests
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 38025ff0af5..425f54fb079 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1474,9 +1474,21 @@ public:
Item_cond(THD *thd, Item_cond *item);
Item_cond(List<Item> &nlist)
:Item_bool_func(), list(nlist), abort_on_null(0) {}
- bool add(Item *item) { return list.push_back(item); }
- bool add_at_head(Item *item) { return list.push_front(item); }
- void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
+ bool add(Item *item)
+ {
+ DBUG_ASSERT(item);
+ return list.push_back(item);
+ }
+ bool add_at_head(Item *item)
+ {
+ DBUG_ASSERT(item);
+ return list.push_front(item);
+ }
+ void add_at_head(List<Item> *nlist)
+ {
+ DBUG_ASSERT(nlist->elements);
+ list.prepand(nlist);
+ }
bool fix_fields(THD *, Item **ref);
enum Type type() const { return COND_ITEM; }
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b9f59fac4d6..1d88343ad6d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
else
{
DBUG_ASSERT(cond->type() == Item::COND_ITEM);
- ((Item_cond *) cond)->add_at_head(&eq_list);
+ if (eq_list.elements)
+ ((Item_cond *) cond)->add_at_head(&eq_list);
}
cond->quick_fix_field();
@@ -15657,7 +15658,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
Item_cond_and *cond=new Item_cond_and();
TABLE *table=join_tab->table;
- int error;
+ int error= 0;
if (!cond)
DBUG_RETURN(TRUE);
@@ -15675,7 +15676,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
cond->fix_fields(thd, (Item**)&cond);
if (join_tab->select)
{
- error=(int) cond->add(join_tab->select->cond);
+ if (join_tab->select->cond)
+ error=(int) cond->add(join_tab->select->cond);
join_tab->select_cond=join_tab->select->cond=cond;
}
else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,