#At file:///home/dlenev/src/bzr/mysql-trunk-bugfixing-bug27480/ based on revid:dmitry.lenev@stripped
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 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
- 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->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.
+ No_such_table_error_handler no_such_table_handler;
+ error= open_table(thd, tables, new_frm_mem, ot_ctx);
+ 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;
- error= open_table(thd, tables, new_frm_mem, ot_ctx);
- safe_to_ignore_table= no_such_table_handler.safely_trapped_errors();
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
- 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)
- if (open_and_process_temporary_table(thd, tl))
- goto error;
- 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)
- /* 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)
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
- 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;
if (mode == VIEW_ALTER && fill_defined_view_parts(thd, view))
Attachment: [text/bzr-bundle] email@example.com
|• bzr commit into mysql-trunk-bugfixing branch (Dmitry.Lenev:3394) Bug#27480||Dmitry Lenev||2 Dec|