[Commits] Rev 2906: Merge in http://bazaar.launchpad.net/~maria-captains/maria/5.2

knielsen at knielsen-hq.org knielsen at knielsen-hq.org
Mon Jan 10 15:54:27 EET 2011


At http://bazaar.launchpad.net/~maria-captains/maria/5.2

------------------------------------------------------------
revno: 2906 [merge]
revision-id: knielsen at knielsen-hq.org-20110110135426-og3r30f6vfw6c3yk
parent: knielsen at knielsen-hq.org-20110110135309-1htrrsod0s3i3haz
parent: knielsen at knielsen-hq.org-20101227213737-69axme9nj22hgylw
committer: knielsen at knielsen-hq.org
branch nick: work-5.2-percona-mwl47
timestamp: Mon 2011-01-10 14:54:26 +0100
message:
  Merge
added:
  mysql-test/suite/rpl/r/rpl_row_index_choice.result rpl_row_index_choice-20101227203242-xexy0aedoanxras2-1
  mysql-test/suite/rpl/t/rpl_row_index_choice.test rpl_row_index_choice-20101227203242-xexy0aedoanxras2-2
modified:
  sql/log_event.cc               sp1f-log_event.cc-19700101030959-msmqlflsngxosswid2hpzxly5vfqdddc
  sql/log_event.h                sp1f-log_event.h-19700101030959-clq6ett55tcqbpys2i4cpfrdccq7j4om
=== added file 'mysql-test/suite/rpl/r/rpl_row_index_choice.result'
--- a/mysql-test/suite/rpl/r/rpl_row_index_choice.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_index_choice.result	2010-12-27 21:37:37 +0000
@@ -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="";

=== added file 'mysql-test/suite/rpl/t/rpl_row_index_choice.test'
--- a/mysql-test/suite/rpl/t/rpl_row_index_choice.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/rpl/t/rpl_row_index_choice.test	2010-12-27 21:37:37 +0000
@@ -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="";

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	2011-01-10 13:53:09 +0000
+++ b/sql/log_event.cc	2011-01-10 13:54:26 +0000
@@ -7139,7 +7139,8 @@ Rows_log_event::Rows_log_event(THD *thd_
     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 cha
 #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
    */ 
   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)"));
-
-    /* The 0th key is active: search the table using the index */
-    if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE)))
+    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 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
     /* 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
       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
   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_ope
     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_oper
   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_e
 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_oper
   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;
 }

=== modified file 'sql/log_event.h'
--- a/sql/log_event.h	2011-01-10 13:53:09 +0000
+++ b/sql/log_event.h	2011-01-10 13:54:26 +0000
@@ -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);
 



More information about the commits mailing list