diff options
author | bell@sanja.is.com.ua <> | 2005-01-04 18:04:16 +0200 |
---|---|---|
committer | bell@sanja.is.com.ua <> | 2005-01-04 18:04:16 +0200 |
commit | a8a5f3590cb1badf544f7454d783a71a1bdf6dbc (patch) | |
tree | 614f6803a8c639e656f89a70e02feda14d66d919 /sql | |
parent | a99921fb3949fec0a2c7eaa2f96ad9ab071f53f3 (diff) | |
download | mariadb-git-a8a5f3590cb1badf544f7454d783a71a1bdf6dbc.tar.gz |
fixed bugs in view code with prepared statemnts
Diffstat (limited to 'sql')
-rw-r--r-- | sql/sql_acl.cc | 2 | ||||
-rw-r--r-- | sql/sql_base.cc | 32 | ||||
-rw-r--r-- | sql/sql_insert.cc | 4 | ||||
-rw-r--r-- | sql/sql_parse.cc | 2 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 79 | ||||
-rw-r--r-- | sql/sql_update.cc | 10 | ||||
-rw-r--r-- | sql/sql_view.cc | 24 | ||||
-rw-r--r-- | sql/table.cc | 11 |
8 files changed, 116 insertions, 48 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index ba00c1d3fa7..25f26938e84 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -3317,7 +3317,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, { GRANT_TABLE *grant_table; 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 diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 0b0bf6df7ad..87e4f5df1cc 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2089,7 +2089,12 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list, DBUG_RETURN(WRONG_GRANT); #endif 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 { 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 */ if (register_tree_change && item_ref) thd->change_item_tree(ref, item_ref); + else if (item_ref) + *ref= item_ref; } 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 *embedding; TABLE *table= tables->table; + bool alias_used= 0; if (!table_name || (!my_strcasecmp(table_alias_charset, table_name, tables->alias) && @@ -3016,6 +3024,8 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, { iterator= &view_iter; view= 1; + alias_used= my_strcasecmp(table_alias_charset, + tables->real_name, tables->alias); } else { @@ -3037,15 +3047,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, ¬_used_field_index, TRUE)) { 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) { item= new Item_ref(it->ref(), tables->view_name.str, field_name); } + if (!found++) + (void) it->replace(item); // Replace '*' + else + it->after(item); #ifndef NO_EMBEDDED_ACCESS_CHECKS if (any_privileges) { @@ -3099,9 +3109,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name, else if (allocate_view_names && thd->lex->current_select->first_execution) { - Item_field *item= new Item_field(thd->strdup(tables->view_db.str), - thd->strdup(tables->view_name.str), - thd->strdup(field_name)); + 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(field_name)); /* during cleunup() this item will be put in list to replace expression from VIEW diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 45b62ef8d83..dc80081bbc8 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -138,7 +138,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields, } // For the values we need select_priv #ifndef NO_EMBEDDED_ACCESS_CHECKS - table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege); + table->grant.want_privilege= (SELECT_ACL & ~table->grant.privilege); #endif 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) { LEX *lex= thd->lex; - TABLE_LIST *first_select_table= - (TABLE_LIST*) lex->select_lex.table_list.first; TABLE_LIST *first_select_leaf_table; int res; DBUG_ENTER("mysql_insert_select_prepare"); diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 442d398889f..60caa3ff421 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4330,7 +4330,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables, TABLE_LIST *org_tables=tables; 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) || my_tz_check_n_skip_implicit_tables(&tables, thd->lex->time_zone_tables_used)) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 88f90e393f6..b65d0e137ce 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -968,6 +968,9 @@ static int mysql_test_update(Prepared_statement *stmt, THD *thd= stmt->thd; uint table_count= 0; SELECT_LEX *select= &stmt->lex->select_lex; +#ifndef NO_EMBEDDED_ACCESS_CHECKS + uint want_privilege; +#endif DBUG_ENTER("mysql_test_update"); if (update_precheck(thd, table_list)) @@ -990,17 +993,29 @@ static int mysql_test_update(Prepared_statement *stmt, 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) || - mysql_handle_derived(thd->lex, &mysql_derived_prepare) || - (thd->fill_derived_tables() && - mysql_handle_derived(thd->lex, &mysql_derived_filling))) + mysql_handle_derived(thd->lex, &mysql_derived_prepare)) 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, &select->where, select->order_list.elements, (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; 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 { 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, stmt->lex->value_list, 0, 0, 0)) res= 1; @@ -1391,12 +1412,39 @@ 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 SYNOPSIS mysql_test_insert_select() stmt prepared statemen handler - tables list of tables queries + tables list of tables of query RETURN VALUE 0 success @@ -1411,26 +1459,23 @@ static int mysql_test_insert_select(Prepared_statement *stmt, LEX *lex= stmt->lex; 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) { // don't allocate insert_values tables->table->insert_values=(byte *)1; } - /* - insert/replace from SELECT give its SELECT_LEX for SELECT, - and item_list belong to SELECT - */ - lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE; - res= select_like_statement_test(stmt, tables, &mysql_insert_select_prepare, + if ((res= insert_precheck(stmt->thd, tables))) + return res; + + /* store it, because mysql_insert_select_prepare_tester change it */ + first_local_table= (TABLE_LIST *)lex->select_lex.table_list.first; + DBUG_ASSERT(first_local_table != 0); + + res= select_like_statement_test(stmt, tables, + &mysql_insert_select_prepare_tester, 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.resolve_mode= SELECT_LEX::INSERT_MODE; return res; diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 5ca25bbac3e..5e7bdf69dbb 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -170,10 +170,8 @@ int mysql_update(THD *thd, table->quick_keys.clear_all(); #ifndef NO_EMBEDDED_ACCESS_CHECKS - /* In case of view TABLE_LIST contain right privilages request */ - want_privilege= (table_list->view ? - table_list->grant.want_privilege : - table->grant.want_privilege); + /* TABLE_LIST contain right privilages request */ + want_privilege= table_list->grant.want_privilege; #endif if (mysql_prepare_update(thd, table_list, &conds, order_num, order)) DBUG_RETURN(1); @@ -221,7 +219,7 @@ int mysql_update(THD *thd, #ifndef NO_EMBEDDED_ACCESS_CHECKS /* Check values */ table_list->grant.want_privilege= table->grant.want_privilege= - (SELECT_ACL & ~table->grant.privilege); + (SELECT_ACL & ~~table->grant.privilege); #endif 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 */ - if (!tl->derived) + if (!tl->derived && !tl->belong_to_view) { uint want_privilege= tl->updating ? UPDATE_ACL : SELECT_ACL; if (!using_lock_tables) diff --git a/sql/sql_view.cc b/sql/sql_view.cc index bafb57c44b0..e982eb8e6be 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -680,18 +680,6 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) 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 underlying tables */ @@ -710,6 +698,18 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table) 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 */ old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query && lex->safe_to_cache_query); diff --git a/sql/table.cc b/sql/table.cc index e9b89d6b124..12862d21ac0 100644 --- a/sql/table.cc +++ b/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)) goto err; + if (check_option && !check_option->fixed && + check_option->fix_fields(thd, ancestor, &where)) + goto err; restore_want_privilege(); /* 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 */ 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; List_iterator_fast<Item_func_match> li(*(view->select_lex.ftfunc_list)); while ((ifm= li++)) current_select_save->ftfunc_list->push_front(ifm); + if (arena) + thd->restore_backup_item_arena(arena, &backup); } ok: |