Automerge.
This commit is contained in:
commit
b68ca5e88c
@ -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);
|
|||||||
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
|
||||||
|
@ -969,6 +969,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");
|
||||||
@ -1099,7 +1105,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))
|
||||||
@ -1143,7 +1149,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
|
||||||
@ -10212,6 +10219,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;
|
||||||
@ -15637,32 +15645,7 @@ 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;
|
||||||
{
|
|
||||||
/*
|
|
||||||
For ROLLUP queries each constant item referenced in GROUP BY list
|
|
||||||
is wrapped up into an Item_func object yielding the same value
|
|
||||||
as the constant item. The objects of the wrapper class are never
|
|
||||||
considered as constant items and besides they inherit all
|
|
||||||
properties of the Item_result_field class.
|
|
||||||
This wrapping allows us to ensure writing constant items
|
|
||||||
into temporary tables whenever the result of the ROLLUP
|
|
||||||
operation has to be written into a temporary table, e.g. when
|
|
||||||
ROLLUP is used together with DISTINCT in the SELECT list.
|
|
||||||
Usually when creating temporary tables for a intermidiate
|
|
||||||
result we do not include fields for constant expressions.
|
|
||||||
*/
|
|
||||||
Item* new_item= new Item_func_rollup_const(item);
|
|
||||||
if (!new_item)
|
|
||||||
return 1;
|
|
||||||
new_item->fix_fields(thd, (Item **) 0);
|
|
||||||
thd->change_item_tree(it.ref(), new_item);
|
|
||||||
for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
|
|
||||||
{
|
|
||||||
if (*tmp->item == item)
|
|
||||||
thd->change_item_tree(tmp->item, new_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (item->type() == Item::FUNC_ITEM && !found_in_group)
|
if (item->type() == Item::FUNC_ITEM && !found_in_group)
|
||||||
@ -15681,6 +15664,59 @@ bool JOIN::rollup_init()
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Wrap all constant Items 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
|
||||||
|
as the constant item. The objects of the wrapper class are never
|
||||||
|
considered as constant items and besides they inherit all
|
||||||
|
properties of the Item_result_field class.
|
||||||
|
This wrapping allows us to ensure writing constant items
|
||||||
|
into temporary tables whenever the result of the ROLLUP
|
||||||
|
operation has to be written into a temporary table, e.g. when
|
||||||
|
ROLLUP is used together with DISTINCT in the SELECT list.
|
||||||
|
Usually when creating temporary tables for a intermidiate
|
||||||
|
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);
|
||||||
|
if (!new_item)
|
||||||
|
return 1;
|
||||||
|
new_item->fix_fields(thd, (Item **) 0);
|
||||||
|
thd->change_item_tree(it.ref(), new_item);
|
||||||
|
for (ORDER *tmp= group_tmp; tmp; tmp= tmp->next)
|
||||||
|
{
|
||||||
|
if (*tmp->item == item)
|
||||||
|
thd->change_item_tree(tmp->item, new_item);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
it.rewind();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -512,6 +512,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);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user