Commit d99b8004 authored by Alexey Botchkov's avatar Alexey Botchkov

SQL syntax extended with START TRANSACTION READ ONLY|READ WRITE

and SET TRANSACTION READ ONLT|READ WRITE
statements.


per-file comments:
  mysql-test/include/check-warnings.test
        READ ONLY transaction flag cleaned.
  mysql-test/r/commit.result
        result updated
  mysql-test/r/read_only.result
        result updated
  mysql-test/t/commit.test
        tests added.
  mysql-test/t/read_only.test
        tests added
  sql/lex.h
        ONLY symbol added.
  sql/sql_base.cc
        DBUG_RETURN added.
  sql/sql_parse.cc
        implementations added.
  sql/sql_yacc.yy
        SQL syntax extended.
  storage/perfschema/gen_pfs_lex_token
        changes forced by lex.h
  storage/perfschema/pfs_lex_token.h
        changes forced by lex.h
parent f277f27a
...@@ -14,10 +14,12 @@ set SQL_LOG_BIN=0; ...@@ -14,10 +14,12 @@ set SQL_LOG_BIN=0;
# Turn off any debug crashes, allow the variable to be # Turn off any debug crashes, allow the variable to be
# non existent in release builds # non existent in release builds
--error 0,1193 --error 0,1193
set debug_dbug=""; set debug="";
use mtr; use mtr;
# Allow this session to read-write even if server is started
# with --transaction-read-only
set session transaction read write;
create temporary table error_log ( create temporary table error_log (
row int auto_increment primary key, row int auto_increment primary key,
......
...@@ -264,9 +264,313 @@ Should only read the '1000' as this transaction is now in REP READ ...@@ -264,9 +264,313 @@ Should only read the '1000' as this transaction is now in REP READ
COMMIT AND NO CHAIN; COMMIT AND NO CHAIN;
SET @@completion_type=0; SET @@completion_type=0;
COMMIT AND NO CHAIN; COMMIT AND NO CHAIN;
SET @autocommit=1; SET @@autocommit=1;
COMMIT; COMMIT;
DROP TABLE t1; DROP TABLE t1;
# #
# End of test cases for Bug#20837 # End of test cases for Bug#20837
# #
#
# WL#5968 Implement START TRANSACTION READ (WRITE|ONLY);
#
#
# Test 1: Check supported syntax
START TRANSACTION;
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
START TRANSACTION READ WRITE;
COMMIT;
START TRANSACTION READ ONLY, READ WRITE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT;
COMMIT;
START TRANSACTION READ WRITE, WITH CONSISTENT SNAPSHOT;
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY;
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT, READ WRITE;
COMMIT;
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT, READ WRITE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '' at line 1
SET TRANSACTION READ ONLY;
SET TRANSACTION READ WRITE;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE;
SET TRANSACTION READ ONLY, ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION READ WRITE, ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION READ ONLY, READ WRITE;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'READ WRITE' at line 1
COMMIT;
#
# Test 2: Check setting of variable.
SET SESSION TRANSACTION READ WRITE;
SELECT @@tx_read_only;
@@tx_read_only
0
SET SESSION TRANSACTION READ ONLY;
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE;
SELECT @@tx_read_only;
@@tx_read_only
0
SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL REPEATABLE READ;
SELECT @@tx_read_only;
@@tx_read_only
1
START TRANSACTION;
# Not allowed inside a transaction
SET TRANSACTION READ ONLY;
ERROR 25001: Transaction characteristics can't be changed while a transaction is in progress
# But these are allowed.
SET SESSION TRANSACTION READ ONLY;
SET GLOBAL TRANSACTION READ ONLY;
COMMIT;
SET SESSION TRANSACTION READ WRITE;
SET GLOBAL TRANSACTION READ WRITE;
#
# Test 3: Test that write operations are properly blocked.
CREATE TABLE t1(a INT);
CREATE TEMPORARY TABLE temp_t2(a INT);
SET SESSION TRANSACTION READ ONLY;
# 1: DDL should be blocked, also on temporary tables.
CREATE TABLE t3(a INT);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
ALTER TABLE t1 COMMENT "Test";
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DROP TABLE t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CREATE TEMPORARY TABLE temp_t3(a INT);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
ALTER TABLE temp_t2 COMMENT "Test";
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DROP TEMPORARY TABLE temp_t2;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CREATE FUNCTION f1() RETURNS INT RETURN 1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DROP FUNCTION f1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CREATE PROCEDURE p1() BEGIN END;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DROP PROCEDURE p1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CREATE VIEW v1 AS SELECT 1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
SET SESSION TRANSACTION READ WRITE;
CREATE VIEW v1 AS SELECT 1;
SET SESSION TRANSACTION READ ONLY;
DROP VIEW v1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
SET SESSION TRANSACTION READ WRITE;
DROP VIEW v1;
SET SESSION TRANSACTION READ ONLY;
RENAME TABLE t1 TO t2;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
RENAME TABLE temp_t2 TO temp_t3;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
TRUNCATE TABLE t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CREATE DATABASE db1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DROP DATABASE db1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
SET SESSION TRANSACTION READ WRITE;
# 2: DML should be blocked on non-temporary tables.
START TRANSACTION READ ONLY;
INSERT INTO t1 VALUES (1), (2);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
UPDATE t1 SET a= 3;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
# 3: DML should be allowed on temporary tables.
INSERT INTO temp_t2 VALUES (1), (2);
UPDATE temp_t2 SET a= 3;
DELETE FROM temp_t2;
# 4: Queries should not be blocked.
SELECT * FROM t1;
a
SELECT * FROM temp_t2;
a
HANDLER t1 OPEN;
HANDLER t1 READ FIRST;
a
HANDLER t1 CLOSE;
HANDLER temp_t2 OPEN;
HANDLER temp_t2 READ FIRST;
a
HANDLER temp_t2 CLOSE;
# 5: Prepared statements
PREPARE stmt FROM "DELETE FROM t1";
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
PREPARE stmt FROM "DELETE FROM temp_t2";
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
# 6: Stored routines
CREATE FUNCTION f1() RETURNS INT
BEGIN
DELETE FROM t1;
RETURN 1;
END|
CREATE FUNCTION f2() RETURNS INT
BEGIN
DELETE FROM temp_t2;
RETURN 1;
END|
CREATE PROCEDURE p1() DELETE FROM t1;
CREATE PROCEDURE p2() DELETE FROM temp_t2;
START TRANSACTION READ ONLY;
SELECT f1();
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
SELECT f2();
f2()
1
CALL p1();
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
CALL p2();
COMMIT;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
# 7: Views
CREATE VIEW v1 AS SELECT a FROM t1;
START TRANSACTION READ ONLY;
INSERT INTO v1 VALUES (1), (2);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
SELECT * FROM v1;
a
COMMIT;
DROP VIEW v1;
# 8: LOCK TABLE
SET SESSION TRANSACTION READ ONLY;
LOCK TABLE t1 WRITE;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
LOCK TABLE t1 READ;
UNLOCK TABLES;
SET SESSION TRANSACTION READ WRITE;
DROP TABLE temp_t2, t1;
#
# Test 4: SET TRANSACTION, CHAINing transactions
CREATE TABLE t1(a INT);
SET SESSION TRANSACTION READ ONLY;
START TRANSACTION;
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
COMMIT;
START TRANSACTION READ WRITE;
DELETE FROM t1;
COMMIT;
SET SESSION TRANSACTION READ WRITE;
SET TRANSACTION READ ONLY;
START TRANSACTION;
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
COMMIT;
START TRANSACTION READ WRITE;
DELETE FROM t1;
COMMIT;
START TRANSACTION READ ONLY;
SELECT * FROM t1;
a
COMMIT AND CHAIN;
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
COMMIT;
START TRANSACTION READ ONLY;
SELECT * FROM t1;
a
ROLLBACK AND CHAIN;
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
COMMIT;
DROP TABLE t1;
#
# Test 5: Test that reserved keyword ONLY is still allowed as
# identifier - both directly and in SPs.
SET @only= 1;
CREATE TABLE t1 (only INT);
INSERT INTO t1 (only) values (1);
SELECT only FROM t1 WHERE only = 1;
only
1
DROP TABLE t1;
CREATE PROCEDURE p1()
BEGIN
DECLARE only INT DEFAULT 1;
END|
CALL p1();
DROP PROCEDURE p1;
#
# Test 6: Check that XA transactions obey default access mode.
CREATE TABLE t1(a INT);
SET TRANSACTION READ ONLY;
XA START 'test1';
INSERT INTO t1 VALUES (1);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
UPDATE t1 SET a=2;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
DELETE FROM t1;
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
XA END 'test1';
XA PREPARE 'test1';
XA COMMIT 'test1';
DROP TABLE t1;
#
# Test 7: SET TRANSACTION inside stored routines
CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY;
CALL p1();
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION READ WRITE;
DROP PROCEDURE p1;
CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY,
ISOLATION LEVEL SERIALIZABLE;
CALL p1();
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION READ WRITE, ISOLATION LEVEL REPEATABLE READ;
DROP PROCEDURE p1;
CREATE FUNCTION f1() RETURNS INT
BEGIN
SET SESSION TRANSACTION READ ONLY;
RETURN 1;
END|
SELECT f1();
f1()
1
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION READ WRITE;
DROP FUNCTION f1;
CREATE FUNCTION f1() RETURNS INT
BEGIN
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY;
RETURN 1;
END|
SELECT f1();
f1()
1
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE;
DROP FUNCTION f1;
#
# Test 8: SET TRANSACTION and auto-commit
SELECT @@autocommit;
@@autocommit
1
CREATE TABLE t1(a INT) engine=InnoDB;
SET TRANSACTION READ ONLY;
SELECT * FROM t1;
a
# This statement should work, since last statement committed.
INSERT INTO t1 VALUES (1);
DROP TABLE t1;
...@@ -157,3 +157,40 @@ delete from mysql.columns_priv where User like 'mysqltest_%'; ...@@ -157,3 +157,40 @@ delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges; flush privileges;
drop database mysqltest_db1; drop database mysqltest_db1;
set global read_only= @start_read_only; set global read_only= @start_read_only;
#
# WL#5968 Implement START TRANSACTION READ (WRITE|ONLY);
#
#
# Test interaction with read_only system variable.
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2);
CREATE USER user1;
SET GLOBAL read_only= 1;
# All allowed with super privilege
START TRANSACTION;
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
START TRANSACTION READ WRITE;
COMMIT;
# We allow implicit RW transaction without super privilege
# for compatibility reasons
START TRANSACTION;
# Check that table updates are still disallowed.
INSERT INTO t1 VALUES (3);
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
UPDATE t1 SET a= 1;
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
DELETE FROM t1;
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
# Explicit RW trans is not allowed without super privilege
START TRANSACTION READ WRITE;
ERROR HY000: The MariaDB server is running with the --read-only option so it cannot execute this statement
COMMIT;
DROP USER user1;
SET GLOBAL read_only= 0;
DROP TABLE t1;
#
# WL#5968: Implement START TRANSACTION READ (WRITE|ONLY);
#
#
# Test9: The --transaction-read-only startup option.
# Check that the option was set by the .opt file.
SELECT @@tx_read_only;
@@tx_read_only
1
# Also for new connections. Switching to con1
SELECT @@tx_read_only;
@@tx_read_only
1
SET SESSION TRANSACTION READ WRITE;
SELECT @@tx_read_only;
@@tx_read_only
0
# Connection default
SELECT @@tx_read_only;
@@tx_read_only
1
#
# Test 10: SET TRANSACTION / START TRANSACTION + implicit commit.
SET SESSION TRANSACTION READ WRITE;
SET TRANSACTION READ ONLY;
# Since DDL does implicit commit before starting, SET TRANSACTION
# will have no effect because the "next" transaction will already
# be over before the DDL statement starts.
CREATE TABLE t1 (a INT);
START TRANSACTION READ ONLY;
# The same happens with START TRANSACTION
DROP TABLE t1;
#
# Test 11: INSERT DELAYED
CREATE TABLE t1(a INT);
START TRANSACTION READ ONLY;
INSERT DELAYED INTO t1 VALUES (1);
ERROR 25006: Cannot execute statement in a READ ONLY transaction.
COMMIT;
DROP TABLE t1;
...@@ -338,7 +338,7 @@ COMMIT AND NO CHAIN; ...@@ -338,7 +338,7 @@ COMMIT AND NO CHAIN;
# #
# Cleanup # Cleanup
# #
SET @autocommit=1; SET @@autocommit=1;
COMMIT; COMMIT;
disconnect con1; disconnect con1;
...@@ -348,3 +348,360 @@ DROP TABLE t1; ...@@ -348,3 +348,360 @@ DROP TABLE t1;
--echo # --echo #
--echo # End of test cases for Bug#20837 --echo # End of test cases for Bug#20837
--echo # --echo #
--echo #
--echo # WL#5968 Implement START TRANSACTION READ (WRITE|ONLY);
--echo #
--echo #
--echo # Test 1: Check supported syntax
START TRANSACTION;
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
START TRANSACTION READ WRITE;
COMMIT;
--error ER_PARSE_ERROR
START TRANSACTION READ ONLY, READ WRITE;
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT;
COMMIT;
START TRANSACTION READ WRITE, WITH CONSISTENT SNAPSHOT;
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT, READ ONLY;
COMMIT;
START TRANSACTION WITH CONSISTENT SNAPSHOT, READ WRITE;
COMMIT;
--error ER_PARSE_ERROR
START TRANSACTION READ ONLY, WITH CONSISTENT SNAPSHOT, READ WRITE;
SET TRANSACTION READ ONLY;
SET TRANSACTION READ WRITE;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY;
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ WRITE;
SET TRANSACTION READ ONLY, ISOLATION LEVEL READ COMMITTED;
SET TRANSACTION READ WRITE, ISOLATION LEVEL READ COMMITTED;
--error ER_PARSE_ERROR
SET TRANSACTION READ ONLY, READ WRITE;
COMMIT;
--echo #
--echo # Test 2: Check setting of variable.
SET SESSION TRANSACTION READ WRITE;
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ ONLY;
SELECT @@tx_read_only;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE;
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ ONLY, ISOLATION LEVEL REPEATABLE READ;
SELECT @@tx_read_only;
START TRANSACTION;
--echo # Not allowed inside a transaction
--error ER_CANT_CHANGE_TX_CHARACTERISTICS
SET TRANSACTION READ ONLY;
--echo # But these are allowed.
SET SESSION TRANSACTION READ ONLY;
SET GLOBAL TRANSACTION READ ONLY;
COMMIT;
# Reset to defaults
SET SESSION TRANSACTION READ WRITE;
SET GLOBAL TRANSACTION READ WRITE;
--echo #
--echo # Test 3: Test that write operations are properly blocked.
CREATE TABLE t1(a INT);
CREATE TEMPORARY TABLE temp_t2(a INT);
SET SESSION TRANSACTION READ ONLY;
--echo # 1: DDL should be blocked, also on temporary tables.
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE TABLE t3(a INT);
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
ALTER TABLE t1 COMMENT "Test";
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP TABLE t1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE TEMPORARY TABLE temp_t3(a INT);
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
ALTER TABLE temp_t2 COMMENT "Test";
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP TEMPORARY TABLE temp_t2;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE FUNCTION f1() RETURNS INT RETURN 1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP FUNCTION f1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE PROCEDURE p1() BEGIN END;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP PROCEDURE p1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE VIEW v1 AS SELECT 1;
SET SESSION TRANSACTION READ WRITE;
CREATE VIEW v1 AS SELECT 1;
SET SESSION TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP VIEW v1;
SET SESSION TRANSACTION READ WRITE;
DROP VIEW v1;
SET SESSION TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
RENAME TABLE t1 TO t2;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
RENAME TABLE temp_t2 TO temp_t3;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
TRUNCATE TABLE t1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CREATE DATABASE db1;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DROP DATABASE db1;
SET SESSION TRANSACTION READ WRITE;
--echo # 2: DML should be blocked on non-temporary tables.
START TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
INSERT INTO t1 VALUES (1), (2);
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
UPDATE t1 SET a= 3;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
--echo # 3: DML should be allowed on temporary tables.
INSERT INTO temp_t2 VALUES (1), (2);
UPDATE temp_t2 SET a= 3;
DELETE FROM temp_t2;
--echo # 4: Queries should not be blocked.
SELECT * FROM t1;
SELECT * FROM temp_t2;
HANDLER t1 OPEN;
HANDLER t1 READ FIRST;
HANDLER t1 CLOSE;
HANDLER temp_t2 OPEN;
HANDLER temp_t2 READ FIRST;
HANDLER temp_t2 CLOSE;
--echo # 5: Prepared statements
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
PREPARE stmt FROM "DELETE FROM t1";
PREPARE stmt FROM "DELETE FROM temp_t2";
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
COMMIT;
--echo # 6: Stored routines
delimiter |;
CREATE FUNCTION f1() RETURNS INT
BEGIN
DELETE FROM t1;
RETURN 1;
END|
CREATE FUNCTION f2() RETURNS INT
BEGIN
DELETE FROM temp_t2;
RETURN 1;
END|
delimiter ;|
CREATE PROCEDURE p1() DELETE FROM t1;
CREATE PROCEDURE p2() DELETE FROM temp_t2;
START TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
SELECT f1();
SELECT f2();
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
CALL p1();
CALL p2();
COMMIT;
DROP FUNCTION f1;
DROP FUNCTION f2;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
--echo # 7: Views
CREATE VIEW v1 AS SELECT a FROM t1;
# Not supported for temporary tables.
START TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
INSERT INTO v1 VALUES (1), (2);
SELECT * FROM v1;
COMMIT;
DROP VIEW v1;
--echo # 8: LOCK TABLE
SET SESSION TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
LOCK TABLE t1 WRITE;
LOCK TABLE t1 READ;
UNLOCK TABLES;
# Not supported for temporary tables.
SET SESSION TRANSACTION READ WRITE;
DROP TABLE temp_t2, t1;
--echo #
--echo # Test 4: SET TRANSACTION, CHAINing transactions
CREATE TABLE t1(a INT);
SET SESSION TRANSACTION READ ONLY;
START TRANSACTION;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
COMMIT;
START TRANSACTION READ WRITE;
DELETE FROM t1;
COMMIT;
SET SESSION TRANSACTION READ WRITE;
SET TRANSACTION READ ONLY;
START TRANSACTION;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
COMMIT;
START TRANSACTION READ WRITE;
DELETE FROM t1;
COMMIT;
START TRANSACTION READ ONLY;
SELECT * FROM t1;
COMMIT AND CHAIN;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
COMMIT;
START TRANSACTION READ ONLY;
SELECT * FROM t1;
ROLLBACK AND CHAIN;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
COMMIT;
DROP TABLE t1;
--echo #
--echo # Test 5: Test that reserved keyword ONLY is still allowed as
--echo # identifier - both directly and in SPs.
SET @only= 1;
CREATE TABLE t1 (only INT);
INSERT INTO t1 (only) values (1);
SELECT only FROM t1 WHERE only = 1;
DROP TABLE t1;
DELIMITER |;
CREATE PROCEDURE p1()
BEGIN
DECLARE only INT DEFAULT 1;
END|
DELIMITER ;|
CALL p1();
DROP PROCEDURE p1;
--echo #
--echo # Test 6: Check that XA transactions obey default access mode.
CREATE TABLE t1(a INT);
SET TRANSACTION READ ONLY;
XA START 'test1';
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
INSERT INTO t1 VALUES (1);
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
UPDATE t1 SET a=2;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
DELETE FROM t1;
XA END 'test1';
XA PREPARE 'test1';
XA COMMIT 'test1';
DROP TABLE t1;
--echo #
--echo # Test 7: SET TRANSACTION inside stored routines
CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY;
CALL p1();
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ WRITE;
DROP PROCEDURE p1;
CREATE PROCEDURE p1() SET SESSION TRANSACTION READ ONLY,
ISOLATION LEVEL SERIALIZABLE;
CALL p1();
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ WRITE, ISOLATION LEVEL REPEATABLE READ;
DROP PROCEDURE p1;
delimiter |;
CREATE FUNCTION f1() RETURNS INT
BEGIN
SET SESSION TRANSACTION READ ONLY;
RETURN 1;
END|
delimiter ;|
SELECT f1();
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ WRITE;
DROP FUNCTION f1;
delimiter |;
CREATE FUNCTION f1() RETURNS INT
BEGIN
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE, READ ONLY;
RETURN 1;
END|
delimiter ;|
SELECT f1();
SELECT @@tx_read_only;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ, READ WRITE;
DROP FUNCTION f1;
--echo #
--echo # Test 8: SET TRANSACTION and auto-commit
SELECT @@autocommit;
CREATE TABLE t1(a INT) engine=InnoDB;
SET TRANSACTION READ ONLY;
SELECT * FROM t1;
--echo # This statement should work, since last statement committed.
INSERT INTO t1 VALUES (1);
DROP TABLE t1;
...@@ -299,6 +299,65 @@ flush privileges; ...@@ -299,6 +299,65 @@ flush privileges;
drop database mysqltest_db1; drop database mysqltest_db1;
set global read_only= @start_read_only; set global read_only= @start_read_only;
--echo #
--echo # WL#5968 Implement START TRANSACTION READ (WRITE|ONLY);
--echo #
--echo #
--echo # Test interaction with read_only system variable.
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2);
CREATE USER user1;
connect (con1, localhost, user1);
connection default;
SET GLOBAL read_only= 1;
--echo # All allowed with super privilege
START TRANSACTION;
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
START TRANSACTION READ WRITE;
COMMIT;
--echo # We allow implicit RW transaction without super privilege
--echo # for compatibility reasons
connection con1;
START TRANSACTION;
--echo # Check that table updates are still disallowed.
--error ER_OPTION_PREVENTS_STATEMENT
INSERT INTO t1 VALUES (3);
--error ER_OPTION_PREVENTS_STATEMENT
UPDATE t1 SET a= 1;
--error ER_OPTION_PREVENTS_STATEMENT
DELETE FROM t1;
COMMIT;
START TRANSACTION READ ONLY;
COMMIT;
--echo # Explicit RW trans is not allowed without super privilege
--error ER_OPTION_PREVENTS_STATEMENT
START TRANSACTION READ WRITE;
COMMIT;
disconnect con1;
--source include/wait_until_disconnected.inc
connection default;
DROP USER user1;
SET GLOBAL read_only= 0;
DROP TABLE t1;
# Wait till all disconnects are completed # Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc --source include/wait_until_count_sessions.inc
--transaction-read-only=true
--source include/not_embedded.inc
--echo #
--echo # WL#5968: Implement START TRANSACTION READ (WRITE|ONLY);
--echo #
--echo #
--echo # Test9: The --transaction-read-only startup option.
--echo # Check that the option was set by the .opt file.
SELECT @@tx_read_only;
--echo # Also for new connections. Switching to con1
connect (con1, localhost, root);
SELECT @@tx_read_only;
SET SESSION TRANSACTION READ WRITE;
SELECT @@tx_read_only;
disconnect con1;
--source include/wait_until_disconnected.inc
--echo # Connection default
connection default;
SELECT @@tx_read_only;
--echo #
--echo # Test 10: SET TRANSACTION / START TRANSACTION + implicit commit.
SET SESSION TRANSACTION READ WRITE;
--disable_ps_protocol
SET TRANSACTION READ ONLY;
--echo # Since DDL does implicit commit before starting, SET TRANSACTION
--echo # will have no effect because the "next" transaction will already
--echo # be over before the DDL statement starts.
CREATE TABLE t1 (a INT);
START TRANSACTION READ ONLY;
--echo # The same happens with START TRANSACTION
DROP TABLE t1;
--enable_ps_protocol
--echo #
--echo # Test 11: INSERT DELAYED
CREATE TABLE t1(a INT);
START TRANSACTION READ ONLY;
--error ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION
INSERT DELAYED INTO t1 VALUES (1);
COMMIT;
DROP TABLE t1;
...@@ -402,6 +402,7 @@ static SYMBOL symbols[] = { ...@@ -402,6 +402,7 @@ static SYMBOL symbols[] = {
{ "ONE", SYM(ONE_SYM)}, { "ONE", SYM(ONE_SYM)},
{ "ONE_SHOT", SYM(ONE_SHOT_SYM)}, { "ONE_SHOT", SYM(ONE_SHOT_SYM)},
{ "ONLINE", SYM(ONLINE_SYM)}, { "ONLINE", SYM(ONLINE_SYM)},
{ "ONLY", SYM(ONLY_SYM)},
{ "OPEN", SYM(OPEN_SYM)}, { "OPEN", SYM(OPEN_SYM)},
{ "OPTIMIZE", SYM(OPTIMIZE)}, { "OPTIMIZE", SYM(OPTIMIZE)},
{ "OPTIONS", SYM(OPTIONS_SYM)}, { "OPTIONS", SYM(OPTIONS_SYM)},
......
...@@ -4722,7 +4722,7 @@ lock_table_names(THD *thd, ...@@ -4722,7 +4722,7 @@ lock_table_names(THD *thd,
if (thd->tx_read_only) if (thd->tx_read_only)
{ {
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0)); my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
return true; DBUG_RETURN(true);
} }
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) && if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
......
...@@ -4005,6 +4005,7 @@ case SQLCOM_PREPARE: ...@@ -4005,6 +4005,7 @@ case SQLCOM_PREPARE:
{ {
/* Reset the isolation level if no chaining transaction. */ /* Reset the isolation level if no chaining transaction. */
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
thd->tx_read_only= thd->variables.tx_read_only;
} }
/* Disconnect the current client connection. */ /* Disconnect the current client connection. */
if (tx_release) if (tx_release)
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment