3394 Dmitry Lenev 2010-12-02
Prerequisite patch for Bug#27480 (Extend CREATE TEMPORARY TABLES
privilege to allow temp table operations).
Review fixes in progress. Streamline handling of temporary tables
for prelocking list elements.
modified:
sql/sp_head.cc
sql/sql_base.cc
sql/sql_prepare.cc
sql/sql_view.cc
3393 Dmitry Lenev 2010-12-01
Prerequisite patch for Bug#27480 (Extend CREATE TEMPORARY TABLES
privilege to allow temp table operations).
Review fixes in progress. Fixed handling of administrative commands,
extended test-coverage.
modified:
mysql-test/r/grant4.result
mysql-test/t/grant4.test
sql/sql_admin.cc
sql/sql_parse.cc
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-11-30 08:30:48 +0000
+++ b/sql/sp_head.cc 2010-12-02 06:57:30 +0000
@@ -4176,11 +4176,6 @@ sp_head::add_used_tables_to_table_list(T
table->prelocking_placeholder= 1;
table->belong_to_view= belong_to_view;
table->trg_event_map= stab->trg_event_map;
-
- table->open_type=
- find_temporary_table(thd, table->db, table->table_name) ?
- OT_TEMPORARY_OR_BASE : OT_BASE_ONLY;
-
/*
Since we don't allow DDL on base tables in prelocked mode it
is safe to infer the type of metadata lock from the type of
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-11-29 14:13:07 +0000
+++ b/sql/sql_base.cc 2010-12-02 06:57:30 +0000
@@ -4320,37 +4320,45 @@ open_and_process_table(THD *thd, LEX *le
if (tables->prelocking_placeholder)
{
- if (tables->open_type == OT_TEMPORARY_OR_BASE)
+ /*
+ We're opening a table from the prelocking list.
+
+ Since this table list element might have been added after pre-opening
+ of temporary tables we have to try to open temporary table for it.
+
+ We can't simply skip this table list element and postpone opening of
+ temporary tabletill the execution of substatement for several reasons:
+ - Temporary table can be a MERGE table with base underlying tables,
+ so its underlying tables has to be properly open and locked at
+ prelocking stage. TODO/FIXME: Add test case for this scenario.
+ - Temporary table can be a MERGE table and we might be in PREPARE
+ phase for a prepared statement. In this case it is important to call
+ HA_ATTACH_CHILDREN for all merge children.
+ This is necessary because merge children remember "TABLE_SHARE ref type"
+ and "TABLE_SHARE def version" in the HA_ATTACH_CHILDREN operation.
+ If HA_ATTACH_CHILDREN is not called, these attributes are not set.
+ Then, during the first EXECUTE, those attributes need to be updated.
+ That would cause statement re-preparing (because changing those
+ attributes during EXECUTE is caught by THD::m_reprepare_observer).
+ The problem is that since those attributes are not set in merge
+ children, another round of PREPARE will not help.
+ */
+ error= open_and_process_temporary_table(thd, tables);
+
+ if (!error && !tables->table)
{
/*
- We're opening a table from the prelocking list. When adding to this
- list, TABLE_LIST::open_type is set as follows:
- - if there is a temporary table with that name,
- open_type is OT_TEMPORARY_OR_BASE (there might be also a base
- table, but that's not important because temporary tables take
- precedence over base ones);
- - otherwise (no temporary table), open_type is OT_BASE_ONLY.
-
- If there is a temporary table for that TABLE_LIST instance, there
- is no reason to pre-open base table. Proper table will be choosen
- and opened during execution.
+ For the tables added by the pre-locking code, attempt to open
+ the table but fail silently if the table does not exist.
+ The real failure will occur when/if a statement attempts to use
+ that table.
*/
- DBUG_RETURN(FALSE);
+ No_such_table_error_handler no_such_table_handler;
+ thd->push_internal_handler(&no_such_table_handler);
+ error= open_table(thd, tables, new_frm_mem, ot_ctx);
+ thd->pop_internal_handler();
+ safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
}
-
- DBUG_ASSERT(tables->open_type == OT_BASE_ONLY);
-
- /*
- For the tables added by the pre-locking code, attempt to open
- the table but fail silently if the table does not exist.
- The real failure will occur when/if a statement attempts to use
- that table.
- */
- No_such_table_error_handler no_such_table_handler;
- thd->push_internal_handler(&no_such_table_handler);
- error= open_table(thd, tables, new_frm_mem, ot_ctx);
- thd->pop_internal_handler();
- safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
}
else
error= open_table(thd, tables, new_frm_mem, ot_ctx);
=== modified file 'sql/sql_prepare.cc'
--- a/sql/sql_prepare.cc 2010-11-29 14:13:07 +0000
+++ b/sql/sql_prepare.cc 2010-12-02 06:57:30 +0000
@@ -2125,87 +2125,6 @@ static bool check_prepared_statement(Pre
break;
}
- /*
- Open temporary tables added by prelocking.
-
- Here we need to open temporary tables added by prelocking and ensure
- that HA_ATTACH_CHILDREN is called for them.
-
- This is needed to handle properly the case as follows:
- - create temporary tables 'tmp1' and 'tmp2;
- - create a merge table 'mrg1' from 'tmp1' and 'tmp2';
- - create a stored routine (let's say a stored function),
- which is using 'mrg1';
- - prepare a statement that deals with the stored routine
- (e.g. SELECT <stored function>).
-
- So, the case might be like this:
- CREATE TEMPORARY TABLE tmp1(a INT);
- CREATE TEMPORARY TABLE tmp2(a INT);
- CREATE TABLE mrg1(a INT) ENGINE=MERGE UNION=(tmp1, tmp2);
- CREATE FUNCTION f1() RETURNS INT RETURN (SELECT COUNT(*) FROM mrg1);
- PREPARE stmt1 FROM 'SELECT f1()';
-
- What's going on is this:
- - 'tables' are empty for the statement being prepared;
- - thus, before the "big switch" no temporary table is opened;
- - after 'f1' is opened, 'mrg1' is added to the prelocking list;
- - after 'mrg1' is opened, 'tmp1' and 'tmp2' are added to 'tables';
- - so, here we have not-opened temporary tables 'tmp1' and 'tmp2'
- in the 'tables' list.
-
- The thing is that HA_ATTACH_CHILDREN must be called for all merge
- children during the prepare phase. This is critical because merge
- children remembers "TABLE_SHARE ref type" and "TABLE_SHARE def version"
- in the HA_ATTACH_CHILDREN operation.
-
- If HA_ATTACH_CHILDREN is not called, these attributes are not set.
- Then, during the first EXECUTE, those attributes need to be updated.
- That would cause statement re-preparing (because changing those
- attributes during EXECUTE is caught by THD::m_reprepare_observer).
- The problem is that since those attributes are not set in merge children,
- another round of PREPARE will not help. The attributes will be
- remembered, but as soon as close_thread_tables() is called at the end
- of PREPARE, this information will be lost again.
- */
-
- if (sql_command_flags[sql_command] & CF_PREOPEN_TMP_TABLES)
- {
- List<TABLE_LIST> new_tl_arr;
-
- for (TABLE_LIST *tl= lex->query_tables; tl; tl= tl->next_global)
- {
- if (tl->table)
- continue;
-
- if (open_and_process_temporary_table(thd, tl))
- goto error;
-
- new_tl_arr.push_back(tl);
- }
-
- /*
- Ensure that HA_ATTACH_CHILDREN has been called for newly added (by
- prelocking) merge tables.
- */
- {
- List_iterator_fast<TABLE_LIST> new_tl_arr_it(new_tl_arr);
- TABLE_LIST *tl;
- while ((tl= new_tl_arr_it++))
- {
- if (!tl->table ||
- tl->table->file->ht->db_type != DB_TYPE_MRG_MYISAM)
- continue;
-
- /* MERGE tables need to access parent and child TABLE_LISTs. */
- DBUG_ASSERT(tl->table->pos_in_table_list == tl);
-
- if (tl->table->file->extra(HA_EXTRA_ATTACH_CHILDREN))
- goto error;
- }
- }
- }
-
if (res == 0)
DBUG_RETURN(stmt->is_sql_prepare() ?
FALSE : (send_prep_stmt(stmt, 0) || thd->protocol->flush()));
=== modified file 'sql/sql_view.cc'
--- a/sql/sql_view.cc 2010-11-30 08:30:48 +0000
+++ b/sql/sql_view.cc 2010-12-02 06:57:30 +0000
@@ -441,18 +441,6 @@ bool mysql_create_view(THD *thd, TABLE_L
goto err;
}
- /*
- Open matching temporary tables for table list elements added by
- prelocking algorithm. We need this in order to catch cases when
- view uses functions that use temporary tables (note that this
- check is not robust).
- */
- if (open_and_process_temporary_table_list(thd, lex->query_tables))
- {
- res= TRUE;
- goto err;
- }
-
view= lex->unlink_first_table(&link_to_local);
if (mode == VIEW_ALTER && fill_defined_view_parts(thd, view))
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk-bugfixing branch (Dmitry.Lenev:3393 to 3394)Bug#27480 | Dmitry Lenev | 2 Dec |