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).
This commit is contained in:
parent
94d722b6a4
commit
70092601bc
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
122
sql/sql_parse.cc
122
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))
|
||||
@ -7773,6 +7824,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.
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -484,6 +484,11 @@ int ha_myisammrg::add_children_list(void)
|
||||
/* Set the expected table version, to not cause spurious re-prepare. */
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user