diff options
author | Michael Widenius <monty@askmonty.org> | 2012-08-07 07:25:15 +0300 |
---|---|---|
committer | Michael Widenius <monty@askmonty.org> | 2012-08-07 07:25:15 +0300 |
commit | b39e6e3d093b45f792959ef06fea1c175263ae1a (patch) | |
tree | b642aba6ff438e50d67a884f4cb5d9c6c3287644 /sql/sql_parse.cc | |
parent | 0a70eb33d159036c5d3f6929df57c2f18bda8471 (diff) | |
download | mariadb-git-b39e6e3d093b45f792959ef06fea1c175263ae1a.tar.gz |
Added support of thd->tx_read_only
Moved timestamp handling from all handler::write() methods in the storage engines to handler::ha_write
sql/handler.cc:
Added PSI_CALL's
Diffstat (limited to 'sql/sql_parse.cc')
-rw-r--r-- | sql/sql_parse.cc | 184 |
1 files changed, 171 insertions, 13 deletions
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 17a6cf0f379..19a8ba2b533 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -291,26 +291,54 @@ void init_update_queries(void) sql_command_flags[SQLCOM_DROP_EVENT]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_UPDATE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_UPDATE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_INSERT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_INSERT_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_DELETE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_DELETE_MULTI]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED;; sql_command_flags[SQLCOM_REPLACE]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED;; sql_command_flags[SQLCOM_REPLACE_SELECT]= CF_CHANGES_DATA | CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; sql_command_flags[SQLCOM_SELECT]= CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; - sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | CF_AUTO_COMMIT_TRANS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE | + CF_CAN_BE_EXPLAINED; + // (1) so that subquery is traced when doing "SET @var = (subquery)" + /* + @todo SQLCOM_SET_OPTION should have CF_CAN_GENERATE_ROW_EVENTS + set, because it may invoke a stored function that generates row + events. /Sven + */ + sql_command_flags[SQLCOM_SET_OPTION]= CF_REEXECUTION_FRAGILE | + CF_AUTO_COMMIT_TRANS | + CF_OPTIMIZER_TRACE; // (1) + // (1) so that subquery is traced when doing "DO @var := (subquery)" sql_command_flags[SQLCOM_DO]= CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE; // (1) sql_command_flags[SQLCOM_SHOW_STATUS_PROC]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE; sql_command_flags[SQLCOM_SHOW_STATUS]= CF_STATUS_COMMAND | CF_REEXECUTION_FRAGILE; @@ -351,6 +379,11 @@ void init_update_queries(void) sql_command_flags[SQLCOM_SHOW_CREATE_EVENT]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROFILES]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_PROFILE]= CF_STATUS_COMMAND; + /* + @todo SQLCOM_BINLOG_BASE64_EVENT should have + CF_CAN_GENERATE_ROW_EVENTS set, because this surely generates row + events. /Sven + */ sql_command_flags[SQLCOM_BINLOG_BASE64_EVENT]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_CLIENT_STATS]= CF_STATUS_COMMAND; sql_command_flags[SQLCOM_SHOW_USER_STATS]= CF_STATUS_COMMAND; @@ -366,6 +399,12 @@ void init_update_queries(void) sql_command_flags[SQLCOM_GRANT]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_REVOKE]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_OPTIMIZE]= CF_CHANGES_DATA; + /* + @todo SQLCOM_CREATE_FUNCTION should have CF_AUTO_COMMIT_TRANS + set. this currently is binlogged *before* the transaction if + executed inside a transaction because it does not have an implicit + pre-commit and is written to the statement cache. /Sven + */ sql_command_flags[SQLCOM_CREATE_FUNCTION]= CF_CHANGES_DATA; sql_command_flags[SQLCOM_CREATE_PROCEDURE]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_CREATE_SPFUNCTION]= CF_CHANGES_DATA | CF_AUTO_COMMIT_TRANS; @@ -382,8 +421,13 @@ void init_update_queries(void) last called (or executed) statement is preserved. See mysql_execute_command() for how CF_ROW_COUNT is used. */ + /* + (1): without it, in "CALL some_proc((subq))", subquery would not be + traced. + */ sql_command_flags[SQLCOM_CALL]= CF_REEXECUTION_FRAGILE | - CF_CAN_GENERATE_ROW_EVENTS; + CF_CAN_GENERATE_ROW_EVENTS | + CF_OPTIMIZER_TRACE; // (1) sql_command_flags[SQLCOM_EXECUTE]= CF_CAN_GENERATE_ROW_EVENTS; /* @@ -411,6 +455,104 @@ void init_update_queries(void) sql_command_flags[SQLCOM_CREATE_SERVER]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_ALTER_SERVER]= CF_AUTO_COMMIT_TRANS; sql_command_flags[SQLCOM_DROP_SERVER]= CF_AUTO_COMMIT_TRANS; + + /* + The following statements can deal with temporary tables, + so temporary tables should be pre-opened for those statements to + simplify privilege checking. + + There are other statements that deal with temporary tables and open + them, but which are not listed here. The thing is that the order of + pre-opening temporary tables for those statements is somewhat custom. + */ + sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_DROP_TABLE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_TRUNCATE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_LOAD]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_DROP_INDEX]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_UPDATE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_UPDATE_MULTI]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_INSERT_SELECT]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_DELETE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_DELETE_MULTI]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_REPLACE_SELECT]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_SELECT]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_SET_OPTION]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_DO]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_CALL]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_CHECKSUM]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_ANALYZE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_CHECK]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_OPTIMIZE]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_REPAIR]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_PRELOAD_KEYS]|= CF_PREOPEN_TMP_TABLES; + sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_PREOPEN_TMP_TABLES; + + /* + DDL statements that should start with closing opened handlers. + + We use this flag only for statements for which open HANDLERs + have to be closed before emporary tables are pre-opened. + */ + sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_DROP_TABLE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_TRUNCATE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_REPAIR]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_OPTIMIZE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_ANALYZE]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_CHECK]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_DROP_INDEX]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_PRELOAD_KEYS]|= CF_HA_CLOSE; + sql_command_flags[SQLCOM_ASSIGN_TO_KEYCACHE]|= CF_HA_CLOSE; + + /* + Mark statements that always are disallowed in read-only + transactions. Note that according to the SQL standard, + even temporary table DDL should be disallowed. + */ + sql_command_flags[SQLCOM_CREATE_TABLE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_TABLE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_TABLE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_RENAME_TABLE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_INDEX]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_INDEX]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_DB]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_DB]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_DB_UPGRADE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_DB]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_VIEW]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_VIEW]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_TRIGGER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_TRIGGER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_EVENT]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_EVENT]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_EVENT]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_USER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_RENAME_USER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_USER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_SERVER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_SERVER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_SERVER]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_CREATE_SPFUNCTION]|=CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_DROP_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_PROCEDURE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_FUNCTION]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_TRUNCATE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_ALTER_TABLESPACE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_REPAIR]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_OPTIMIZE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_GRANT]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_REVOKE]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_REVOKE_ALL]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_INSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS; + sql_command_flags[SQLCOM_UNINSTALL_PLUGIN]|= CF_DISALLOW_IN_RO_TRANS; } bool sqlcom_can_generate_row_events(const THD *thd) @@ -2115,6 +2257,19 @@ mysql_execute_command(THD *thd) DEBUG_SYNC(thd,"before_execute_sql_command"); #endif + /* + Check if we are in a read-only transaction and we're trying to + execute a statement which should always be disallowed in such cases. + + Note that this check is done after any implicit commits. + */ + if (thd->tx_read_only && + (sql_command_flags[lex->sql_command] & CF_DISALLOW_IN_RO_TRANS)) + { + my_error(ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION, MYF(0)); + goto error; + } + switch (lex->sql_command) { case SQLCOM_SHOW_EVENTS: @@ -3766,12 +3921,13 @@ end_with_restore_list: if (tx_chain) { if (trans_begin(thd)) - goto error; + goto error; } else { /* 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) @@ -4325,6 +4481,7 @@ create_sp_error: isolation level to the session default. */ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + thd->tx_read_only= thd->variables.tx_read_only; my_ok(thd); break; case SQLCOM_XA_ROLLBACK: @@ -4336,6 +4493,7 @@ create_sp_error: isolation level to the session default. */ thd->tx_isolation= (enum_tx_isolation) thd->variables.tx_isolation; + thd->tx_read_only= thd->variables.tx_read_only; my_ok(thd); break; case SQLCOM_XA_RECOVER: |