List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:November 10 2010 3:05pm
Subject:bzr commit into mysql-5.5-runtime branch (jon.hauglid:3179) Bug#50619
View as plain text  
#At file:///export/home/x/mysql-5.5-runtime-bug50619/ based on revid:jon.hauglid@stripped

 3179 Jon Olav Hauglid	2010-11-10
      Bug #50619 assert in handler::update_auto_increment
      
      This assert could happen during subsequent inserts if -1 had
      already been inserted into an auto increment column.
      
      The root cause of the problem is that auto increment values are
      internally stored unsigned while auto increment column types can
      be signed values. When an explict value is set for the auto 
      increment column, the internal auto increment value is reset to
      the explicit value + 1. However, if the explicit value is -1,
      converting this value to unsigned and adding 1 will yield 0 as
      a result (due to overflow). Since 0 would be outside the reserved
      auto increment interval for the insert (auto increment values
      should start at 1), the assert would be triggered.
      
      This patch fixes the problem by checking if the explicit value
      is negative. If this is the case, auto increment values are not
      reset.
      
      Test case added to auto_increment.test.

    modified:
      mysql-test/r/auto_increment.result
      mysql-test/t/auto_increment.test
      sql/handler.cc
      sql/handler.h
=== modified file 'mysql-test/r/auto_increment.result'
--- a/mysql-test/r/auto_increment.result	2010-08-18 09:35:41 +0000
+++ b/mysql-test/r/auto_increment.result	2010-11-10 15:05:22 +0000
@@ -476,3 +476,16 @@ SELECT a FROM t2;
 a
 2
 DROP TABLE t1, t2;
+#
+# Bug#50619 assert in handler::update_auto_increment
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (pk INT AUTO_INCREMENT, PRIMARY KEY (pk));
+INSERT INTO t1 VALUES (-1);
+CREATE TRIGGER tr1 BEFORE DELETE ON t1 FOR EACH ROW SET @aux = 1 ;
+REPLACE INTO t1 (pk) VALUES (NULL), (-1);
+SELECT * FROM t1;
+pk
+-1
+1
+DROP TABLE t1;

=== modified file 'mysql-test/t/auto_increment.test'
--- a/mysql-test/t/auto_increment.test	2010-08-18 09:35:41 +0000
+++ b/mysql-test/t/auto_increment.test	2010-11-10 15:05:22 +0000
@@ -342,3 +342,20 @@ SELECT a FROM t2;
 
 DROP TABLE t1, t2;
 
+
+--echo #
+--echo # Bug#50619 assert in handler::update_auto_increment
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1 (pk INT AUTO_INCREMENT, PRIMARY KEY (pk));
+INSERT INTO t1 VALUES (-1);
+CREATE TRIGGER tr1 BEFORE DELETE ON t1 FOR EACH ROW SET @aux = 1 ;
+# This caused an assert
+REPLACE INTO t1 (pk) VALUES (NULL), (-1);
+SELECT * FROM t1;
+
+DROP TABLE t1;

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	2010-10-18 11:27:52 +0000
+++ b/sql/handler.cc	2010-11-10 15:05:22 +0000
@@ -2204,14 +2204,14 @@ compute_next_insert_id(ulonglong nr,stru
 }
 
 
-void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
+void handler::adjust_next_insert_id_after_explicit_value(longlong nr)
 {
   /*
     If we have set THD::next_insert_id previously and plan to insert an
     explicitely-specified value larger than this, we need to increase
     THD::next_insert_id to be greater than the explicit value.
   */
-  if ((next_insert_id > 0) && (nr >= next_insert_id))
+  if ((next_insert_id > 0) && (nr >=0) && ((ulonglong)nr >= next_insert_id))
     set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
 }
 
@@ -2348,7 +2348,7 @@ int handler::update_auto_increment()
   */
   DBUG_ASSERT(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
 
-  if ((nr= table->next_number_field->val_int()) != 0 ||
+  if ((table->next_number_field->val_int() != 0) ||
       (table->auto_increment_field_not_null &&
       thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
   {
@@ -2358,7 +2358,8 @@ int handler::update_auto_increment()
       the last NULL needs to insert 3764, not the value of the first NULL plus
       1).
     */
-    adjust_next_insert_id_after_explicit_value(nr);
+    adjust_next_insert_id_after_explicit_value(
+      table->next_number_field->val_int());
     insert_id_for_cur_row= 0; // didn't generate anything
     DBUG_RETURN(0);
   }

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2010-10-06 14:34:28 +0000
+++ b/sql/handler.h	2010-11-10 15:05:22 +0000
@@ -1358,7 +1358,7 @@ public:
   int ha_drop_partitions(const char *path);
   int ha_rename_partitions(const char *path);
 
-  void adjust_next_insert_id_after_explicit_value(ulonglong nr);
+  void adjust_next_insert_id_after_explicit_value(longlong nr);
   int update_auto_increment();
   void print_keydup_error(uint key_nr, const char *msg);
   virtual void print_error(int error, myf errflag);


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20101110150522-bg2nayj2r2pxor2m.bundle
Thread
bzr commit into mysql-5.5-runtime branch (jon.hauglid:3179) Bug#50619Jon Olav Hauglid10 Nov
  • Re: bzr commit into mysql-5.5-runtime branch (jon.hauglid:3179) Bug#50619Guilhem Bichot12 Nov
    • Re: bzr commit into mysql-5.5-runtime branch (jon.hauglid:3179)Bug#50619Jon Olav Hauglid13 Dec