Commit 7fd2461c authored by Sergey Glukhov's avatar Sergey Glukhov

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.
parent ebaba11c
...@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL; ...@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
b COUNT(DISTINCT a) b COUNT(DISTINCT a)
NULL 1 NULL 1
DROP TABLE t1; 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 End of 5.0 tests
...@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL); ...@@ -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; SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
DROP TABLE t1; 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 --echo End of 5.0 tests
...@@ -1474,9 +1474,21 @@ class Item_cond :public Item_bool_func ...@@ -1474,9 +1474,21 @@ class Item_cond :public Item_bool_func
Item_cond(THD *thd, Item_cond *item); Item_cond(THD *thd, Item_cond *item);
Item_cond(List<Item> &nlist) Item_cond(List<Item> &nlist)
:Item_bool_func(), list(nlist), abort_on_null(0) {} :Item_bool_func(), list(nlist), abort_on_null(0) {}
bool add(Item *item) { return list.push_back(item); } bool add(Item *item)
bool add_at_head(Item *item) { return list.push_front(item); } {
void add_at_head(List<Item> *nlist) { list.prepand(nlist); } 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); bool fix_fields(THD *, Item **ref);
enum Type type() const { return COND_ITEM; } enum Type type() const { return COND_ITEM; }
......
...@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels, ...@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
else else
{ {
DBUG_ASSERT(cond->type() == Item::COND_ITEM); 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(); cond->quick_fix_field();
...@@ -15657,7 +15658,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) ...@@ -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(); Item_cond_and *cond=new Item_cond_and();
TABLE *table=join_tab->table; TABLE *table=join_tab->table;
int error; int error= 0;
if (!cond) if (!cond)
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -15675,7 +15676,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab) ...@@ -15675,7 +15676,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
cond->fix_fields(thd, (Item**)&cond); cond->fix_fields(thd, (Item**)&cond);
if (join_tab->select) 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; join_tab->select_cond=join_tab->select->cond=cond;
} }
else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0, else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,
......
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