Commit c98a054f authored by unknown's avatar unknown

MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution of PS with...

MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution of PS with LEFT JOIN and MERGE view or SELECT SQ

1. Transformation of row IN subquery made the same as single value.
2. replace_where_subcondition() made working on several layers of OR/AND because it called on expression before fix_fields().
parent c85db2c4
...@@ -4709,6 +4709,37 @@ q 1 q ...@@ -4709,6 +4709,37 @@ q 1 q
q 1 q q 1 q
drop view v1; drop view v1;
drop table t1,t2; drop table t1,t2;
#
# MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
# of PS with LEFT JOIN and MERGE view or SELECT SQ
#
CREATE TABLE t1 (i1 INT, c1 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
CREATE TABLE t2 (c2 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('foobar'),('qux');
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1 ) IN ( SELECT c2 FROM t2 ) AND i1 <= 2 ;
PREPARE stmt FROM 'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)';
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
drop view v1;
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1, c1 ) IN ( SELECT c2, c2 FROM t2 ) AND i1 <= 2 ;
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
EXECUTE stmt;
i1 c1 i1 c1
1 foo NULL NULL
2 bar NULL NULL
deallocate prepare stmt;
drop view v1;
drop table t1,t2;
# ----------------------------------------------------------------- # -----------------------------------------------------------------
# -- End of 5.3 tests. # -- End of 5.3 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
......
...@@ -4647,6 +4647,34 @@ SELECT * FROM t2 LEFT JOIN v1 ON ( c=b AND a IN ( 1,6 ) ); ...@@ -4647,6 +4647,34 @@ SELECT * FROM t2 LEFT JOIN v1 ON ( c=b AND a IN ( 1,6 ) );
drop view v1; drop view v1;
drop table t1,t2; drop table t1,t2;
--echo #
--echo # MDEV-5153: Server crashes in Item_ref::fix_fields on 2nd execution
--echo # of PS with LEFT JOIN and MERGE view or SELECT SQ
--echo #
CREATE TABLE t1 (i1 INT, c1 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
CREATE TABLE t2 (c2 VARCHAR(6)) ENGINE=MyISAM;
INSERT INTO t2 VALUES ('foobar'),('qux');
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1 ) IN ( SELECT c2 FROM t2 ) AND i1 <= 2 ;
PREPARE stmt FROM 'SELECT * FROM t1 LEFT JOIN v1 ON (v1.i1 = t1.i1)';
EXECUTE stmt;
EXECUTE stmt;
drop view v1;
CREATE ALGORITHM=MERGE VIEW v1 AS SELECT * FROM t1 WHERE ( c1, c1 ) IN ( SELECT c2, c2 FROM t2 ) AND i1 <= 2 ;
EXECUTE stmt;
EXECUTE stmt;
deallocate prepare stmt;
drop view v1;
drop table t1,t2;
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
--echo # -- End of 5.3 tests. --echo # -- End of 5.3 tests.
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
......
...@@ -1436,9 +1436,11 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg) ...@@ -1436,9 +1436,11 @@ bool Item_in_optimizer::eval_not_null_tables(uchar *opt_arg)
bool Item_in_optimizer::fix_left(THD *thd, Item **ref) bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{ {
DBUG_ENTER("Item_in_optimizer::fix_left");
if ((!args[0]->fixed && args[0]->fix_fields(thd, args)) || if ((!args[0]->fixed && args[0]->fix_fields(thd, args)) ||
(!cache && !(cache= Item_cache::get_cache(args[0])))) (!cache && !(cache= Item_cache::get_cache(args[0]))))
return 1; DBUG_RETURN(1);
DBUG_PRINT("info", ("actual fix fields"));
cache->setup(args[0]); cache->setup(args[0]);
if (cache->cols() == 1) if (cache->cols() == 1)
...@@ -1460,10 +1462,13 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref) ...@@ -1460,10 +1462,13 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
{ {
my_error(ER_NOT_SUPPORTED_YET, MYF(0), my_error(ER_NOT_SUPPORTED_YET, MYF(0),
"SUBQUERY in ROW in left expression of IN/ALL/ANY"); "SUBQUERY in ROW in left expression of IN/ALL/ANY");
return 1; DBUG_RETURN(1);
} }
if (args[0]->element_index(i)->used_tables()) if (args[0]->element_index(i)->used_tables())
{
((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT); ((Item_cache *)cache->element_index(i))->set_used_tables(OUTER_REF_TABLE_BIT);
cache->set_used_tables(OUTER_REF_TABLE_BIT);
}
else else
((Item_cache *)cache->element_index(i))->set_used_tables(0); ((Item_cache *)cache->element_index(i))->set_used_tables(0);
} }
...@@ -1477,7 +1482,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref) ...@@ -1477,7 +1482,7 @@ bool Item_in_optimizer::fix_left(THD *thd, Item **ref)
cache->store(args[0]); cache->store(args[0]);
cache->cache_value(); cache->cache_value();
} }
return 0; DBUG_RETURN(0);
} }
......
...@@ -2177,11 +2177,11 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join, ...@@ -2177,11 +2177,11 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
DBUG_RETURN(true); DBUG_RETURN(true);
Item *item_eq= Item *item_eq=
new Item_func_eq(new new Item_func_eq(new
Item_ref(&select_lex->context, Item_direct_ref(&select_lex->context,
(*optimizer->get_cache())-> (*optimizer->get_cache())->
addr(i), addr(i),
(char *)"<no matter>", (char *)"<no matter>",
(char *)in_left_expr_name), (char *)in_left_expr_name),
new new
Item_ref(&select_lex->context, Item_ref(&select_lex->context,
select_lex->ref_pointer_array + i, select_lex->ref_pointer_array + i,
...@@ -2462,7 +2462,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg) ...@@ -2462,7 +2462,7 @@ bool Item_in_subselect::inject_in_to_exists_cond(JOIN *join_arg)
bool bool
Item_in_subselect::select_in_like_transformer(JOIN *join) Item_in_subselect::select_in_like_transformer(JOIN *join)
{ {
Query_arena *arena, backup; Query_arena *arena= 0, backup;
SELECT_LEX *current= thd->lex->current_select; SELECT_LEX *current= thd->lex->current_select;
const char *save_where= thd->where; const char *save_where= thd->where;
bool trans_res= true; bool trans_res= true;
...@@ -2484,9 +2484,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) ...@@ -2484,9 +2484,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
} }
} }
if (changed)
DBUG_RETURN(false);
thd->where= "IN/ALL/ANY subquery"; thd->where= "IN/ALL/ANY subquery";
/* /*
...@@ -2497,25 +2494,29 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) ...@@ -2497,25 +2494,29 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
note: we won't need Item_in_optimizer when handling degenerate cases note: we won't need Item_in_optimizer when handling degenerate cases
like "... IN (SELECT 1)" like "... IN (SELECT 1)"
*/ */
arena= thd->activate_stmt_arena_if_needed(&backup);
if (!optimizer) if (!optimizer)
{ {
arena= thd->activate_stmt_arena_if_needed(&backup);
result= (!(optimizer= new Item_in_optimizer(left_expr, this))); result= (!(optimizer= new Item_in_optimizer(left_expr, this)));
if (arena)
thd->restore_active_arena(arena, &backup);
if (result) if (result)
goto err; goto out;
} }
thd->lex->current_select= current->return_after_parsing(); thd->lex->current_select= current->return_after_parsing();
result= (!left_expr->fixed && result= optimizer->fix_left(thd, optimizer->arguments());
left_expr->fix_fields(thd, optimizer->arguments()));
/* fix_fields can change reference to left_expr, we need reassign it */ /* fix_fields can change reference to left_expr, we need reassign it */
left_expr= optimizer->arguments()[0]; left_expr= optimizer->arguments()[0];
thd->lex->current_select= current; thd->lex->current_select= current;
if (changed)
{
trans_res= false;
goto out;
}
if (result) if (result)
goto err; goto out;
/* /*
Both transformers call fix_fields() only for Items created inside them, Both transformers call fix_fields() only for Items created inside them,
...@@ -2524,7 +2525,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) ...@@ -2524,7 +2525,6 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
of Item, we have to call fix_fields() for it only with original arena to of Item, we have to call fix_fields() for it only with original arena to
avoid memory leack) avoid memory leack)
*/ */
arena= thd->activate_stmt_arena_if_needed(&backup);
if (left_expr->cols() == 1) if (left_expr->cols() == 1)
trans_res= single_value_transformer(join); trans_res= single_value_transformer(join);
else else
...@@ -2539,9 +2539,9 @@ Item_in_subselect::select_in_like_transformer(JOIN *join) ...@@ -2539,9 +2539,9 @@ Item_in_subselect::select_in_like_transformer(JOIN *join)
} }
trans_res= row_value_transformer(join); trans_res= row_value_transformer(join);
} }
out:
if (arena) if (arena)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
err:
thd->where= save_where; thd->where= save_where;
DBUG_RETURN(trans_res); DBUG_RETURN(trans_res);
} }
......
...@@ -1252,11 +1252,11 @@ void get_delayed_table_estimates(TABLE *table, ...@@ -1252,11 +1252,11 @@ void get_delayed_table_estimates(TABLE *table,
@brief Replaces an expression destructively inside the expression tree of @brief Replaces an expression destructively inside the expression tree of
the WHERE clase. the WHERE clase.
@note Because of current requirements for semijoin flattening, we do not @note We substitute AND/OR structure because it was copied by
need to recurse here, hence this function will only examine the top-level copy_andor_structure and some changes could be done in the copy but
AND conditions. (see JOIN::prepare, comment starting with "Check if the should be left permanent, also there could be several layers of AND over
subquery predicate can be executed via materialization". AND and OR over OR because ::fix_field() possibly is not called.
@param join The top-level query. @param join The top-level query.
@param old_cond The expression to be replaced. @param old_cond The expression to be replaced.
@param new_cond The expression to be substituted. @param new_cond The expression to be substituted.
...@@ -1284,13 +1284,20 @@ static bool replace_where_subcondition(JOIN *join, Item **expr, ...@@ -1284,13 +1284,20 @@ static bool replace_where_subcondition(JOIN *join, Item **expr,
Item *item; Item *item;
while ((item= li++)) while ((item= li++))
{ {
if (item == old_cond) if (item == old_cond)
{ {
li.replace(new_cond); li.replace(new_cond);
if (do_fix_fields) if (do_fix_fields)
new_cond->fix_fields(join->thd, li.ref()); new_cond->fix_fields(join->thd, li.ref());
return FALSE; return FALSE;
} }
else if (item->type() == Item::COND_ITEM)
{
DBUG_ASSERT(!(*expr)->fixed);
replace_where_subcondition(join, li.ref(),
old_cond, new_cond,
do_fix_fields);
}
} }
} }
/* /*
......
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