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)
......
...@@ -730,6 +730,116 @@ static bool add_create_index (LEX *lex, Key::Keytype type, ...@@ -730,6 +730,116 @@ static bool add_create_index (LEX *lex, Key::Keytype type,
return FALSE; 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 { %union {
int num; int num;
...@@ -788,10 +898,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -788,10 +898,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%pure_parser /* We have threads */ %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. We should not introduce new conflicts any more.
*/ */
%expect 174 %expect 171
/* /*
Comments for TOKENS. Comments for TOKENS.
...@@ -1172,6 +1282,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1172,6 +1282,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ON /* SQL-2003-R */ %token ON /* SQL-2003-R */
%token ONE_SHOT_SYM %token ONE_SHOT_SYM
%token ONE_SYM %token ONE_SYM
%token ONLY_SYM /* SQL-2003-R */
%token ONLINE_SYM %token ONLINE_SYM
%token OPEN_SYM /* SQL-2003-R */ %token OPEN_SYM /* SQL-2003-R */
%token OPTIMIZE %token OPTIMIZE
...@@ -1475,14 +1586,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1475,14 +1586,21 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_option opt_if_not_exists opt_no_write_to_binlog table_option opt_if_not_exists opt_no_write_to_binlog
opt_temporary all_or_any opt_distinct opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option opt_ignore_leaves fulltext_options spatial_type union_option
start_transaction_opts field_def field_def
union_opt select_derived_init option_type2 union_opt select_derived_init transaction_access_mode_types
opt_natural_language_mode opt_query_expansion opt_natural_language_mode opt_query_expansion
opt_ev_status opt_ev_on_completion ev_on_completion opt_ev_comment 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 ev_alter_on_schedule_completion opt_ev_rename_to opt_ev_sql_stmt
optional_flush_tables_arguments opt_dyncol_type dyncol_type optional_flush_tables_arguments opt_dyncol_type dyncol_type
opt_time_precision kill_type kill_option int_num 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> %type <m_yes_no_unk>
opt_chain opt_release opt_chain opt_release
...@@ -1610,7 +1728,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1610,7 +1728,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
ref_list opt_match_clause opt_on_update_delete use ref_list opt_match_clause opt_on_update_delete use
opt_delete_options opt_delete_option varchar nchar nvarchar opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name table_alias_ref_list table_alias_ref 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_attribute opt_attribute_list attribute column_list column_list_id
opt_column_list grant_privileges grant_ident grant_list grant_option opt_column_list grant_privileges grant_ident grant_list grant_option
object_privilege object_privilege_list user_list rename_list object_privilege object_privilege_list user_list rename_list
...@@ -7100,20 +7218,56 @@ slave: ...@@ -7100,20 +7218,56 @@ slave:
; ;
start: start:
START_SYM TRANSACTION_SYM start_transaction_opts START_SYM TRANSACTION_SYM opt_start_transaction_option_list
{ {
LEX *lex= Lex; LEX *lex= Lex;
lex->sql_command= SQLCOM_BEGIN; 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; lex->start_transaction_opt= $3;
} }
; ;
start_transaction_opts: opt_start_transaction_option_list:
/*empty*/ { $$ = 0; } /* empty */
| WITH CONSISTENT_SYM SNAPSHOT_SYM {
$$= 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; $$= 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: slave_thread_opts:
...@@ -13148,6 +13302,7 @@ keyword_sp: ...@@ -13148,6 +13302,7 @@ keyword_sp:
| ONE_SHOT_SYM {} | ONE_SHOT_SYM {}
| ONE_SYM {} | ONE_SYM {}
| ONLINE_SYM {} | ONLINE_SYM {}
| ONLY_SYM {}
| PACK_KEYS_SYM {} | PACK_KEYS_SYM {}
| PAGE_SYM {} | PAGE_SYM {}
| PARTIAL {} | PARTIAL {}
...@@ -13271,8 +13426,15 @@ keyword_sp: ...@@ -13271,8 +13426,15 @@ keyword_sp:
/* Option functions */ /* 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:
SET opt_option SET
{ {
LEX *lex=Lex; LEX *lex=Lex;
lex->sql_command= SQLCOM_SET_OPTION; lex->sql_command= SQLCOM_SET_OPTION;
...@@ -13281,115 +13443,96 @@ set: ...@@ -13281,115 +13443,96 @@ set:
lex->var_list.empty(); lex->var_list.empty();
lex->one_shot_set= 0; lex->one_shot_set= 0;
lex->autocommit= 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: // Start of option value list
option_type_value start_option_value_list:
| option_value_list ',' option_type_value option_value_no_option_type
;
option_type_value:
{ {
THD *thd= YYTHD; if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
LEX *lex= thd->lex; MYSQL_YYABORT;
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();
}
} }
ext_option_value option_value_list_continued
| TRANSACTION_SYM
{ {
THD *thd= YYTHD; Lex->option_type= OPT_DEFAULT;
LEX *lex= thd->lex; }
Lex_input_stream *lip= YYLIP; transaction_characteristics
{
if (lex->sphead) if (sp_create_assignment_instr(YYTHD, yychar == YYEMPTY))
{ MYSQL_YYABORT;
sp_head *sp= lex->sphead; }
| 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, // Start of option value list, option_type was given
lex))) start_option_value_list_following_option_type:
MYSQL_YYABORT; 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;
}
;
/* // Remainder of the option value list after first option value.
Extract the query statement from the tokenizer. The option_value_list_continued:
end is either lip->ptr, if there was no lookahead, /* empty */
lip->tok_end otherwise. | ',' option_value_list
*/ ;
if (yychar == YYEMPTY)
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, // Repeating list of option values after first option value.
qbuff.length + 5))) option_value_list:
MYSQL_YYABORT; {
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, // Wrapper around option values following the first option value in the stmt.
qbuff.length); option_value:
qbuff.length+= 4; option_type
i->m_query= qbuff; {
if (sp->add_instr(i)) Lex->option_type= $1;
MYSQL_YYABORT;
}
if (lex->sphead->restore_lex(thd))
MYSQL_YYABORT;
}
} }
option_value_following_option_type
| option_value_no_option_type
; ;
option_type: option_type:
option_type2 {} GLOBAL_SYM { $$=OPT_GLOBAL; }
| GLOBAL_SYM { $$=OPT_GLOBAL; }
| LOCAL_SYM { $$=OPT_SESSION; } | LOCAL_SYM { $$=OPT_SESSION; }
| SESSION_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: opt_var_type:
/* empty */ { $$=OPT_SESSION; } /* empty */ { $$=OPT_SESSION; }
| GLOBAL_SYM { $$=OPT_GLOBAL; } | GLOBAL_SYM { $$=OPT_GLOBAL; }
...@@ -13404,74 +13547,62 @@ opt_var_ident_type: ...@@ -13404,74 +13547,62 @@ opt_var_ident_type:
| SESSION_SYM '.' { $$=OPT_SESSION; } | SESSION_SYM '.' { $$=OPT_SESSION; }
; ;
ext_option_value: // Option values with preceeding option_type.
sys_option_value option_value_following_option_type:
| option_type2 option_value 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 values without preceeding option_type.
option_type internal_variable_name equal set_expr_or_default option_value_no_option_type:
internal_variable_name equal set_expr_or_default
{ {
THD *thd= YYTHD; THD *thd= YYTHD;
LEX *lex= Lex; 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 */ /* We are in trigger and assigning value to field of new row */
if ($1) if (set_trigger_new_row(YYTHD, name, $3))
{
my_parse_error(ER(ER_SYNTAX_ERROR));
MYSQL_YYABORT;
}
if (set_trigger_new_row(YYTHD, name, $4))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
else if ($2.var) else if ($1.var)
{ {
if ($1)
lex->option_type= $1;
/* It is a system variable. */ /* 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; MYSQL_YYABORT;
} }
else else
{ {
sp_pcontext *spc= lex->spcont; sp_pcontext *spc= lex->spcont;
sp_variable_t *spv= spc->find_variable(name); sp_variable *spv= spc->find_variable(name, false);
if ($1)
{
my_parse_error(ER(ER_SYNTAX_ERROR));
MYSQL_YYABORT;
}
/* It is a local variable. */ /* It is a local variable. */
if (set_local_variable(thd, spv, $4)) if (set_local_variable(thd, spv, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
} }
| option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types | '@' ident_or_text equal expr
{
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
{ {
Item_func_set_user_var *item; Item_func_set_user_var *item;
item= new (YYTHD->mem_root) Item_func_set_user_var($2, $4); item= new (YYTHD->mem_root) Item_func_set_user_var($2, $4);
...@@ -13517,7 +13648,7 @@ option_value: ...@@ -13517,7 +13648,7 @@ option_value:
names.str= (char *)"names"; names.str= (char *)"names";
names.length= 5; 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); my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), names.str);
else else
my_parse_error(ER(ER_SYNTAX_ERROR)); my_parse_error(ER(ER_SYNTAX_ERROR));
...@@ -13553,7 +13684,7 @@ option_value: ...@@ -13553,7 +13684,7 @@ option_value:
pw.str= (char *)"password"; pw.str= (char *)"password";
pw.length= 8; 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); my_error(ER_SP_BAD_VAR_SHADOW, MYF(0), pw.str);
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -13562,6 +13693,7 @@ option_value: ...@@ -13562,6 +13693,7 @@ option_value:
MYSQL_YYABORT; MYSQL_YYABORT;
user->host=null_lex_str; user->host=null_lex_str;
user->user.str=thd->security_ctx->user; 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); set_var_password *var= new set_var_password(user, $3);
if (var == NULL) if (var == NULL)
MYSQL_YYABORT; MYSQL_YYABORT;
...@@ -13666,6 +13798,54 @@ internal_variable_name: ...@@ -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: isolation_types:
READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; } READ_SYM UNCOMMITTED_SYM { $$= ISO_READ_UNCOMMITTED; }
| READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; } | READ_SYM COMMITTED_SYM { $$= ISO_READ_COMMITTED; }
......
...@@ -636,273 +636,274 @@ lex_token_string lex_token_array[]= ...@@ -636,273 +636,274 @@ lex_token_string lex_token_array[]=
/* 617 */ { "ON", 2}, /* 617 */ { "ON", 2},
/* 618 */ { "ONE_SHOT", 8}, /* 618 */ { "ONE_SHOT", 8},
/* 619 */ { "ONE", 3}, /* 619 */ { "ONE", 3},
/* 620 */ { "ONLINE", 6}, /* 620 */ { "ONLY", 4},
/* 621 */ { "OPEN", 4}, /* 621 */ { "ONLINE", 6},
/* 622 */ { "OPTIMIZE", 8}, /* 622 */ { "OPEN", 4},
/* 623 */ { "OPTIONS", 7}, /* 623 */ { "OPTIMIZE", 8},
/* 624 */ { "OPTION", 6}, /* 624 */ { "OPTIONS", 7},
/* 625 */ { "OPTIONALLY", 10}, /* 625 */ { "OPTION", 6},
/* 626 */ { "|", 1}, /* 626 */ { "OPTIONALLY", 10},
/* 627 */ { "ORDER", 5}, /* 627 */ { "|", 1},
/* 628 */ { "||", 2}, /* 628 */ { "ORDER", 5},
/* 629 */ { "OR", 2}, /* 629 */ { "||", 2},
/* 630 */ { "OUTER", 5}, /* 630 */ { "OR", 2},
/* 631 */ { "OUTFILE", 7}, /* 631 */ { "OUTER", 5},
/* 632 */ { "OUT", 3}, /* 632 */ { "OUTFILE", 7},
/* 633 */ { "OWNER", 5}, /* 633 */ { "OUT", 3},
/* 634 */ { "PACK_KEYS", 9}, /* 634 */ { "OWNER", 5},
/* 635 */ { "PAGE", 4}, /* 635 */ { "PACK_KEYS", 9},
/* 636 */ { "PAGE_CHECKSUM", 13}, /* 636 */ { "PAGE", 4},
/* 637 */ { "?", 1}, /* 637 */ { "PAGE_CHECKSUM", 13},
/* 638 */ { "PARSER", 6}, /* 638 */ { "?", 1},
/* 639 */ { "PARSE_VCOL_EXPR", 15}, /* 639 */ { "PARSER", 6},
/* 640 */ { "PARTIAL", 7}, /* 640 */ { "PARSE_VCOL_EXPR", 15},
/* 641 */ { "PARTITIONING", 12}, /* 641 */ { "PARTIAL", 7},
/* 642 */ { "PARTITIONS", 10}, /* 642 */ { "PARTITIONING", 12},
/* 643 */ { "PARTITION", 9}, /* 643 */ { "PARTITIONS", 10},
/* 644 */ { "PASSWORD", 8}, /* 644 */ { "PARTITION", 9},
/* 645 */ { "PERSISTENT", 10}, /* 645 */ { "PASSWORD", 8},
/* 646 */ { "PHASE", 5}, /* 646 */ { "PERSISTENT", 10},
/* 647 */ { "PLUGINS", 7}, /* 647 */ { "PHASE", 5},
/* 648 */ { "PLUGIN", 6}, /* 648 */ { "PLUGINS", 7},
/* 649 */ { "POINT", 5}, /* 649 */ { "PLUGIN", 6},
/* 650 */ { "POLYGON", 7}, /* 650 */ { "POINT", 5},
/* 651 */ { "PORT", 4}, /* 651 */ { "POLYGON", 7},
/* 652 */ { "POSITION", 8}, /* 652 */ { "PORT", 4},
/* 653 */ { "PRECISION", 9}, /* 653 */ { "POSITION", 8},
/* 654 */ { "PREPARE", 7}, /* 654 */ { "PRECISION", 9},
/* 655 */ { "PRESERVE", 8}, /* 655 */ { "PREPARE", 7},
/* 656 */ { "PREV", 4}, /* 656 */ { "PRESERVE", 8},
/* 657 */ { "PRIMARY", 7}, /* 657 */ { "PREV", 4},
/* 658 */ { "PRIVILEGES", 10}, /* 658 */ { "PRIMARY", 7},
/* 659 */ { "PROCEDURE", 9}, /* 659 */ { "PRIVILEGES", 10},
/* 660 */ { "PROCESS", 7}, /* 660 */ { "PROCEDURE", 9},
/* 661 */ { "PROCESSLIST", 11}, /* 661 */ { "PROCESS", 7},
/* 662 */ { "PROFILE", 7}, /* 662 */ { "PROCESSLIST", 11},
/* 663 */ { "PROFILES", 8}, /* 663 */ { "PROFILE", 7},
/* 664 */ { "PROXY", 5}, /* 664 */ { "PROFILES", 8},
/* 665 */ { "PURGE", 5}, /* 665 */ { "PROXY", 5},
/* 666 */ { "SQL_TSI_QUARTER", 15}, /* 666 */ { "PURGE", 5},
/* 667 */ { "QUERY", 5}, /* 667 */ { "SQL_TSI_QUARTER", 15},
/* 668 */ { "QUICK", 5}, /* 668 */ { "QUERY", 5},
/* 669 */ { "RANGE", 5}, /* 669 */ { "QUICK", 5},
/* 670 */ { "READS", 5}, /* 670 */ { "RANGE", 5},
/* 671 */ { "READ_ONLY", 9}, /* 671 */ { "READS", 5},
/* 672 */ { "READ", 4}, /* 672 */ { "READ_ONLY", 9},
/* 673 */ { "READ_WRITE", 10}, /* 673 */ { "READ", 4},
/* 674 */ { "REAL", 4}, /* 674 */ { "READ_WRITE", 10},
/* 675 */ { "REBUILD", 7}, /* 675 */ { "REAL", 4},
/* 676 */ { "RECOVER", 7}, /* 676 */ { "REBUILD", 7},
/* 677 */ { "REDOFILE", 8}, /* 677 */ { "RECOVER", 7},
/* 678 */ { "REDO_BUFFER_SIZE", 16}, /* 678 */ { "REDOFILE", 8},
/* 679 */ { "REDUNDANT", 9}, /* 679 */ { "REDO_BUFFER_SIZE", 16},
/* 680 */ { "REFERENCES", 10}, /* 680 */ { "REDUNDANT", 9},
/* 681 */ { "RLIKE", 5}, /* 681 */ { "REFERENCES", 10},
/* 682 */ { "RELAY", 5}, /* 682 */ { "RLIKE", 5},
/* 683 */ { "RELAYLOG", 8}, /* 683 */ { "RELAY", 5},
/* 684 */ { "RELAY_LOG_FILE", 14}, /* 684 */ { "RELAYLOG", 8},
/* 685 */ { "RELAY_LOG_POS", 13}, /* 685 */ { "RELAY_LOG_FILE", 14},
/* 686 */ { "RELAY_THREAD", 12}, /* 686 */ { "RELAY_LOG_POS", 13},
/* 687 */ { "RELEASE", 7}, /* 687 */ { "RELAY_THREAD", 12},
/* 688 */ { "RELOAD", 6}, /* 688 */ { "RELEASE", 7},
/* 689 */ { "REMOVE", 6}, /* 689 */ { "RELOAD", 6},
/* 690 */ { "RENAME", 6}, /* 690 */ { "REMOVE", 6},
/* 691 */ { "REORGANIZE", 10}, /* 691 */ { "RENAME", 6},
/* 692 */ { "REPAIR", 6}, /* 692 */ { "REORGANIZE", 10},
/* 693 */ { "REPEATABLE", 10}, /* 693 */ { "REPAIR", 6},
/* 694 */ { "REPEAT", 6}, /* 694 */ { "REPEATABLE", 10},
/* 695 */ { "REPLACE", 7}, /* 695 */ { "REPEAT", 6},
/* 696 */ { "REPLICATION", 11}, /* 696 */ { "REPLACE", 7},
/* 697 */ { "REQUIRE", 7}, /* 697 */ { "REPLICATION", 11},
/* 698 */ { "RESET", 5}, /* 698 */ { "REQUIRE", 7},
/* 699 */ { "RESIGNAL", 8}, /* 699 */ { "RESET", 5},
/* 700 */ { "USER_RESOURCES", 14}, /* 700 */ { "RESIGNAL", 8},
/* 701 */ { "RESTORE", 7}, /* 701 */ { "USER_RESOURCES", 14},
/* 702 */ { "RESTRICT", 8}, /* 702 */ { "RESTORE", 7},
/* 703 */ { "RESUME", 6}, /* 703 */ { "RESTRICT", 8},
/* 704 */ { "RETURNS", 7}, /* 704 */ { "RESUME", 6},
/* 705 */ { "RETURN", 6}, /* 705 */ { "RETURNS", 7},
/* 706 */ { "REVOKE", 6}, /* 706 */ { "RETURN", 6},
/* 707 */ { "RIGHT", 5}, /* 707 */ { "REVOKE", 6},
/* 708 */ { "ROLLBACK", 8}, /* 708 */ { "RIGHT", 5},
/* 709 */ { "ROLLUP", 6}, /* 709 */ { "ROLLBACK", 8},
/* 710 */ { "ROUTINE", 7}, /* 710 */ { "ROLLUP", 6},
/* 711 */ { "ROWS", 4}, /* 711 */ { "ROUTINE", 7},
/* 712 */ { "ROW_FORMAT", 10}, /* 712 */ { "ROWS", 4},
/* 713 */ { "ROW", 3}, /* 713 */ { "ROW_FORMAT", 10},
/* 714 */ { "RTREE", 5}, /* 714 */ { "ROW", 3},
/* 715 */ { "SAVEPOINT", 9}, /* 715 */ { "RTREE", 5},
/* 716 */ { "SCHEDULE", 8}, /* 716 */ { "SAVEPOINT", 9},
/* 717 */ { "SCHEMA_NAME", 11}, /* 717 */ { "SCHEDULE", 8},
/* 718 */ { "SECOND_MICROSECOND", 18}, /* 718 */ { "SCHEMA_NAME", 11},
/* 719 */ { "SQL_TSI_SECOND", 14}, /* 719 */ { "SECOND_MICROSECOND", 18},
/* 720 */ { "SECURITY", 8}, /* 720 */ { "SQL_TSI_SECOND", 14},
/* 721 */ { "SELECT", 6}, /* 721 */ { "SECURITY", 8},
/* 722 */ { "SENSITIVE", 9}, /* 722 */ { "SELECT", 6},
/* 723 */ { "SEPARATOR", 9}, /* 723 */ { "SENSITIVE", 9},
/* 724 */ { "SERIALIZABLE", 12}, /* 724 */ { "SEPARATOR", 9},
/* 725 */ { "SERIAL", 6}, /* 725 */ { "SERIALIZABLE", 12},
/* 726 */ { "SESSION", 7}, /* 726 */ { "SERIAL", 6},
/* 727 */ { "SERVER", 6}, /* 727 */ { "SESSION", 7},
/* 728 */ { "SERVER_OPTIONS", 14}, /* 728 */ { "SERVER", 6},
/* 729 */ { "SET", 3}, /* 729 */ { "SERVER_OPTIONS", 14},
/* 730 */ { ":=", 2}, /* 730 */ { "SET", 3},
/* 731 */ { "SHARE", 5}, /* 731 */ { ":=", 2},
/* 732 */ { "<<", 2}, /* 732 */ { "SHARE", 5},
/* 733 */ { ">>", 2}, /* 733 */ { "<<", 2},
/* 734 */ { "SHOW", 4}, /* 734 */ { ">>", 2},
/* 735 */ { "SHUTDOWN", 8}, /* 735 */ { "SHOW", 4},
/* 736 */ { "SIGNAL", 6}, /* 736 */ { "SHUTDOWN", 8},
/* 737 */ { "SIGNED", 6}, /* 737 */ { "SIGNAL", 6},
/* 738 */ { "SIMPLE", 6}, /* 738 */ { "SIGNED", 6},
/* 739 */ { "SLAVE", 5}, /* 739 */ { "SIMPLE", 6},
/* 740 */ { "SLOW", 4}, /* 740 */ { "SLAVE", 5},
/* 741 */ { "SMALLINT", 8}, /* 741 */ { "SLOW", 4},
/* 742 */ { "SNAPSHOT", 8}, /* 742 */ { "SMALLINT", 8},
/* 743 */ { "SOCKET", 6}, /* 743 */ { "SNAPSHOT", 8},
/* 744 */ { "SOFT", 4}, /* 744 */ { "SOCKET", 6},
/* 745 */ { "SONAME", 6}, /* 745 */ { "SOFT", 4},
/* 746 */ { "SOUNDS", 6}, /* 746 */ { "SONAME", 6},
/* 747 */ { "SOURCE", 6}, /* 747 */ { "SOUNDS", 6},
/* 748 */ { "SPATIAL", 7}, /* 748 */ { "SOURCE", 6},
/* 749 */ { "SPECIFIC", 8}, /* 749 */ { "SPATIAL", 7},
/* 750 */ { "SQLEXCEPTION", 12}, /* 750 */ { "SPECIFIC", 8},
/* 751 */ { "SQLSTATE", 8}, /* 751 */ { "SQLEXCEPTION", 12},
/* 752 */ { "SQLWARNING", 10}, /* 752 */ { "SQLSTATE", 8},
/* 753 */ { "SQL_BIG_RESULT", 14}, /* 753 */ { "SQLWARNING", 10},
/* 754 */ { "SQL_BUFFER_RESULT", 17}, /* 754 */ { "SQL_BIG_RESULT", 14},
/* 755 */ { "SQL_CACHE", 9}, /* 755 */ { "SQL_BUFFER_RESULT", 17},
/* 756 */ { "SQL_CALC_FOUND_ROWS", 19}, /* 756 */ { "SQL_CACHE", 9},
/* 757 */ { "SQL_NO_CACHE", 12}, /* 757 */ { "SQL_CALC_FOUND_ROWS", 19},
/* 758 */ { "SQL_SMALL_RESULT", 16}, /* 758 */ { "SQL_NO_CACHE", 12},
/* 759 */ { "SQL", 3}, /* 759 */ { "SQL_SMALL_RESULT", 16},
/* 760 */ { "SQL_THREAD", 10}, /* 760 */ { "SQL", 3},
/* 761 */ { "SSL", 3}, /* 761 */ { "SQL_THREAD", 10},
/* 762 */ { "STARTING", 8}, /* 762 */ { "SSL", 3},
/* 763 */ { "STARTS", 6}, /* 763 */ { "STARTING", 8},
/* 764 */ { "START", 5}, /* 764 */ { "STARTS", 6},
/* 765 */ { "STATUS", 6}, /* 765 */ { "START", 5},
/* 766 */ { "STDDEV_SAMP", 11}, /* 766 */ { "STATUS", 6},
/* 767 */ { "STDDEV_POP", 10}, /* 767 */ { "STDDEV_SAMP", 11},
/* 768 */ { "STOP", 4}, /* 768 */ { "STDDEV_POP", 10},
/* 769 */ { "STORAGE", 7}, /* 769 */ { "STOP", 4},
/* 770 */ { "STRAIGHT_JOIN", 13}, /* 770 */ { "STORAGE", 7},
/* 771 */ { "STRING", 6}, /* 771 */ { "STRAIGHT_JOIN", 13},
/* 772 */ { "SUBCLASS_ORIGIN", 15}, /* 772 */ { "STRING", 6},
/* 773 */ { "SUBDATE", 7}, /* 773 */ { "SUBCLASS_ORIGIN", 15},
/* 774 */ { "SUBJECT", 7}, /* 774 */ { "SUBDATE", 7},
/* 775 */ { "SUBPARTITIONS", 13}, /* 775 */ { "SUBJECT", 7},
/* 776 */ { "SUBPARTITION", 12}, /* 776 */ { "SUBPARTITIONS", 13},
/* 777 */ { "SUBSTRING", 9}, /* 777 */ { "SUBPARTITION", 12},
/* 778 */ { "SUM", 3}, /* 778 */ { "SUBSTRING", 9},
/* 779 */ { "SUPER", 5}, /* 779 */ { "SUM", 3},
/* 780 */ { "SUSPEND", 7}, /* 780 */ { "SUPER", 5},
/* 781 */ { "SWAPS", 5}, /* 781 */ { "SUSPEND", 7},
/* 782 */ { "SWITCHES", 8}, /* 782 */ { "SWAPS", 5},
/* 783 */ { "SYSDATE", 7}, /* 783 */ { "SWITCHES", 8},
/* 784 */ { "TABLES", 6}, /* 784 */ { "SYSDATE", 7},
/* 785 */ { "TABLESPACE", 10}, /* 785 */ { "TABLES", 6},
/* 786 */ { "TABLE_REF_PRIORITY", 18}, /* 786 */ { "TABLESPACE", 10},
/* 787 */ { "TABLE_STATISTICS", 16}, /* 787 */ { "TABLE_REF_PRIORITY", 18},
/* 788 */ { "TABLE", 5}, /* 788 */ { "TABLE_STATISTICS", 16},
/* 789 */ { "TABLE_CHECKSUM", 14}, /* 789 */ { "TABLE", 5},
/* 790 */ { "TABLE_NAME", 10}, /* 790 */ { "TABLE_CHECKSUM", 14},
/* 791 */ { "TEMPORARY", 9}, /* 791 */ { "TABLE_NAME", 10},
/* 792 */ { "TEMPTABLE", 9}, /* 792 */ { "TEMPORARY", 9},
/* 793 */ { "TERMINATED", 10}, /* 793 */ { "TEMPTABLE", 9},
/* 794 */ { "(text)", 6}, /* 794 */ { "TERMINATED", 10},
/* 795 */ { "TEXT", 4}, /* 795 */ { "(text)", 6},
/* 796 */ { "THAN", 4}, /* 796 */ { "TEXT", 4},
/* 797 */ { "THEN", 4}, /* 797 */ { "THAN", 4},
/* 798 */ { "TIMESTAMP", 9}, /* 798 */ { "THEN", 4},
/* 799 */ { "TIMESTAMPADD", 12}, /* 799 */ { "TIMESTAMP", 9},
/* 800 */ { "TIMESTAMPDIFF", 13}, /* 800 */ { "TIMESTAMPADD", 12},
/* 801 */ { "TIME", 4}, /* 801 */ { "TIMESTAMPDIFF", 13},
/* 802 */ { "TINYBLOB", 8}, /* 802 */ { "TIME", 4},
/* 803 */ { "TINYINT", 7}, /* 803 */ { "TINYBLOB", 8},
/* 804 */ { "TINYTEXT", 8}, /* 804 */ { "TINYINT", 7},
/* 805 */ { "TO", 2}, /* 805 */ { "TINYTEXT", 8},
/* 806 */ { "TRAILING", 8}, /* 806 */ { "TO", 2},
/* 807 */ { "TRANSACTION", 11}, /* 807 */ { "TRAILING", 8},
/* 808 */ { "TRANSACTIONAL", 13}, /* 808 */ { "TRANSACTION", 11},
/* 809 */ { "TRIGGERS", 8}, /* 809 */ { "TRANSACTIONAL", 13},
/* 810 */ { "TRIGGER", 7}, /* 810 */ { "TRIGGERS", 8},
/* 811 */ { "TRIM", 4}, /* 811 */ { "TRIGGER", 7},
/* 812 */ { "TRUE", 4}, /* 812 */ { "TRIM", 4},
/* 813 */ { "TRUNCATE", 8}, /* 813 */ { "TRUE", 4},
/* 814 */ { "TYPES", 5}, /* 814 */ { "TRUNCATE", 8},
/* 815 */ { "TYPE", 4}, /* 815 */ { "TYPES", 5},
/* 816 */ { "UDF_RETURNS", 11}, /* 816 */ { "TYPE", 4},
/* 817 */ { "(ulonglong)", 11}, /* 817 */ { "UDF_RETURNS", 11},
/* 818 */ { "UNCOMMITTED", 11}, /* 818 */ { "(ulonglong)", 11},
/* 819 */ { "UNDEFINED", 9}, /* 819 */ { "UNCOMMITTED", 11},
/* 820 */ { "(_charset)", 10}, /* 820 */ { "UNDEFINED", 9},
/* 821 */ { "UNDOFILE", 8}, /* 821 */ { "(_charset)", 10},
/* 822 */ { "UNDO_BUFFER_SIZE", 16}, /* 822 */ { "UNDOFILE", 8},
/* 823 */ { "UNDO", 4}, /* 823 */ { "UNDO_BUFFER_SIZE", 16},
/* 824 */ { "UNICODE", 7}, /* 824 */ { "UNDO", 4},
/* 825 */ { "UNINSTALL", 9}, /* 825 */ { "UNICODE", 7},
/* 826 */ { "UNION", 5}, /* 826 */ { "UNINSTALL", 9},
/* 827 */ { "UNIQUE", 6}, /* 827 */ { "UNION", 5},
/* 828 */ { "UNKNOWN", 7}, /* 828 */ { "UNIQUE", 6},
/* 829 */ { "UNLOCK", 6}, /* 829 */ { "UNKNOWN", 7},
/* 830 */ { "UNSIGNED", 8}, /* 830 */ { "UNLOCK", 6},
/* 831 */ { "UNTIL", 5}, /* 831 */ { "UNSIGNED", 8},
/* 832 */ { "UPDATE", 6}, /* 832 */ { "UNTIL", 5},
/* 833 */ { "UPGRADE", 7}, /* 833 */ { "UPDATE", 6},
/* 834 */ { "USAGE", 5}, /* 834 */ { "UPGRADE", 7},
/* 835 */ { "SYSTEM_USER", 11}, /* 835 */ { "USAGE", 5},
/* 836 */ { "USER_STATISTICS", 15}, /* 836 */ { "SYSTEM_USER", 11},
/* 837 */ { "USE_FRM", 7}, /* 837 */ { "USER_STATISTICS", 15},
/* 838 */ { "USE", 3}, /* 838 */ { "USE_FRM", 7},
/* 839 */ { "USING", 5}, /* 839 */ { "USE", 3},
/* 840 */ { "UTC_DATE", 8}, /* 840 */ { "USING", 5},
/* 841 */ { "UTC_TIMESTAMP", 13}, /* 841 */ { "UTC_DATE", 8},
/* 842 */ { "UTC_TIME", 8}, /* 842 */ { "UTC_TIMESTAMP", 13},
/* 843 */ { "VALUES", 6}, /* 843 */ { "UTC_TIME", 8},
/* 844 */ { "VALUE", 5}, /* 844 */ { "VALUES", 6},
/* 845 */ { "VARBINARY", 9}, /* 845 */ { "VALUE", 5},
/* 846 */ { "VARCHARACTER", 12}, /* 846 */ { "VARBINARY", 9},
/* 847 */ { "VARIABLES", 9}, /* 847 */ { "VARCHARACTER", 12},
/* 848 */ { "VAR_POP", 7}, /* 848 */ { "VARIABLES", 9},
/* 849 */ { "VARYING", 7}, /* 849 */ { "VAR_POP", 7},
/* 850 */ { "VAR_SAMP", 8}, /* 850 */ { "VARYING", 7},
/* 851 */ { "VIA", 3}, /* 851 */ { "VAR_SAMP", 8},
/* 852 */ { "VIEW", 4}, /* 852 */ { "VIA", 3},
/* 853 */ { "VIRTUAL", 7}, /* 853 */ { "VIEW", 4},
/* 854 */ { "WAIT", 4}, /* 854 */ { "VIRTUAL", 7},
/* 855 */ { "WARNINGS", 8}, /* 855 */ { "WAIT", 4},
/* 856 */ { "WEEK", 4}, /* 856 */ { "WARNINGS", 8},
/* 857 */ { "WHEN", 4}, /* 857 */ { "WEEK", 4},
/* 858 */ { "WHERE", 5}, /* 858 */ { "WHEN", 4},
/* 859 */ { "WHILE", 5}, /* 859 */ { "WHERE", 5},
/* 860 */ { "WITH", 4}, /* 860 */ { "WHILE", 5},
/* 861 */ { "WITH CUBE", 9}, /* 861 */ { "WITH", 4},
/* 862 */ { "WITH ROLLUP", 11}, /* 862 */ { "WITH CUBE", 9},
/* 863 */ { "WORK", 4}, /* 863 */ { "WITH ROLLUP", 11},
/* 864 */ { "WRAPPER", 7}, /* 864 */ { "WORK", 4},
/* 865 */ { "WRITE", 5}, /* 865 */ { "WRAPPER", 7},
/* 866 */ { "X509", 4}, /* 866 */ { "WRITE", 5},
/* 867 */ { "XA", 2}, /* 867 */ { "X509", 4},
/* 868 */ { "XML", 3}, /* 868 */ { "XA", 2},
/* 869 */ { "XOR", 3}, /* 869 */ { "XML", 3},
/* 870 */ { "YEAR_MONTH", 10}, /* 870 */ { "XOR", 3},
/* 871 */ { "YEAR", 4}, /* 871 */ { "YEAR_MONTH", 10},
/* 872 */ { "ZEROFILL", 8}, /* 872 */ { "YEAR", 4},
/* 873 */ { "?", 1}, /* 873 */ { "ZEROFILL", 8},
/* 874 */ { "?, ...", 6}, /* 874 */ { "?", 1},
/* 875 */ { "(?)", 3}, /* 875 */ { "?, ...", 6},
/* 876 */ { "(?) /* , ... */", 15}, /* 876 */ { "(?)", 3},
/* 877 */ { "(...)", 5}, /* 877 */ { "(?) /* , ... */", 15},
/* 878 */ { "(...) /* , ... */", 17}, /* 878 */ { "(...)", 5},
/* 879 */ { "UNUSED", 6}, /* 879 */ { "(...) /* , ... */", 17},
/* 880 */ { "UNUSED", 6},
/* DUMMY */ { "", 0} /* DUMMY */ { "", 0}
}; };
/* PFS specific tokens. */ /* PFS specific tokens. */
#define TOK_PFS_GENERIC_VALUE 873 #define TOK_PFS_GENERIC_VALUE 874
#define TOK_PFS_GENERIC_VALUE_LIST 874 #define TOK_PFS_GENERIC_VALUE_LIST 875
#define TOK_PFS_ROW_SINGLE_VALUE 875 #define TOK_PFS_ROW_SINGLE_VALUE 876
#define TOK_PFS_ROW_SINGLE_VALUE_LIST 876 #define TOK_PFS_ROW_SINGLE_VALUE_LIST 877
#define TOK_PFS_ROW_MULTIPLE_VALUE 877 #define TOK_PFS_ROW_MULTIPLE_VALUE 878
#define TOK_PFS_ROW_MULTIPLE_VALUE_LIST 878 #define TOK_PFS_ROW_MULTIPLE_VALUE_LIST 879
#define TOK_PFS_UNUSED 879 #define TOK_PFS_UNUSED 880
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