Commit 406e680b authored by Alexey Kopytov's avatar Alexey Kopytov

Automerge.

parents ea412fc2 23b05d00
...@@ -733,4 +733,24 @@ SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; ...@@ -733,4 +733,24 @@ SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP;
1 1
1 1
DROP TABLE t1; DROP TABLE t1;
#
# Bug #48131: crash group by with rollup, distinct,
# filesort, with temporary tables
#
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (100);
SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
a b
1 100
1 NULL
2 100
2 NULL
NULL NULL
SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
b
100
NULL
DROP TABLE t1, t2;
End of 5.0 tests End of 5.0 tests
...@@ -375,4 +375,19 @@ INSERT INTO t1 VALUES(0); ...@@ -375,4 +375,19 @@ INSERT INTO t1 VALUES(0);
SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP; SELECT 1 FROM t1 GROUP BY (DATE(NULL)) WITH ROLLUP;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #48131: crash group by with rollup, distinct,
--echo # filesort, with temporary tables
--echo #
CREATE TABLE t1 (a INT NOT NULL PRIMARY KEY);
INSERT INTO t1 VALUES (1), (2);
CREATE TABLE t2 (b INT);
INSERT INTO t2 VALUES (100);
SELECT a, b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
SELECT DISTINCT b FROM t1, t2 GROUP BY a, b WITH ROLLUP;
DROP TABLE t1, t2;
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -928,6 +928,12 @@ JOIN::optimize() ...@@ -928,6 +928,12 @@ JOIN::optimize()
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (select_lex->olap == ROLLUP_TYPE && rollup_process_const_fields())
{
DBUG_PRINT("error", ("Error: rollup_process_fields() failed"));
DBUG_RETURN(1);
}
/* Remove distinct if only const tables */ /* Remove distinct if only const tables */
select_distinct= select_distinct && (const_tables != tables); select_distinct= select_distinct && (const_tables != tables);
thd_proc_info(thd, "preparing"); thd_proc_info(thd, "preparing");
...@@ -1055,7 +1061,7 @@ JOIN::optimize() ...@@ -1055,7 +1061,7 @@ JOIN::optimize()
join_tab[const_tables].select->quick->get_type() != join_tab[const_tables].select->quick->get_type() !=
QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)) QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX))
{ {
if (group_list && if (group_list && rollup.state == ROLLUP::STATE_NONE &&
list_contains_unique_index(join_tab[const_tables].table, list_contains_unique_index(join_tab[const_tables].table,
find_field_in_order_list, find_field_in_order_list,
(void *) group_list)) (void *) group_list))
...@@ -1093,7 +1099,8 @@ JOIN::optimize() ...@@ -1093,7 +1099,8 @@ JOIN::optimize()
if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE) if (! hidden_group_fields && rollup.state == ROLLUP::STATE_NONE)
select_distinct=0; select_distinct=0;
} }
else if (select_distinct && tables - const_tables == 1) else if (select_distinct && tables - const_tables == 1 &&
rollup.state == ROLLUP::STATE_NONE)
{ {
/* /*
We are only using one table. In this case we change DISTINCT to a We are only using one table. In this case we change DISTINCT to a
...@@ -9873,6 +9880,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields, ...@@ -9873,6 +9880,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
for (; cur_group ; cur_group= cur_group->next, key_part_info++) for (; cur_group ; cur_group= cur_group->next, key_part_info++)
{ {
Field *field=(*cur_group->item)->get_tmp_table_field(); Field *field=(*cur_group->item)->get_tmp_table_field();
DBUG_ASSERT(field->table == table);
bool maybe_null=(*cur_group->item)->maybe_null; bool maybe_null=(*cur_group->item)->maybe_null;
key_part_info->null_bit=0; key_part_info->null_bit=0;
key_part_info->field= field; key_part_info->field= field;
...@@ -15018,9 +15026,29 @@ bool JOIN::rollup_init() ...@@ -15018,9 +15026,29 @@ bool JOIN::rollup_init()
{ {
item->maybe_null= 1; item->maybe_null= 1;
found_in_group= 1; found_in_group= 1;
if (item->const_item()) break;
}
}
if (item->type() == Item::FUNC_ITEM && !found_in_group)
{ {
bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1;
/* /*
We have to prevent creation of a field in a temporary table for
an expression that contains GROUP BY attributes.
Marking the expression item as 'with_sum_func' will ensure this.
*/
if (changed)
item->with_sum_func= 1;
}
}
return 0;
}
/**
Wrap all constant Items in GROUP BY list.
For ROLLUP queries each constant item referenced in GROUP BY list For ROLLUP queries each constant item referenced in GROUP BY list
is wrapped up into an Item_func object yielding the same value is wrapped up into an Item_func object yielding the same value
as the constant item. The objects of the wrapper class are never as the constant item. The objects of the wrapper class are never
...@@ -15032,7 +15060,27 @@ bool JOIN::rollup_init() ...@@ -15032,7 +15060,27 @@ bool JOIN::rollup_init()
ROLLUP is used together with DISTINCT in the SELECT list. ROLLUP is used together with DISTINCT in the SELECT list.
Usually when creating temporary tables for a intermidiate Usually when creating temporary tables for a intermidiate
result we do not include fields for constant expressions. result we do not include fields for constant expressions.
*/
@retval
0 if ok
@retval
1 on error
*/
bool JOIN::rollup_process_const_fields()
{
ORDER *group_tmp;
Item *item;
List_iterator<Item> it(all_fields);
for (group_tmp= group_list; group_tmp; group_tmp= group_tmp->next)
{
if (!(*group_tmp->item)->const_item())
continue;
while ((item= it++))
{
if (*group_tmp->item == item)
{
Item* new_item= new Item_func_rollup_const(item); Item* new_item= new Item_func_rollup_const(item);
if (!new_item) if (!new_item)
return 1; return 1;
...@@ -15043,22 +15091,10 @@ bool JOIN::rollup_init() ...@@ -15043,22 +15091,10 @@ bool JOIN::rollup_init()
if (*tmp->item == item) if (*tmp->item == item)
thd->change_item_tree(tmp->item, new_item); thd->change_item_tree(tmp->item, new_item);
} }
break;
} }
} }
} it.rewind();
if (item->type() == Item::FUNC_ITEM && !found_in_group)
{
bool changed= FALSE;
if (change_group_ref(thd, (Item_func *) item, group_list, &changed))
return 1;
/*
We have to prevent creation of a field in a temporary table for
an expression that contains GROUP BY attributes.
Marking the expression item as 'with_sum_func' will ensure this.
*/
if (changed)
item->with_sum_func= 1;
}
} }
return 0; return 0;
} }
......
...@@ -452,6 +452,7 @@ public: ...@@ -452,6 +452,7 @@ public:
} }
bool rollup_init(); bool rollup_init();
bool rollup_process_const_fields();
bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields, bool rollup_make_fields(List<Item> &all_fields, List<Item> &fields,
Item_sum ***func); Item_sum ***func);
int rollup_send_data(uint idx); int rollup_send_data(uint idx);
......
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