3402 Dmitry Lenev 2010-12-22
Prerequisite patch for Bug#27480 (Extend CREATE TEMPORARY
TABLES privilege to allow temp table operations).
Review fixes in progress. Final (almost) batch of fixes.
modified:
mysql-test/r/alter_table.result
mysql-test/r/handler_myisam.result
mysql-test/r/temp_table.result
mysql-test/suite/innodb/r/innodb_mysql.result
mysql-test/suite/innodb/t/innodb_mysql.test
mysql-test/suite/rpl/r/rpl_create_if_not_exists.result
mysql-test/suite/rpl/t/rpl_create_if_not_exists.test
mysql-test/t/alter_table.test
mysql-test/t/handler_myisam.test
mysql-test/t/temp_table.test
sql/log_event.cc
sql/sql_admin.cc
sql/sql_base.cc
sql/sql_base.h
sql/sql_class.h
sql/sql_handler.cc
sql/sql_parse.cc
sql/sql_partition_admin.cc
sql/sql_show.cc
sql/sql_table.cc
sql/sql_truncate.cc
3401 Dmitry Lenev 2010-12-14
Prerequisite patch for Bug#27480 (Extend CREATE TEMPORARY
TABLES privilege to allow temp table operations).
Review fixes in progress. Polish handling of OT_TEMPORARY_ONLY
flag and streamline process of table opening.
modified:
sql/sql_base.cc
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result 2010-08-30 06:38:09 +0000
+++ b/mysql-test/r/alter_table.result 2010-12-22 15:23:28 +0000
@@ -1383,3 +1383,14 @@ ALTER TABLE t1 CHANGE a id INT;
affected rows: 0
info: Records: 0 Duplicates: 0 Warnings: 0
DROP TABLE t1;
+#
+# Additional coverage for refactoring which is made as part
+# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+# to allow temp table operations".
+#
+# At some point the below test case failed on assertion.
+DROP TABLE IF EXISTS t1;
+CREATE TEMPORARY TABLE t1 (i int) ENGINE=MyISAM;
+ALTER TABLE t1 DISCARD TABLESPACE;
+ERROR HY000: Table storage engine for 't1' doesn't have this option
+DROP TABLE t1;
=== modified file 'mysql-test/r/handler_myisam.result'
--- a/mysql-test/r/handler_myisam.result 2010-11-29 14:13:07 +0000
+++ b/mysql-test/r/handler_myisam.result 2010-12-22 15:23:28 +0000
@@ -1859,15 +1859,20 @@ a b
HANDLER t1 CLOSE;
DROP TABLE t1;
#
-# Bug#27480
+# Additional coverage for refactoring which is made as part
+# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+# to allow temp table operations".
#
+# Check that DDL on temporary table properly closes HANDLER cursors
+# for this table belonging to the same connection.
CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
# -- CREATE TABLE
HANDLER t1 OPEN;
-CREATE TABLE t2 SELECT * FROM t1;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1 SELECT 1 AS f1;
+Warnings:
+Note 1050 Table 't1' already exists
HANDLER t1 READ FIRST;
ERROR 42S02: Unknown table 't1' in HANDLER
-DROP TABLE t2;
# -- REPAIR TABLE
HANDLER t1 OPEN;
REPAIR TABLE t1;
@@ -1901,6 +1906,21 @@ HANDLER t1 OPEN;
ALTER TABLE t1 ADD COLUMN b INT;
HANDLER t1 READ FIRST;
ERROR 42S02: Unknown table 't1' in HANDLER
+# -- CREATE INDEX
+HANDLER t1 OPEN;
+CREATE INDEX b ON t1 (b);
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- DROP INDEX
+HANDLER t1 OPEN;
+DROP INDEX b ON t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
+# -- TRUNCATE TABLE
+HANDLER t1 OPEN;
+TRUNCATE TABLE t1;
+HANDLER t1 READ FIRST;
+ERROR 42S02: Unknown table 't1' in HANDLER
# -- DROP TABLE
HANDLER t1 OPEN;
DROP TABLE t1;
=== modified file 'mysql-test/r/temp_table.result'
--- a/mysql-test/r/temp_table.result 2010-11-29 14:13:07 +0000
+++ b/mysql-test/r/temp_table.result 2010-12-22 15:23:28 +0000
@@ -223,6 +223,10 @@ CREATE TEMPORARY TABLE bug48067.t1 (c1 i
DROP DATABASE bug48067;
DROP TEMPORARY table bug48067.t1;
End of 5.1 tests
+#
+# Test that admin statements work for temporary tables.
+#
+DROP TABLE IF EXISTS t1,t2;
CREATE TEMPORARY TABLE t1(a INT);
CREATE TEMPORARY TABLE t2(b INT);
CREATE TEMPORARY TABLE t3(c INT);
@@ -266,3 +270,4 @@ Table Op Msg_type Msg_text
test.t1 repair status OK
test.t2 repair status OK
test.t3 repair status OK
+DROP TABLES t1, t2, t3;
=== modified file 'mysql-test/suite/innodb/r/innodb_mysql.result'
--- a/mysql-test/suite/innodb/r/innodb_mysql.result 2010-11-26 13:46:21 +0000
+++ b/mysql-test/suite/innodb/r/innodb_mysql.result 2010-12-22 15:23:28 +0000
@@ -2830,4 +2830,17 @@ PACK_KEYS=0;
CREATE INDEX a ON t1 (a);
CREATE INDEX c on t1 (c);
DROP TABLE t1;
+#
+# Additional coverage for refactoring which is made as part
+# of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+# to allow temp table operations".
+#
+# Check that OPTIMIZE table works for temporary InnoDB tables.
+DROP TABLE IF EXISTS t1;
+CREATE TEMPORARY TABLE t1 (a INT) ENGINE=InnoDB;
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize note Table does not support optimize, doing recreate + analyze instead
+test.t1 optimize status OK
+DROP TABLE t1;
End of 6.0 tests
=== modified file 'mysql-test/suite/innodb/t/innodb_mysql.test'
--- a/mysql-test/suite/innodb/t/innodb_mysql.test 2010-11-23 11:04:47 +0000
+++ b/mysql-test/suite/innodb/t/innodb_mysql.test 2010-12-22 15:23:28 +0000
@@ -992,4 +992,19 @@ CREATE INDEX c on t1 (c);
DROP TABLE t1;
+
+--echo #
+--echo # Additional coverage for refactoring which is made as part
+--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+--echo # to allow temp table operations".
+--echo #
+--echo # Check that OPTIMIZE table works for temporary InnoDB tables.
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TEMPORARY TABLE t1 (a INT) ENGINE=InnoDB;
+OPTIMIZE TABLE t1;
+DROP TABLE t1;
+
+
--echo End of 6.0 tests
=== modified file 'mysql-test/suite/rpl/r/rpl_create_if_not_exists.result'
--- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result 2010-08-30 08:40:42 +0000
+++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result 2010-12-22 15:23:28 +0000
@@ -126,3 +126,17 @@ show binlog events from <binlog_start>;
Log_name Pos Event_type Server_id End_log_pos Info
DROP VIEW v1;
DROP TABLE t1, t2;
+#
+# Test case which has failed on assertion after refactoring which was
+# made as part of fix for bug #27480 "Extend CREATE TEMPORARY TABLES
+# privilege to allow temp table operations".
+#
+CREATE TEMPORARY TABLE t1 (id int);
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+# The below statement should succeed with warning and
+# should not crash due to failing assertion.
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+Warnings:
+Note 1050 Table 't2' already exists
+# Clean-up.
+DROP TABLE t1, t2;
=== modified file 'mysql-test/suite/rpl/t/rpl_create_if_not_exists.test'
--- a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test 2010-08-30 08:40:42 +0000
+++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test 2010-12-22 15:23:28 +0000
@@ -173,4 +173,21 @@ DROP VIEW v1;
DROP TABLE t1, t2;
+
+--echo #
+--echo # Test case which has failed on assertion after refactoring which was
+--echo # made as part of fix for bug #27480 "Extend CREATE TEMPORARY TABLES
+--echo # privilege to allow temp table operations".
+--echo #
+CREATE TEMPORARY TABLE t1 (id int);
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+--echo # The below statement should succeed with warning and
+--echo # should not crash due to failing assertion.
+CREATE TABLE IF NOT EXISTS t2 LIKE t1;
+--echo # Clean-up.
+DROP TABLE t1, t2;
+sync_slave_with_master;
+connection master;
+
+
source include/master-slave-end.inc;
=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test 2010-07-26 09:22:38 +0000
+++ b/mysql-test/t/alter_table.test 2010-12-22 15:23:28 +0000
@@ -1144,3 +1144,18 @@ INSERT INTO t1 VALUES (1, 1), (2, 2);
ALTER TABLE t1 CHANGE a id INT;
--disable_info
DROP TABLE t1;
+
+
+--echo #
+--echo # Additional coverage for refactoring which is made as part
+--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+--echo # to allow temp table operations".
+--echo #
+--echo # At some point the below test case failed on assertion.
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+CREATE TEMPORARY TABLE t1 (i int) ENGINE=MyISAM;
+--error ER_ILLEGAL_HA
+ALTER TABLE t1 DISCARD TABLESPACE;
+DROP TABLE t1;
=== modified file 'mysql-test/t/handler_myisam.test'
--- a/mysql-test/t/handler_myisam.test 2010-11-29 14:13:07 +0000
+++ b/mysql-test/t/handler_myisam.test 2010-12-22 15:23:28 +0000
@@ -98,19 +98,21 @@ DROP TABLE t1;
--echo #
---echo # Bug#27480
+--echo # Additional coverage for refactoring which is made as part
+--echo # of fix for bug #27480 "Extend CREATE TEMPORARY TABLES privilege
+--echo # to allow temp table operations".
--echo #
+--echo # Check that DDL on temporary table properly closes HANDLER cursors
+--echo # for this table belonging to the same connection.
CREATE TEMPORARY TABLE t1 AS SELECT 1 AS f1;
--echo # -- CREATE TABLE
HANDLER t1 OPEN;
-CREATE TABLE t2 SELECT * FROM t1;
+CREATE TEMPORARY TABLE IF NOT EXISTS t1 SELECT 1 AS f1;
--error ER_UNKNOWN_TABLE
HANDLER t1 READ FIRST;
-DROP TABLE t2;
-
--echo # -- REPAIR TABLE
HANDLER t1 OPEN;
REPAIR TABLE t1;
@@ -141,6 +143,24 @@ ALTER TABLE t1 ADD COLUMN b INT;
--error ER_UNKNOWN_TABLE
HANDLER t1 READ FIRST;
+--echo # -- CREATE INDEX
+HANDLER t1 OPEN;
+CREATE INDEX b ON t1 (b);
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- DROP INDEX
+HANDLER t1 OPEN;
+DROP INDEX b ON t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
+--echo # -- TRUNCATE TABLE
+HANDLER t1 OPEN;
+TRUNCATE TABLE t1;
+--error ER_UNKNOWN_TABLE
+HANDLER t1 READ FIRST;
+
--echo # -- DROP TABLE
HANDLER t1 OPEN;
DROP TABLE t1;
=== modified file 'mysql-test/t/temp_table.test'
--- a/mysql-test/t/temp_table.test 2010-11-29 14:13:07 +0000
+++ b/mysql-test/t/temp_table.test 2010-12-22 15:23:28 +0000
@@ -252,8 +252,12 @@ DROP TEMPORARY table bug48067.t1;
--echo End of 5.1 tests
-# Check admin statements.
-
+--echo #
+--echo # Test that admin statements work for temporary tables.
+--echo #
+--disable_warnings
+DROP TABLE IF EXISTS t1,t2;
+--enable_warnings
CREATE TEMPORARY TABLE t1(a INT);
CREATE TEMPORARY TABLE t2(b INT);
CREATE TEMPORARY TABLE t3(c INT);
@@ -288,3 +292,5 @@ INSERT INTO t2 VALUES (11), (12), (13);
INSERT INTO t3 VALUES (101), (102), (103);
REPAIR TABLE t1, t2, t3;
+
+DROP TABLES t1, t2, t3;
=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc 2010-11-29 16:55:45 +0000
+++ b/sql/log_event.cc 2010-12-22 15:23:28 +0000
@@ -5302,7 +5302,8 @@ int Load_log_event::do_apply_event(NET*
update it inside mysql_load().
*/
List<Item> tmp_list;
- if (mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
+ if (open_temporary_table_list(thd, &tables) ||
+ mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
handle_dup, ignore, net != 0))
thd->is_slave_error= 1;
if (thd->cuted_fields)
=== modified file 'sql/sql_admin.cc'
--- a/sql/sql_admin.cc 2010-12-14 09:15:37 +0000
+++ b/sql/sql_admin.cc 2010-12-22 15:23:28 +0000
@@ -17,7 +17,6 @@
#include "keycaches.h" // get_key_cache
#include "sql_base.h" // Open_table_context
#include "lock.h" // MYSQL_OPEN_*
-#include "sql_handler.h" // mysql_ha_rm_tables
#include "partition_element.h" // PART_ADMIN
#include "sql_partition.h" // set_part_state
#include "transaction.h" // trans_rollback_stmt
@@ -565,6 +564,13 @@ static bool mysql_admin_table(THD* thd,
HA_ADMIN_NEEDS_ALTER))
{
DBUG_PRINT("admin", ("recreating table"));
+ /*
+ Temporary table are always created by current server so they never
+ require upgrade. So we don't need to pre-open them before calling
+ mysql_recreate_table().
+ */
+ DBUG_ASSERT(! table->table->s->tmp_table);
+
trans_rollback_stmt(thd);
trans_rollback(thd);
close_thread_tables(thd);
@@ -723,7 +729,9 @@ send_result_message:
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
- result_code= mysql_recreate_table(thd, table);
+ /* Don't forget to pre-open temporary tables. */
+ result_code= (open_temporary_table_list(thd, table) ||
+ mysql_recreate_table(thd, table));
reenable_binlog(thd);
/*
mysql_recreate_table() can push OK or ERROR.
@@ -737,14 +745,15 @@ send_result_message:
trans_commit(thd);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
- if (!result_code && // recreation went ok
- !table->table) // not a temporary table opened above
+ /* Clear references to TABLE and MDL_ticket after releasing them. */
+ table->table= NULL;
+ table->mdl_request.ticket= NULL;
+ if (!result_code) // recreation went ok
{
- /* Clear the ticket released above. */
- table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
table->mdl_request.set_type(MDL_SHARED_WRITE);
- if ((table->table= open_ltable(thd, table, lock_type, 0)))
+ if (!open_temporary_table_list(thd, table) &&
+ (table->table= open_n_lock_single_table(thd, table, lock_type, 0)))
{
result_code= table->table->file->ha_analyze(thd, check_opt);
if (result_code == HA_ADMIN_ALREADY_DONE)
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-12-14 15:31:57 +0000
+++ b/sql/sql_base.cc 2010-12-22 15:23:28 +0000
@@ -2621,8 +2621,7 @@ bool open_table(THD *thd, TABLE_LIST *ta
if (thd->killed)
DBUG_RETURN(TRUE);
- key_length= (create_table_def_key(thd, key, table_list, 1) -
- TMP_TABLE_KEY_EXTRA);
+ key_length= create_table_def_key(thd, key, table_list, 0);
/*
If we're in pre-locked or LOCK TABLES mode, let's try to find the
@@ -4303,7 +4302,7 @@ open_and_process_table(THD *thd, LEX *le
(TABLE_LIST::table is not NULL), that TABLE object must be a pre-opened
temporary table.
*/
- DBUG_ASSERT(is_temporary_table(tables->table));
+ DBUG_ASSERT(is_temporary_table(tables));
}
else if (tables->open_type == OT_TEMPORARY_ONLY)
{
@@ -5973,6 +5972,9 @@ static void update_field_dependencies(TH
of this thread. Temporary tables are thread-local and "shadow" base
tables with the same name.
+ @note In most cases one should use open_temporary_tables() instead
+ of this call.
+
@note One should finalize process of opening temporary table for table
list element by calling open_and_process_table(). This function
is responsible for table version checking and handling of merge
@@ -5998,16 +6000,21 @@ bool open_temporary_table(THD *thd, TABL
*/
DBUG_ASSERT(tl->table == NULL);
+ /*
+ This function should not be called for cases when derived or I_S
+ tables can be met since table list elements for such tables can
+ have invalid db or table name.
+ Instead open_temporary_table_list() should be used.
+ */
+ DBUG_ASSERT(!tl->derived && !tl->schema_table);
+
if (tl->open_type == OT_BASE_ONLY)
{
DBUG_PRINT("info", ("skip_temporary is set"));
DBUG_RETURN(FALSE);
}
- char table_key[MAX_DBKEY_LENGTH];
- uint table_key_length= create_table_def_key(thd, table_key, tl, 1);
-
- TABLE *table= find_temporary_table(thd, table_key, table_key_length);
+ TABLE *table= find_temporary_table(thd, tl);
if (!table)
{
@@ -6050,12 +6057,33 @@ bool open_temporary_table(THD *thd, TABL
}
+/**
+ Pre-open temporary tables corresponding to table list elements.
+
+ @note One should finalize process of opening temporary tables
+ by calling open_tables(). This function is responsible
+ for table version checking and handling of merge tables.
+
+ @return Error status.
+ @retval FALSE On success. If a temporary tables exists for the
+ given element, tl->table is set.
+ @retval TRUE On error. my_error() has been called.
+*/
+
bool open_temporary_table_list(THD *thd, TABLE_LIST *tl_list)
{
DBUG_ENTER("open_temporary_table_list");
for (TABLE_LIST *tl= tl_list; tl; tl= tl->next_global)
{
+ if (tl->derived || tl->schema_table)
+ {
+ /*
+ Derived and I_S tables will be handled by a later call to open_tables().
+ */
+ continue;
+ }
+
if (open_temporary_table(thd, tl))
DBUG_RETURN(TRUE);
}
=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h 2010-12-14 09:15:37 +0000
+++ b/sql/sql_base.h 2010-12-22 15:23:28 +0000
@@ -572,27 +572,12 @@ private:
/**
- Indicate if a TABLE instance represents a temporary table.
-*/
-
-inline bool is_temporary_table(TABLE *table)
-{
- /*
- NOTE: 'table->s' might be NULL for specially constructed TABLE_LIST
- instances, like for SHOW TRIGGERS LIKE ...
- */
-
- return table->s && table->s->tmp_table != NO_TMP_TABLE;
-}
-
-
-/**
- Indicate if a TABLE_LIST instance represents a temporary table.
+ Check if a TABLE_LIST instance represents a pre-opened temporary table.
*/
inline bool is_temporary_table(TABLE_LIST *tl)
{
- return tl->table ? is_temporary_table(tl->table) : FALSE;
+ return tl->table ? (tl->table->s->tmp_table != NO_TMP_TABLE) : FALSE;
}
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2010-12-06 10:36:38 +0000
+++ b/sql/sql_class.h 2010-12-22 15:23:28 +0000
@@ -3703,7 +3703,7 @@ public:
#define CF_PREOPEN_TMP_TABLES (1U << 10)
/**
- Identfies statements for which open handlers should be closed in the
+ Identifies statements for which open handlers should be closed in the
beginning of the statement.
*/
#define CF_HA_CLOSE (1U << 11)
=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc 2010-12-14 09:15:37 +0000
+++ b/sql/sql_handler.cc 2010-12-22 15:23:28 +0000
@@ -287,7 +287,11 @@ bool mysql_ha_open(THD *thd, TABLE_LIST
*/
DBUG_ASSERT(! hash_tables->table);
- error= open_temporary_table(thd, hash_tables);
+ /*
+ TODO/FIXME: In the upcoming patch we somehow should handle
+ situation with privilege check for temporary table.
+ */
+ error= open_temporary_table_list(thd, hash_tables);
if (!error)
error= open_tables(thd, &hash_tables, &counter, 0);
=== modified file 'sql/sql_parse.cc'
--- a/sql/sql_parse.cc 2010-12-14 09:15:37 +0000
+++ b/sql/sql_parse.cc 2010-12-22 15:23:28 +0000
@@ -369,7 +369,7 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_SHOW_PROCESSLIST]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_GRANTS]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_DB]= CF_STATUS_COMMAND;
- sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
+ sql_command_flags[SQLCOM_SHOW_CREATE]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_MASTER_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_SLAVE_STAT]= CF_STATUS_COMMAND;
sql_command_flags[SQLCOM_SHOW_CREATE_PROC]= CF_STATUS_COMMAND;
@@ -455,7 +455,6 @@ void init_update_queries(void)
them, but which are not listed here. The thing is that the order of
pre-opening temporary tables for those statements is somewhat custom.
*/
-
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES;
@@ -484,9 +483,11 @@ void init_update_queries(void)
sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_PREOPEN_TMP_TABLES;
/*
- DDL statements should start with closing opened handlers.
- */
+ DDL statements that should start with closing opened handlers.
+ We use this flag only for statements for which open HANDLERs
+ have to be closed before emporary tables are pre-opened.
+ */
sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_HA_CLOSE;
sql_command_flags[SQLCOM_TRUNCATE]|= CF_HA_CLOSE;
@@ -1252,7 +1253,7 @@ bool dispatch_command(enum enum_server_c
thd->set_query(fields, query_length);
general_log_print(thd, command, "%s %s", table_list.table_name, fields);
- if (open_temporary_table(thd, &table_list))
+ if (open_temporary_table_list(thd, &table_list))
break;
if (check_table_access(thd, SELECT_ACL, &table_list,
@@ -2072,9 +2073,25 @@ mysql_execute_command(THD *thd)
DEBUG_SYNC(thd,"before_execute_sql_command");
#endif
+ /*
+ Close tables open by HANDLERs before executing DDL statement
+ which is going to affect those tables.
+
+ This should happen before temporary tables are pre-opened as
+ otherwise we will get errors about attempt to re-open tables
+ if table to be changed is open through HANDLER.
+
+ Note that even although this is done before any privilege
+ checks there is no security problem here as closing open
+ HANDLER doesn't require any privileges anyway.
+ */
if (sql_command_flags[lex->sql_command] & CF_HA_CLOSE)
mysql_ha_rm_tables(thd, all_tables);
+ /*
+ Pre-open temporary tables to simplify privilege checking
+ for statements which need this.
+ */
if (sql_command_flags[lex->sql_command] & CF_PREOPEN_TMP_TABLES)
{
if (open_temporary_table_list(thd, all_tables))
@@ -2382,6 +2399,10 @@ case SQLCOM_PREPARE:
goto end_with_restore_list;
}
+ /*
+ Pre-open temporary tables from UNION clause to simplify privilege
+ checking for them.
+ */
if (lex->create_info.merge_list.elements)
{
if (open_temporary_table_list(
@@ -3218,12 +3239,10 @@ end_with_restore_list:
Here we have to pre-open temporary tables for LOCK TABLES.
CF_PREOPEN_TMP_TABLES is not set for this SQL statement simply
- because LOCK TABLES calls close_thread_tables() firstly (it's called
- from release_transactional_locks() above).
-
- close_thread_tables() closes all open tables, so even if
- CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened in a
- usual way, they would be closed by close_thread_tables().
+ because LOCK TABLES calls close_thread_tables() as a first thing
+ (it's called from unlock_locked_tables() above). So even if
+ CF_PREOPEN_TMP_TABLES was set and the tables would be pre-opened
+ in a usual way, they would have been closed.
*/
if (open_temporary_table_list(thd, all_tables))
@@ -4630,6 +4649,7 @@ bool check_single_table_access(THD *thd,
&all_tables->grant.m_internal,
0, no_errors))
goto deny;
+
/* Show only 1 table for check_grant */
if (!(all_tables->belong_to_view &&
(thd->lex->sql_command == SQLCOM_SHOW_FIELDS)) &&
@@ -4953,6 +4973,12 @@ static bool check_show_access(THD *thd,
DBUG_ASSERT(dst_table);
+ /*
+ TODO/FIXME: In the upcoming patch we somehow should handle
+ situation when table in question is a temporary
+ table.
+ */
+
if (check_access(thd, SELECT_ACL, dst_table->db,
&dst_table->grant.privilege,
&dst_table->grant.m_internal,
=== modified file 'sql/sql_partition_admin.cc'
--- a/sql/sql_partition_admin.cc 2010-11-16 00:55:42 +0000
+++ b/sql/sql_partition_admin.cc 2010-12-22 15:23:28 +0000
@@ -20,7 +20,6 @@
#include "sql_cmd.h" // Sql_cmd
#include "sql_alter.h" // Sql_cmd_alter_table
#include "sql_partition.h" // struct partition_info, etc.
-#include "sql_handler.h" // mysql_ha_rm_tables
#include "sql_base.h" // open_and_lock_tables, etc
#include "debug_sync.h" // DEBUG_SYNC
#include "sql_truncate.h" // mysql_truncate_table,
@@ -492,9 +491,6 @@ bool Sql_cmd_alter_table_exchange_partit
partition_name= alter_info->partition_names.head();
- /* Clear open tables from the threads table handler cache */
- mysql_ha_rm_tables(thd, table_list);
-
/* Don't allow to exchange with log table */
swap_table_list= table_list->next_local;
if (check_if_log_table(swap_table_list->db_length, swap_table_list->db,
=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc 2010-12-14 09:15:37 +0000
+++ b/sql/sql_show.cc 2010-12-22 15:23:28 +0000
@@ -3635,8 +3635,6 @@ int get_all_tables(THD *thd, TABLE_LIST
show_table_list->i_s_requested_object=
schema_table->i_s_requested_object;
DEBUG_SYNC(thd, "before_open_in_get_all_tables");
- if (open_temporary_table_list(thd, show_table_list))
- goto err;
res= open_normal_and_derived_tables(thd, show_table_list,
(MYSQL_OPEN_IGNORE_FLUSH |
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc 2010-12-14 09:15:37 +0000
+++ b/sql/sql_table.cc 2010-12-22 15:23:28 +0000
@@ -4800,6 +4800,7 @@ bool mysql_create_like_table(THD* thd, T
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
@@ -4808,14 +4809,20 @@ bool mysql_create_like_table(THD* thd, T
*/
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,
@@ -4825,13 +4832,16 @@ bool mysql_create_like_table(THD* thd, T
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
@@ -4854,9 +4864,9 @@ err:
static int
mysql_discard_or_import_tablespace(THD *thd,
TABLE_LIST *table_list,
- enum tablespace_op_type tablespace_op)
+ Alter_info *alter_info)
{
- TABLE *table;
+ Alter_table_prelocking_strategy alter_prelocking_strategy(alter_info);
my_bool discard;
int error;
DBUG_ENTER("mysql_discard_or_import_tablespace");
@@ -4868,21 +4878,30 @@ mysql_discard_or_import_tablespace(THD *
thd_proc_info(thd, "discard_or_import_tablespace");
- discard= test(tablespace_op == DISCARD_TABLESPACE);
+ discard= test(alter_info->tablespace_op == DISCARD_TABLESPACE);
/*
We set this flag so that ha_innobase::open and ::external_lock() do
not complain when we lock the table
*/
thd->tablespace_op= TRUE;
+ /*
+ Adjust values of table-level and metadata which was set in parser
+ for the case general ALTER TABLE.
+ */
table_list->mdl_request.set_type(MDL_SHARED_WRITE);
- if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
+ table_list->lock_type= TL_WRITE;
+ /* Do not open views. */
+ table_list->required_type= FRMTYPE_TABLE;
+
+ if (open_and_lock_tables(thd, table_list, FALSE, 0,
+ &alter_prelocking_strategy))
{
thd->tablespace_op=FALSE;
DBUG_RETURN(-1);
}
- error= table->file->ha_discard_or_import_tablespace(discard);
+ error= table_list->table->file->ha_discard_or_import_tablespace(discard);
thd_proc_info(thd, "end");
@@ -4913,7 +4932,7 @@ err:
DBUG_RETURN(0);
}
- table->file->print_error(error, MYF(0));
+ table_list->table->file->print_error(error, MYF(0));
DBUG_RETURN(-1);
}
@@ -5939,7 +5958,7 @@ bool mysql_alter_table(THD *thd,char *ne
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
/* Conditionally writes to binlog. */
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
- alter_info->tablespace_op));
+ alter_info));
/*
Code below can handle only base tables so ensure that we won't open a view.
@@ -7328,7 +7347,7 @@ bool mysql_checksum_table(THD *thd, TABL
/* Allow to open real tables only. */
table->required_type= FRMTYPE_TABLE;
- if (open_temporary_table(thd, table) ||
+ if (open_temporary_table_list(thd, table) ||
open_and_lock_tables(thd, table, FALSE, 0))
{
t= NULL;
=== modified file 'sql/sql_truncate.cc'
--- a/sql/sql_truncate.cc 2010-11-29 14:13:07 +0000
+++ b/sql/sql_truncate.cc 2010-12-22 15:23:28 +0000
@@ -18,7 +18,6 @@
#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_* flags
#include "sql_acl.h" // DROP_ACL
No bundle (reason: useless for push emails).
| Thread |
|---|
| • bzr push into mysql-trunk-bugfixing branch (Dmitry.Lenev:3401 to 3402)Bug#27480 | Dmitry Lenev | 22 Dec |