fixed bugs in view code with prepared statemnts
sql/sql_acl.cc: block checking view underlying tables sql/sql_base.cc: item registration fixed fixed non registred item resolving fixed result of outo-merge fixed creation reference if alias used sql/sql_insert.cc: layout fixed removed unused variable sql/sql_parse.cc: block checking view underlying tables sql/sql_prepare.cc: make preparation check same as usual check sql/sql_update.cc: made want_privilege assignment simplier block checking view underlying tables sql/sql_view.cc: belong_to_view assignmebt moved after privileges check sql/table.cc: check option fix field added arena management added
This commit is contained in:
parent
592ffbcd68
commit
34f313eeaf
@ -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,
|
|||||||
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)
|
||||||
*ref= trans[i].item;
|
{
|
||||||
|
if (register_tree_change)
|
||||||
|
thd->change_item_tree(ref, trans[i].item);
|
||||||
|
else
|
||||||
|
*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,
|
|||||||
/* 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,
|
|||||||
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,
|
|||||||
{
|
{
|
||||||
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,
|
|||||||
¬_used_field_index, TRUE))
|
¬_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,9 +3109,15 @@ 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;
|
||||||
thd->strdup(tables->view_name.str),
|
if (alias_used)
|
||||||
thd->strdup(field_name));
|
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(field_name));
|
||||||
/*
|
/*
|
||||||
during cleunup() this item will be put in list to replace
|
during cleunup() this item will be put in list to replace
|
||||||
expression from VIEW
|
expression from VIEW
|
||||||
|
@ -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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
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,
|
|||||||
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,
|
|||||||
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,
|
|||||||
#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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
|||||||
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)
|
|||||||
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);
|
||||||
|
11
sql/table.cc
11
sql/table.cc
@ -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,
|
|||||||
/* 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:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user