summaryrefslogtreecommitdiff
path: root/sql/handler.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/handler.cc')
-rw-r--r--sql/handler.cc253
1 files changed, 135 insertions, 118 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index bd415122388..748a51f5c59 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -30,11 +30,10 @@
#include "sql_table.h" // build_table_filename
#include "sql_parse.h" // check_stack_overrun
#include "sql_acl.h" // SUPER_ACL
-#include "sql_base.h" // free_io_cache
+#include "sql_base.h" // TDC_element
#include "discover.h" // extension_based_table_discovery, etc
#include "log_event.h" // *_rows_log_event
#include "create_options.h"
-#include "rpl_filter.h"
#include <myisampack.h>
#include "transaction.h"
#include "myisam.h"
@@ -325,7 +324,7 @@ int ha_init_errors(void)
/* Set the dedicated error messages. */
SETMSG(HA_ERR_KEY_NOT_FOUND, ER_DEFAULT(ER_KEY_NOT_FOUND));
SETMSG(HA_ERR_FOUND_DUPP_KEY, ER_DEFAULT(ER_DUP_KEY));
- SETMSG(HA_ERR_RECORD_CHANGED, "Update wich is recoverable");
+ SETMSG(HA_ERR_RECORD_CHANGED, "Update which is recoverable");
SETMSG(HA_ERR_WRONG_INDEX, "Wrong index given to function");
SETMSG(HA_ERR_CRASHED, ER_DEFAULT(ER_NOT_KEYFILE));
SETMSG(HA_ERR_WRONG_IN_RECORD, ER_DEFAULT(ER_CRASHED_ON_USAGE));
@@ -3931,9 +3930,7 @@ int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt)
if it is started.
*/
-inline
-void
-handler::mark_trx_read_write()
+void handler::mark_trx_read_write_internal()
{
Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
/*
@@ -4227,7 +4224,7 @@ handler::check_if_supported_inplace_alter(TABLE *altered_table,
IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
if (table->file->check_if_incompatible_data(create_info, table_changes)
== COMPATIBLE_DATA_YES)
- DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
+ DBUG_RETURN(HA_ALTER_INPLACE_NO_LOCK);
DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
}
@@ -5050,7 +5047,9 @@ bool ha_table_exists(THD *thd, const char *db, const char *table_name,
Table_exists_error_handler no_such_table_handler;
thd->push_internal_handler(&no_such_table_handler);
- TABLE_SHARE *share= tdc_acquire_share(thd, db, table_name, flags);
+ table.init_one_table(db, strlen(db), table_name, strlen(table_name),
+ table_name, TL_READ);
+ TABLE_SHARE *share= tdc_acquire_share(thd, &table, flags);
thd->pop_internal_handler();
if (hton && share)
@@ -5579,30 +5578,47 @@ bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
correct for the table.
A row in the given table should be replicated if:
+ - It's not called by partition engine
- Row-based replication is enabled in the current thread
- The binlog is enabled
- It is not a temporary table
- The binary log is open
- The database the table resides in shall be binlogged (binlog_*_db rules)
- table is not mysql.event
+
+ RETURN VALUE
+ 0 No binary logging in row format
+ 1 Row needs to be logged
*/
-static bool check_table_binlog_row_based(THD *thd, TABLE *table)
+inline bool handler::check_table_binlog_row_based(bool binlog_row)
{
- if (table->s->cached_row_logging_check == -1)
+ if (unlikely((table->in_use->variables.sql_log_bin_off)))
+ return 0; /* Called by partitioning engine */
+ if (unlikely((!check_table_binlog_row_based_done)))
{
- int const check(table->s->tmp_table == NO_TMP_TABLE &&
- ! table->no_replicate &&
- binlog_filter->db_ok(table->s->db.str));
- table->s->cached_row_logging_check= check;
+ check_table_binlog_row_based_done= 1;
+ check_table_binlog_row_based_result=
+ check_table_binlog_row_based_internal(binlog_row);
}
+ return check_table_binlog_row_based_result;
+}
- DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
- table->s->cached_row_logging_check == 1);
+bool handler::check_table_binlog_row_based_internal(bool binlog_row)
+{
+ THD *thd= table->in_use;
- return (thd->is_current_stmt_binlog_format_row() &&
- table->s->cached_row_logging_check &&
#ifdef WITH_WSREP
+ /* only InnoDB tables will be replicated through binlog emulation */
+ if (binlog_row &&
+ ((WSREP_EMULATE_BINLOG(thd) &&
+ table->file->partition_ht()->db_type != DB_TYPE_INNODB) ||
+ (thd->wsrep_ignore_table == true)))
+ return 0;
+#endif
+
+ return (table->s->cached_row_logging_check &&
+ thd->is_current_stmt_binlog_format_row() &&
/*
Wsrep partially enables binary logging if it have not been
explicitly turned on. As a result we return 'true' if we are in
@@ -5617,14 +5633,13 @@ static bool check_table_binlog_row_based(THD *thd, TABLE *table)
Otherwise, return 'true' if binary logging is on.
*/
- (thd->variables.sql_log_bin_off != 1) &&
- ((WSREP_EMULATE_BINLOG(thd) && (thd->wsrep_exec_mode != REPL_RECV)) ||
- ((WSREP(thd) || (thd->variables.option_bits & OPTION_BIN_LOG)) &&
- mysql_bin_log.is_open())));
-#else
- (thd->variables.option_bits & OPTION_BIN_LOG) &&
- mysql_bin_log.is_open());
-#endif
+ IF_WSREP(((WSREP_EMULATE_BINLOG(thd) &&
+ (thd->wsrep_exec_mode != REPL_RECV)) ||
+ ((WSREP(thd) ||
+ (thd->variables.option_bits & OPTION_BIN_LOG)) &&
+ mysql_bin_log.is_open())),
+ (thd->variables.option_bits & OPTION_BIN_LOG) &&
+ mysql_bin_log.is_open()));
}
@@ -5658,54 +5673,51 @@ static int write_locked_table_maps(THD *thd)
DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps()));
- if (thd->get_binlog_table_maps() == 0)
+ MYSQL_LOCK *locks[2];
+ locks[0]= thd->extra_lock;
+ locks[1]= thd->lock;
+ my_bool with_annotate= thd->variables.binlog_annotate_row_events &&
+ thd->query() && thd->query_length();
+
+ for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
{
- MYSQL_LOCK *locks[2];
- locks[0]= thd->extra_lock;
- locks[1]= thd->lock;
- my_bool with_annotate= thd->variables.binlog_annotate_row_events &&
- thd->query() && thd->query_length();
+ MYSQL_LOCK const *const lock= locks[i];
+ if (lock == NULL)
+ continue;
- for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
+ TABLE **const end_ptr= lock->table + lock->table_count;
+ for (TABLE **table_ptr= lock->table ;
+ table_ptr != end_ptr ;
+ ++table_ptr)
{
- MYSQL_LOCK const *const lock= locks[i];
- if (lock == NULL)
- continue;
-
- TABLE **const end_ptr= lock->table + lock->table_count;
- for (TABLE **table_ptr= lock->table ;
- table_ptr != end_ptr ;
- ++table_ptr)
+ TABLE *const table= *table_ptr;
+ DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
+ if (table->current_lock == F_WRLCK &&
+ table->file->check_table_binlog_row_based(0))
{
- TABLE *const table= *table_ptr;
- DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
- if (table->current_lock == F_WRLCK &&
- check_table_binlog_row_based(thd, table))
- {
- /*
- We need to have a transactional behavior for SQLCOM_CREATE_TABLE
- (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
- compatible behavior with the STMT based replication even when
- the table is not transactional. In other words, if the operation
- fails while executing the insert phase nothing is written to the
- binlog.
-
- Note that at this point, we check the type of a set of tables to
- create the table map events. In the function binlog_log_row(),
- which calls the current function, we check the type of the table
- of the current row.
- */
- bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
- table->file->has_transactions();
- int const error= thd->binlog_write_table_map(table, has_trans,
- &with_annotate);
- /*
- If an error occurs, it is the responsibility of the caller to
- roll back the transaction.
- */
- if (unlikely(error))
- DBUG_RETURN(1);
- }
+ /*
+ We need to have a transactional behavior for SQLCOM_CREATE_TABLE
+ (e.g. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
+ compatible behavior with the STMT based replication even when
+ the table is not transactional. In other words, if the operation
+ fails while executing the insert phase nothing is written to the
+ binlog.
+
+ Note that at this point, we check the type of a set of tables to
+ create the table map events. In the function binlog_log_row(),
+ which calls the current function, we check the type of the table
+ of the current row.
+ */
+ bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+ table->file->has_transactions();
+ int const error= thd->binlog_write_table_map(table, has_trans,
+ &with_annotate);
+ /*
+ If an error occurs, it is the responsibility of the caller to
+ roll back the transaction.
+ */
+ if (unlikely(error))
+ DBUG_RETURN(1);
}
}
}
@@ -5715,44 +5727,50 @@ static int write_locked_table_maps(THD *thd)
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
-static int binlog_log_row(TABLE* table,
- const uchar *before_record,
- const uchar *after_record,
- Log_func *log_func)
+
+
+static int binlog_log_row_internal(TABLE* table,
+ const uchar *before_record,
+ const uchar *after_record,
+ Log_func *log_func)
{
bool error= 0;
THD *const thd= table->in_use;
- /* only InnoDB tables will be replicated through binlog emulation */
- if (WSREP_EMULATE_BINLOG(thd) &&
- table->file->partition_ht()->db_type != DB_TYPE_INNODB)
- return 0;
-
- if (check_table_binlog_row_based(thd, table))
+ /*
+ If there are no table maps written to the binary log, this is
+ the first row handled in this statement. In that case, we need
+ to write table maps for all locked tables to the binary log.
+ */
+ if (likely(!(error= ((thd->get_binlog_table_maps() == 0 &&
+ write_locked_table_maps(thd))))))
{
/*
- If there are no table maps written to the binary log, this is
- the first row handled in this statement. In that case, we need
- to write table maps for all locked tables to the binary log.
+ We need to have a transactional behavior for SQLCOM_CREATE_TABLE
+ (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
+ compatible behavior with the STMT based replication even when
+ the table is not transactional. In other words, if the operation
+ fails while executing the insert phase nothing is written to the
+ binlog.
*/
- if (likely(!(error= write_locked_table_maps(thd))))
- {
- /*
- We need to have a transactional behavior for SQLCOM_CREATE_TABLE
- (i.e. CREATE TABLE... SELECT * FROM TABLE) in order to keep a
- compatible behavior with the STMT based replication even when
- the table is not transactional. In other words, if the operation
- fails while executing the insert phase nothing is written to the
- binlog.
- */
- bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
- table->file->has_transactions();
- error= (*log_func)(thd, table, has_trans, before_record, after_record);
- }
+ bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
+ table->file->has_transactions();
+ error= (*log_func)(thd, table, has_trans, before_record, after_record);
}
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
}
+static inline int binlog_log_row(TABLE* table,
+ const uchar *before_record,
+ const uchar *after_record,
+ Log_func *log_func)
+{
+ if (!table->file->check_table_binlog_row_based(1))
+ return 0;
+ return binlog_log_row_internal(table, before_record, after_record, log_func);
+}
+
+
int handler::ha_external_lock(THD *thd, int lock_type)
{
int error;
@@ -5845,12 +5863,12 @@ int handler::ha_reset()
DBUG_ASSERT(table->key_read == 0);
/* ensure that ha_index_end / ha_rnd_end has been called */
DBUG_ASSERT(inited == NONE);
- /* Free cache used by filesort */
- free_io_cache(table);
/* reset the bitmaps to point to defaults */
table->default_column_bitmaps();
pushed_cond= NULL;
tracker= NULL;
+ mark_trx_read_write_done= check_table_binlog_row_based_done=
+ check_table_binlog_row_based_result= 0;
/* Reset information about pushed engine conditions */
cancel_pushed_idx_cond();
/* Reset information about pushed index conditions */
@@ -5875,14 +5893,13 @@ int handler::ha_write_row(uchar *buf)
{ error= write_row(buf); })
MYSQL_INSERT_ROW_DONE(error);
- if (unlikely(error))
- DBUG_RETURN(error);
- rows_changed++;
- if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
- DBUG_RETURN(error); /* purecov: inspected */
-
+ if (likely(!error))
+ {
+ rows_changed++;
+ error= binlog_log_row(table, 0, buf, log_func);
+ }
DEBUG_SYNC_C("ha_write_row_end");
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
@@ -5908,12 +5925,12 @@ int handler::ha_update_row(const uchar *old_data, uchar *new_data)
{ error= update_row(old_data, new_data);})
MYSQL_UPDATE_ROW_DONE(error);
- if (unlikely(error))
- return error;
- rows_changed++;
- if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
- return error;
- return 0;
+ if (likely(!error))
+ {
+ rows_changed++;
+ error= binlog_log_row(table, old_data, new_data, log_func);
+ }
+ return error;
}
int handler::ha_delete_row(const uchar *buf)
@@ -5935,12 +5952,12 @@ int handler::ha_delete_row(const uchar *buf)
TABLE_IO_WAIT(tracker, m_psi, PSI_TABLE_DELETE_ROW, active_index, 0,
{ error= delete_row(buf);})
MYSQL_DELETE_ROW_DONE(error);
- if (unlikely(error))
- return error;
- rows_changed++;
- if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
- return error;
- return 0;
+ if (likely(!error))
+ {
+ rows_changed++;
+ error= binlog_log_row(table, buf, 0, log_func);
+ }
+ return error;
}