diff options
author | Sergey Vojtovich <svoj@mariadb.org> | 2013-09-20 13:12:53 +0400 |
---|---|---|
committer | Sergey Vojtovich <svoj@mariadb.org> | 2013-09-20 13:12:53 +0400 |
commit | 815c607dcfa4a43be73e42c325956eda16e24c91 (patch) | |
tree | bb36fd8012e2e29163d1b14bac9c05f18b7a01d7 | |
parent | 8b5938a1276ffc4fe7f63a21c08a342f301cca30 (diff) | |
download | mariadb-git-815c607dcfa4a43be73e42c325956eda16e24c91.tar.gz |
MDEV-4879 - Merge test cases for new CREATE TEMPORARY TABLE privilege model
- merged test cases for MySQL bug#27480
- fixed that LOCK TABLES was unable to open temporary table
(covered by grant2 test, merged appropriate code from 5.6)
- commented lines that cause server crash in merge test, reported
MDEV-5042 (not relevant to bug#27480)
-rw-r--r-- | mysql-test/r/grant2.result | 373 | ||||
-rw-r--r-- | mysql-test/r/grant4.result | 57 | ||||
-rw-r--r-- | mysql-test/r/merge.result | 87 | ||||
-rw-r--r-- | mysql-test/r/ps_ddl.result | 40 | ||||
-rw-r--r-- | mysql-test/r/temp_table.result | 48 | ||||
-rw-r--r-- | mysql-test/suite/handler/myisam.result | 86 | ||||
-rw-r--r-- | mysql-test/suite/handler/myisam.test | 89 | ||||
-rw-r--r-- | mysql-test/suite/rpl/r/rpl_create_if_not_exists.result | 14 | ||||
-rw-r--r-- | mysql-test/suite/rpl/t/rpl_create_if_not_exists.test | 17 | ||||
-rw-r--r-- | mysql-test/t/grant2.test | 362 | ||||
-rw-r--r-- | mysql-test/t/grant4.test | 59 | ||||
-rw-r--r-- | mysql-test/t/merge.test | 80 | ||||
-rw-r--r-- | mysql-test/t/ps_ddl.test | 43 | ||||
-rw-r--r-- | mysql-test/t/temp_table.test | 43 | ||||
-rw-r--r-- | sql/sql_parse.cc | 33 |
15 files changed, 1429 insertions, 2 deletions
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result index 196f6601d48..9d92abbda07 100644 --- a/mysql-test/r/grant2.result +++ b/mysql-test/r/grant2.result @@ -472,3 +472,376 @@ root localhost Y FLUSH PRIVILEGES; USE test; End of 5.1 tests + +# -- +# -- Bug#11746602: 27480 - Extend CREATE TEMPORARY TABLES privilege to +# -- allow temp table operations +# -- +# -- Bug#12771903: User with create temporary tables priv only has full +# -- access to a regular table +# -- + +############################################################################ +# Setup environment. +########################################################################### +DROP DATABASE IF EXISTS mysqltest_db1; +DROP DATABASE IF EXISTS mysqltest_db2; +CREATE DATABASE mysqltest_db1; +CREATE DATABASE mysqltest_db2; +# mysqltest_u1@localhost has CREATE_TMP_ACL, FILE_ACL and EXECUTE_ACL only +# (EXECUTE_ACL is needed to call p0, and FILE_ACL is needed for SELECT +# OUTFILE/LOAD DATA INFILE). +GRANT FILE ON *.* TO mysqltest_u1@localhost; +GRANT CREATE TEMPORARY TABLES, EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost; +# mysqltest_u2@localhost has all privileges but CREATE_TMP_ACL. +GRANT ALL PRIVILEGES ON mysqltest_db1.* TO mysqltest_u2@localhost; +REVOKE CREATE TEMPORARY TABLES ON mysqltest_db1.* FROM mysqltest_u2@localhost; +# mysqltest_u3@localhost has CREATE_TMP_ACL & EXECUTE_ACL. +# This user is required to check SUID-stored-routines. +GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost; +GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u3@localhost; +# mysqltest_u4@localhost has only EXECUTE_ACL. +# We need this user to check that once created temporary tables +# are accessible by anyone. +GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost; +# mysqltest_u5@localhost has CREATE_TMP_ACL and SELECT_ACL, UPDATE_ACL, +# DELETE_ACL on mysqltest_db1; and only CREATE_TMP_ACL on mysqltest_db2. +# By means of this user we check privileges required for merge tables. +GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u5@localhost; +GRANT CREATE TEMPORARY TABLES ON mysqltest_db2.* TO mysqltest_u5@localhost; +GRANT SELECT, UPDATE, DELETE ON mysqltest_db1.* TO mysqltest_u5@localhost; +# Create stored routine to test how privilege checking is done for its +# arguments. +CREATE PROCEDURE mysqltest_db1.p0(i INT) SELECT i; +# Create SUID-stored-routines. +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p1() +CREATE TEMPORARY TABLE t4(x INT); +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p2() +INSERT INTO t4 VALUES (1), (2), (3); +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p3() +SELECT * FROM t4 ORDER BY x; +# We need separate key cache to test CACHE INDEX and LOAD INDEX. +SET GLOBAL keycache1.key_buffer_size = 128 * 1024; +CREATE TABLE mysqltest_db2.t2_1(a INT); +########################################################################### +# Check that CREATE_TMP_ACL is enough to issue almost any supported +# SQL-statement against temporary tables (loosely follow order in +# sql_command enum). +########################################################################### + +# -- connect con1, mysqltest_u1@localhost, mysqltest_db1 +# +# Variants of CREATE TABLE. +# +CREATE TEMPORARY TABLE t1(a INT); +CREATE TEMPORARY TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a)); +CREATE TEMPORARY TABLE t4 SELECT * FROM t1; +# Check that we do *not* allow creation of MERGE table with underlying +# temporary table without additional privileges. +CREATE TEMPORARY TABLE t5(a INT) ENGINE = MyISAM; +CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (t5); +ERROR 42000: SELECT, UPDATE, DELETE command denied to user 'mysqltest_u1'@'localhost' for table 't5' +# Check that we allow creation of MERGE table with no underlying table +# without additional privileges. +CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (); +# +# SELECT. +# +INSERT INTO t1 VALUES (1), (2), (3); +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +# +# CREATE/DROP INDEX. +# +CREATE INDEX idx1 ON t3(b); +DROP INDEX idx1 ON t3; +# +# ALTER TABLE. +# +ALTER TABLE t4 ADD COLUMN b INT; +# Check that we allow altering of MERGE table with no underlying +# without additional privileges. +ALTER TABLE t6 UNION = (); +# Check that we do *not* allow altering of MERGE table with underlying +# temporary table without additional privileges. +ALTER TABLE t6 UNION = (t5); +ERROR 42000: SELECT, UPDATE, DELETE command denied to user 'mysqltest_u1'@'localhost' for table 't5' +# +# Simple INSERT and INSERT ... SELECT. +# +INSERT INTO t1 VALUES (4); +INSERT INTO t2 SELECT a FROM t1; +SELECT * FROM t1 ORDER BY a; +a +1 +2 +3 +4 +SELECT * FROM t2 ORDER BY a; +a +1 +2 +3 +4 +# +# UPDATE and multi-UPDATE. +# +UPDATE t1 SET a = a * 10; +UPDATE t1 SET a = 100 WHERE a = 10; +UPDATE t1, t2 SET t1.a = 200 WHERE t1.a = t2.a * 10 AND t1.a = 20; +SELECT * FROM t1 ORDER BY a; +a +30 +40 +100 +200 +# +# DELETE and multi-DELETE. +# +DELETE FROM t1 WHERE a = 100; +DELETE t1 FROM t1, t2 WHERE t1.a = t2.a * 100 AND t1.a = 200; +SELECT * FROM t1 ORDER BY a; +a +30 +40 +# +# TRUNCATE TABLE. +# +TRUNCATE TABLE t1; +SELECT * FROM t1 ORDER BY a; +a +# +# SHOW COLUMNS/DESCRIBE and SHOW KEYS. +# +SHOW COLUMNS FROM t1; +Field Type Null Key Default Extra +SHOW KEYS FROM t3; +Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment Index_comment +t3 0 PRIMARY 1 a A 0 NULL NULL BTREE +# +# SHOW CREATE TABLE. +# +SHOW CREATE TABLE t1; +Table Create Table +t1 CREATE TEMPORARY TABLE `t1` ( + `a` int(11) DEFAULT NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 +# +# LOAD DATA INFILE (also SELECT INTO OUTFILE). +# +INSERT INTO t1 VALUES (1), (2), (3); +SELECT a INTO OUTFILE 'MYSQLTEST_VARDIR/tmp/bug27480.txt' FROM t1 ; +LOAD DATA INFILE 'MYSQLTEST_VARDIR/tmp/bug27480.txt' INTO TABLE t1; +SELECT * FROM t1 ORDER BY a; +a +1 +1 +2 +2 +3 +3 +# +# SET. +# +SET @a := (SELECT COUNT(*) FROM t1); +SELECT @a; +@a +6 +# +# LOCK TABLES. +# +LOCK TABLES t1 READ; +UNLOCK TABLES; +# +# CHECK/REPAIR/ANALYZE/OPTIMIZE and CHECKSUM. +# +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 analyze status OK +CHECK TABLE t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 check status OK +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 optimize status Table is already up to date +REPAIR TABLE t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 repair status OK +# +# REPLACE and REPLACE ... SELECT. +# +INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333); +REPLACE INTO t3 VALUES (1, 1111), (4, 444), (0, 001); +REPLACE INTO t2 SELECT b FROM t3; +SELECT * FROM t2 ORDER BY a; +a +1 +1 +2 +3 +4 +222 +333 +444 +1111 +SELECT * FROM t3 ORDER BY a; +a b +0 1 +1 1111 +2 222 +3 333 +4 444 +# +# CACHE and LOAD INDEX. +# +CACHE INDEX t3 IN keycache1; +Table Op Msg_type Msg_text +mysqltest_db1.t3 assign_to_keycache status OK +LOAD INDEX INTO CACHE t3; +Table Op Msg_type Msg_text +mysqltest_db1.t3 preload_keys status OK +# +# RENAME (doesn't work for temporary tables, thus should fail). +# +RENAME TABLE t3 TO t3_1; +ERROR 42000: DROP, ALTER command denied to user 'mysqltest_u1'@'localhost' for table 't3' +# +# HANDLER OPEN/READ/CLOSE. +# +HANDLER t1 OPEN; +HANDLER t1 READ NEXT; +a +1 +HANDLER t1 CLOSE; +# +# DO. +# +DO (SELECT COUNT(*) FROM t1); +# +# CHECKSUM TABLE. +# +DELETE FROM t1; +CHECKSUM TABLE t1; +Table Checksum +mysqltest_db1.t1 0 +# +# CALL. +# +CALL p0((SELECT COUNT(*) FROM t1)); +i +0 +# +# PREPARE, EXECUTE and DEALLOCATE. +# +PREPARE stmt1 FROM 'SELECT * FROM t1 ORDER BY a'; +PREPARE stmt2 FROM 'SELECT * FROM t2 ORDER BY a'; +EXECUTE stmt1; +a +EXECUTE stmt2; +a +1 +1 +2 +3 +4 +222 +333 +444 +1111 +DEALLOCATE PREPARE stmt1; +DEALLOCATE PREPARE stmt2; +# +# DROP TABLE and DROP TEMPORARY TABLE. +# +DROP TABLE t1; +CREATE TEMPORARY TABLE t1(a INT); +DROP TEMPORARY TABLE t1; +########################################################################### +# - Check that even having all privileges but CREATE_TMP_ACL is not enough +# to create temporary tables. +# - Check that creation/working with temporary tables is possible via +# SUID-stored-routines. +# - Check that even outside of SUID context we can access temporary +# table once it is created. +########################################################################### + +# -- connect con2, mysqltest_u2@localhost, mysqltest_db1 +CREATE TEMPORARY TABLE t2(a INT); +ERROR 42000: Access denied for user 'mysqltest_u2'@'localhost' to database 'mysqltest_db1' +CALL p1(); +CALL p2(); +CALL p3(); +x +1 +2 +3 +# Check that once table is created it can be accessed even +# outside of such a SUID context. +INSERT INTO t4 VALUES (4); +UPDATE t4 SET x = 10 WHERE x = 1; +DELETE FROM t4 WHERE x < 3; +SELECT * FROM t4 ORDER BY x; +x +3 +4 +10 +DROP TEMPORARY TABLE t4; +########################################################################### +# - Check that once table is created it can be accessed from within any +# context, even by user without any privileges on tables. +########################################################################### + +# -- connect con3, mysqltest_u4@localhost, mysqltest_db1 +CALL p1(); +INSERT INTO t4 VALUES (4); +UPDATE t4 SET x = 10 WHERE x = 1; +DELETE FROM t4 WHERE x < 3; +SELECT * FROM t4 ORDER BY x; +x +4 +DROP TEMPORARY TABLE t4; +########################################################################### +# Check special case for MERGE-tables: +# - CREATE_TMP_ACL is required to create a temporary merge table; +# - SELECT_ACL, UPDATE_ACL and DELETE_ACL are required to include +# a temporary table into the underlying-table-list. +########################################################################### + +# -- connect con4, mysqltest_u5@localhost, mysqltest_db1 +CREATE TEMPORARY TABLE t7(a INT); +CREATE TEMPORARY TABLE t8(a INT); +CREATE TEMPORARY TABLE t9(a INT); +CREATE TEMPORARY TABLE t10(a INT) ENGINE = MERGE UNION = (t7, t8); +ALTER TABLE t10 UNION = (t9); +ALTER TABLE t10 UNION = (mysqltest_db2.t2_1); +ERROR 42000: SELECT, UPDATE, DELETE command denied to user 'mysqltest_u5'@'localhost' for table 't2_1' +CREATE TEMPORARY TABLE mysqltest_db2.t2_2(a INT) ENGINE = MERGE UNION = (t7, t8); +ALTER TABLE mysqltest_db2.t2_2 UNION = (t9); +ALTER TABLE mysqltest_db2.t2_2 UNION = (); +DROP TEMPORARY TABLE mysqltest_db2.t2_2; +DROP TEMPORARY TABLE t10; +DROP TEMPORARY TABLE t7; +DROP TEMPORARY TABLE t8; +DROP TEMPORARY TABLE t9; +########################################################################### +# That's all. Cleanup. +########################################################################### + +# -- connection: default +# -- disconnect con1 +# All remaining temporary tables are automatically dropped. +# -- disconnect con2 +# -- disconnect con3 +# -- disconnect con4 +SET GLOBAL keycache1.key_buffer_size = 0; +DROP DATABASE mysqltest_db1; +DROP DATABASE mysqltest_db2; +DROP USER mysqltest_u1@localhost; +DROP USER mysqltest_u2@localhost; +DROP USER mysqltest_u3@localhost; +DROP USER mysqltest_u4@localhost; +DROP USER mysqltest_u5@localhost; diff --git a/mysql-test/r/grant4.result b/mysql-test/r/grant4.result index 65ab92c1afd..60617acbd1f 100644 --- a/mysql-test/r/grant4.result +++ b/mysql-test/r/grant4.result @@ -121,3 +121,60 @@ View Create View character_set_client collation_connection v3 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v3` AS select `t_select_priv`.`a` AS `a`,`t_select_priv`.`b` AS `b` from `t_select_priv` latin1 latin1_swedish_ci drop database mysqltest_db1; drop user mysqltest_u1@localhost; +# +# 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 for statements like CHECK/REPAIR and OPTIMIZE TABLE +# privileges for all tables involved are checked before processing +# any tables. Doing otherwise, i.e. checking privileges for table +# right before processing it might result in lost results for tables +# which were processed by the time when table for which privileges +# are insufficient are discovered. +# +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*mysqltest_u1 Checking table"); +drop database if exists mysqltest_db1; +create database mysqltest_db1; +# Create tables which we are going to CHECK/REPAIR. +create table mysqltest_db1.t1 (a int, key(a)) engine=myisam; +create table mysqltest_db1.t2 (b int); +insert into mysqltest_db1.t1 values (1), (2); +insert into mysqltest_db1.t2 values (1); +# Create user which will try to do this. +create user mysqltest_u1@localhost; +grant insert, select on mysqltest_db1.t1 to mysqltest_u1@localhost; +# Corrupt t1 by replacing t1.MYI with a corrupt + unclosed one created +# by doing: 'create table t1 (a int key(a))' +# head -c1024 t1.MYI > corrupt_t1.MYI +flush table mysqltest_db1.t1; +# Switching to connection 'con1'. +check table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 check warning 1 client is using or hasn't closed the table properly +mysqltest_db1.t1 check error Size of indexfile is: 1024 Should be: 2048 +mysqltest_db1.t1 check warning Size of datafile is: 14 Should be: 7 +mysqltest_db1.t1 check error Corrupt +# The below statement should fail before repairing t1. +# Otherwise info about such repair will be missing from its result-set. +repair table mysqltest_db1.t1, mysqltest_db1.t2; +ERROR 42000: SELECT, INSERT command denied to user 'mysqltest_u1'@'localhost' for table 't2' +# The same is true for CHECK TABLE statement. +check table mysqltest_db1.t1, mysqltest_db1.t2; +ERROR 42000: SELECT command denied to user 'mysqltest_u1'@'localhost' for table 't2' +check table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 check warning Table is marked as crashed +mysqltest_db1.t1 check warning 1 client is using or hasn't closed the table properly +mysqltest_db1.t1 check error Size of indexfile is: 1024 Should be: 2048 +mysqltest_db1.t1 check warning Size of datafile is: 14 Should be: 7 +mysqltest_db1.t1 check error Corrupt +repair table mysqltest_db1.t1; +Table Op Msg_type Msg_text +mysqltest_db1.t1 repair warning Number of rows changed from 1 to 2 +mysqltest_db1.t1 repair status OK +# Clean-up. +# Switching to connection 'default'. +drop database mysqltest_db1; +drop user mysqltest_u1@localhost; diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result index ff75f653368..7cb9e5bb423 100644 --- a/mysql-test/r/merge.result +++ b/mysql-test/r/merge.result @@ -3826,3 +3826,90 @@ test.m1 repair error Corrupt drop tables m1, t1, t4; drop view t3; End of 5.5 tests +# +# 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 prelocking works correctly for various variants of +# merge tables. +drop table if exists t1, t2, m1; +drop function if exists f1; +create table t1 (j int); +insert into t1 values (1); +create function f1() returns int return (select count(*) from m1); +create temporary table t2 (a int) engine=myisam; +insert into t2 values (1); +create temporary table m1 (a int) engine=merge union=(t2); +select f1() from t1; +f1() +1 +drop tables t2, m1; +create table t2 (a int) engine=myisam; +insert into t2 values (1); +create table m1 (a int) engine=merge union=(t2); +select f1() from t1; +f1() +1 +drop table m1; +create temporary table m1 (a int) engine=merge union=(t2); +select f1() from t1; +f1() +1 +drop tables t1, t2, m1; +drop function f1; +# +# Check that REPAIR/CHECK and CHECKSUM statements work correctly +# for various variants of merge tables. +create table t1 (a int) engine=myisam; +insert into t1 values (1); +create table m1 (a int) engine=merge union=(t1); +check table m1; +Table Op Msg_type Msg_text +test.m1 check status OK +repair table m1; +Table Op Msg_type Msg_text +test.m1 repair note The storage engine for the table doesn't support repair +checksum table m1; +Table Checksum +test.m1 3459908756 +drop tables t1, m1; +create temporary table t1 (a int) engine=myisam; +insert into t1 values (1); +create temporary table m1 (a int) engine=merge union=(t1); +check table m1; +Table Op Msg_type Msg_text +test.m1 check status OK +repair table m1; +Table Op Msg_type Msg_text +test.m1 repair note The storage engine for the table doesn't support repair +checksum table m1; +Table Checksum +test.m1 3459908756 +drop tables t1, m1; +create table t1 (a int) engine=myisam; +insert into t1 values (1); +create temporary table m1 (a int) engine=merge union=(t1); +check table m1; +Table Op Msg_type Msg_text +test.m1 check status OK +repair table m1; +Table Op Msg_type Msg_text +test.m1 repair note The storage engine for the table doesn't support repair +checksum table m1; +Table Checksum +test.m1 3459908756 +drop tables t1, m1; +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS m1; +DROP TRIGGER IF EXISTS trg1; +DROP TABLE IF EXISTS q1; +DROP TABLE IF EXISTS q2; +CREATE TABLE t1(a INT); +CREATE TABLE m1(a INT) ENGINE = MERGE UNION (q1, q2); +CREATE TRIGGER trg1 BEFORE DELETE ON t1 +FOR EACH ROW +INSERT INTO m1 VALUES (1); +DROP TRIGGER trg1; +DROP TABLE t1; +DROP TABLE m1; diff --git a/mysql-test/r/ps_ddl.result b/mysql-test/r/ps_ddl.result index 7a8b38bec75..8284e974574 100644 --- a/mysql-test/r/ps_ddl.result +++ b/mysql-test/r/ps_ddl.result @@ -2502,3 +2502,43 @@ drop procedure if exists p_verify_reprepare_count; drop procedure if exists p1; drop function if exists f1; drop view if exists v1, v2; +# +# Additional coverage for refactoring which was made as part of work +# on bug '27480: Extend CREATE TEMPORARY TABLES privilege to allow +# temp table operations'. +# +# Check that we don't try to pre-open temporary tables for the elements +# from prelocking list, as this can lead to unwarranted ER_CANT_REOPEN +# errors. +DROP TABLE IF EXISTS t1, tm; +CREATE TABLE t1 (a INT); +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW +SET @a:= (SELECT COUNT(*) FROM t1); +# Prelocking list for the below statement should +# contain t1 twice - once for the INSERT and once +# SELECT from the trigger. +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES (1)'; +EXECUTE stmt1; +# Create temporary table which will shadow t1. +CREATE TEMPORARY TABLE t1 (b int); +# The below execution of statement should not fail with ER_CANT_REOPEN +# error. Instead stmt1 should be auto-matically reprepared and succeed. +EXECUTE stmt1; +DEALLOCATE PREPARE stmt1; +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +# +# Also check that we properly reset table list elements from UNION +# clause of CREATE TABLE and ALTER TABLE statements. +# +CREATE TEMPORARY TABLE t1 (i INT); +PREPARE stmt2 FROM 'CREATE TEMPORARY TABLE tm (i INT) ENGINE=MERGE UNION=(t1)'; +EXECUTE stmt2; +DROP TEMPORARY TABLE tm; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt2; +PREPARE stmt3 FROM 'ALTER TABLE tm UNION=(t1)'; +EXECUTE stmt3; +EXECUTE stmt3; +DEALLOCATE PREPARE stmt3; +DROP TEMPORARY TABLES tm, t1; diff --git a/mysql-test/r/temp_table.result b/mysql-test/r/temp_table.result index a5182a03e63..0a1701be0d7 100644 --- a/mysql-test/r/temp_table.result +++ b/mysql-test/r/temp_table.result @@ -243,3 +243,51 @@ CREATE TEMPORARY TABLE bug48067.t1 (c1 int); 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); +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); +ANALYZE TABLE t1, t2, t3; +Table Op Msg_type Msg_text +test.t1 analyze status OK +test.t2 analyze status OK +test.t3 analyze status OK +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); +CHECK TABLE t1, t2, t3; +Table Op Msg_type Msg_text +test.t1 check status OK +test.t2 check status OK +test.t3 check status OK +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); +CHECKSUM TABLE t1, t2, t3; +Table Checksum +test.t1 xxx +test.t2 xxx +test.t3 xxx +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); +OPTIMIZE TABLE t1, t2, t3; +Table Op Msg_type Msg_text +test.t1 optimize status OK +test.t2 optimize status OK +test.t3 optimize status OK +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); +REPAIR TABLE t1, t2, t3; +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; diff --git a/mysql-test/suite/handler/myisam.result b/mysql-test/suite/handler/myisam.result index fcf6d4c133c..0942a91acbc 100644 --- a/mysql-test/suite/handler/myisam.result +++ b/mysql-test/suite/handler/myisam.result @@ -1803,4 +1803,90 @@ a b 4 40 HANDLER t1 CLOSE; 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 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 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 +# -- REPAIR TABLE +HANDLER t1 OPEN; +REPAIR TABLE t1; +Table Op Msg_type Msg_text +test.t1 repair status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +# -- ANALYZE TABLE +HANDLER t1 OPEN; +ANALYZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +# -- OPTIMIZE TABLE +HANDLER t1 OPEN; +OPTIMIZE TABLE t1; +Table Op Msg_type Msg_text +test.t1 optimize status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +# -- CHECK TABLE +HANDLER t1 OPEN; +CHECK TABLE t1; +Table Op Msg_type Msg_text +test.t1 check status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +# -- ALTER TABLE +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; +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +CREATE TEMPORARY TABLE t1(a INT, b INT, INDEX i(a)); +set global keycache1.key_cache_block_size=2048; +set global keycache1.key_buffer_size=1*1024*1024; +set global keycache1.key_buffer_size=1024*1024; +# -- CACHE INDEX +HANDLER t1 OPEN; +CACHE INDEX t1 IN keycache1; +Table Op Msg_type Msg_text +test.t1 assign_to_keycache status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER +# -- LOAD INDEX +HANDLER t1 OPEN; +LOAD INDEX INTO CACHE t1; +Table Op Msg_type Msg_text +test.t1 preload_keys status OK +HANDLER t1 READ FIRST; +ERROR 42S02: Unknown table 't1' in HANDLER End of 5.1 tests diff --git a/mysql-test/suite/handler/myisam.test b/mysql-test/suite/handler/myisam.test index c6acf1e822c..a2d87630aef 100644 --- a/mysql-test/suite/handler/myisam.test +++ b/mysql-test/suite/handler/myisam.test @@ -79,4 +79,93 @@ HANDLER t1 CLOSE; 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 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 TEMPORARY TABLE IF NOT EXISTS t1 SELECT 1 AS f1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- REPAIR TABLE +HANDLER t1 OPEN; +REPAIR TABLE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- ANALYZE TABLE +HANDLER t1 OPEN; +ANALYZE TABLE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- OPTIMIZE TABLE +HANDLER t1 OPEN; +OPTIMIZE TABLE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- CHECK TABLE +HANDLER t1 OPEN; +CHECK TABLE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- ALTER TABLE +HANDLER t1 OPEN; +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; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +CREATE TEMPORARY TABLE t1(a INT, b INT, INDEX i(a)); + +set global keycache1.key_cache_block_size=2048; +set global keycache1.key_buffer_size=1*1024*1024; +set global keycache1.key_buffer_size=1024*1024; + +--echo # -- CACHE INDEX +HANDLER t1 OPEN; +CACHE INDEX t1 IN keycache1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + +--echo # -- LOAD INDEX +HANDLER t1 OPEN; +LOAD INDEX INTO CACHE t1; +--error ER_UNKNOWN_TABLE +HANDLER t1 READ FIRST; + + --echo End of 5.1 tests diff --git a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result index c6f58b66758..14f81fcb9b1 100644 --- a/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result +++ b/mysql-test/suite/rpl/r/rpl_create_if_not_exists.result @@ -114,4 +114,18 @@ Note 1050 Table 'v1' already exists include/show_binlog_events.inc 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; include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test index c9658105847..72f1201c93c 100644 --- a/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test +++ b/mysql-test/suite/rpl/t/rpl_create_if_not_exists.test @@ -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/rpl_end.inc diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test index 6c2ba0dd6fc..cde3d12b0ce 100644 --- a/mysql-test/t/grant2.test +++ b/mysql-test/t/grant2.test @@ -667,5 +667,367 @@ USE test; --echo End of 5.1 tests + +--echo +--echo # -- +--echo # -- Bug#11746602: 27480 - Extend CREATE TEMPORARY TABLES privilege to +--echo # -- allow temp table operations +--echo # -- +--echo # -- Bug#12771903: User with create temporary tables priv only has full +--echo # -- access to a regular table +--echo # -- +--echo + +--echo ############################################################################ +--echo # Setup environment. +--echo ########################################################################### + +--disable_warnings +DROP DATABASE IF EXISTS mysqltest_db1; +DROP DATABASE IF EXISTS mysqltest_db2; +--enable_warnings + +CREATE DATABASE mysqltest_db1; +CREATE DATABASE mysqltest_db2; + +--echo # mysqltest_u1@localhost has CREATE_TMP_ACL, FILE_ACL and EXECUTE_ACL only +--echo # (EXECUTE_ACL is needed to call p0, and FILE_ACL is needed for SELECT +--echo # OUTFILE/LOAD DATA INFILE). +GRANT FILE ON *.* TO mysqltest_u1@localhost; +GRANT CREATE TEMPORARY TABLES, EXECUTE ON mysqltest_db1.* TO mysqltest_u1@localhost; + +--echo # mysqltest_u2@localhost has all privileges but CREATE_TMP_ACL. +GRANT ALL PRIVILEGES ON mysqltest_db1.* TO mysqltest_u2@localhost; +REVOKE CREATE TEMPORARY TABLES ON mysqltest_db1.* FROM mysqltest_u2@localhost; + +--echo # mysqltest_u3@localhost has CREATE_TMP_ACL & EXECUTE_ACL. +--echo # This user is required to check SUID-stored-routines. +GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u3@localhost; +GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u3@localhost; + +--echo # mysqltest_u4@localhost has only EXECUTE_ACL. +--echo # We need this user to check that once created temporary tables +--echo # are accessible by anyone. +GRANT EXECUTE ON mysqltest_db1.* TO mysqltest_u4@localhost; + +--echo # mysqltest_u5@localhost has CREATE_TMP_ACL and SELECT_ACL, UPDATE_ACL, +--echo # DELETE_ACL on mysqltest_db1; and only CREATE_TMP_ACL on mysqltest_db2. +--echo # By means of this user we check privileges required for merge tables. +GRANT CREATE TEMPORARY TABLES ON mysqltest_db1.* TO mysqltest_u5@localhost; +GRANT CREATE TEMPORARY TABLES ON mysqltest_db2.* TO mysqltest_u5@localhost; +GRANT SELECT, UPDATE, DELETE ON mysqltest_db1.* TO mysqltest_u5@localhost; + +--echo # Create stored routine to test how privilege checking is done for its +--echo # arguments. +CREATE PROCEDURE mysqltest_db1.p0(i INT) SELECT i; + +--echo # Create SUID-stored-routines. +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p1() + CREATE TEMPORARY TABLE t4(x INT); + +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p2() + INSERT INTO t4 VALUES (1), (2), (3); + +CREATE DEFINER = mysqltest_u3@localhost PROCEDURE mysqltest_db1.p3() + SELECT * FROM t4 ORDER BY x; + +--echo # We need separate key cache to test CACHE INDEX and LOAD INDEX. +SET GLOBAL keycache1.key_buffer_size = 128 * 1024; + +CREATE TABLE mysqltest_db2.t2_1(a INT); + +--echo ########################################################################### +--echo # Check that CREATE_TMP_ACL is enough to issue almost any supported +--echo # SQL-statement against temporary tables (loosely follow order in +--echo # sql_command enum). +--echo ########################################################################### + +--echo +--echo # -- connect con1, mysqltest_u1@localhost, mysqltest_db1 +--connect (con1,localhost,mysqltest_u1,,mysqltest_db1) + +--echo # +--echo # Variants of CREATE TABLE. +--echo # +CREATE TEMPORARY TABLE t1(a INT); +CREATE TEMPORARY TABLE t2 LIKE t1; +CREATE TEMPORARY TABLE t3(a INT, b INT, PRIMARY KEY (a)); +CREATE TEMPORARY TABLE t4 SELECT * FROM t1; +--echo # Check that we do *not* allow creation of MERGE table with underlying +--echo # temporary table without additional privileges. +CREATE TEMPORARY TABLE t5(a INT) ENGINE = MyISAM; +--error ER_TABLEACCESS_DENIED_ERROR +CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (t5); +--echo # Check that we allow creation of MERGE table with no underlying table +--echo # without additional privileges. +CREATE TEMPORARY TABLE t6(a INT) ENGINE = MERGE UNION = (); + +--echo # +--echo # SELECT. +--echo # +INSERT INTO t1 VALUES (1), (2), (3); +SELECT * FROM t1 ORDER BY a; + +--echo # +--echo # CREATE/DROP INDEX. +--echo # +CREATE INDEX idx1 ON t3(b); +DROP INDEX idx1 ON t3; + +--echo # +--echo # ALTER TABLE. +--echo # +ALTER TABLE t4 ADD COLUMN b INT; +--echo # Check that we allow altering of MERGE table with no underlying +--echo # without additional privileges. +ALTER TABLE t6 UNION = (); +--echo # Check that we do *not* allow altering of MERGE table with underlying +--echo # temporary table without additional privileges. +--error ER_TABLEACCESS_DENIED_ERROR +ALTER TABLE t6 UNION = (t5); + +--echo # +--echo # Simple INSERT and INSERT ... SELECT. +--echo # +INSERT INTO t1 VALUES (4); +INSERT INTO t2 SELECT a FROM t1; +SELECT * FROM t1 ORDER BY a; +SELECT * FROM t2 ORDER BY a; + +--echo # +--echo # UPDATE and multi-UPDATE. +--echo # +UPDATE t1 SET a = a * 10; +UPDATE t1 SET a = 100 WHERE a = 10; +UPDATE t1, t2 SET t1.a = 200 WHERE t1.a = t2.a * 10 AND t1.a = 20; +SELECT * FROM t1 ORDER BY a; + +--echo # +--echo # DELETE and multi-DELETE. +--echo # +DELETE FROM t1 WHERE a = 100; +DELETE t1 FROM t1, t2 WHERE t1.a = t2.a * 100 AND t1.a = 200; +SELECT * FROM t1 ORDER BY a; + +--echo # +--echo # TRUNCATE TABLE. +--echo # +TRUNCATE TABLE t1; +SELECT * FROM t1 ORDER BY a; + +--echo # +--echo # SHOW COLUMNS/DESCRIBE and SHOW KEYS. +--echo # +SHOW COLUMNS FROM t1; +SHOW KEYS FROM t3; + +--echo # +--echo # SHOW CREATE TABLE. +--echo # +SHOW CREATE TABLE t1; + +--echo # +--echo # LOAD DATA INFILE (also SELECT INTO OUTFILE). +--echo # +INSERT INTO t1 VALUES (1), (2), (3); +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval SELECT a INTO OUTFILE '$MYSQLTEST_VARDIR/tmp/bug27480.txt' FROM t1 +--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR +--eval LOAD DATA INFILE '$MYSQLTEST_VARDIR/tmp/bug27480.txt' INTO TABLE t1 +--remove_file $MYSQLTEST_VARDIR/tmp/bug27480.txt +SELECT * FROM t1 ORDER BY a; + +--echo # +--echo # SET. +--echo # +SET @a := (SELECT COUNT(*) FROM t1); +SELECT @a; + +--echo # +--echo # LOCK TABLES. +--echo # +LOCK TABLES t1 READ; +UNLOCK TABLES; + +--echo # +--echo # CHECK/REPAIR/ANALYZE/OPTIMIZE and CHECKSUM. +--echo # +ANALYZE TABLE t1; +CHECK TABLE t1; +OPTIMIZE TABLE t1; +REPAIR TABLE t1; + +--echo # +--echo # REPLACE and REPLACE ... SELECT. +--echo # +INSERT INTO t3 VALUES (1, 111), (2, 222), (3, 333); +REPLACE INTO t3 VALUES (1, 1111), (4, 444), (0, 001); +REPLACE INTO t2 SELECT b FROM t3; +SELECT * FROM t2 ORDER BY a; +SELECT * FROM t3 ORDER BY a; + +--echo # +--echo # CACHE and LOAD INDEX. +--echo # +CACHE INDEX t3 IN keycache1; +LOAD INDEX INTO CACHE t3; + +--echo # +--echo # RENAME (doesn't work for temporary tables, thus should fail). +--echo # +--error ER_TABLEACCESS_DENIED_ERROR +RENAME TABLE t3 TO t3_1; + +--echo # +--echo # HANDLER OPEN/READ/CLOSE. +--echo # +HANDLER t1 OPEN; +HANDLER t1 READ NEXT; +HANDLER t1 CLOSE; + +--echo # +--echo # DO. +--echo # +DO (SELECT COUNT(*) FROM t1); + +--echo # +--echo # CHECKSUM TABLE. +--echo # +DELETE FROM t1; +CHECKSUM TABLE t1; + +--echo # +--echo # CALL. +--echo # +CALL p0((SELECT COUNT(*) FROM t1)); + +--echo # +--echo # PREPARE, EXECUTE and DEALLOCATE. +--echo # +PREPARE stmt1 FROM 'SELECT * FROM t1 ORDER BY a'; +PREPARE stmt2 FROM 'SELECT * FROM t2 ORDER BY a'; +EXECUTE stmt1; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt1; +DEALLOCATE PREPARE stmt2; + +--echo # +--echo # DROP TABLE and DROP TEMPORARY TABLE. +--echo # +DROP TABLE t1; + +CREATE TEMPORARY TABLE t1(a INT); +DROP TEMPORARY TABLE t1; + + +--echo ########################################################################### +--echo # - Check that even having all privileges but CREATE_TMP_ACL is not enough +--echo # to create temporary tables. +--echo # - Check that creation/working with temporary tables is possible via +--echo # SUID-stored-routines. +--echo # - Check that even outside of SUID context we can access temporary +--echo # table once it is created. +--echo ########################################################################### + +--echo +--echo # -- connect con2, mysqltest_u2@localhost, mysqltest_db1 +--connect (con2,localhost,mysqltest_u2,,mysqltest_db1) + +--error ER_DBACCESS_DENIED_ERROR +CREATE TEMPORARY TABLE t2(a INT); + +CALL p1(); + +CALL p2(); + +CALL p3(); + +--echo # Check that once table is created it can be accessed even +--echo # outside of such a SUID context. +INSERT INTO t4 VALUES (4); +UPDATE t4 SET x = 10 WHERE x = 1; +DELETE FROM t4 WHERE x < 3; +SELECT * FROM t4 ORDER BY x; +DROP TEMPORARY TABLE t4; + +--echo ########################################################################### +--echo # - Check that once table is created it can be accessed from within any +--echo # context, even by user without any privileges on tables. +--echo ########################################################################### + +--echo +--echo # -- connect con3, mysqltest_u4@localhost, mysqltest_db1 +--connect (con3,localhost,mysqltest_u4,,mysqltest_db1) + +CALL p1(); +INSERT INTO t4 VALUES (4); +UPDATE t4 SET x = 10 WHERE x = 1; +DELETE FROM t4 WHERE x < 3; +SELECT * FROM t4 ORDER BY x; +DROP TEMPORARY TABLE t4; + +--echo ########################################################################### +--echo # Check special case for MERGE-tables: +--echo # - CREATE_TMP_ACL is required to create a temporary merge table; +--echo # - SELECT_ACL, UPDATE_ACL and DELETE_ACL are required to include +--echo # a temporary table into the underlying-table-list. +--echo ########################################################################### + +--echo +--echo # -- connect con4, mysqltest_u5@localhost, mysqltest_db1 +--connect (con4,localhost,mysqltest_u5,,mysqltest_db1) + +CREATE TEMPORARY TABLE t7(a INT); +CREATE TEMPORARY TABLE t8(a INT); +CREATE TEMPORARY TABLE t9(a INT); +CREATE TEMPORARY TABLE t10(a INT) ENGINE = MERGE UNION = (t7, t8); + +ALTER TABLE t10 UNION = (t9); +--error ER_TABLEACCESS_DENIED_ERROR +ALTER TABLE t10 UNION = (mysqltest_db2.t2_1); + +CREATE TEMPORARY TABLE mysqltest_db2.t2_2(a INT) ENGINE = MERGE UNION = (t7, t8); + +ALTER TABLE mysqltest_db2.t2_2 UNION = (t9); +ALTER TABLE mysqltest_db2.t2_2 UNION = (); + +DROP TEMPORARY TABLE mysqltest_db2.t2_2; +DROP TEMPORARY TABLE t10; + +DROP TEMPORARY TABLE t7; +DROP TEMPORARY TABLE t8; +DROP TEMPORARY TABLE t9; + +--echo ########################################################################### +--echo # That's all. Cleanup. +--echo ########################################################################### + +--echo +--echo # -- connection: default +--connection default + +--echo # -- disconnect con1 +--echo # All remaining temporary tables are automatically dropped. +--disconnect con1 + +--echo # -- disconnect con2 +--disconnect con2 + +--echo # -- disconnect con3 +--disconnect con3 + +--echo # -- disconnect con4 +--disconnect con4 + +SET GLOBAL keycache1.key_buffer_size = 0; +DROP DATABASE mysqltest_db1; +DROP DATABASE mysqltest_db2; +DROP USER mysqltest_u1@localhost; +DROP USER mysqltest_u2@localhost; +DROP USER mysqltest_u3@localhost; +DROP USER mysqltest_u4@localhost; +DROP USER mysqltest_u5@localhost; + + # Wait till we reached the initial number of concurrent sessions --source include/wait_until_count_sessions.inc diff --git a/mysql-test/t/grant4.test b/mysql-test/t/grant4.test index c30e0c28f31..756454237f5 100644 --- a/mysql-test/t/grant4.test +++ b/mysql-test/t/grant4.test @@ -142,3 +142,62 @@ connection default; disconnect con1; drop database mysqltest_db1; drop user mysqltest_u1@localhost; + + +--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 for statements like CHECK/REPAIR and OPTIMIZE TABLE +--echo # privileges for all tables involved are checked before processing +--echo # any tables. Doing otherwise, i.e. checking privileges for table +--echo # right before processing it might result in lost results for tables +--echo # which were processed by the time when table for which privileges +--echo # are insufficient are discovered. +--echo # +call mtr.add_suppression("Got an error from thread_id=.*ha_myisam.cc:"); +call mtr.add_suppression("MySQL thread id .*, query id .* localhost.*mysqltest_u1 Checking table"); +--disable_warnings +drop database if exists mysqltest_db1; +--enable_warnings +let $MYSQLD_DATADIR = `SELECT @@datadir`; +create database mysqltest_db1; +--echo # Create tables which we are going to CHECK/REPAIR. +create table mysqltest_db1.t1 (a int, key(a)) engine=myisam; +create table mysqltest_db1.t2 (b int); +insert into mysqltest_db1.t1 values (1), (2); +insert into mysqltest_db1.t2 values (1); +--echo # Create user which will try to do this. +create user mysqltest_u1@localhost; +grant insert, select on mysqltest_db1.t1 to mysqltest_u1@localhost; +connect (con1,localhost,mysqltest_u1,,); +connection default; + +--echo # Corrupt t1 by replacing t1.MYI with a corrupt + unclosed one created +--echo # by doing: 'create table t1 (a int key(a))' +--echo # head -c1024 t1.MYI > corrupt_t1.MYI +flush table mysqltest_db1.t1; +--remove_file $MYSQLD_DATADIR/mysqltest_db1/t1.MYI +--copy_file std_data/corrupt_t1.MYI $MYSQLD_DATADIR/mysqltest_db1/t1.MYI + +--echo # Switching to connection 'con1'. +connection con1; +check table mysqltest_db1.t1; +--echo # The below statement should fail before repairing t1. +--echo # Otherwise info about such repair will be missing from its result-set. +--error ER_TABLEACCESS_DENIED_ERROR +repair table mysqltest_db1.t1, mysqltest_db1.t2; +--echo # The same is true for CHECK TABLE statement. +--error ER_TABLEACCESS_DENIED_ERROR +check table mysqltest_db1.t1, mysqltest_db1.t2; +check table mysqltest_db1.t1; +repair table mysqltest_db1.t1; + +--echo # Clean-up. +disconnect con1; +--source include/wait_until_disconnected.inc +--echo # Switching to connection 'default'. +connection default; +drop database mysqltest_db1; +drop user mysqltest_u1@localhost; diff --git a/mysql-test/t/merge.test b/mysql-test/t/merge.test index 7e198275730..18ec2b3d62f 100644 --- a/mysql-test/t/merge.test +++ b/mysql-test/t/merge.test @@ -2873,6 +2873,86 @@ drop view t3; --echo End of 5.5 tests + +--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 prelocking works correctly for various variants of +--echo # merge tables. +--disable_warnings +drop table if exists t1, t2, m1; +drop function if exists f1; +--enable_warnings +create table t1 (j int); +insert into t1 values (1); +create function f1() returns int return (select count(*) from m1); +create temporary table t2 (a int) engine=myisam; +insert into t2 values (1); +create temporary table m1 (a int) engine=merge union=(t2); +select f1() from t1; +drop tables t2, m1; +create table t2 (a int) engine=myisam; +insert into t2 values (1); +create table m1 (a int) engine=merge union=(t2); +select f1() from t1; +drop table m1; +create temporary table m1 (a int) engine=merge union=(t2); +select f1() from t1; +drop tables t1, t2, m1; +drop function f1; +--echo # +--echo # Check that REPAIR/CHECK and CHECKSUM statements work correctly +--echo # for various variants of merge tables. +create table t1 (a int) engine=myisam; +insert into t1 values (1); +create table m1 (a int) engine=merge union=(t1); +check table m1; +repair table m1; +checksum table m1; +drop tables t1, m1; +create temporary table t1 (a int) engine=myisam; +insert into t1 values (1); +create temporary table m1 (a int) engine=merge union=(t1); +check table m1; +repair table m1; +checksum table m1; +drop tables t1, m1; +create table t1 (a int) engine=myisam; +insert into t1 values (1); +create temporary table m1 (a int) engine=merge union=(t1); +check table m1; +repair table m1; +checksum table m1; +drop tables t1, m1; + +# Check effect of Bug#27480-preliminary patch: +# a merge-table with non-existing children, opened from a prelocked list. + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS m1; +DROP TRIGGER IF EXISTS trg1; +DROP TABLE IF EXISTS q1; +DROP TABLE IF EXISTS q2; +--enable_warnings + +CREATE TABLE t1(a INT); +CREATE TABLE m1(a INT) ENGINE = MERGE UNION (q1, q2); + +CREATE TRIGGER trg1 BEFORE DELETE ON t1 +FOR EACH ROW + INSERT INTO m1 VALUES (1); + +# Uncomment the following to lines when MDEV-5042 is fixed. +#--error ER_WRONG_MRG_TABLE +#DELETE FROM t1; + +DROP TRIGGER trg1; +DROP TABLE t1; +DROP TABLE m1; + --disable_result_log --disable_query_log eval set global storage_engine=$default; diff --git a/mysql-test/t/ps_ddl.test b/mysql-test/t/ps_ddl.test index f7d14464e4e..c34800976c7 100644 --- a/mysql-test/t/ps_ddl.test +++ b/mysql-test/t/ps_ddl.test @@ -2216,3 +2216,46 @@ drop procedure if exists p1; drop function if exists f1; drop view if exists v1, v2; --enable_warnings + + +--echo # +--echo # Additional coverage for refactoring which was made as part of work +--echo # on bug '27480: Extend CREATE TEMPORARY TABLES privilege to allow +--echo # temp table operations'. +--echo # +--echo # Check that we don't try to pre-open temporary tables for the elements +--echo # from prelocking list, as this can lead to unwarranted ER_CANT_REOPEN +--echo # errors. +--disable_warnings ONCE +DROP TABLE IF EXISTS t1, tm; +CREATE TABLE t1 (a INT); +CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW + SET @a:= (SELECT COUNT(*) FROM t1); +--echo # Prelocking list for the below statement should +--echo # contain t1 twice - once for the INSERT and once +--echo # SELECT from the trigger. +PREPARE stmt1 FROM 'INSERT INTO t1 VALUES (1)'; +EXECUTE stmt1; +--echo # Create temporary table which will shadow t1. +CREATE TEMPORARY TABLE t1 (b int); +--echo # The below execution of statement should not fail with ER_CANT_REOPEN +--echo # error. Instead stmt1 should be auto-matically reprepared and succeed. +EXECUTE stmt1; +DEALLOCATE PREPARE stmt1; +DROP TEMPORARY TABLE t1; +DROP TABLE t1; +--echo # +--echo # Also check that we properly reset table list elements from UNION +--echo # clause of CREATE TABLE and ALTER TABLE statements. +--echo # +CREATE TEMPORARY TABLE t1 (i INT); +PREPARE stmt2 FROM 'CREATE TEMPORARY TABLE tm (i INT) ENGINE=MERGE UNION=(t1)'; +EXECUTE stmt2; +DROP TEMPORARY TABLE tm; +EXECUTE stmt2; +DEALLOCATE PREPARE stmt2; +PREPARE stmt3 FROM 'ALTER TABLE tm UNION=(t1)'; +EXECUTE stmt3; +EXECUTE stmt3; +DEALLOCATE PREPARE stmt3; +DROP TEMPORARY TABLES tm, t1; diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test index dd4ee2f6676..f594f0c6c48 100644 --- a/mysql-test/t/temp_table.test +++ b/mysql-test/t/temp_table.test @@ -276,3 +276,46 @@ DROP DATABASE bug48067; DROP TEMPORARY table bug48067.t1; --echo End of 5.1 tests + +--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); + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); + +ANALYZE TABLE t1, t2, t3; + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); + +CHECK TABLE t1, t2, t3; + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); + +--replace_column 2 xxx +CHECKSUM TABLE t1, t2, t3; + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); + +OPTIMIZE TABLE t1, t2, t3; + +INSERT INTO t1 VALUES (1), (2), (3); +INSERT INTO t2 VALUES (11), (12), (13); +INSERT INTO t3 VALUES (101), (102), (103); + +REPAIR TABLE t1, t2, t3; + +DROP TABLES t1, t2, t3; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 4663146674c..6a3d5a420e9 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -121,6 +121,7 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables); static void sql_kill(THD *thd, longlong id, killed_state state, killed_type type); static void sql_kill_user(THD *thd, LEX_USER *user, killed_state state); +static bool lock_tables_precheck(THD *thd, TABLE_LIST *tables); static bool execute_show_status(THD *, TABLE_LIST *); static bool execute_rename_table(THD *, TABLE_LIST *, TABLE_LIST *); @@ -3728,8 +3729,7 @@ end_with_restore_list: if (open_temporary_tables(thd, all_tables)) goto error; - if (check_table_access(thd, LOCK_TABLES_ACL | SELECT_ACL, all_tables, - FALSE, UINT_MAX, FALSE)) + if (lock_tables_precheck(thd, all_tables)) goto error; thd->variables.option_bits|= OPTION_TABLE_LOCK; @@ -7901,6 +7901,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 |