List:Commits« Previous MessageNext Message »
From:ingo Date:July 4 2007 1:33pm
Subject:bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158
View as plain text  
Below is the list of changes that have just been committed into a local
6.0-falcon repository of istruewing. When istruewing does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-07-04 15:32:31+02:00, istruewing@stripped +4 -0
  Bug#28158 - table->read_set is set incorrectly,
              causing wrong error message in Falcon
  
  An error message about a duplicate key could show a wrong key
  value when not all columns of the key were used to select the
  rows for update.
  
  Some storage engines return a record with only the selected
  columns filled.
  
  This is fixed by re-reading the record with a read_set which
  includes all columns of the duplicate key after a duplicate key
  error happens and before the error message is printed.

  mysql-test/r/ndb_update.result@stripped, 2007-07-04 15:32:19+02:00, istruewing@stripped +46 -0
    Bug#28158 - table->read_set is set incorrectly,
                causing wrong error message in Falcon
    Added test result.

  mysql-test/t/disabled.def@stripped, 2007-07-04 15:32:19+02:00, istruewing@stripped +0 -2
    Bug#28158 - table->read_set is set incorrectly,
                causing wrong error message in Falcon
    Enabled test cases falcon_bug_28158 and falcon_bug_28165.

  mysql-test/t/ndb_update.test@stripped, 2007-07-04 15:32:19+02:00, istruewing@stripped +49 -1
    Bug#28158 - table->read_set is set incorrectly,
                causing wrong error message in Falcon
    Added test from falcon_bug_28158.

  sql/sql_update.cc@stripped, 2007-07-04 15:32:19+02:00, istruewing@stripped +89 -0
    Bug#28158 - table->read_set is set incorrectly,
                causing wrong error message in Falcon
    Added a function for re-reading a record with a read_set
    that contains all fields used by a duplicate key.
    Called the function before every call to handler::print_error(),
    which could print a duplicate key value.

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	istruewing
# Host:	chilla.local
# Root:	/home/mydev/mysql-5.1-falcon-bug28158

--- 1.245/sql/sql_update.cc	2007-07-04 15:33:09 +02:00
+++ 1.246/sql/sql_update.cc	2007-07-04 15:33:09 +02:00
@@ -83,6 +83,75 @@ static bool check_fields(THD *thd, List<
 }
 
 
+/**
+  @brief Re-read record if more columns are needed for error message.
+
+  @detail If we got a duplicate key error, we want to write an error
+    message containing the value of the duplicate key. If we do not have
+    all fields of the key value in record[0], we need to re-read the
+    record with a proper read_set.
+
+  @param[in] error   error number
+  @param[in] table   table
+*/
+
+static void prepare_record_for_error_message(int error, TABLE *table)
+{
+  Field **field_p;
+  Field *field;
+  uint keynr;
+  MY_BITMAP unique_map; /* Fields in offended unique. */
+  my_bitmap_map unique_map_buf[bitmap_buffer_size(MAX_FIELDS)];
+  DBUG_ENTER("prepare_record_for_error_message");
+
+  /*
+    Only duplicate key errors print the key value.
+    If storage engine does always read all columns, we have the value alraedy.
+  */
+  if ((error != HA_ERR_FOUND_DUPP_KEY) ||
+      !(table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ))
+    DBUG_VOID_RETURN;
+
+  /*
+    Get the number of the offended index.
+    We will see MAX_KEY if the engine cannot determine the affected index.
+  */
+  if ((keynr= table->file->get_dup_key(error)) >= MAX_KEY)
+    DBUG_VOID_RETURN;
+
+  /* Create unique_map with all fields used by that index. */
+  bitmap_init(&unique_map, unique_map_buf, table->s->fields, FALSE);
+  table->mark_columns_used_by_index_no_reset(keynr, &unique_map);
+
+  /* Subtract read_set and write_set. */
+  bitmap_subtract(&unique_map, table->read_set);
+  bitmap_subtract(&unique_map, table->write_set);
+
+  /*
+    If the unique index uses columns that are neither in read_set
+    nor in write_set, we must re-read the record.
+    Otherwise no need to do anything.
+  */
+  if (bitmap_is_clear_all(&unique_map))
+    DBUG_VOID_RETURN;
+
+  /* Get identifier of last read record into table->file->ref. */
+  table->file->position(table->record[0]);
+  /* Add all fields used by unique index to read_set. */
+  bitmap_union(table->read_set, &unique_map);
+  /* Tell the engine about the new set. */
+  table->file->column_bitmaps_signal();
+  /* Read record that is identified by table->file->ref. */
+  (void) table->file->rnd_pos(table->record[1], table->file->ref);
+  /* Copy the newly read columns into the new record. */
+  for (field_p= table->field; (field= *field_p); field_p++)
+    if (bitmap_is_set(&unique_map, field->field_index))
+      field->copy_from_tmp(table->s->rec_buff_length);
+
+  DBUG_VOID_RETURN;
+}
+
+
 /*
   Process usual UPDATE
 
@@ -471,6 +540,13 @@ int mysql_update(THD *thd,
     will_batch= !table->file->start_bulk_update();
 
   /*
+    Assure that we can use position()
+    if we need to create an error message.
+  */
+  if (table->file->ha_table_flags() & HA_PARTIAL_COLUMN_READ)
+    table->prepare_for_position();
+
+  /*
     We can use compare_record() to optimize away updates if
     the table handler is returning all columns OR if
     if all updated columns are read
@@ -570,6 +646,8 @@ int mysql_update(THD *thd,
           */
           if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
             thd->fatal_error(); /* Other handler errors are fatal */
