diff options
author | unknown <sanja@montyprogram.com> | 2013-06-27 17:42:18 +0300 |
---|---|---|
committer | unknown <sanja@montyprogram.com> | 2013-06-27 17:42:18 +0300 |
commit | 70092601bc3fa0fbae06b12c1e77b81d05bc3224 (patch) | |
tree | 41d08024013f6b845fb23be2defcc31d9e1009a2 | |
parent | 94d722b6a43b86ee760f07915921cf58f9869a5d (diff) | |
download | mariadb-git-70092601bc3fa0fbae06b12c1e77b81d05bc3224.tar.gz |
merge of 2876.430.11 & 2876.430.1
CF_PREOPEN_TMP_TABLES & CF_HA_CLOSE & Patch for Bug#11746602 (27480: Extend CREATE TEMPORARY TABLES
privilege to allow temp table operations).
-rw-r--r-- | sql/sql_acl.cc | 1 | ||||
-rw-r--r-- | sql/sql_admin.cc | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 15 | ||||
-rw-r--r-- | sql/sql_base.h | 6 | ||||
-rw-r--r-- | sql/sql_db.cc | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 6 | ||||
-rw-r--r-- | sql/sql_parse.cc | 122 | ||||
-rw-r--r-- | sql/sql_prepare.cc | 1 | ||||
-rw-r--r-- | sql/sql_rename.cc | 2 | ||||
-rw-r--r-- | sql/sql_table.cc | 55 | ||||
-rw-r--r-- | sql/sql_truncate.cc | 28 | ||||
-rw-r--r-- | sql/sql_view.cc | 3 | ||||
-rw-r--r-- | storage/myisammrg/ha_myisammrg.cc | 5 |
13 files changed, 168 insertions, 81 deletions
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 2771ee25ffd..ad1fd349fb7 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -4643,6 +4643,7 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables, Note that during creation of temporary table we still need to check if user has CREATE_TMP_ACL. */ + tl->grant.privilege|= TMP_TABLE_ACLS; tl->grant.want_privilege= 0; continue; } diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index 214cfdd0bbb..b21619753cf 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -122,8 +122,7 @@ static int prepare_for_repair(THD *thd, TABLE_LIST *table_list, MDL_EXCLUSIVE, MDL_TRANSACTION); if (lock_table_names(thd, table_list, table_list->next_global, - thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + thd->variables.lock_wait_timeout, 0)) DBUG_RETURN(0); has_mdl_lock= TRUE; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 468cb4d9c46..c7ac0695cf1 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -2276,14 +2276,15 @@ TABLE *find_temporary_table(THD *thd, int drop_temporary_table(THD *thd, TABLE_LIST *table_list, bool *is_trans) { - TABLE *table; DBUG_ENTER("drop_temporary_table"); DBUG_PRINT("tmptable", ("closing table: '%s'.'%s'", table_list->db, table_list->table_name)); - if (!(table= find_temporary_table(thd, table_list))) + if (!is_temporary_table(table_list)) DBUG_RETURN(1); + TABLE *table= table_list->table; + /* Table might be in use by some outer statement. */ if (table->query_id && table->query_id != thd->query_id) { @@ -2291,8 +2292,7 @@ int drop_temporary_table(THD *thd, TABLE_LIST *table_list, bool *is_trans) DBUG_RETURN(-1); } - if (is_trans != NULL) - *is_trans= table->file->has_transactions(); + *is_trans= table->file->has_transactions(); /* If LOCK TABLES list is not empty and contains this table, @@ -2300,6 +2300,7 @@ int drop_temporary_table(THD *thd, TABLE_LIST *table_list, bool *is_trans) */ mysql_lock_remove(thd, thd->lock, table); close_temporary_table(thd, table, 1, 1); + table_list->table= NULL; DBUG_RETURN(0); } @@ -4238,8 +4239,7 @@ recover_from_failed_open(THD *thd) case OT_DISCOVER: { if ((result= lock_table_names(thd, m_failed_table, NULL, - get_timeout(), - MYSQL_OPEN_SKIP_TEMPORARY))) + get_timeout(), 0))) break; tdc_remove_table(thd, TDC_RT_REMOVE_ALL, m_failed_table->db, @@ -4255,8 +4255,7 @@ recover_from_failed_open(THD *thd) case OT_REPAIR: { if ((result= lock_table_names(thd, m_failed_table, NULL, - get_timeout(), - MYSQL_OPEN_SKIP_TEMPORARY))) + get_timeout(), 0))) break; tdc_remove_table(thd, TDC_RT_REMOVE_ALL, m_failed_table->db, diff --git a/sql/sql_base.h b/sql/sql_base.h index e4bb60d20a0..ef54c2b813f 100644 --- a/sql/sql_base.h +++ b/sql/sql_base.h @@ -93,7 +93,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, /* mysql_lock_tables() and open_table() flags bits */ #define MYSQL_OPEN_IGNORE_GLOBAL_READ_LOCK 0x0001 #define MYSQL_OPEN_IGNORE_FLUSH 0x0002 -#define MYSQL_OPEN_TEMPORARY_ONLY 0x0004 +/* MYSQL_OPEN_TEMPORARY_ONLY (0x0004) is not used anymore. */ #define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008 #define MYSQL_LOCK_LOG_TABLE 0x0010 /** @@ -106,8 +106,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, a new instance of the table. */ #define MYSQL_OPEN_GET_NEW_TABLE 0x0040 -/** Don't look up the table in the list of temporary tables. */ -#define MYSQL_OPEN_SKIP_TEMPORARY 0x0080 +/* 0x0080 used to be MYSQL_OPEN_SKIP_TEMPORARY */ /** Fail instead of waiting when conficting metadata lock is discovered. */ #define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100 /** Open tables using MDL_SHARED lock instead of one specified in parser. */ @@ -140,7 +139,6 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update, MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY |\ MYSQL_LOCK_IGNORE_TIMEOUT |\ MYSQL_OPEN_GET_NEW_TABLE |\ - MYSQL_OPEN_SKIP_TEMPORARY |\ MYSQL_OPEN_HAS_MDL_LOCK) bool open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root, diff --git a/sql/sql_db.cc b/sql/sql_db.cc index f0bb5448520..38df88076e6 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -815,7 +815,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) /* Lock all tables and stored routines about to be dropped. */ if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY) || + 0) || lock_db_routines(thd, db)) goto exit; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index be8915c83e1..12222fddca9 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -3918,10 +3918,10 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info, { /* This shouldn't happen as creation of temporary table should make - it preparable for open. But let us do close_temporary_table() here - just in case. + it preparable for open. Anyway we can't drop temporary table if + we are unable to find it. */ - drop_temporary_table(thd, create_table, NULL); + DBUG_ASSERT(0); } else table= create_table->table; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e3503c171ac..3d217b29242 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -24,7 +24,7 @@ // set_handler_table_locks, // lock_global_read_lock, // make_global_read_lock_block_commit -#include "sql_base.h" // find_temporary_tablesx +#include "sql_base.h" // find_temporary_table #include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE, query_cache_* #include "sql_show.h" // mysqld_list_*, mysqld_show_*, // calc_sum_of_all_status @@ -44,7 +44,6 @@ #include "sql_table.h" // mysql_create_like_table, // mysql_create_table, // mysql_alter_table, - // mysql_recreate_table, // mysql_backup_table, // mysql_restore_table #include "sql_reload.h" // reload_acl_and_cache @@ -124,6 +123,7 @@ static void sql_kill(THD *thd, ulong id, killed_state state); static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state); static bool execute_show_status(THD *, TABLE_LIST *); static bool execute_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); +static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables); const char *any_db="*any*"; // Special symbol for check_access @@ -499,6 +499,7 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_DO]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_HA_OPEN]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CALL]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_CHECKSUM]|= CF_PREOPEN_TMP_TABLES; sql_command_flags[SQLCOM_ANALYZE]|= CF_PREOPEN_TMP_TABLES; @@ -2413,6 +2414,7 @@ mysql_execute_command(THD *thd) if (open_temporary_tables(thd, all_tables)) goto error; } + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -2422,8 +2424,7 @@ mysql_execute_command(THD *thd) #endif case SQLCOM_SHOW_STATUS_PROC: case SQLCOM_SHOW_STATUS_FUNC: - if ((res= check_table_access(thd, SELECT_ACL, all_tables, FALSE, - UINT_MAX, FALSE))) + if (lock_tables_precheck(thd, all_tables)) goto error; res= execute_sqlcom_select(thd, all_tables); break; @@ -2798,12 +2799,6 @@ case SQLCOM_PREPARE: } #endif - /* - Close any open handlers for the table. We need to this extra call here - as there may have been new handlers created since the previous call. - */ - mysql_ha_rm_tables(thd, create_table); - if (select_lex->item_list.elements) // With select { select_result *result; @@ -4173,6 +4168,9 @@ end_with_restore_list: DBUG_ASSERT(first_table == all_tables && first_table != 0); if (check_table_access(thd, SELECT_ACL, all_tables, FALSE, UINT_MAX, FALSE)) goto error; + /* Close temporary tables which were pre-opened for privilege checking. */ + close_thread_tables(thd); + all_tables->table= NULL; res= mysql_ha_open(thd, first_table, 0); break; case SQLCOM_HA_CLOSE: @@ -5519,6 +5517,9 @@ static bool check_show_access(THD *thd, TABLE_LIST *table) if (check_grant(thd, SELECT_ACL, dst_table, TRUE, UINT_MAX, FALSE)) return TRUE; /* Access denied */ + close_thread_tables(thd); + dst_table->table= NULL; + /* Access granted */ return FALSE; } @@ -5604,10 +5605,10 @@ check_table_access(THD *thd, ulong requirements,TABLE_LIST *tables, DBUG_PRINT("info", ("derived: %d view: %d", tables->derived != 0, tables->view != 0)); - if (tables->is_anonymous_derived_table() || - (tables->table && tables->table->s && - (int)tables->table->s->tmp_table)) + + if (tables->is_anonymous_derived_table()) continue; + thd->security_ctx= sctx; if (check_access(thd, want_access, tables->get_db_name(), @@ -7465,6 +7466,19 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); + /* + Temporary tables are pre-opened in 'tables' list only. Here we need to + initialize TABLE instances in 'aux_tables' list. + */ + for (TABLE_LIST *tl= aux_tables; tl; tl= tl->next_global) + { + if (tl->table) + continue; + + if (tl->correspondent_table) + tl->table= tl->correspondent_table->table; + } + /* sql_yacc guarantees that tables and aux_tables are not zero */ DBUG_ASSERT(aux_tables != 0); if (check_table_access(thd, SELECT_ACL, tables, FALSE, UINT_MAX, FALSE)) @@ -7733,9 +7747,9 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, CREATE TABLE ... SELECT, also require INSERT. */ - want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? - CREATE_TMP_ACL : CREATE_ACL) | - (select_lex->item_list.elements ? INSERT_ACL : 0); + want_priv= (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ? + CREATE_TMP_ACL : + (CREATE_ACL | (select_lex->item_list.elements ? INSERT_ACL : 0)); if (check_access(thd, want_priv, create_table->db, &create_table->grant.privilege, @@ -7744,11 +7758,48 @@ bool create_table_precheck(THD *thd, TABLE_LIST *tables, goto err; /* If it is a merge table, check privileges for merge children. */ - if (lex->create_info.merge_list.first && - check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, - lex->create_info.merge_list.first, - FALSE, UINT_MAX, FALSE)) - goto err; + if (lex->create_info.merge_list.first) + { + /* + The user must have (SELECT_ACL | UPDATE_ACL | DELETE_ACL) on the + underlying base tables, even if there are temporary tables with the same + names. + + From user's point of view, it might look as if the user must have these + privileges on temporary tables to create a merge table over them. This is + one of two cases when a set of privileges is required for operations on + temporary tables (see also CREATE TABLE). + + The reason for this behavior stems from the following facts: + + - For merge tables, the underlying table privileges are checked only + at CREATE TABLE / ALTER TABLE time. + + In other words, once a merge table is created, the privileges of + the underlying tables can be revoked, but the user will still have + access to the merge table (provided that the user has privileges on + the merge table itself). + + - Temporary tables shadow base tables. + + I.e. there might be temporary and base tables with the same name, and + the temporary table takes the precedence in all operations. + + - For temporary MERGE tables we do not track if their child tables are + base or temporary. As result we can't guarantee that privilege check + which was done in presence of temporary child will stay relevant later + as this temporary table might be removed. + + If SELECT_ACL | UPDATE_ACL | DELETE_ACL privileges were not checked for + the underlying *base* tables, it would create a security breach as in + Bug#12771903. + */ + + if (check_table_access(thd, SELECT_ACL | UPDATE_ACL | DELETE_ACL, + lex->create_info.merge_list.first, + FALSE, UINT_MAX, FALSE)) + goto err; + } if (want_priv != CREATE_TMP_ACL && check_grant(thd, want_priv, create_table, FALSE, 1, FALSE)) @@ -7774,6 +7825,35 @@ err: /** + Check privileges for LOCK TABLES statement. + + @param thd Thread context. + @param tables List of tables to be locked. + + @retval FALSE - Success. + @retval TRUE - Failure. +*/ + +static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables) +{ + TABLE_LIST *first_not_own_table= thd->lex->first_not_own_table(); + + for (TABLE_LIST *table= tables; table != first_not_own_table && table; + table= table->next_global) + { + if (is_temporary_table(table)) + continue; + + if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, table, + FALSE, 1, FALSE)) + return TRUE; + } + + return FALSE; +} + + +/** negate given expression. @param thd thread handler diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 75c05f140bc..d6fcfab3a31 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -106,6 +106,7 @@ When one supplies long data for a placeholder: #include "sp_head.h" #include "sp.h" #include "sp_cache.h" +#include "sql_handler.h" // mysql_ha_rm_tables #include "probes_mysql.h" #ifdef EMBEDDED_LIBRARY /* include MYSQL_BIND headers */ diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 53dbbb43bb0..dd729125223 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -142,7 +142,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list, bool silent) } if (lock_table_names(thd, table_list, 0, thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + 0)) goto err; for (ren_table= table_list; ren_table; ren_table= ren_table->next_local) diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e5860b1ab9a..2783a5bb829 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2072,15 +2072,13 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, (void) delete_statistics_for_table(thd, &db_name, &table_name); } } - - mysql_ha_rm_tables(thd, tables); if (!drop_temporary) { if (!thd->locked_tables_mode) { - if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + if (lock_table_names(thd, tables, NULL, + thd->variables.lock_wait_timeout, 0)) DBUG_RETURN(true); for (table= tables; table; table= table->next_local) { @@ -2206,6 +2204,9 @@ static uint32 comment_length(THD *thd, uint32 comment_pos, @note This function assumes that metadata locks have already been taken. It is also assumed that the tables have been removed from TDC. + @note This function assumes that temporary tables to be dropped have + been pre-opened using corresponding table list elements. + @todo When logging to the binary log, we should log tmp_tables and transactional tables as separate statements if we are in a transaction; This is needed to get these tables into the @@ -5060,6 +5061,7 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, String query(buf, sizeof(buf), system_charset_info); query.length(0); // Have to zero it since constructor doesn't Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN); + bool new_table= FALSE; // Whether newly created table is open. /* The condition avoids a crash as described in BUG#48506. Other @@ -5068,14 +5070,21 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, */ if (!table->view) { - /* - Here we open the destination table, on which we already have - exclusive metadata lock. This is needed for store_create_info() - to work. The table will be closed by close_thread_table() at - the end of this branch. - */ - if (open_table(thd, table, thd->mem_root, &ot_ctx)) - goto err; + if (!table->table) + { + + /* + In order for store_create_info() to work we need to open + destination table if it is not already open (i.e. if it + has not existed before). We don't need acquire metadata + lock in order to do this as we already hold exclusive + lock on this table. The table will be closed by + close_thread_table() at the end of this branch. + */ + if (open_table(thd, table, thd->mem_root, &ot_ctx)) + goto err; + new_table= TRUE; + } int result __attribute__((unused))= store_create_info(thd, table, &query, @@ -5085,13 +5094,16 @@ bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table, if (write_bin_log(thd, TRUE, query.ptr(), query.length())) goto err; - DBUG_ASSERT(thd->open_tables == table->table); - /* - When opening the table, we ignored the locked tables - (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table without - risking to close some locked table. - */ - close_thread_table(thd, &thd->open_tables); + if (new_table) + { + DBUG_ASSERT(thd->open_tables == table->table); + /* + When opening the table, we ignored the locked tables + (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table + without risking to close some locked table. + */ + close_thread_table(thd, &thd->open_tables); + } } } else // Case 1 @@ -8821,11 +8833,6 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, if (! thd->in_sub_stmt) trans_rollback_stmt(thd); close_thread_tables(thd); - /* - Don't release metadata locks, this will be done at - statement end. - */ - table->table=0; // For query cache } if (protocol->write()) goto err; diff --git a/sql/sql_truncate.cc b/sql/sql_truncate.cc index ce6a8c09cdd..810daefb987 100644 --- a/sql/sql_truncate.cc +++ b/sql/sql_truncate.cc @@ -18,9 +18,8 @@ #include "sql_class.h" // THD #include "sql_base.h" // open_and_lock_tables #include "sql_table.h" // write_bin_log -#include "sql_handler.h" // mysql_ha_rm_tables #include "datadict.h" // dd_recreate_table() -#include "lock.h" // MYSQL_OPEN_TEMPORARY_ONLY +#include "lock.h" // MYSQL_OPEN_* flags #include "sql_acl.h" // DROP_ACL #include "sql_parse.h" // check_one_table_access() #include "sql_truncate.h" @@ -199,9 +198,7 @@ int Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref, */ /* If it is a temporary table, no need to take locks. */ - if (is_tmp_table) - flags= MYSQL_OPEN_TEMPORARY_ONLY; - else + if (!is_tmp_table) { /* We don't need to load triggers. */ DBUG_ASSERT(table_ref->trg_event_map == 0); @@ -216,7 +213,7 @@ int Sql_cmd_truncate_table::handler_truncate(THD *thd, TABLE_LIST *table_ref, the MDL lock taken above and otherwise there is no way to wait for FLUSH TABLES in deadlock-free fashion. */ - flags= MYSQL_OPEN_IGNORE_FLUSH | MYSQL_OPEN_SKIP_TEMPORARY; + flags= MYSQL_OPEN_IGNORE_FLUSH; /* Even though we have an MDL lock on the table here, we don't pass MYSQL_OPEN_HAS_MDL_LOCK to open_and_lock_tables @@ -346,8 +343,7 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref, /* Acquire an exclusive lock. */ DBUG_ASSERT(table_ref->next_global == NULL); if (lock_table_names(thd, table_ref, NULL, - thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + thd->variables.lock_wait_timeout, 0)) DBUG_RETURN(TRUE); if (dd_check_storage_engine_flag(thd, table_ref->db, table_ref->table_name, @@ -399,26 +395,28 @@ bool Sql_cmd_truncate_table::lock_table(THD *thd, TABLE_LIST *table_ref, bool Sql_cmd_truncate_table::truncate_table(THD *thd, TABLE_LIST *table_ref) { int error; - TABLE *table; bool binlog_stmt; DBUG_ENTER("Sql_cmd_truncate_table::truncate_table"); + DBUG_ASSERT((!table_ref->table) || + (table_ref->table && table_ref->table->s)); + /* Initialize, or reinitialize in case of reexecution (SP). */ m_ticket_downgrade= NULL; - /* Remove table from the HANDLER's hash. */ - mysql_ha_rm_tables(thd, table_ref); - /* If it is a temporary table, no need to take locks. */ - if ((table= find_temporary_table(thd, table_ref))) + if (is_temporary_table(table_ref)) { + TABLE *tmp_table= table_ref->table; + /* In RBR, the statement is not binlogged if the table is temporary. */ binlog_stmt= !thd->is_current_stmt_binlog_format_row(); /* Note that a temporary table cannot be partitioned. */ - if (ha_check_storage_engine_flag(table->s->db_type(), HTON_CAN_RECREATE)) + if (ha_check_storage_engine_flag(tmp_table->s->db_type(), + HTON_CAN_RECREATE)) { - if ((error= recreate_temporary_table(thd, table))) + if ((error= recreate_temporary_table(thd, tmp_table))) binlog_stmt= FALSE; /* No need to binlog failed truncate-by-recreate. */ DBUG_ASSERT(! thd->transaction.stmt.modified_non_trans_table); diff --git a/sql/sql_view.cc b/sql/sql_view.cc index 036c04bf2f6..d99867836cf 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -1665,8 +1665,7 @@ bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode) DBUG_RETURN(TRUE); } - if (lock_table_names(thd, views, 0, thd->variables.lock_wait_timeout, - MYSQL_OPEN_SKIP_TEMPORARY)) + if (lock_table_names(thd, views, 0, thd->variables.lock_wait_timeout, 0)) DBUG_RETURN(TRUE); for (view= views; view; view= view->next_local) diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc index 0971e9297d5..d919fb59502 100644 --- a/storage/myisammrg/ha_myisammrg.cc +++ b/storage/myisammrg/ha_myisammrg.cc @@ -485,6 +485,11 @@ int ha_myisammrg::add_children_list(void) child_l->set_table_ref_id(mrg_child_def->get_child_table_ref_type(), mrg_child_def->get_child_def_version()); /* + Copy parent's prelocking attribute to allow opening of child + temporary residing in the prelocking list. + */ + child_l->prelocking_placeholder= parent_l->prelocking_placeholder; + /* For statements which acquire a SNW metadata lock on a parent table and then later try to upgrade it to an X lock (e.g. ALTER TABLE), SNW locks should be also taken on the children tables. |