Commit a8a5f359 authored by bell@sanja.is.com.ua's avatar bell@sanja.is.com.ua

fixed bugs in view code with prepared statemnts

parent a99921fb
...@@ -3317,7 +3317,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, ...@@ -3317,7 +3317,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
{ {
GRANT_TABLE *grant_table; GRANT_TABLE *grant_table;
if (!(~table->grant.privilege & want_access) || if (!(~table->grant.privilege & want_access) ||
table->derived || table->schema_table) table->derived || table->schema_table || table->belong_to_view)
{ {
/* /*
It is subquery in the FROM clause. VIEW set table->derived after It is subquery in the FROM clause. VIEW set table->derived after
......
...@@ -2089,7 +2089,12 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, ...@@ -2089,7 +2089,12 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
DBUG_RETURN(WRONG_GRANT); DBUG_RETURN(WRONG_GRANT);
#endif #endif
if (thd->lex->current_select->no_wrap_view_item) if (thd->lex->current_select->no_wrap_view_item)
{
if (register_tree_change)
thd->change_item_tree(ref, trans[i].item);
else
*ref= trans[i].item; *ref= trans[i].item;
}
else else
{ {
Item_ref *item_ref= new Item_ref(&trans[i].item, Item_ref *item_ref= new Item_ref(&trans[i].item,
...@@ -2098,6 +2103,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, ...@@ -2098,6 +2103,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
/* as far as Item_ref have defined reference it do not need tables */ /* as far as Item_ref have defined reference it do not need tables */
if (register_tree_change && item_ref) if (register_tree_change && item_ref)
thd->change_item_tree(ref, item_ref); thd->change_item_tree(ref, item_ref);
else if (item_ref)
*ref= item_ref;
} }
DBUG_RETURN((Field*) view_ref_found); DBUG_RETURN((Field*) view_ref_found);
} }
...@@ -2944,6 +2951,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ...@@ -2944,6 +2951,7 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
TABLE_LIST *last; TABLE_LIST *last;
TABLE_LIST *embedding; TABLE_LIST *embedding;
TABLE *table= tables->table; TABLE *table= tables->table;
bool alias_used= 0;
if (!table_name || (!my_strcasecmp(table_alias_charset, table_name, if (!table_name || (!my_strcasecmp(table_alias_charset, table_name,
tables->alias) && tables->alias) &&
...@@ -3016,6 +3024,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ...@@ -3016,6 +3024,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
{ {
iterator= &view_iter; iterator= &view_iter;
view= 1; view= 1;
alias_used= my_strcasecmp(table_alias_charset,
tables->real_name, tables->alias);
} }
else else
{ {
...@@ -3037,15 +3047,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ...@@ -3037,15 +3047,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
&not_used_field_index, TRUE)) &not_used_field_index, TRUE))
{ {
Item *item= iterator->item(thd); Item *item= iterator->item(thd);
if (!found++)
(void) it->replace(item); // Replace '*'
else
it->after(item);
if (view && !thd->lex->current_select->no_wrap_view_item) if (view && !thd->lex->current_select->no_wrap_view_item)
{ {
item= new Item_ref(it->ref(), tables->view_name.str, item= new Item_ref(it->ref(), tables->view_name.str,
field_name); field_name);
} }
if (!found++)
(void) it->replace(item); // Replace '*'
else
it->after(item);
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges) if (any_privileges)
{ {
...@@ -3099,7 +3109,13 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ...@@ -3099,7 +3109,13 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
else if (allocate_view_names && else if (allocate_view_names &&
thd->lex->current_select->first_execution) thd->lex->current_select->first_execution)
{ {
Item_field *item= new Item_field(thd->strdup(tables->view_db.str), Item_field *item;
if (alias_used)
item= new Item_field(0,
thd->strdup(tables->alias),
thd->strdup(field_name));
else
item= new Item_field(thd->strdup(tables->view_db.str),
thd->strdup(tables->view_name.str), thd->strdup(tables->view_name.str),
thd->strdup(field_name)); thd->strdup(field_name));
/* /*
......
...@@ -138,7 +138,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields, ...@@ -138,7 +138,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
} }
// For the values we need select_priv // For the values we need select_priv
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege);
#endif #endif
if (check_key_in_view(thd, table_list) || if (check_key_in_view(thd, table_list) ||
...@@ -1720,8 +1720,6 @@ bool delayed_insert::handle_inserts(void) ...@@ -1720,8 +1720,6 @@ bool delayed_insert::handle_inserts(void)
bool mysql_insert_select_prepare(THD *thd) bool mysql_insert_select_prepare(THD *thd)
{ {
LEX *lex= thd->lex; LEX *lex= thd->lex;
TABLE_LIST *first_select_table=
(TABLE_LIST*) lex->select_lex.table_list.first;
TABLE_LIST *first_select_leaf_table; TABLE_LIST *first_select_leaf_table;
int res; int res;
DBUG_ENTER("mysql_insert_select_prepare"); DBUG_ENTER("mysql_insert_select_prepare");
......
...@@ -4330,7 +4330,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, ...@@ -4330,7 +4330,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
TABLE_LIST *org_tables=tables; TABLE_LIST *org_tables=tables;
for (; tables; tables= tables->next_global) for (; tables; tables= tables->next_global)
{ {
if (tables->derived || tables->schema_table || if (tables->derived || tables->schema_table || tables->belong_to_view ||
(tables->table && (int)tables->table->tmp_table) || (tables->table && (int)tables->table->tmp_table) ||
my_tz_check_n_skip_implicit_tables(&tables, my_tz_check_n_skip_implicit_tables(&tables,
thd->lex->time_zone_tables_used)) thd->lex->time_zone_tables_used))
......
...@@ -968,6 +968,9 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -968,6 +968,9 @@ static int mysql_test_update(Prepared_statement *stmt,
THD *thd= stmt->thd; THD *thd= stmt->thd;
uint table_count= 0; uint table_count= 0;
SELECT_LEX *select= &stmt->lex->select_lex; SELECT_LEX *select= &stmt->lex->select_lex;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint want_privilege;
#endif
DBUG_ENTER("mysql_test_update"); DBUG_ENTER("mysql_test_update");
if (update_precheck(thd, table_list)) if (update_precheck(thd, table_list))
...@@ -990,17 +993,29 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -990,17 +993,29 @@ static int mysql_test_update(Prepared_statement *stmt,
return 2; return 2;
} }
/*
thd->fill_derived_tables() is false here for sure (because it is
preparation of PS, so we even do not check it
*/
if (lock_tables(thd, table_list, table_count) || if (lock_tables(thd, table_list, table_count) ||
mysql_handle_derived(thd->lex, &mysql_derived_prepare) || mysql_handle_derived(thd->lex, &mysql_derived_prepare))
(thd->fill_derived_tables() &&
mysql_handle_derived(thd->lex, &mysql_derived_filling)))
DBUG_RETURN(1); DBUG_RETURN(1);
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* TABLE_LIST contain right privilages request */
want_privilege= table_list->grant.want_privilege;
#endif
if (!(res= mysql_prepare_update(thd, table_list, if (!(res= mysql_prepare_update(thd, table_list,
&select->where, &select->where,
select->order_list.elements, select->order_list.elements,
(ORDER *) select->order_list.first))) (ORDER *) select->order_list.first)))
{ {
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table_list->grant.want_privilege=
table_list->table->grant.want_privilege=
want_privilege;
#endif
thd->lex->select_lex.no_wrap_view_item= 1; thd->lex->select_lex.no_wrap_view_item= 1;
if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0)) if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0))
{ {
...@@ -1010,6 +1025,12 @@ static int mysql_test_update(Prepared_statement *stmt, ...@@ -1010,6 +1025,12 @@ static int mysql_test_update(Prepared_statement *stmt,
else else
{ {
thd->lex->select_lex.no_wrap_view_item= 0; thd->lex->select_lex.no_wrap_view_item= 0;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */
table_list->grant.want_privilege=
table_list->table->grant.want_privilege=
(SELECT_ACL & ~table_list->table->grant.privilege);
#endif
if (setup_fields(thd, 0, table_list, if (setup_fields(thd, 0, table_list,
stmt->lex->value_list, 0, 0, 0)) stmt->lex->value_list, 0, 0, 0))
res= 1; res= 1;
...@@ -1390,13 +1411,40 @@ static int mysql_test_multidelete(Prepared_statement *stmt, ...@@ -1390,13 +1411,40 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
} }
/*
Wrapper for mysql_insert_select_prepare, to make change of local tables
after open_and_lock_tables() call.
SYNOPSIS
mysql_insert_select_prepare_tester()
thd thread handler
NOTE: we need remove first local tables after open_and_lock_tables,
because mysql_handle_derived use local tables lists
*/
static bool mysql_insert_select_prepare_tester(THD *thd)
{
SELECT_LEX *first_select= &thd->lex->select_lex;
/* Skip first table, which is the table we are inserting in */
first_select->table_list.first= (byte*)((TABLE_LIST*)first_select->
table_list.first)->next_local;
/*
insert/replace from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
first_select->resolve_mode= SELECT_LEX::SELECT_MODE;
mysql_insert_select_prepare(thd);
}
/* /*
Validate and prepare for execution INSERT ... SELECT statement Validate and prepare for execution INSERT ... SELECT statement
SYNOPSIS SYNOPSIS
mysql_test_insert_select() mysql_test_insert_select()
stmt prepared statemen handler stmt prepared statemen handler
tables list of tables queries tables list of tables of query
RETURN VALUE RETURN VALUE
0 success 0 success
...@@ -1411,26 +1459,23 @@ static int mysql_test_insert_select(Prepared_statement *stmt, ...@@ -1411,26 +1459,23 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
LEX *lex= stmt->lex; LEX *lex= stmt->lex;
TABLE_LIST *first_local_table; TABLE_LIST *first_local_table;
if ((res= insert_precheck(stmt->thd, tables)))
return res;
first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
DBUG_ASSERT(first_local_table != 0);
/* Skip first table, which is the table we are inserting in */
lex->select_lex.table_list.first= (byte*) first_local_table->next_local;
if (tables->table) if (tables->table)
{ {
// don't allocate insert_values // don't allocate insert_values
tables->table->insert_values=(byte *)1; tables->table->insert_values=(byte *)1;
} }
/* if ((res= insert_precheck(stmt->thd, tables)))
insert/replace from SELECT give its SELECT_LEX for SELECT, return res;
and item_list belong to SELECT
*/ /* store it, because mysql_insert_select_prepare_tester change it */
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first;
res= select_like_statement_test(stmt, tables, &mysql_insert_select_prepare, DBUG_ASSERT(first_local_table != 0);
res= select_like_statement_test(stmt, tables,
&mysql_insert_select_prepare_tester,
OPTION_SETUP_TABLES_DONE); OPTION_SETUP_TABLES_DONE);
/* revert changes*/ /* revert changes made by mysql_insert_select_prepare_tester */
lex->select_lex.table_list.first= (byte*) first_local_table; lex->select_lex.table_list.first= (byte*) first_local_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE; lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
return res; return res;
......
...@@ -170,10 +170,8 @@ int mysql_update(THD *thd, ...@@ -170,10 +170,8 @@ int mysql_update(THD *thd,
table->quick_keys.clear_all(); table->quick_keys.clear_all();
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* In case of view TABLE_LIST contain right privilages request */ /* TABLE_LIST contain right privilages request */
want_privilege= (table_list->view ? want_privilege= table_list->grant.want_privilege;
table_list->grant.want_privilege :
table->grant.want_privilege);
#endif #endif
if (mysql_prepare_update(thd, table_list, &conds, order_num, order)) if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
DBUG_RETURN(1); DBUG_RETURN(1);
...@@ -221,7 +219,7 @@ int mysql_update(THD *thd, ...@@ -221,7 +219,7 @@ int mysql_update(THD *thd,
#ifndef NO_EMBEDDED_ACCESS_CHECKS #ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Check values */ /* Check values */
table_list->grant.want_privilege= table->grant.want_privilege= table_list->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~table->grant.privilege); (SELECT_ACL & ~~table->grant.privilege);
#endif #endif
if (setup_fields(thd, 0, table_list, values, 1, 0, 0)) if (setup_fields(thd, 0, table_list, values, 1, 0, 0))
{ {
...@@ -715,7 +713,7 @@ bool mysql_multi_update_prepare(THD *thd) ...@@ -715,7 +713,7 @@ bool mysql_multi_update_prepare(THD *thd)
} }
/* Check access privileges for table */ /* Check access privileges for table */
if (!tl->derived) if (!tl->derived && !tl->belong_to_view)
{ {
uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL;
if (!using_lock_tables) if (!using_lock_tables)
......
...@@ -679,18 +679,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -679,18 +679,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (lex->spfuns.array.buffer) if (lex->spfuns.array.buffer)
hash_free(&lex->spfuns); hash_free(&lex->spfuns);
/*
mark to avoid temporary table using and put view reference and find
last view table
*/
for (tbl= view_tables;
tbl;
tbl= (view_tables_tail= tbl)->next_global)
{
tbl->skip_temporary= 1;
tbl->belong_to_view= top_view;
}
/* /*
check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show check rights to run commands (EXPLAIN SELECT & SHOW CREATE) which show
underlying tables underlying tables
...@@ -710,6 +698,18 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) ...@@ -710,6 +698,18 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
goto err; goto err;
} }
/*
mark to avoid temporary table using and put view reference and find
last view table
*/
for (tbl= view_tables;
tbl;
tbl= (view_tables_tail= tbl)->next_global)
{
tbl->skip_temporary= 1;
tbl->belong_to_view= top_view;
}
/* move SQL_NO_CACHE & Co to whole query */ /* move SQL_NO_CACHE & Co to whole query */
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
lex->safe_to_cache_query); lex->safe_to_cache_query);
......
...@@ -1726,6 +1726,9 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds, ...@@ -1726,6 +1726,9 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
} }
if (where && !where->fixed && where->fix_fields(thd, ancestor, &where)) if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
goto err; goto err;
if (check_option && !check_option->fixed &&
check_option->fix_fields(thd, ancestor, &where))
goto err;
restore_want_privilege(); restore_want_privilege();
/* WHERE/ON resolved => we can rename fields */ /* WHERE/ON resolved => we can rename fields */
...@@ -1873,11 +1876,19 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds, ...@@ -1873,11 +1876,19 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
/* full text function moving to current select */ /* full text function moving to current select */
if (view->select_lex.ftfunc_list->elements) if (view->select_lex.ftfunc_list->elements)
{ {
Item_arena *arena= thd->current_arena, backup;
if (arena->is_conventional())
arena= 0; // For easier test
else
thd->set_n_backup_item_arena(arena, &backup);
Item_func_match *ifm; Item_func_match *ifm;
List_iterator_fast<Item_func_match> List_iterator_fast<Item_func_match>
li(*(view->select_lex.ftfunc_list)); li(*(view->select_lex.ftfunc_list));
while ((ifm= li++)) while ((ifm= li++))
current_select_save->ftfunc_list->push_front(ifm); current_select_save->ftfunc_list->push_front(ifm);
if (arena)
thd->restore_backup_item_arena(arena, &backup);
} }
ok: ok:
......
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