diff options
Diffstat (limited to 'sql/sql_lex.h')
-rw-r--r-- | sql/sql_lex.h | 221 |
1 files changed, 188 insertions, 33 deletions
diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 2635a31f1a3..c6662501cf6 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -47,6 +47,53 @@ class Key; class File_parser; class Key_part_spec; +#ifdef MYSQL_SERVER +/* + There are 8 different type of table access so there is no more than + combinations 2^8 = 256: + + . STMT_READS_TRANS_TABLE + + . STMT_READS_NON_TRANS_TABLE + + . STMT_READS_TEMP_TRANS_TABLE + + . STMT_READS_TEMP_NON_TRANS_TABLE + + . STMT_WRITES_TRANS_TABLE + + . STMT_WRITES_NON_TRANS_TABLE + + . STMT_WRITES_TEMP_TRANS_TABLE + + . STMT_WRITES_TEMP_NON_TRANS_TABLE + + The unsafe conditions for each combination is represented within a byte + and stores the status of the option --binlog-direct-non-trans-updates, + whether the trx-cache is empty or not, and whether the isolation level + is lower than ISO_REPEATABLE_READ: + + . option (OFF/ON) + . trx-cache (empty/not empty) + . isolation (>= ISO_REPEATABLE_READ / < ISO_REPEATABLE_READ) + + bits 0 : . OFF, . empty, . >= ISO_REPEATABLE_READ + bits 1 : . OFF, . empty, . < ISO_REPEATABLE_READ + bits 2 : . OFF, . not empty, . >= ISO_REPEATABLE_READ + bits 3 : . OFF, . not empty, . < ISO_REPEATABLE_READ + bits 4 : . ON, . empty, . >= ISO_REPEATABLE_READ + bits 5 : . ON, . empty, . < ISO_REPEATABLE_READ + bits 6 : . ON, . not empty, . >= ISO_REPEATABLE_READ + bits 7 : . ON, . not empty, . < ISO_REPEATABLE_READ +*/ +extern uint binlog_unsafe_map[256]; +/* + Initializes the array with unsafe combinations and its respective + conditions. +*/ +void binlog_unsafe_map_init(); +#endif + /** used by the parser to store internal variable name */ @@ -919,6 +966,24 @@ enum enum_alter_table_change_level ALTER_TABLE_INDEX_CHANGED= 2 }; + +/** + Temporary hack to enable a class bound forward declaration + of the enum_alter_table_change_level enumeration. To be + removed once Alter_info is moved to the sql_alter.h + header. +*/ +class Alter_table_change_level +{ +private: + typedef enum enum_alter_table_change_level enum_type; + enum_type value; +public: + void operator = (enum_type v) { value = v; } + operator enum_type () { return value; } +}; + + /** @brief Parsing data for CREATE or ALTER TABLE. @@ -1286,33 +1351,33 @@ public: */ STMT_READS_TRANS_TABLE= 0, /* - If a transactional table is about to be updated. - */ - STMT_WRITES_TRANS_TABLE, - /* If a non-transactional table is about to be read. Note that a write implies a read. */ STMT_READS_NON_TRANS_TABLE, /* - If a non-transactional table is about to be updated. - */ - STMT_WRITES_NON_TRANS_TABLE, - /* If a temporary transactional table is about to be read. Note that a write implies a read. */ STMT_READS_TEMP_TRANS_TABLE, /* - If a temporary transactional table is about to be updated. - */ - STMT_WRITES_TEMP_TRANS_TABLE, - /* If a temporary non-transactional table is about to be read. Note that a write implies a read. */ STMT_READS_TEMP_NON_TRANS_TABLE, /* + If a transactional table is about to be updated. + */ + STMT_WRITES_TRANS_TABLE, + /* + If a non-transactional table is about to be updated. + */ + STMT_WRITES_NON_TRANS_TABLE, + /* + If a temporary transactional table is about to be updated. + */ + STMT_WRITES_TEMP_TRANS_TABLE, + /* If a temporary non-transactional table is about to be updated. */ STMT_WRITES_TEMP_NON_TRANS_TABLE, @@ -1322,7 +1387,58 @@ public: */ STMT_ACCESS_TABLE_COUNT }; + + static inline const char *stmt_accessed_table_string(enum_stmt_accessed_table accessed_table) + { + switch (accessed_table) + { + case STMT_READS_TRANS_TABLE: + return "STMT_READS_TRANS_TABLE"; + break; + case STMT_READS_NON_TRANS_TABLE: + return "STMT_READS_NON_TRANS_TABLE"; + break; + case STMT_READS_TEMP_TRANS_TABLE: + return "STMT_READS_TEMP_TRANS_TABLE"; + break; + case STMT_READS_TEMP_NON_TRANS_TABLE: + return "STMT_READS_TEMP_NON_TRANS_TABLE"; + break; + case STMT_WRITES_TRANS_TABLE: + return "STMT_WRITES_TRANS_TABLE"; + break; + case STMT_WRITES_NON_TRANS_TABLE: + return "STMT_WRITES_NON_TRANS_TABLE"; + break; + case STMT_WRITES_TEMP_TRANS_TABLE: + return "STMT_WRITES_TEMP_TRANS_TABLE"; + break; + case STMT_WRITES_TEMP_NON_TRANS_TABLE: + return "STMT_WRITES_TEMP_NON_TRANS_TABLE"; + break; + case STMT_ACCESS_TABLE_COUNT: + default: + DBUG_ASSERT(0); + break; + } + } + #define BINLOG_DIRECT_ON 0xF0 /* unsafe when + --binlog-direct-non-trans-updates + is ON */ + + #define BINLOG_DIRECT_OFF 0xF /* unsafe when + --binlog-direct-non-trans-updates + is OFF */ + + #define TRX_CACHE_EMPTY 0x33 /* unsafe when trx-cache is empty */ + + #define TRX_CACHE_NOT_EMPTY 0xCC /* unsafe when trx-cache is not empty */ + + #define IL_LT_REPEATABLE 0xAA /* unsafe when < ISO_REPEATABLE_READ */ + + #define IL_GTE_REPEATABLE 0x55 /* unsafe when >= ISO_REPEATABLE_READ */ + /** Sets the type of table that is about to be accessed while executing a statement. @@ -1332,7 +1448,7 @@ public: */ inline void set_stmt_accessed_table(enum_stmt_accessed_table accessed_table) { - DBUG_ENTER("THD::set_stmt_accessed_table"); + DBUG_ENTER("LEX::set_stmt_accessed_table"); DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT); stmt_accessed_table_flag |= (1U << accessed_table); @@ -1345,7 +1461,7 @@ public: statement. @param accessed_table Enumeration type that defines the type of table, - e.g. temporary, transactional, non-transactional. + e.g. temporary, transactional, non-transactional. @return @retval TRUE if the type of the table is about to be accessed @@ -1353,7 +1469,7 @@ public: */ inline bool stmt_accessed_table(enum_stmt_accessed_table accessed_table) { - DBUG_ENTER("THD::stmt_accessed_table"); + DBUG_ENTER("LEX::stmt_accessed_table"); DBUG_ASSERT(accessed_table >= 0 && accessed_table < STMT_ACCESS_TABLE_COUNT); @@ -1361,40 +1477,79 @@ public: } /** - Checks if a temporary table is about to be accessed while executing a - statement. + Checks if a temporary non-transactional table is about to be accessed + while executing a statement. @return - @retval TRUE if a temporary table is about to be accessed + @retval TRUE if a temporary non-transactional table is about to be + accessed @retval FALSE otherwise */ - inline bool stmt_accessed_temp_table() + inline bool stmt_accessed_non_trans_temp_table() { - DBUG_ENTER("THD::stmt_accessed_temp_table"); + DBUG_ENTER("THD::stmt_accessed_non_trans_temp_table"); DBUG_RETURN((stmt_accessed_table_flag & - ((1U << STMT_READS_TEMP_TRANS_TABLE) | - (1U << STMT_WRITES_TEMP_TRANS_TABLE) | - (1U << STMT_READS_TEMP_NON_TRANS_TABLE) | + ((1U << STMT_READS_TEMP_NON_TRANS_TABLE) | (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0); } - /** - Checks if a temporary non-transactional table is about to be accessed - while executing a statement. + /* + Checks if a mixed statement is unsafe. + + @param in_multi_stmt_transaction_mode defines if there is an on-going + multi-transactional statement. + @param binlog_direct defines if --binlog-direct-non-trans-updates is + active. + @param trx_cache_is_not_empty defines if the trx-cache is empty or not. + @param trx_isolation defines the isolation level. + @return - @retval TRUE if a temporary non-transactional table is about to be - accessed + @retval TRUE if the mixed statement is unsafe @retval FALSE otherwise */ - inline bool stmt_accessed_non_trans_temp_table() + inline bool is_mixed_stmt_unsafe(bool in_multi_stmt_transaction_mode, + bool binlog_direct, + bool trx_cache_is_not_empty, + uint tx_isolation) { - DBUG_ENTER("THD::stmt_accessed_non_trans_temp_table"); + bool unsafe= FALSE; - DBUG_RETURN((stmt_accessed_table_flag & - ((1U << STMT_READS_TEMP_NON_TRANS_TABLE) | - (1U << STMT_WRITES_TEMP_NON_TRANS_TABLE))) != 0); + if (in_multi_stmt_transaction_mode) + { + uint condition= + (binlog_direct ? BINLOG_DIRECT_ON : BINLOG_DIRECT_OFF) & + (trx_cache_is_not_empty ? TRX_CACHE_NOT_EMPTY : TRX_CACHE_EMPTY) & + (tx_isolation >= ISO_REPEATABLE_READ ? IL_GTE_REPEATABLE : IL_LT_REPEATABLE); + + unsafe= (binlog_unsafe_map[stmt_accessed_table_flag] & condition); + +#if !defined(DBUG_OFF) + DBUG_PRINT("LEX::is_mixed_stmt_unsafe", ("RESULT %02X %02X %02X\n", condition, + binlog_unsafe_map[stmt_accessed_table_flag], + (binlog_unsafe_map[stmt_accessed_table_flag] & condition))); + + int type_in= 0; + for (; type_in < STMT_ACCESS_TABLE_COUNT; type_in++) + { + if (stmt_accessed_table((enum_stmt_accessed_table) type_in)) + DBUG_PRINT("LEX::is_mixed_stmt_unsafe", ("ACCESSED %s ", + stmt_accessed_table_string((enum_stmt_accessed_table) type_in))); + } +#endif + } + + if (stmt_accessed_table(STMT_WRITES_NON_TRANS_TABLE) && + stmt_accessed_table(STMT_READS_TRANS_TABLE) && + tx_isolation < ISO_REPEATABLE_READ) + unsafe= TRUE; + else if (stmt_accessed_table(STMT_WRITES_TEMP_NON_TRANS_TABLE) && + stmt_accessed_table(STMT_READS_TRANS_TABLE) && + tx_isolation < ISO_REPEATABLE_READ) + unsafe= TRUE; + + return(unsafe); } /** |