Commit 285160de authored by unknown's avatar unknown

MDEV-5981: name resolution issues with views and multi-update in ps-protocol

It is triple bug with one test suite:
1. Incorrect outer table detection
2. Incorrect leaf table processing for multi-update (should be full like for usual updates and inserts)
3. ON condition fix_fields() fould be called for all tables of the query.
parent a24ea50d
...@@ -4806,6 +4806,24 @@ id test ...@@ -4806,6 +4806,24 @@ id test
1 0 1 0
drop view v1; drop view v1;
drop table t1; drop table t1;
#
# MDEV-5981: name resolution issues with views and multi-update
# in ps-protocol
#
create table t1 (id1 int primary key, val1 varchar(20));
insert into t1 values (1, 'test1');
create table t2 (id2 int primary key, val2 varchar(20));
insert into t2 values (1, 'test2');
create algorithm=merge view v1 as select id1 as id1v1, val1 as val1v1 from t1;
create algorithm=merge view v2 as
select t2.id2 as id2v2, t2.val2 as val2v2
from t2, v1
where t2.id2 = v1.id1v1;
prepare stmt1 from "update v2 set val2v2 = 'test19' where 1 = id2v2";
execute stmt1;
deallocate prepare stmt1;
drop view v1,v2;
drop table t1,t2;
# ----------------------------------------------------------------- # -----------------------------------------------------------------
# -- End of 5.3 tests. # -- End of 5.3 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
......
...@@ -4739,6 +4739,25 @@ select * from v1; ...@@ -4739,6 +4739,25 @@ select * from v1;
drop view v1; drop view v1;
drop table t1; drop table t1;
--echo #
--echo # MDEV-5981: name resolution issues with views and multi-update
--echo # in ps-protocol
--echo #
create table t1 (id1 int primary key, val1 varchar(20));
insert into t1 values (1, 'test1');
create table t2 (id2 int primary key, val2 varchar(20));
insert into t2 values (1, 'test2');
create algorithm=merge view v1 as select id1 as id1v1, val1 as val1v1 from t1;
create algorithm=merge view v2 as
select t2.id2 as id2v2, t2.val2 as val2v2
from t2, v1
where t2.id2 = v1.id1v1;
prepare stmt1 from "update v2 set val2v2 = 'test19' where 1 = id2v2";
execute stmt1;
deallocate prepare stmt1;
drop view v1,v2;
drop table t1,t2;
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
--echo # -- End of 5.3 tests. --echo # -- End of 5.3 tests.
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
......
...@@ -4336,6 +4336,10 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select) ...@@ -4336,6 +4336,10 @@ bool is_outer_table(TABLE_LIST *table, SELECT_LEX *select)
DBUG_ASSERT(table->select_lex != select); DBUG_ASSERT(table->select_lex != select);
TABLE_LIST *tl; TABLE_LIST *tl;
if (table->belong_to_view &&
table->belong_to_view->select_lex == select)
return FALSE;
for (tl= select->master_unit()->derived; for (tl= select->master_unit()->derived;
tl && tl->is_merged_derived(); tl && tl->is_merged_derived();
select= tl->select_lex, tl= select->master_unit()->derived) select= tl->select_lex, tl= select->master_unit()->derived)
......
...@@ -8449,6 +8449,77 @@ void wrap_ident(THD *thd, Item **conds) ...@@ -8449,6 +8449,77 @@ void wrap_ident(THD *thd, Item **conds)
thd->restore_active_arena(arena, &backup); thd->restore_active_arena(arena, &backup);
} }
/**
Prepare ON expression
@param thd Thread handle
@param table Pointer to table list
@param is_update Update flag
@retval TRUE error.
@retval FALSE OK.
*/
bool setup_on_expr(THD *thd, TABLE_LIST *table, bool is_update)
{
#ifndef EMBEDDED_LIBRARY // Avoid compiler warning
uchar buff[STACK_BUFF_ALLOC]; // Max argument in function
#endif
if (check_stack_overrun(thd, STACK_MIN_SIZE, buff))
return TRUE; // Fatal error flag is set!
for(; table; table= table->next_local)
{
TABLE_LIST *embedded; /* The table at the current level of nesting. */
TABLE_LIST *embedding= table; /* The parent nested table reference. */
do
{
embedded= embedding;
DBUG_PRINT("XXX", ("check: %s", table->alias));
if (embedded->on_expr)
{
thd->where="on clause";
embedded->on_expr->mark_as_condition_AND_part(embedded);
if ((!embedded->on_expr->fixed &&
embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
embedded->on_expr->check_cols(1))
return TRUE;
}
/*
If it's a semi-join nest, fix its "left expression", as it is used by
the SJ-Materialization
*/
if (embedded->sj_subq_pred)
{
Item **left_expr= &embedded->sj_subq_pred->left_expr;
if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr))
return TRUE;
}
embedding= embedded->embedding;
}
while (embedding &&
embedding->nested_join->join_list.head() == embedded);
if (table->is_merged_derived())
{
SELECT_LEX *select_lex= table->get_single_select();
setup_on_expr(thd, select_lex->get_table_list(), is_update);
}
/* process CHECK OPTION */
if (is_update)
{
TABLE_LIST *view= table->top_table();
if (view->effective_with_check)
{
if (view->prepare_check_option(thd))
return TRUE;
thd->change_item_tree(&table->check_option, view->check_option);
}
}
}
return FALSE;
}
/* /*
Fix all conditions and outer join expressions. Fix all conditions and outer join expressions.
...@@ -8474,7 +8545,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, ...@@ -8474,7 +8545,6 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
SELECT_LEX *select_lex= thd->lex->current_select; SELECT_LEX *select_lex= thd->lex->current_select;
Query_arena *arena= thd->stmt_arena, backup; Query_arena *arena= thd->stmt_arena, backup;
TABLE_LIST *table= NULL; // For HP compilers TABLE_LIST *table= NULL; // For HP compilers
List_iterator<TABLE_LIST> ti(leaves);
/* /*
it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX it_is_update set to TRUE when tables of primary SELECT_LEX (SELECT_LEX
which belong to LEX, i.e. most up SELECT) will be updated by which belong to LEX, i.e. most up SELECT) will be updated by
...@@ -8537,51 +8607,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves, ...@@ -8537,51 +8607,8 @@ int setup_conds(THD *thd, TABLE_LIST *tables, List<TABLE_LIST> &leaves,
Apply fix_fields() to all ON clauses at all levels of nesting, Apply fix_fields() to all ON clauses at all levels of nesting,
including the ones inside view definitions. including the ones inside view definitions.
*/ */
while ((table= ti++)) if (setup_on_expr(thd, tables, it_is_update))
{ goto err_no_arena;
TABLE_LIST *embedded; /* The table at the current level of nesting. */
TABLE_LIST *embedding= table; /* The parent nested table reference. */
do
{
embedded= embedding;
if (embedded->on_expr)
{
/* Make a join an a expression */
thd->where="on clause";
embedded->on_expr->mark_as_condition_AND_part(embedded);
if ((!embedded->on_expr->fixed &&
embedded->on_expr->fix_fields(thd, &embedded->on_expr)) ||
embedded->on_expr->check_cols(1))
goto err_no_arena;
}
/*
If it's a semi-join nest, fix its "left expression", as it is used by
the SJ-Materialization
*/
if (embedded->sj_subq_pred)
{
Item **left_expr= &embedded->sj_subq_pred->left_expr;
if (!(*left_expr)->fixed && (*left_expr)->fix_fields(thd, left_expr))
goto err_no_arena;
}
embedding= embedded->embedding;
}
while (embedding &&
embedding->nested_join->join_list.head() == embedded);
/* process CHECK OPTION */
if (it_is_update)
{
TABLE_LIST *view= table->top_table();
if (view->effective_with_check)
{
if (view->prepare_check_option(thd))
goto err_no_arena;
thd->change_item_tree(&table->check_option, view->check_option);
}
}
}
if (!thd->stmt_arena->is_conventional()) if (!thd->stmt_arena->is_conventional())
{ {
......
...@@ -591,7 +591,9 @@ JOIN::prepare(Item ***rref_pointer_array, ...@@ -591,7 +591,9 @@ JOIN::prepare(Item ***rref_pointer_array,
if (!(select_options & OPTION_SETUP_TABLES_DONE) && if (!(select_options & OPTION_SETUP_TABLES_DONE) &&
setup_tables_and_check_access(thd, &select_lex->context, join_list, setup_tables_and_check_access(thd, &select_lex->context, join_list,
tables_list, select_lex->leaf_tables, tables_list, select_lex->leaf_tables,
FALSE, SELECT_ACL, SELECT_ACL, FALSE)) FALSE, SELECT_ACL, SELECT_ACL,
(thd->lex->sql_command ==
SQLCOM_UPDATE_MULTI)))
DBUG_RETURN(-1); DBUG_RETURN(-1);
/* /*
......
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