summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <knielsen@knielsen-hq.org>2011-01-10 14:54:26 +0100
committerunknown <knielsen@knielsen-hq.org>2011-01-10 14:54:26 +0100
commite6d4ba1b0519976f58b020c44b585bab9db242f5 (patch)
tree50317d1c38183c95a04f617ea9b454b5fcb58dee
parent32379aeba9222d255f151bdea4954932fe784021 (diff)
parent3abce27e9d45282084aa8d0972ffb6721bac16f5 (diff)
downloadmariadb-git-e6d4ba1b0519976f58b020c44b585bab9db242f5.tar.gz
Merge
-rw-r--r--mysql-test/suite/rpl/r/rpl_row_index_choice.result143
-rw-r--r--mysql-test/suite/rpl/t/rpl_row_index_choice.test241
-rw-r--r--sql/log_event.cc128
-rw-r--r--sql/log_event.h3
4 files changed, 492 insertions, 23 deletions
diff --git a/mysql-test/suite/rpl/r/rpl_row_index_choice.result b/mysql-test/suite/rpl/r/rpl_row_index_choice.result
new file mode 100644
index 00000000000..d04576489af
--- /dev/null
+++ b/mysql-test/suite/rpl/r/rpl_row_index_choice.result
@@ -0,0 +1,143 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1 (a int, b varchar(100), fulltext(b)) engine=MyISAM;
+INSERT INTO t1 VALUES (1,"a"), (2,"b");
+UPDATE t1 SET b='A' WHERE a=1;
+DELETE FROM t1 WHERE a=2;
+SELECT * FROM t1 ORDER BY a;
+a b
+1 A
+DROP TABLE t1;
+CREATE TABLE t1 (d INT PRIMARY KEY) ENGINE=myisam;
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 SELECT d+1 FROM t1;
+INSERT INTO t1 SELECT d+2 FROM t1;
+INSERT INTO t1 SELECT d+4 FROM t1;
+INSERT INTO t1 SELECT d+8 FROM t1;
+INSERT INTO t1 SELECT d+16 FROM t1;
+INSERT INTO t1 SELECT d+32 FROM t1;
+INSERT INTO t1 SELECT d+64 FROM t1;
+INSERT INTO t1 SELECT d+128 FROM t1;
+INSERT INTO t1 SELECT d+256 FROM t1;
+INSERT INTO t1 SELECT d+512 FROM t1;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT,
+KEY wrong_key(a),
+KEY expected_key(b,c),
+KEY wrong_key2(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d
+4 1 5 10042
+DROP TABLE t2;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT NOT NULL, e INT,
+UNIQUE wrong_key3(a,e),
+KEY wrong_key4(b,c),
+UNIQUE expected_key(d)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, NULL FROM t1;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d e
+4 1 5 10042 NULL
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+KEY wrong_key5(b),
+UNIQUE expected_key(d),
+KEY wrong_key6(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d
+4 1 5 10042
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+KEY expected_key(b),
+KEY wrong_key7(d),
+KEY wrong_key8(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d
+4 1 5 10042
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT,
+UNIQUE wrong_key9(d),
+KEY wrong_key10(a),
+PRIMARY KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan,slave_crash_if_index_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d
+4 1 5 10042
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+UNIQUE wrong_key11(e),
+KEY wrong_key12(a),
+KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+ANALYZE TABLE t2;
+Table Op Msg_type Msg_text
+test.t2 analyze status OK
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d e
+4 1 5 10042 NULL
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+KEY wrong_key13(a),
+UNIQUE expected_key(e),
+KEY wrong_key14(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+# Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+a b c d e
+4 1 5 10042 NULL
+DROP TABLE t2;
+CREATE TABLE t2 (a INT NOT NULL, d INT) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d FROM t1;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+SELECT * FROM t2 WHERE d IN (10042,53);
+a d
+4 10042
+DROP TABLE t2;
+DROP TABLE t1;
+SET GLOBAL debug="";
diff --git a/mysql-test/suite/rpl/t/rpl_row_index_choice.test b/mysql-test/suite/rpl/t/rpl_row_index_choice.test
new file mode 100644
index 00000000000..a4ff999ec69
--- /dev/null
+++ b/mysql-test/suite/rpl/t/rpl_row_index_choice.test
@@ -0,0 +1,241 @@
+--source include/have_binlog_format_row.inc
+--source include/master-slave.inc
+--source include/have_debug.inc
+--source include/have_innodb.inc
+
+# Bug#58997: Row-based replication breaks on table with only fulltext index:
+connection master;
+CREATE TABLE t1 (a int, b varchar(100), fulltext(b)) engine=MyISAM;
+INSERT INTO t1 VALUES (1,"a"), (2,"b");
+UPDATE t1 SET b='A' WHERE a=1;
+DELETE FROM t1 WHERE a=2;
+
+sync_slave_with_master;
+
+connection slave;
+
+SELECT * FROM t1 ORDER BY a;
+
+connection master;
+DROP TABLE t1;
+
+
+# A utility table used to populate subsequent tables in various ways.
+connection master;
+CREATE TABLE t1 (d INT PRIMARY KEY) ENGINE=myisam;
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 SELECT d+1 FROM t1;
+INSERT INTO t1 SELECT d+2 FROM t1;
+INSERT INTO t1 SELECT d+4 FROM t1;
+INSERT INTO t1 SELECT d+8 FROM t1;
+INSERT INTO t1 SELECT d+16 FROM t1;
+INSERT INTO t1 SELECT d+32 FROM t1;
+INSERT INTO t1 SELECT d+64 FROM t1;
+INSERT INTO t1 SELECT d+128 FROM t1;
+INSERT INTO t1 SELECT d+256 FROM t1;
+INSERT INTO t1 SELECT d+512 FROM t1;
+
+# Test that we pick the better multi-column index, even if the
+# single-column index is more selective in the first column.
+CREATE TABLE t2 (a INT, b INT, c INT, d INT,
+ KEY wrong_key(a),
+ KEY expected_key(b,c),
+ KEY wrong_key2(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+# Test that we don't pick a unique index with NULLS over a more selective
+# non-unique index.
+connection master;
+DROP TABLE t2;
+CREATE TABLE t2 (a INT, b INT, c INT, d INT NOT NULL, e INT,
+ UNIQUE wrong_key3(a,e),
+ KEY wrong_key4(b,c),
+ UNIQUE expected_key(d)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, NULL FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+# Test that we pick a reasonable index when there is no rec_per_key[]
+# information (no ANALYZE TABLE).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+ KEY wrong_key5(b),
+ UNIQUE expected_key(d),
+ KEY wrong_key6(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Also test without ANALYZE when we pick the sub-optimal index.
+# In this case the key on (d) is the best one, but without ANALYZE TABLE we
+# have no information and will pick the first one on (b).
+# (This test should be updated if we improve the index selection, of course).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT NOT NULL,
+ KEY expected_key(b),
+ KEY wrong_key7(d),
+ KEY wrong_key8(c)) ENGINE=myisam;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Test that we pick the primary key for InnoDB, if available.
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT,
+ UNIQUE wrong_key9(d),
+ KEY wrong_key10(a),
+ PRIMARY KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan,slave_crash_if_index_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Test that we pick a good index for InnoDB when primary key is not available.
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+ UNIQUE wrong_key11(e),
+ KEY wrong_key12(a),
+ KEY expected_key(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+
+sync_slave_with_master;
+connection slave;
+ANALYZE TABLE t2;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# When there is no ANALYZE TABLE, InnoDB will just report "1" for index
+# cardinality for all indexes in rec_per_key. So currently we cannot choose
+# index to use intelligently. Just test that we work as expected (select
+# first index, remember that unique keys are sorted first by server).
+CREATE TABLE t2 (a INT NOT NULL, b INT NOT NULL, c INT NOT NULL, d INT, e INT,
+ KEY wrong_key13(a),
+ UNIQUE expected_key(e),
+ KEY wrong_key14(c,b)) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d MOD 41, d MOD 37, d, IF(d<10, d, NULL) FROM t1;
+
+sync_slave_with_master;
+connection slave;
+--echo # Slave will crash if using the wrong or no index
+SET GLOBAL debug="+d,slave_crash_if_wrong_index,slave_crash_if_table_scan";
+
+connection master;
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+# Finally, test behaviour when no indexes are available at all.
+CREATE TABLE t2 (a INT NOT NULL, d INT) ENGINE=innodb;
+INSERT INTO t2 SELECT d DIV 10, d FROM t1;
+
+UPDATE t2 SET d=10042 WHERE d=42;
+DELETE FROM t2 WHERE d=53;
+
+sync_slave_with_master;
+connection slave;
+SELECT * FROM t2 WHERE d IN (10042,53);
+
+connection master;
+DROP TABLE t2;
+
+
+connection master;
+DROP TABLE t1;
+sync_slave_with_master;
+connection slave;
+SET GLOBAL debug="";
diff --git a/sql/log_event.cc b/sql/log_event.cc
index d4f71194121..a7d3f7dee5c 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -7139,7 +7139,8 @@ Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, ulong tid,
m_width(tbl_arg ? tbl_arg->s->fields : 1),
m_rows_buf(0), m_rows_cur(0), m_rows_end(0), m_flags(0)
#ifdef HAVE_REPLICATION
- , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL)
+ , m_curr_row(NULL), m_curr_row_end(NULL),
+ m_key(NULL), m_key_info(NULL), m_key_nr(0)
#endif
{
/*
@@ -7187,7 +7188,8 @@ Rows_log_event::Rows_log_event(const char *buf, uint event_len,
#endif
m_table_id(0), m_rows_buf(0), m_rows_cur(0), m_rows_end(0)
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
- , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL)
+ , m_curr_row(NULL), m_curr_row_end(NULL),
+ m_key(NULL), m_key_info(NULL), m_key_nr(0)
#endif
{
DBUG_ENTER("Rows_log_event::Rows_log_event(const char*,...)");
@@ -9189,6 +9191,86 @@ record_compare_exit:
return result;
}
+
+/**
+ Find the best key to use when locating the row in @c find_row().
+
+ A primary key is preferred if it exists; otherwise a unique index is
+ preferred. Else we pick the index with the smalles rec_per_key value.
+
+ If a suitable key is found, set @c m_key, @c m_key_nr and @c m_key_info
+ member fields appropriately.
+
+ @returns Error code on failure, 0 on success.
+*/
+int Rows_log_event::find_key()
+{
+ uint i, best_key_nr, last_part;
+ KEY *key, *best_key;
+ ulong best_rec_per_key, tmp;
+ DBUG_ENTER("Rows_log_event::find_key");
+ DBUG_ASSERT(m_table && m_table->in_use != NULL);
+
+ best_key_nr= MAX_KEY;
+ LINT_INIT(best_key);
+ LINT_INIT(best_rec_per_key);
+
+ /*
+ Keys are sorted so that any primary key is first, followed by unique keys,
+ followed by any other. So we will automatically pick the primary key if
+ it exists.
+ */
+ for (i= 0, key= m_table->key_info; i < m_table->s->keys; i++, key++)
+ {
+ if (!m_table->s->keys_in_use.is_set(i))
+ continue;
+ /*
+ We cannot use a unique key with NULL-able columns to uniquely identify
+ a row (but we can still select it for range scan below if nothing better
+ is available).
+ */
+ if ((key->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME)
+ {
+ best_key_nr= i;
+ best_key= key;
+ break;
+ }
+ /*
+ We can only use a non-unique key if it allows range scans (ie. skip
+ FULLTEXT indexes and such).
+ */
+ last_part= key->key_parts - 1;
+ DBUG_PRINT("info", ("Index %s rec_per_key[%u]= %lu",
+ key->name, last_part, key->rec_per_key[last_part]));
+ if (!(m_table->file->index_flags(i, last_part, 1) & HA_READ_NEXT))
+ continue;
+
+ tmp= key->rec_per_key[last_part];
+ if (best_key_nr == MAX_KEY || (tmp > 0 && tmp < best_rec_per_key))
+ {
+ best_key_nr= i;
+ best_key= key;
+ best_rec_per_key= tmp;
+ }
+ }
+
+ if (best_key_nr == MAX_KEY)
+ {
+ m_key_info= NULL;
+ DBUG_RETURN(0);
+ }
+
+ // Allocate buffer for key searches
+ m_key= (uchar *) my_malloc(best_key->key_length, MYF(MY_WME));
+ if (m_key == NULL)
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+ m_key_info= best_key;
+ m_key_nr= best_key_nr;
+
+ DBUG_RETURN(0);;
+}
+
+
/**
Locate the current row in event's table.
@@ -9288,12 +9370,17 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
*/
store_record(table,record[1]);
- if (table->s->keys > 0 && table->s->keys_in_use.is_set(0))
+ if (m_key_info)
{
- DBUG_PRINT("info",("locating record using primary key (index_read)"));
+ DBUG_PRINT("info",("locating record using key #%u [%s] (index_read)",
+ m_key_nr, m_key_info->name));
+ /* We use this to test that the correct key is used in test cases. */
+ DBUG_EXECUTE_IF("slave_crash_if_wrong_index",
+ if(0 != strcmp(m_key_info->name,"expected_key")) abort(););
- /* The 0th key is active: search the table using the index */
- if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE)))
+ /* The key is active: search the table using the index */
+ if (!table->file->inited &&
+ (error= table->file->ha_index_init(m_key_nr, FALSE)))
{
DBUG_PRINT("info",("ha_index_init returns error %d",error));
table->file->print_error(error, MYF(0));
@@ -9303,14 +9390,14 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
/* Fill key data for the row */
DBUG_ASSERT(m_key);
- key_copy(m_key, table->record[0], table->key_info, 0);
+ key_copy(m_key, table->record[0], m_key_info, 0);
/*
Don't print debug messages when running valgrind since they can
trigger false warnings.
*/
#ifndef HAVE_valgrind
- DBUG_DUMP("key data", m_key, table->key_info->key_length);
+ DBUG_DUMP("key data", m_key, m_key_info->key_length);
#endif
/*
@@ -9396,6 +9483,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
record we are looking for is stored in record[1].
*/
DBUG_PRINT("info",("non-unique index, scanning it to find matching record"));
+ /* We use this to test that the correct key is used in test cases. */
+ DBUG_EXECUTE_IF("slave_crash_if_index_scan", abort(););
while (record_compare(table))
{
@@ -9434,6 +9523,8 @@ int Rows_log_event::find_row(const Relay_log_info *rli)
else
{
DBUG_PRINT("info",("locating record using table scan (rnd_next)"));
+ /* We use this to test that the correct key is used in test cases. */
+ DBUG_EXECUTE_IF("slave_crash_if_table_scan", abort(););
int restart_count= 0; // Number of times scanning has restarted from top
@@ -9553,14 +9644,7 @@ Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability
return 0;
}
- if (m_table->s->keys > 0)
- {
- // Allocate buffer for key searches
- m_key= (uchar*)my_malloc(m_table->key_info->key_length, MYF(MY_WME));
- if (!m_key)
- return HA_ERR_OUT_OF_MEM;
- }
- return 0;
+ return find_key();
}
int
@@ -9571,6 +9655,7 @@ Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability
m_table->file->ha_index_or_rnd_end();
my_free(m_key, MYF(MY_ALLOW_ZERO_PTR));
m_key= NULL;
+ m_key_info= NULL;
return error;
}
@@ -9673,13 +9758,9 @@ Update_rows_log_event::Update_rows_log_event(const char *buf, uint event_len,
int
Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
{
- if (m_table->s->keys > 0)
- {
- // Allocate buffer for key searches
- m_key= (uchar*)my_malloc(m_table->key_info->key_length, MYF(MY_WME));
- if (!m_key)
- return HA_ERR_OUT_OF_MEM;
- }
+ int err;
+ if ((err= find_key()))
+ return err;
m_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
@@ -9694,6 +9775,7 @@ Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability
m_table->file->ha_index_or_rnd_end();
my_free(m_key, MYF(MY_ALLOW_ZERO_PTR)); // Free for multi_malloc
m_key= NULL;
+ m_key_info= NULL;
return error;
}
diff --git a/sql/log_event.h b/sql/log_event.h
index 6593929eb91..1fb117ccc92 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -3652,7 +3652,10 @@ protected:
const uchar *m_curr_row; /* Start of the row being processed */
const uchar *m_curr_row_end; /* One-after the end of the current row */
uchar *m_key; /* Buffer to keep key value during searches */
+ KEY *m_key_info; /* Pointer to KEY info for m_key_nr */
+ uint m_key_nr; /* Key number */
+ int find_key(); // Find a best key to use in find_row()
int find_row(const Relay_log_info *const);
int write_row(const Relay_log_info *const, const bool);