+
+          prepare_record_for_error_message(error, table);
 	  table->file->print_error(error,MYF(0));
 	  error= 1;
 	  break;
@@ -593,13 +671,16 @@ int mysql_update(THD *thd,
         {
  	  if (error)
           {
+            /* purecov: begin inspected */
             /*
               The handler should not report error of duplicate keys if they
               are ignored. This is a requirement on batching handlers.
             */
+            prepare_record_for_error_message(error, table);
             table->file->print_error(error,MYF(0));
             error= 1;
             break;
+            /* purecov: end */
           }
           /*
             Either an error was found and we are ignoring errors or there
@@ -665,9 +746,12 @@ int mysql_update(THD *thd,
       in the batched update.
     */
   {
+    /* purecov: begin inspected */
     thd->fatal_error();
+    prepare_record_for_error_message(loc_error, table);
     table->file->print_error(loc_error,MYF(0));
     error= 1;
+    /* purecov: end */
   }
   else
     updated-= dup_key_found;
@@ -1525,6 +1609,8 @@ bool multi_update::send_data(List<Item> 
             */
             if (table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
               thd->fatal_error(); /* Other handler errors are fatal */
+
+            prepare_record_for_error_message(error, table);
             table->file->print_error(error,MYF(0));
             DBUG_RETURN(1);
           }
@@ -1752,8 +1838,11 @@ int multi_update::do_updates(bool from_s
 err:
   if (!from_send_error)
   {
+    /* purecov: begin inspected */
     thd->fatal_error();
+    prepare_record_for_error_message(local_error, table);
     table->file->print_error(local_error,MYF(0));
+    /* purecov: end */
   }
 
 err2:

--- 1.335/mysql-test/t/disabled.def	2007-07-04 15:33:09 +02:00
+++ 1.336/mysql-test/t/disabled.def	2007-07-04 15:33:10 +02:00
@@ -72,8 +72,6 @@ falcon_bug_26827    : Bug#26827 2007-03-
 falcon_bug_27426    : Bug#27426 2007-03-27 hakank Currently failing
 falcon_bug_27997    : Bug#27997 2007-04-21 hakank Currently failing
 falcon_bug_28026    : Bug#28026 2007-04-25 hakank Currently failing
-falcon_bug_28158    : Bug#28158 2007-05-02 hakank Currently failing
-falcon_bug_28165    : Bug#28158 2007-05-02 hakank Currently failing because of Bug#28158
 falcon_bug_29246    : Bug#29246 2007-06-21 hakank Currently failing
 falcon_bug_29319    : Bug#29319 2007-06-24 hakank Currently failing
 falcon_page_size_1  : Bug#23220 2007-02-19 hakank Currently failing

--- 1.20/mysql-test/r/ndb_update.result	2007-07-04 15:33:10 +02:00
+++ 1.21/mysql-test/r/ndb_update.result	2007-07-04 15:33:10 +02:00
@@ -1,4 +1,6 @@
 DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
 CREATE TABLE t1 (
 pk1 INT NOT NULL PRIMARY KEY,
 b INT NOT NULL,
@@ -40,3 +42,47 @@ pk1	b	c
 12	2	2
 14	1	1
 DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (a int, b int, KEY (a, b)) ENGINE=ndbcluster;
+CREATE TABLE t2 (a int, b int, UNIQUE KEY (a, b)) ENGINE=ndbcluster;
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a, b)) ENGINE=ndbcluster;
+INSERT INTO t1 VALUES (1, 2);
+INSERT INTO t1 VALUES (2, 2);
+INSERT INTO t2 VALUES (1, 2);
+INSERT INTO t2 VALUES (2, 2);
+INSERT INTO t3 VALUES (1, 2);
+INSERT INTO t3 VALUES (2, 2);
+UPDATE t1 SET a = 1;
+UPDATE t1 SET a = 1 ORDER BY a;
+UPDATE t2 SET a = 1;
+ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
+UPDATE t2 SET a = 1 ORDER BY a;
+ERROR 23000: Duplicate entry '' for key '*UNKNOWN*'
+UPDATE t3 SET a = 1;
+ERROR 23000: Duplicate entry '1-2' for key 'PRIMARY'
+UPDATE t3 SET a = 1 ORDER BY a;
+ERROR 23000: Duplicate entry '1-2' for key 'PRIMARY'
+SELECT count(*) FROM t1;
+count(*)
+2
+SELECT count(*) FROM t2;
+count(*)
+2
+SELECT count(*) FROM t3;
+count(*)
+2
+SELECT * FROM t1 ORDER by a;
+a	b
+1	2
+1	2
+SELECT * FROM t2 ORDER by a;
+a	b
+1	2
+2	2
+SELECT * FROM t3 ORDER by a;
+a	b
+1	2
+2	2
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+End of 5.1 tests

--- 1.10/mysql-test/t/ndb_update.test	2007-07-04 15:33:10 +02:00
+++ 1.11/mysql-test/t/ndb_update.test	2007-07-04 15:33:10 +02:00
@@ -3,10 +3,12 @@
 
 --disable_warnings
 DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
 --enable_warnings
 
 #
-# Basic test of INSERT in NDB 
+# Basic test of UPDATE in NDB 
 #
 
 #
@@ -39,3 +41,49 @@ DROP TABLE IF EXISTS t1;
 --enable_warnings
 
 # End of 4.1 tests
+
+#
+# Bug#28158: table->read_set is set incorrectly,
+#            causing wrong error message in Falcon
+#
+CREATE TABLE t1 (a int, b int, KEY (a, b)) ENGINE=ndbcluster;
+CREATE TABLE t2 (a int, b int, UNIQUE KEY (a, b)) ENGINE=ndbcluster;
+CREATE TABLE t3 (a int, b int, PRIMARY KEY (a, b)) ENGINE=ndbcluster;
+#
+INSERT INTO t1 VALUES (1, 2);
+INSERT INTO t1 VALUES (2, 2);
+#
+INSERT INTO t2 VALUES (1, 2);
+INSERT INTO t2 VALUES (2, 2);
+#
+INSERT INTO t3 VALUES (1, 2);
+INSERT INTO t3 VALUES (2, 2);
+#
+UPDATE t1 SET a = 1;
+UPDATE t1 SET a = 1 ORDER BY a;
+#
+--error 1582
+UPDATE t2 SET a = 1;
+--error 1582
+UPDATE t2 SET a = 1 ORDER BY a;
+#
+--error 1582
+UPDATE t3 SET a = 1;
+--error 1582
+UPDATE t3 SET a = 1 ORDER BY a;
+#
+SELECT count(*) FROM t1;
+SELECT count(*) FROM t2;
+SELECT count(*) FROM t3;
+SELECT * FROM t1 ORDER by a;
+SELECT * FROM t2 ORDER by a;
+SELECT * FROM t3 ORDER by a;
+#
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+DROP TABLE IF EXISTS t2;
+DROP TABLE IF EXISTS t3;
+--enable_warnings
+
+--echo End of 5.1 tests
+
Thread
bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158ingo4 Jul
  • Re: bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158Sergei Golubchik9 Jul
    • Re: bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158Ingo Strüwing10 Jul
      • Re: bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158Sergei Golubchik10 Jul
        • Re: bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158Ingo Strüwing10 Jul
        • Re: bk commit into 6.0-falcon tree (istruewing:1.2567) BUG#28158Ingo Strüwing10 Jul