Commit fe94dec6 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.
parent 79d8de67
...@@ -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