Bug #19434916: FATAL_SIGNAL IN ADD_KEY_EQUAL_FIELDS() WITH
UPDATE VIEW USING OUTER SUBQUERY Issue: ----- While resolving a column which refers to a table/view in an outer query, it's respecitve item object is marked with the outer query's select_lex object. But when the column refers to a view or if the column is part of a subquery in the HAVING clause, an Item_ref object is created. While the reference to the outer query is stored by the Item_ref object, the same is not stored in it's real_item. This creates a problem with the IN-TO-EXISTS optmization. When there is an index over the column in the inner query, it will be considered since the column's real_item object will be mistaken for a local field. This will lead to a crash. SOLUTION: --------- Under the current design, the only way to fix this issue is to check the reginfo.join_tab for a NULL value. If yes, the query should not be worrying about the key use. The testcase and comments added as part of the fix for Bug#17766653 have been backported.
This commit is contained in:
parent
f83d9e4217
commit
415faa122b
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2002, 2013, Oracle and/or its affiliates. All rights reserved.
|
/* Copyright (c) 2002, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -1072,6 +1072,27 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
runtime created Ref item which is deleted at the end
|
runtime created Ref item which is deleted at the end
|
||||||
of the statement. Thus one of 'substitution' arguments
|
of the statement. Thus one of 'substitution' arguments
|
||||||
can be broken in case of PS.
|
can be broken in case of PS.
|
||||||
|
|
||||||
|
@todo
|
||||||
|
Why do we use real_item()/substitutional_item() instead of the plain
|
||||||
|
left_expr?
|
||||||
|
Because left_expr might be a rollbackable item, and we fail to properly
|
||||||
|
rollback all copies of left_expr at end of execution, so we want to
|
||||||
|
avoid creating copies of left_expr as much as possible, so we use
|
||||||
|
real_item() instead.
|
||||||
|
Doing a proper rollback is difficult: the change was registered for the
|
||||||
|
original item which was the left argument of IN. Then this item was
|
||||||
|
copied to left_expr, which is copied below to substitution->args[0]. To
|
||||||
|
do a proper rollback, we would have to restore the content
|
||||||
|
of both copies as well as the original item. There might be more copies,
|
||||||
|
if AND items have been constructed.
|
||||||
|
The same applies to the right expression.
|
||||||
|
However, using real_item()/substitutional_item() brings its own
|
||||||
|
problems: for example, we lose information that the item is an outer
|
||||||
|
reference; the item can thus wrongly be considered for a Keyuse (causing
|
||||||
|
bug#17766653).
|
||||||
|
When WL#6570 removes the "rolling back" system, all
|
||||||
|
real_item()/substitutional_item() in this file should be removed.
|
||||||
*/
|
*/
|
||||||
substitution= func->create(left_expr->real_item(), subs);
|
substitution= func->create(left_expr->real_item(), subs);
|
||||||
DBUG_RETURN(RES_OK);
|
DBUG_RETURN(RES_OK);
|
||||||
@ -1157,6 +1178,9 @@ Item_in_subselect::single_value_transformer(JOIN *join,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
Grep for "WL#6570" to see the relevant comment about real_item.
|
||||||
|
*/
|
||||||
Item *item= (Item*) select_lex->item_list.head()->real_item();
|
Item *item= (Item*) select_lex->item_list.head()->real_item();
|
||||||
|
|
||||||
if (select_lex->table_list.elements)
|
if (select_lex->table_list.elements)
|
||||||
|
@ -3335,6 +3335,18 @@ add_key_field(KEY_FIELD **key_fields,uint and_level, Item_func *cond,
|
|||||||
table_map usable_tables, SARGABLE_PARAM **sargables)
|
table_map usable_tables, SARGABLE_PARAM **sargables)
|
||||||
{
|
{
|
||||||
uint exists_optimize= 0;
|
uint exists_optimize= 0;
|
||||||
|
|
||||||
|
if (field->table->reginfo.join_tab == NULL)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Due to a bug in IN-to-EXISTS (grep for real_item() in item_subselect.cc
|
||||||
|
for more info), an index over a field from an outer query might be
|
||||||
|
considered here, which is incorrect. Their query has been fully
|
||||||
|
optimized already so their reginfo.join_tab is NULL and we reject them.
|
||||||
|
*/
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!(field->flags & PART_KEY_FLAG))
|
if (!(field->flags & PART_KEY_FLAG))
|
||||||
{
|
{
|
||||||
// Don't remove column IS NULL on a LEFT JOIN table
|
// Don't remove column IS NULL on a LEFT JOIN table
|
||||||
|
Loading…
x
Reference in New Issue
Block a user