summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexey Botchkov <holyfoot@askmonty.org>2012-08-25 20:57:17 +0500
committerAlexey Botchkov <holyfoot@askmonty.org>2012-08-25 20:57:17 +0500
commitd99b8004e6b46e2a1b321bf50825254bf841cddb (patch)
tree0d890d92947dc3c08d0ca9d173c26a3eb27768ce
parentf277f27ae2fb4ab45a014027f08093a28acc1c14 (diff)
downloadmariadb-git-d99b8004e6b46e2a1b321bf50825254bf841cddb.tar.gz
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
-rw-r--r--mysql-test/include/check-warnings.test6
-rw-r--r--mysql-test/r/commit.result306
-rw-r--r--mysql-test/r/read_only.result37
-rw-r--r--mysql-test/r/trans_read_only.result40
-rw-r--r--mysql-test/t/commit.test359
-rw-r--r--mysql-test/t/read_only.test59
-rw-r--r--mysql-test/t/trans_read_only-master.opt1
-rw-r--r--mysql-test/t/trans_read_only.test50
-rw-r--r--sql/lex.h1
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_yacc.yy472
-rwxr-xr-xstorage/perfschema/gen_pfs_lex_tokenbin160124 -> 132216 bytes
-rw-r--r--storage/perfschema/pfs_lex_token.h535
14 files changed, 1451 insertions, 418 deletions
diff --git a/mysql-test/include/check-warnings.test b/mysql-test/include/check-warnings.test
index 3a26f7eecb1..720f90d7b02 100644
--- a/mysql-test/include/check-warnings.test
+++ b/mysql-test/include/check-warnings.test
@@ -14,10 +14,12 @@ set SQL_LOG_BIN=0;
# Turn off any debug crashes, allow the variable to be
# non existent in release builds
--error 0,1193
-set debug_dbug="";
-
+set debug="";
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 (
row int auto_increment primary key,
diff --git a/mysql-test/r/commit.result b/mysql-test/r/commit.result
index 00e39c29768..a62d2940d85 100644
--- a/mysql-test/r/commit.result
+++ b/mysql-test/r/commit.result
@@ -264,9 +264,313 @@ Should only read the '1000' as this transaction is now in REP READ
COMMIT AND NO CHAIN;
SET @@completion_type=0;
COMMIT AND NO CHAIN;
-SET @autocommit=1;
+SET @@autocommit=1;
COMMIT;
DROP TABLE t1;
#
# 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;
diff --git a/mysql-test/r/read_only.result b/mysql-test/r/read_only.result
index 1ffe2b86f70..3811c6c5487 100644
--- a/mysql-test/r/read_only.result
+++ b/mysql-test/r/read_only.result
@@ -157,3 +157,40 @@ delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
drop database mysqltest_db1;
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;
diff --git a/mysql-test/r/trans_read_only.result b/mysql-test/r/trans_read_only.result
new file mode 100644
index 00000000000..2b1055d4a7b
--- /dev/null
+++ b/mysql-test/r/trans_read_only.result
@@ -0,0 +1,40 @@
+#
+# 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;
diff --git a/mysql-test/t/commit.test b/mysql-test/t/commit.test
index 6ed784df3c2..c2051358073 100644
--- a/mysql-test/t/commit.test
+++ b/mysql-test/t/commit.test
@@ -338,7 +338,7 @@ COMMIT AND NO CHAIN;
#
# Cleanup
#
-SET @autocommit=1;
+SET @@autocommit=1;
COMMIT;
disconnect con1;
@@ -348,3 +348,360 @@ DROP TABLE t1;
--echo #
--echo # End of test cases for Bug#20837
--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;
diff --git a/mysql-test/t/read_only.test b/mysql-test/t/read_only.test
index 52349747883..8ea0f2db9b7 100644
--- a/mysql-test/t/read_only.test
+++ b/mysql-test/t/read_only.test
@@ -299,6 +299,65 @@ flush privileges;
drop database mysqltest_db1;
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
--source include/wait_until_count_sessions.inc
diff --git a/mysql-test/t/trans_read_only-master.opt b/mysql-test/t/trans_read_only-master.opt
new file mode 100644
index 00000000000..cf84816ec90
--- /dev/null
+++ b/mysql-test/t/trans_read_only-master.opt
@@ -0,0 +1 @@
+--transaction-read-only=true
diff --git a/mysql-test/t/trans_read_only.test b/mysql-test/t/trans_read_only.test
new file mode 100644
index 00000000000..f50fb7db376
--- /dev/null
+++ b/mysql-test/t/trans_read_only.test
@@ -0,0 +1,50 @@
+--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;
diff --git a/sql/lex.h b/sql/lex.h
index 9bd1a9b93aa..6587f5b8a9c 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -402,6 +402,7 @@ static SYMBOL symbols[] = {
{ "ONE", SYM(ONE_SYM)},
{ "ONE_SHOT", SYM(ONE_SHOT_SYM)},
{ "ONLINE", SYM(ONLINE_SYM)},
+ { "ONLY", SYM(ONLY_SYM)},
{ "OPEN", SYM(OPEN_SYM)},
{ "OPTIMIZE", SYM(OPTIMIZE)},
{ "OPTIONS", SYM(OPTIONS_SYM)},
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index fadcd64b98e..07de4b0d761 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -4722,7 +4722,7 @@ lock_table_names(THD *thd,
if (thd->tx_read_only)
{
my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0));
- return true;
+ DBUG_RETURN(true);
}
if (! (flags & MYSQL_OPEN_SKIP_SCOPED_MDL_LOCK) &&
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 48ae2f066db..887bace6c42 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4005,6 +4005,7 @@ end_with_restore_list:
{
/* Reset the isolation level if no chaining transaction. */
thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation;
+ thd->tx_read_only= thd->variables.tx_read_only;
}
/* Disconnect the current client connection. */
if (tx_release)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index e2263e21e8f..7b7f766bbd1 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -730,6 +730,116 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
return FALSE;
}
+
+/**
+ Create a separate LEX for each assignment if in SP.
+
+ If we are in SP we want have own LEX for each assignment.
+ This is mostly because it is hard for several sp_instr_set
+ and sp_instr_set_trigger instructions share one LEX.
+ (Well, it is theoretically possible but adds some extra
+ overhead on preparation for execution stage and IMO less
+ robust).
+
+ QQ: May be we should simply prohibit group assignments in SP?
+
+ @see sp_create_assignment_instr
+
+ @param thd Thread context
+ @param no_lookahead True if the parser has no lookahead
+*/
+
+static void sp_create_assignment_lex(THD *thd, bool no_lookahead)
+{
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+ LEX *old_lex= lex;
+ lex->sphead->reset_lex(thd);
+ lex= thd->lex;
+
+ /* Set new LEX as if we at start of set rule. */
+ lex->sql_command= SQLCOM_SET_OPTION;
+ mysql_init_select(lex);
+ lex->var_list.empty();
+ lex->one_shot_set= 0;
+ lex->autocommit= 0;
+ /* get_ptr() is only correct with no lookahead. */
+ DBUG_ASSERT(no_lookahead);
+ lex->sphead->m_tmp_query= lip->get_ptr();
+ /* Inherit from outer lex. */
+ lex->option_type= old_lex->option_type;
+ }
+}
+
+
+/**
+ Create a SP instruction for a SET assignment.
+
+ @see sp_create_assignment_lex
+
+ @param thd Thread context
+ @param no_lookahead True if the parser has no lookahead
+
+ @return false if success, true otherwise.
+*/
+
+static bool sp_create_assignment_instr(THD *thd, bool no_lookahead)
+{
+ LEX *lex= thd->lex;
+
+ if (lex->sphead)
+ {
+ sp_head *sp= lex->sphead;
+
+ if (!lex->var_list.is_empty())
+ {
+ /*
+ We have assignment to user or system variable or
+ option setting, so we should construct sp_instr_stmt
+ for it.
+ */
+ LEX_STRING qbuff;
+ sp_instr_stmt *i;
+ Lex_input_stream *lip= &thd->m_parser_state->m_lip;
+
+ if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
+ lex)))
+ return true;
+
+ /*
+ Extract the query statement from the tokenizer. The
+ end is either lip->ptr, if there was no lookahead,
+ lip->tok_end otherwise.
+ */
+ if (no_lookahead)
+ qbuff.length= lip->get_ptr() - sp->m_tmp_query;
+ else
+ qbuff.length= lip->get_tok_end() - sp->m_tmp_query;
+
+ if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
+ qbuff.length + 5)))
+ return true;
+
+ strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
+ qbuff.length);
+ qbuff.length+= 4;
+ i->m_query= qbuff;
+ if (sp->add_instr(i))
+ return true;
+ }
+ enum_var_type inner_option_type= lex->option_type;
+ if (lex->sphead->restore_lex(thd))
+ return true;
+ /* Copy option_type to outer lex in case it has changed. */
+ thd->lex->option_type= inner_option_type;
+ }
+ return false;
+}
+
+
%}
%union {
int num;
@@ -788,10 +898,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */
/*
- Currently there are 174 shift/reduce conflicts.
+ Currently there are 171 shift/reduce conflicts.
We should not introduce new conflicts any more.
*/
-%expect 174
+%expect 171
/*
Comments for TOKENS.
@@ -1172,6 +1282,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ON /* SQL-2003-R */
%token ONE_SHOT_SYM
%token ONE_SYM
+%token ONLY_SYM /* SQL-2003-R */
%token ONLINE_SYM
%token OPEN_SYM /* SQL-2003-R */
%token OPTIMIZE
@@ -1475,14 +1586,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_option opt_if_not_exists opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
- start_transaction_opts field_def
- union_opt select_derived_init option_type2
+ field_def
+ union_opt select_derived_init transaction_access_mode_types
opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment
ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num
+/*
+ Bit field of MYSQL_START_TRANS_OPT_* flags.
+*/
+%type <num> opt_start_transaction_option_list
+%type <num> start_transaction_option_list
+%type <num> start_transaction_option
+
%type <m_yes_no_unk>
opt_chain opt_release
@@ -1610,7 +1728,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref
- opt_option opt_place
+ opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges grant_ident grant_list grant_option
object_privilege object_privilege_list user_list rename_list
@@ -7100,20 +7218,56 @@ slave:
;
start:
- START_SYM TRANSACTION_SYM start_transaction_opts
+ START_SYM TRANSACTION_SYM opt_start_transaction_option_list
{
LEX *lex= Lex;
lex->sql_command= SQLCOM_BEGIN;
+ /* READ ONLY and READ WRITE are mutually exclusive. */
+ if (($3 & MYSQL_START_TRANS_OPT_READ_WRITE) &&
+ ($3 & MYSQL_START_TRANS_OPT_READ_ONLY))
+ {
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
lex->start_transaction_opt= $3;
}
;
-start_transaction_opts:
- /*empty*/ { $$ = 0; }
- | WITH CONSISTENT_SYM SNAPSHOT_SYM
+opt_start_transaction_option_list:
+ /* empty */
+ {
+ $$= 0;
+ }
+ | start_transaction_option_list
+ {
+ $$= $1;
+ }
+ ;
+
+start_transaction_option_list:
+ start_transaction_option
+ {
+ $$= $1;
+ }
+ | start_transaction_option_list ',' start_transaction_option
+ {
+ $$= $1 | $3;
+ }
+ ;
+
+start_transaction_option:
+ WITH CONSISTENT_SYM SNAPSHOT_SYM
{
$$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
}
+ | READ_SYM ONLY_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_ONLY;
+ }
+ | READ_SYM WRITE_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_READ_WRITE;
+ }
;
slave_thread_opts:
@@ -13148,6 +13302,7 @@ keyword_sp:
| ONE_SHOT_SYM {}
| ONE_SYM {}
| ONLINE_SYM {}
+ | ONLY_SYM {}
| PACK_KEYS_SYM {}
| PAGE_SYM {}
| PARTIAL {}
@@ -13271,8 +13426,15 @@ keyword_sp:
/* Option functions */
+/*
+ SQLCOM_SET_OPTION statement.
+
+ Note that to avoid shift/reduce conflicts, we have separate rules for the
+ first option listed in the statement.
+*/
+
set:
- SET opt_option
+ SET
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION;
@@ -13281,115 +13443,96 @@ set:
lex->var_list.empty();
lex->one_shot_set= 0;
lex->autocommit= 0;
+ sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
}
- option_value_list
+ start_option_value_list
{}
;
-opt_option:
- /* empty */ {}
- | OPTION {}
- ;
-option_value_list:
- option_type_value
- | option_value_list ',' option_type_value
- ;
-
-option_type_value:
+// Start of option value list
+start_option_value_list:
+ option_value_no_option_type
{
- THD *thd= YYTHD;
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (lex->sphead)
- {
- /*
- If we are in SP we want have own LEX for each assignment.
- This is mostly because it is hard for several sp_instr_set
- and sp_instr_set_trigger instructions share one LEX.
- (Well, it is theoretically possible but adds some extra
- overhead on preparation for execution stage and IMO less
- robust).
-
- QQ: May be we should simply prohibit group assignments in SP?
- */
- lex->sphead->reset_lex(thd);
- lex= thd->lex;
-
- /* Set new LEX as if we at start of set rule. */
- lex->sql_command= SQLCOM_SET_OPTION;
- mysql_init_select(lex);
- lex->option_type=OPT_SESSION;
- lex->var_list.empty();
- lex->one_shot_set= 0;
- lex->autocommit= 0;
- lex->sphead->m_tmp_query= lip->get_tok_start();
- }
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
}
- ext_option_value
+ option_value_list_continued
+ | TRANSACTION_SYM
{
- THD *thd= YYTHD;
- LEX *lex= thd->lex;
- Lex_input_stream *lip= YYLIP;
-
- if (lex->sphead)
- {
- sp_head *sp= lex->sphead;
+ Lex->option_type= OPT_DEFAULT;
+ }
+ transaction_characteristics
+ {
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_type
+ {
+ Lex->option_type= $1;
+ }
+ start_option_value_list_following_option_type
+ ;
- if (!lex->var_list.is_empty())
- {
- /*
- We have assignment to user or system variable or
- option setting, so we should construct sp_instr_stmt
- for it.
- */
- LEX_STRING qbuff;
- sp_instr_stmt *i;
- if (!(i= new sp_instr_stmt(sp->instructions(), lex->spcont,
- lex)))
- MYSQL_YYABORT;
+// Start of option value list, option_type was given
+start_option_value_list_following_option_type:
+ option_value_following_option_type
+ {
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ option_value_list_continued
+ | TRANSACTION_SYM transaction_characteristics
+ {
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
- /*
- Extract the query statement from the tokenizer. The
- end is either lip->ptr, if there was no lookahead,
- lip->tok_end otherwise.
- */
- if (yychar == YYEMPTY)
- qbuff.length= lip->get_ptr() - sp->m_tmp_query;
- else
- qbuff.length= lip->get_tok_end() - sp->m_tmp_query;
+// Remainder of the option value list after first option value.
+option_value_list_continued:
+ /* empty */
+ | ',' option_value_list
+ ;
- if (!(qbuff.str= (char*) alloc_root(thd->mem_root,
- qbuff.length + 5)))
- MYSQL_YYABORT;
+// Repeating list of option values after first option value.
+option_value_list:
+ {
+ sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ | option_value_list ','
+ {
+ sp_create_assignment_lex(YYTHD, yychar == YYEMPTY);
+ }
+ option_value
+ {
+ if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
+ MYSQL_YYABORT;
+ }
+ ;
- strmake(strmake(qbuff.str, "SET ", 4), sp->m_tmp_query,
- qbuff.length);
- qbuff.length+= 4;
- i->m_query= qbuff;
- if (sp->add_instr(i))
- MYSQL_YYABORT;
- }
- if (lex->sphead->restore_lex(thd))
- MYSQL_YYABORT;
- }
+// Wrapper around option values following the first option value in the stmt.
+option_value:
+ option_type
+ {
+ Lex->option_type= $1;
}
+ option_value_following_option_type
+ | option_value_no_option_type
;
option_type:
- option_type2 {}
- | GLOBAL_SYM { $$=OPT_GLOBAL; }
+ GLOBAL_SYM { $$=OPT_GLOBAL; }
| LOCAL_SYM { $$=OPT_SESSION; }
| SESSION_SYM { $$=OPT_SESSION; }
;
-option_type2:
- /* empty */ { $$= OPT_DEFAULT; }
- | ONE_SHOT_SYM { Lex->one_shot_set= 1; $$= OPT_SESSION; }
- ;
-
opt_var_type:
/* empty */ { $$=OPT_SESSION; }
| GLOBAL_SYM { $$=OPT_GLOBAL; }
@@ -13404,74 +13547,62 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; }
;
-ext_option_value:
- sys_option_value
- | option_type2 option_value
+// Option values with preceeding option_type.
+option_value_following_option_type:
+ internal_variable_name equal set_expr_or_default
+ {
+ THD *thd= YYTHD;
+ LEX *lex= Lex;
+
+ if ($1.var && $1.var != trg_new_row_fake_var)
+ {
+ /* It is a system variable. */
+ if (set_system_variable(thd, &$1, lex->option_type, $3))
+ MYSQL_YYABORT;
+ }
+ else
+ {
+ /*
+ Not in trigger assigning value to new row,
+ and option_type preceeding local variable is illegal.
+ */
+ my_parse_error(ER(ER_SYNTAX_ERROR));
+ MYSQL_YYABORT;
+ }
+ }
;
-sys_option_value:
- option_type internal_variable_name equal set_expr_or_default
+// Option values without preceeding option_type.
+option_value_no_option_type:
+ internal_variable_name equal set_expr_or_default
{
THD *thd= YYTHD;
LEX *lex= Lex;
- LEX_STRING *name= &$2.base_name;
+ LEX_STRING *name= &$1.base_name;
- if ($2.var == trg_new_row_fake_var)
+ if ($1.var == trg_new_row_fake_var)
{
/* We are in trigger and assigning value to field of new row */
- if ($1)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
- if (set_trigger_new_row(YYTHD, name, $4))
+ if (set_trigger_new_row(YYTHD, name, $3))
MYSQL_YYABORT;
}
- else if ($2.var)
+ else if ($1.var)
{
- if ($1)
- lex->option_type= $1;
-
/* It is a system variable. */
- if (set_system_variable(thd, &$2, lex->option_type, $4))
+ if (set_system_variable(thd, &$1, lex->option_type, $3))
MYSQL_YYABORT;
}
else
{
sp_pcontext *spc= lex->spcont;
- sp_variable_t *spv= spc->find_variable(name);
-
- if ($1)
- {
- my_parse_error(ER(ER_SYNTAX_ERROR));
- MYSQL_YYABORT;
- }
+ sp_variable *spv= spc->find_variable(name, false);
/* It is a local variable. */
- if (set_local_variable(thd, spv, $4))
+ if (set_local_variable(thd, spv, $3))
MYSQL_YYABORT;
}
}
- | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types
- {
- THD *thd= YYTHD;
- LEX *lex=Lex;
- lex->option_type= $1;
- Item *item= new (thd->mem_root) Item_int((int32) $5);
- if (item == NULL)
- MYSQL_YYABORT;
- set_var *var= new set_var(lex->option_type,
- find_sys_var(thd, "tx_isolation"),
- &null_lex_str,
- item);
- if (var == NULL)
- MYSQL_YYABORT;
- lex->var_list.push_back(var);
- }
- ;
-
-option_value:
- '@' ident_or_text equal expr
+ | '@' ident_or_text equal expr
{
Item_func_set_user_var *item;
item= new (YYTHD->mem_root) Item_func_set_user_var($2, $4);
@@ -13517,7 +13648,7 @@ option_value:
names.str= (char *)"names";
names.length= 5;
- if (spc && spc->find_variable(&names))
+ if (spc && spc->find_variable(&names, false))
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
else
my_parse_error(ER(ER_SYNTAX_ERROR));
@@ -13553,7 +13684,7 @@ option_value:
pw.str= (char *)"password";
pw.length= 8;
- if (spc && spc->find_variable(&pw))
+ if (spc && spc->find_variable(&pw, false))
{
my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
MYSQL_YYABORT;
@@ -13562,6 +13693,7 @@ option_value:
MYSQL_YYABORT;
user->host=null_lex_str;
user->user.str=thd->security_ctx->user;
+ user->user.length= strlen(thd->security_ctx->user);
set_var_password *var= new set_var_password(user, $3);
if (var == NULL)
MYSQL_YYABORT;
@@ -13666,6 +13798,54 @@ internal_variable_name:
}
;
+transaction_characteristics:
+ transaction_access_mode
+ | isolation_level
+ | transaction_access_mode ',' isolation_level
+ | isolation_level ',' transaction_access_mode
+ ;
+
+transaction_access_mode:
+ transaction_access_mode_types
+ {
+ THD *thd= YYTHD;
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int((int32) $1);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= new set_var(lex->option_type,
+ find_sys_var(thd, "tx_read_only"),
+ &null_lex_str,
+ item);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var);
+ }
+ ;
+
+isolation_level:
+ ISOLATION LEVEL_SYM isolation_types
+ {
+ THD *thd= YYTHD;
+ LEX *lex=Lex;
+ Item *item= new (thd->mem_root) Item_int((int32) $3);
+ if (item == NULL)
+ MYSQL_YYABORT;
+ set_var *var= new set_var(lex->option_type,
+ find_sys_var(thd, "tx_isolation"),
+ &null_lex_str,
+ item);
+ if (var == NULL)
+ MYSQL_YYABORT;
+ lex->var_list.push_back(var);
+ }
+ ;
+
+transaction_access_mode_types:
+ READ_SYM ONLY_SYM { $$= true; }
+ | READ_SYM WRITE_SYM { $$= false; }
+ ;
+
isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
| READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
diff --git a/storage/perfschema/gen_pfs_lex_token b/storage/perfschema/gen_pfs_lex_token
index 504a29a75f2..d86469d846c 100755
--- a/storage/perfschema/gen_pfs_lex_token
+++ b/storage/perfschema/gen_pfs_lex_token
Binary files differ
diff --git a/storage/perfschema/pfs_lex_token.h b/storage/perfschema/pfs_lex_token.h
index 43e8f647f9a..c6981a7df6c 100644
--- a/storage/perfschema/pfs_lex_token.h
+++ b/storage/perfschema/pfs_lex_token.h
@@ -636,273 +636,274 @@ lex_token_string lex_token_array[]=
/* 617 */ { "ON", 2},
/* 618 */ { "ONE_SHOT", 8},
/* 619 */ { "ONE", 3},
-/* 620 */ { "ONLINE", 6},
-/* 621 */ { "OPEN", 4},
-/* 622 */ { "OPTIMIZE", 8},
-/* 623 */ { "OPTIONS", 7},
-/* 624 */ { "OPTION", 6},
-/* 625 */ { "OPTIONALLY", 10},
-/* 626 */ { "|", 1},
-/* 627 */ { "ORDER", 5},
-/* 628 */ { "||", 2},
-/* 629 */ { "OR", 2},
-/* 630 */ { "OUTER", 5},
-/* 631 */ { "OUTFILE", 7},
-/* 632 */ { "OUT", 3},
-/* 633 */ { "OWNER", 5},
-/* 634 */ { "PACK_KEYS", 9},
-/* 635 */ { "PAGE", 4},
-/* 636 */ { "PAGE_CHECKSUM", 13},
-/* 637 */ { "?", 1},
-/* 638 */ { "PARSER", 6},
-/* 639 */ { "PARSE_VCOL_EXPR", 15},
-/* 640 */ { "PARTIAL", 7},
-/* 641 */ { "PARTITIONING", 12},
-/* 642 */ { "PARTITIONS", 10},
-/* 643 */ { "PARTITION", 9},
-/* 644 */ { "PASSWORD", 8},
-/* 645 */ { "PERSISTENT", 10},
-/* 646 */ { "PHASE", 5},
-/* 647 */ { "PLUGINS", 7},
-/* 648 */ { "PLUGIN", 6},
-/* 649 */ { "POINT", 5},
-/* 650 */ { "POLYGON", 7},
-/* 651 */ { "PORT", 4},
-/* 652 */ { "POSITION", 8},
-/* 653 */ { "PRECISION", 9},
-/* 654 */ { "PREPARE", 7},
-/* 655 */ { "PRESERVE", 8},
-/* 656 */ { "PREV", 4},
-/* 657 */ { "PRIMARY", 7},
-/* 658 */ { "PRIVILEGES", 10},
-/* 659 */ { "PROCEDURE", 9},
-/* 660 */ { "PROCESS", 7},
-/* 661 */ { "PROCESSLIST", 11},
-/* 662 */ { "PROFILE", 7},
-/* 663 */ { "PROFILES", 8},
-/* 664 */ { "PROXY", 5},
-/* 665 */ { "PURGE", 5},
-/* 666 */ { "SQL_TSI_QUARTER", 15},
-/* 667 */ { "QUERY", 5},
-/* 668 */ { "QUICK", 5},
-/* 669 */ { "RANGE", 5},
-/* 670 */ { "READS", 5},
-/* 671 */ { "READ_ONLY", 9},
-/* 672 */ { "READ", 4},
-/* 673 */ { "READ_WRITE", 10},
-/* 674 */ { "REAL", 4},
-/* 675 */ { "REBUILD", 7},
-/* 676 */ { "RECOVER", 7},
-/* 677 */ { "REDOFILE", 8},
-/* 678 */ { "REDO_BUFFER_SIZE", 16},
-/* 679 */ { "REDUNDANT", 9},
-/* 680 */ { "REFERENCES", 10},
-/* 681 */ { "RLIKE", 5},
-/* 682 */ { "RELAY", 5},
-/* 683 */ { "RELAYLOG", 8},
-/* 684 */ { "RELAY_LOG_FILE", 14},
-/* 685 */ { "RELAY_LOG_POS", 13},
-/* 686 */ { "RELAY_THREAD", 12},
-/* 687 */ { "RELEASE", 7},
-/* 688 */ { "RELOAD", 6},
-/* 689 */ { "REMOVE", 6},
-/* 690 */ { "RENAME", 6},
-/* 691 */ { "REORGANIZE", 10},
-/* 692 */ { "REPAIR", 6},
-/* 693 */ { "REPEATABLE", 10},
-/* 694 */ { "REPEAT", 6},
-/* 695 */ { "REPLACE", 7},
-/* 696 */ { "REPLICATION", 11},
-/* 697 */ { "REQUIRE", 7},
-/* 698 */ { "RESET", 5},
-/* 699 */ { "RESIGNAL", 8},
-/* 700 */ { "USER_RESOURCES", 14},
-/* 701 */ { "RESTORE", 7},
-/* 702 */ { "RESTRICT", 8},
-/* 703 */ { "RESUME", 6},
-/* 704 */ { "RETURNS", 7},
-/* 705 */ { "RETURN", 6},
-/* 706 */ { "REVOKE", 6},
-/* 707 */ { "RIGHT", 5},
-/* 708 */ { "ROLLBACK", 8},
-/* 709 */ { "ROLLUP", 6},
-/* 710 */ { "ROUTINE", 7},
-/* 711 */ { "ROWS", 4},
-/* 712 */ { "ROW_FORMAT", 10},
-/* 713 */ { "ROW", 3},
-/* 714 */ { "RTREE", 5},
-/* 715 */ { "SAVEPOINT", 9},
-/* 716 */ { "SCHEDULE", 8},
-/* 717 */ { "SCHEMA_NAME", 11},
-/* 718 */ { "SECOND_MICROSECOND", 18},
-/* 719 */ { "SQL_TSI_SECOND", 14},
-/* 720 */ { "SECURITY", 8},
-/* 721 */ { "SELECT", 6},
-/* 722 */ { "SENSITIVE", 9},
-/* 723 */ { "SEPARATOR", 9},
-/* 724 */ { "SERIALIZABLE", 12},
-/* 725 */ { "SERIAL", 6},
-/* 726 */ { "SESSION", 7},
-/* 727 */ { "SERVER", 6},
-/* 728 */ { "SERVER_OPTIONS", 14},
-/* 729 */ { "SET", 3},
-/* 730 */ { ":=", 2},
-/* 731 */ { "SHARE", 5},
-/* 732 */ { "<<", 2},
-/* 733 */ { ">>", 2},
-/* 734 */ { "SHOW", 4},
-/* 735 */ { "SHUTDOWN", 8},
-/* 736 */ { "SIGNAL", 6},
-/* 737 */ { "SIGNED", 6},
-/* 738 */ { "SIMPLE", 6},
-/* 739 */ { "SLAVE", 5},
-/* 740 */ { "SLOW", 4},
-/* 741 */ { "SMALLINT", 8},
-/* 742 */ { "SNAPSHOT", 8},
-/* 743 */ { "SOCKET", 6},
-/* 744 */ { "SOFT", 4},
-/* 745 */ { "SONAME", 6},
-/* 746 */ { "SOUNDS", 6},
-/* 747 */ { "SOURCE", 6},
-/* 748 */ { "SPATIAL", 7},
-/* 749 */ { "SPECIFIC", 8},
-/* 750 */ { "SQLEXCEPTION", 12},
-/* 751 */ { "SQLSTATE", 8},
-/* 752 */ { "SQLWARNING", 10},
-/* 753 */ { "SQL_BIG_RESULT", 14},
-/* 754 */ { "SQL_BUFFER_RESULT", 17},
-/* 755 */ { "SQL_CACHE", 9},
-/* 756 */ { "SQL_CALC_FOUND_ROWS", 19},
-/* 757 */ { "SQL_NO_CACHE", 12},
-/* 758 */ { "SQL_SMALL_RESULT", 16},
-/* 759 */ { "SQL", 3},
-/* 760 */ { "SQL_THREAD", 10},
-/* 761 */ { "SSL", 3},
-/* 762 */ { "STARTING", 8},
-/* 763 */ { "STARTS", 6},
-/* 764 */ { "START", 5},
-/* 765 */ { "STATUS", 6},
-/* 766 */ { "STDDEV_SAMP", 11},
-/* 767 */ { "STDDEV_POP", 10},
-/* 768 */ { "STOP", 4},
-/* 769 */ { "STORAGE", 7},
-/* 770 */ { "STRAIGHT_JOIN", 13},
-/* 771 */ { "STRING", 6},
-/* 772 */ { "SUBCLASS_ORIGIN", 15},
-/* 773 */ { "SUBDATE", 7},
-/* 774 */ { "SUBJECT", 7},
-/* 775 */ { "SUBPARTITIONS", 13},
-/* 776 */ { "SUBPARTITION", 12},
-/* 777 */ { "SUBSTRING", 9},
-/* 778 */ { "SUM", 3},
-/* 779 */ { "SUPER", 5},
-/* 780 */ { "SUSPEND", 7},
-/* 781 */ { "SWAPS", 5},
-/* 782 */ { "SWITCHES", 8},
-/* 783 */ { "SYSDATE", 7},
-/* 784 */ { "TABLES", 6},
-/* 785 */ { "TABLESPACE", 10},
-/* 786 */ { "TABLE_REF_PRIORITY", 18},
-/* 787 */ { "TABLE_STATISTICS", 16},
-/* 788 */ { "TABLE", 5},
-/* 789 */ { "TABLE_CHECKSUM", 14},
-/* 790 */ { "TABLE_NAME", 10},
-/* 791 */ { "TEMPORARY", 9},
-/* 792 */ { "TEMPTABLE", 9},
-/* 793 */ { "TERMINATED", 10},
-/* 794 */ { "(text)", 6},
-/* 795 */ { "TEXT", 4},
-/* 796 */ { "THAN", 4},
-/* 797 */ { "THEN", 4},
-/* 798 */ { "TIMESTAMP", 9},
-/* 799 */ { "TIMESTAMPADD", 12},
-/* 800 */ { "TIMESTAMPDIFF", 13},
-/* 801 */ { "TIME", 4},
-/* 802 */ { "TINYBLOB", 8},
-/* 803 */ { "TINYINT", 7},
-/* 804 */ { "TINYTEXT", 8},
-/* 805 */ { "TO", 2},
-/* 806 */ { "TRAILING", 8},
-/* 807 */ { "TRANSACTION", 11},
-/* 808 */ { "TRANSACTIONAL", 13},
-/* 809 */ { "TRIGGERS", 8},
-/* 810 */ { "TRIGGER", 7},
-/* 811 */ { "TRIM", 4},
-/* 812 */ { "TRUE", 4},
-/* 813 */ { "TRUNCATE", 8},
-/* 814 */ { "TYPES", 5},
-/* 815 */ { "TYPE", 4},
-/* 816 */ { "UDF_RETURNS", 11},
-/* 817 */ { "(ulonglong)", 11},
-/* 818 */ { "UNCOMMITTED", 11},
-/* 819 */ { "UNDEFINED", 9},
-/* 820 */ { "(_charset)", 10},
-/* 821 */ { "UNDOFILE", 8},
-/* 822 */ { "UNDO_BUFFER_SIZE", 16},
-/* 823 */ { "UNDO", 4},
-/* 824 */ { "UNICODE", 7},
-/* 825 */ { "UNINSTALL", 9},
-/* 826 */ { "UNION", 5},
-/* 827 */ { "UNIQUE", 6},
-/* 828 */ { "UNKNOWN", 7},
-/* 829 */ { "UNLOCK", 6},
-/* 830 */ { "UNSIGNED", 8},
-/* 831 */ { "UNTIL", 5},
-/* 832 */ { "UPDATE", 6},
-/* 833 */ { "UPGRADE", 7},
-/* 834 */ { "USAGE", 5},
-/* 835 */ { "SYSTEM_USER", 11},
-/* 836 */ { "USER_STATISTICS", 15},
-/* 837 */ { "USE_FRM", 7},
-/* 838 */ { "USE", 3},
-/* 839 */ { "USING", 5},
-/* 840 */ { "UTC_DATE", 8},
-/* 841 */ { "UTC_TIMESTAMP", 13},
-/* 842 */ { "UTC_TIME", 8},
-/* 843 */ { "VALUES", 6},
-/* 844 */ { "VALUE", 5},
-/* 845 */ { "VARBINARY", 9},
-/* 846 */ { "VARCHARACTER", 12},
-/* 847 */ { "VARIABLES", 9},
-/* 848 */ { "VAR_POP", 7},
-/* 849 */ { "VARYING", 7},
-/* 850 */ { "VAR_SAMP", 8},
-/* 851 */ { "VIA", 3},
-/* 852 */ { "VIEW", 4},
-/* 853 */ { "VIRTUAL", 7},
-/* 854 */ { "WAIT", 4},
-/* 855 */ { "WARNINGS", 8},
-/* 856 */ { "WEEK", 4},
-/* 857 */ { "WHEN", 4},
-/* 858 */ { "WHERE", 5},
-/* 859 */ { "WHILE", 5},
-/* 860 */ { "WITH", 4},
-/* 861 */ { "WITH CUBE", 9},
-/* 862 */ { "WITH ROLLUP", 11},
-/* 863 */ { "WORK", 4},
-/* 864 */ { "WRAPPER", 7},
-/* 865 */ { "WRITE", 5},
-/* 866 */ { "X509", 4},
-/* 867 */ { "XA", 2},
-/* 868 */ { "XML", 3},
-/* 869 */ { "XOR", 3},
-/* 870 */ { "YEAR_MONTH", 10},
-/* 871 */ { "YEAR", 4},
-/* 872 */ { "ZEROFILL", 8},
-/* 873 */ { "?", 1},
-/* 874 */ { "?, ...", 6},
-/* 875 */ { "(?)", 3},
-/* 876 */ { "(?) /* , ... */", 15},
-/* 877 */ { "(...)", 5},
-/* 878 */ { "(...) /* , ... */", 17},
-/* 879 */ { "UNUSED", 6},
+/* 620 */ { "ONLY", 4},
+/* 621 */ { "ONLINE", 6},
+/* 622 */ { "OPEN", 4},
+/* 623 */ { "OPTIMIZE", 8},
+/* 624 */ { "OPTIONS", 7},
+/* 625 */ { "OPTION", 6},
+/* 626 */ { "OPTIONALLY", 10},
+/* 627 */ { "|", 1},
+/* 628 */ { "ORDER", 5},
+/* 629 */ { "||", 2},
+/* 630 */ { "OR", 2},
+/* 631 */ { "OUTER", 5},
+/* 632 */ { "OUTFILE", 7},
+/* 633 */ { "OUT", 3},
+/* 634 */ { "OWNER", 5},
+/* 635 */ { "PACK_KEYS", 9},
+/* 636 */ { "PAGE", 4},
+/* 637 */ { "PAGE_CHECKSUM", 13},
+/* 638 */ { "?", 1},
+/* 639 */ { "PARSER", 6},
+/* 640 */ { "PARSE_VCOL_EXPR", 15},
+/* 641 */ { "PARTIAL", 7},
+/* 642 */ { "PARTITIONING", 12},
+/* 643 */ { "PARTITIONS", 10},
+/* 644 */ { "PARTITION", 9},
+/* 645 */ { "PASSWORD", 8},
+/* 646 */ { "PERSISTENT", 10},
+/* 647 */ { "PHASE", 5},
+/* 648 */ { "PLUGINS", 7},
+/* 649 */ { "PLUGIN", 6},
+/* 650 */ { "POINT", 5},
+/* 651 */ { "POLYGON", 7},
+/* 652 */ { "PORT", 4},
+/* 653 */ { "POSITION", 8},
+/* 654 */ { "PRECISION", 9},
+/* 655 */ { "PREPARE", 7},
+/* 656 */ { "PRESERVE", 8},
+/* 657 */ { "PREV", 4},
+/* 658 */ { "PRIMARY", 7},
+/* 659 */ { "PRIVILEGES", 10},
+/* 660 */ { "PROCEDURE", 9},
+/* 661 */ { "PROCESS", 7},
+/* 662 */ { "PROCESSLIST", 11},
+/* 663 */ { "PROFILE", 7},
+/* 664 */ { "PROFILES", 8},
+/* 665 */ { "PROXY", 5},
+/* 666 */ { "PURGE", 5},
+/* 667 */ { "SQL_TSI_QUARTER", 15},
+/* 668 */ { "QUERY", 5},
+/* 669 */ { "QUICK", 5},
+/* 670 */ { "RANGE", 5},
+/* 671 */ { "READS", 5},
+/* 672 */ { "READ_ONLY", 9},
+/* 673 */ { "READ", 4},
+/* 674 */ { "READ_WRITE", 10},
+/* 675 */ { "REAL", 4},
+/* 676 */ { "REBUILD", 7},
+/* 677 */ { "RECOVER", 7},
+/* 678 */ { "REDOFILE", 8},
+/* 679 */ { "REDO_BUFFER_SIZE", 16},
+/* 680 */ { "REDUNDANT", 9},
+/* 681 */ { "REFERENCES", 10},
+/* 682 */ { "RLIKE", 5},
+/* 683 */ { "RELAY", 5},
+/* 684 */ { "RELAYLOG", 8},
+/* 685 */ { "RELAY_LOG_FILE", 14},
+/* 686 */ { "RELAY_LOG_POS", 13},
+/* 687 */ { "RELAY_THREAD", 12},
+/* 688 */ { "RELEASE", 7},
+/* 689 */ { "RELOAD", 6},
+/* 690 */ { "REMOVE", 6},
+/* 691 */ { "RENAME", 6},
+/* 692 */ { "REORGANIZE", 10},
+/* 693 */ { "REPAIR", 6},
+/* 694 */ { "REPEATABLE", 10},
+/* 695 */ { "REPEAT", 6},
+/* 696 */ { "REPLACE", 7},
+/* 697 */ { "REPLICATION", 11},
+/* 698 */ { "REQUIRE", 7},
+/* 699 */ { "RESET", 5},
+/* 700 */ { "RESIGNAL", 8},
+/* 701 */ { "USER_RESOURCES", 14},
+/* 702 */ { "RESTORE", 7},
+/* 703 */ { "RESTRICT", 8},
+/* 704 */ { "RESUME", 6},
+/* 705 */ { "RETURNS", 7},
+/* 706 */ { "RETURN", 6},
+/* 707 */ { "REVOKE", 6},
+/* 708 */ { "RIGHT", 5},
+/* 709 */ { "ROLLBACK", 8},
+/* 710 */ { "ROLLUP", 6},
+/* 711 */ { "ROUTINE", 7},
+/* 712 */ { "ROWS", 4},
+/* 713 */ { "ROW_FORMAT", 10},
+/* 714 */ { "ROW", 3},
+/* 715 */ { "RTREE", 5},
+/* 716 */ { "SAVEPOINT", 9},
+/* 717 */ { "SCHEDULE", 8},
+/* 718 */ { "SCHEMA_NAME", 11},
+/* 719 */ { "SECOND_MICROSECOND", 18},
+/* 720 */ { "SQL_TSI_SECOND", 14},
+/* 721 */ { "SECURITY", 8},
+/* 722 */ { "SELECT", 6},
+/* 723 */ { "SENSITIVE", 9},
+/* 724 */ { "SEPARATOR", 9},
+/* 725 */ { "SERIALIZABLE", 12},
+/* 726 */ { "SERIAL", 6},
+/* 727 */ { "SESSION", 7},
+/* 728 */ { "SERVER", 6},
+/* 729 */ { "SERVER_OPTIONS", 14},
+/* 730 */ { "SET", 3},
+/* 731 */ { ":=", 2},
+/* 732 */ { "SHARE", 5},
+/* 733 */ { "<<", 2},
+/* 734 */ { ">>", 2},
+/* 735 */ { "SHOW", 4},
+/* 736 */ { "SHUTDOWN", 8},
+/* 737 */ { "SIGNAL", 6},
+/* 738 */ { "SIGNED", 6},
+/* 739 */ { "SIMPLE", 6},
+/* 740 */ { "SLAVE", 5},
+/* 741 */ { "SLOW", 4},
+/* 742 */ { "SMALLINT", 8},
+/* 743 */ { "SNAPSHOT", 8},
+/* 744 */ { "SOCKET", 6},
+/* 745 */ { "SOFT", 4},
+/* 746 */ { "SONAME", 6},
+/* 747 */ { "SOUNDS", 6},
+/* 748 */ { "SOURCE", 6},
+/* 749 */ { "SPATIAL", 7},
+/* 750 */ { "SPECIFIC", 8},
+/* 751 */ { "SQLEXCEPTION", 12},
+/* 752 */ { "SQLSTATE", 8},
+/* 753 */ { "SQLWARNING", 10},
+/* 754 */ { "SQL_BIG_RESULT", 14},
+/* 755 */ { "SQL_BUFFER_RESULT", 17},
+/* 756 */ { "SQL_CACHE", 9},
+/* 757 */ { "SQL_CALC_FOUND_ROWS", 19},
+/* 758 */ { "SQL_NO_CACHE", 12},
+/* 759 */ { "SQL_SMALL_RESULT", 16},
+/* 760 */ { "SQL", 3},
+/* 761 */ { "SQL_THREAD", 10},
+/* 762 */ { "SSL", 3},
+/* 763 */ { "STARTING", 8},
+/* 764 */ { "STARTS", 6},
+/* 765 */ { "START", 5},
+/* 766 */ { "STATUS", 6},
+/* 767 */ { "STDDEV_SAMP", 11},
+/* 768 */ { "STDDEV_POP", 10},
+/* 769 */ { "STOP", 4},
+/* 770 */ { "STORAGE", 7},
+/* 771 */ { "STRAIGHT_JOIN", 13},
+/* 772 */ { "STRING", 6},
+/* 773 */ { "SUBCLASS_ORIGIN", 15},
+/* 774 */ { "SUBDATE", 7},
+/* 775 */ { "SUBJECT", 7},
+/* 776 */ { "SUBPARTITIONS", 13},
+/* 777 */ { "SUBPARTITION", 12},
+/* 778 */ { "SUBSTRING", 9},
+/* 779 */ { "SUM", 3},
+/* 780 */ { "SUPER", 5},
+/* 781 */ { "SUSPEND", 7},
+/* 782 */ { "SWAPS", 5},
+/* 783 */ { "SWITCHES", 8},
+/* 784 */ { "SYSDATE", 7},
+/* 785 */ { "TABLES", 6},
+/* 786 */ { "TABLESPACE", 10},
+/* 787 */ { "TABLE_REF_PRIORITY", 18},
+/* 788 */ { "TABLE_STATISTICS", 16},
+/* 789 */ { "TABLE", 5},
+/* 790 */ { "TABLE_CHECKSUM", 14},
+/* 791 */ { "TABLE_NAME", 10},
+/* 792 */ { "TEMPORARY", 9},
+/* 793 */ { "TEMPTABLE", 9},
+/* 794 */ { "TERMINATED", 10},
+/* 795 */ { "(text)", 6},
+/* 796 */ { "TEXT", 4},
+/* 797 */ { "THAN", 4},
+/* 798 */ { "THEN", 4},
+/* 799 */ { "TIMESTAMP", 9},
+/* 800 */ { "TIMESTAMPADD", 12},
+/* 801 */ { "TIMESTAMPDIFF", 13},
+/* 802 */ { "TIME", 4},
+/* 803 */ { "TINYBLOB", 8},
+/* 804 */ { "TINYINT", 7},
+/* 805 */ { "TINYTEXT", 8},
+/* 806 */ { "TO", 2},
+/* 807 */ { "TRAILING", 8},
+/* 808 */ { "TRANSACTION", 11},
+/* 809 */ { "TRANSACTIONAL", 13},
+/* 810 */ { "TRIGGERS", 8},
+/* 811 */ { "TRIGGER", 7},
+/* 812 */ { "TRIM", 4},
+/* 813 */ { "TRUE", 4},
+/* 814 */ { "TRUNCATE", 8},
+/* 815 */ { "TYPES", 5},
+/* 816 */ { "TYPE", 4},
+/* 817 */ { "UDF_RETURNS", 11},
+/* 818 */ { "(ulonglong)", 11},
+/* 819 */ { "UNCOMMITTED", 11},
+/* 820 */ { "UNDEFINED", 9},
+/* 821 */ { "(_charset)", 10},
+/* 822 */ { "UNDOFILE", 8},
+/* 823 */ { "UNDO_BUFFER_SIZE", 16},
+/* 824 */ { "UNDO", 4},
+/* 825 */ { "UNICODE", 7},
+/* 826 */ { "UNINSTALL", 9},
+/* 827 */ { "UNION", 5},
+/* 828 */ { "UNIQUE", 6},
+/* 829 */ { "UNKNOWN", 7},
+/* 830 */ { "UNLOCK", 6},
+/* 831 */ { "UNSIGNED", 8},
+/* 832 */ { "UNTIL", 5},
+/* 833 */ { "UPDATE", 6},
+/* 834 */ { "UPGRADE", 7},
+/* 835 */ { "USAGE", 5},
+/* 836 */ { "SYSTEM_USER", 11},
+/* 837 */ { "USER_STATISTICS", 15},
+/* 838 */ { "USE_FRM", 7},
+/* 839 */ { "USE", 3},
+/* 840 */ { "USING", 5},
+/* 841 */ { "UTC_DATE", 8},
+/* 842 */ { "UTC_TIMESTAMP", 13},
+/* 843 */ { "UTC_TIME", 8},
+/* 844 */ { "VALUES", 6},
+/* 845 */ { "VALUE", 5},
+/* 846 */ { "VARBINARY", 9},
+/* 847 */ { "VARCHARACTER", 12},
+/* 848 */ { "VARIABLES", 9},
+/* 849 */ { "VAR_POP", 7},
+/* 850 */ { "VARYING", 7},
+/* 851 */ { "VAR_SAMP", 8},
+/* 852 */ { "VIA", 3},
+/* 853 */ { "VIEW", 4},
+/* 854 */ { "VIRTUAL", 7},
+/* 855 */ { "WAIT", 4},
+/* 856 */ { "WARNINGS", 8},
+/* 857 */ { "WEEK", 4},
+/* 858 */ { "WHEN", 4},
+/* 859 */ { "WHERE", 5},
+/* 860 */ { "WHILE", 5},
+/* 861 */ { "WITH", 4},
+/* 862 */ { "WITH CUBE", 9},
+/* 863 */ { "WITH ROLLUP", 11},
+/* 864 */ { "WORK", 4},
+/* 865 */ { "WRAPPER", 7},
+/* 866 */ { "WRITE", 5},
+/* 867 */ { "X509", 4},
+/* 868 */ { "XA", 2},
+/* 869 */ { "XML", 3},
+/* 870 */ { "XOR", 3},
+/* 871 */ { "YEAR_MONTH", 10},
+/* 872 */ { "YEAR", 4},
+/* 873 */ { "ZEROFILL", 8},
+/* 874 */ { "?", 1},
+/* 875 */ { "?, ...", 6},
+/* 876 */ { "(?)", 3},
+/* 877 */ { "(?) /* , ... */", 15},
+/* 878 */ { "(...)", 5},
+/* 879 */ { "(...) /* , ... */", 17},
+/* 880 */ { "UNUSED", 6},
/* DUMMY */ { "", 0}
};
/* PFS specific tokens. */
-#define TOK_PFS_GENERIC_VALUE 873
-#define TOK_PFS_GENERIC_VALUE_LIST 874
-#define TOK_PFS_ROW_SINGLE_VALUE 875
-#define TOK_PFS_ROW_SINGLE_VALUE_LIST 876
-#define TOK_PFS_ROW_MULTIPLE_VALUE 877
-#define TOK_PFS_ROW_MULTIPLE_VALUE_LIST 878
-#define TOK_PFS_UNUSED 879
+#define TOK_PFS_GENERIC_VALUE 874
+#define TOK_PFS_GENERIC_VALUE_LIST 875
+#define TOK_PFS_ROW_SINGLE_VALUE 876
+#define TOK_PFS_ROW_SINGLE_VALUE_LIST 877
+#define TOK_PFS_ROW_MULTIPLE_VALUE 878
+#define TOK_PFS_ROW_MULTIPLE_VALUE_LIST 879
+#define TOK_PFS_UNUSED 880