List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 5 2010 12:39pm
Subject:bzr commit into mysql-5.1-innodb branch (marko.makela:3454)
View as plain text  
#At file:///home/marko/innobase/dev/mysql/5.1-innodb/ based on revid:marko.makela@strippedklpheslrxs

 3454 Marko Mäkelä	2010-05-05
      Merge a contribution from Ryan Mack at Facebook:
      
      Bugfix for 53290, fast unique index creation fails on duplicate null values
      
          Summary:
          Bug in the fast index creation code incorrectly considers null
          values to be duplicates during block merging.  Innodb policy is that
          multiple null values are allowed in a unique index.  Null duplicates
          were correctly ignored while sorting individual blocks and with slow
          index creation.
      
          Test Plan:
          mtr, including new test, load dbs using deferred index creation
      
          DiffCamp Revision: 110840
          Reviewed By: mcallaghan
          CC: mcallaghan, mysql-devel@lists
          Revert Plan:
          OK

    added:
      mysql-test/suite/innodb_plugin/r/innodb_bug53290.result
      mysql-test/suite/innodb_plugin/t/innodb_bug53290.test
    modified:
      storage/innodb_plugin/include/rem0cmp.h
      storage/innodb_plugin/rem/rem0cmp.c
      storage/innodb_plugin/row/row0merge.c
=== added file 'mysql-test/suite/innodb_plugin/r/innodb_bug53290.result'
--- a/mysql-test/suite/innodb_plugin/r/innodb_bug53290.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/r/innodb_bug53290.result	2010-05-05 12:39:01 +0000
@@ -0,0 +1,17 @@
+create table bug53290 (x bigint) engine=innodb;
+insert into bug53290 () values (),(),(),(),(),(),(),(),(),(),(),();
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+alter table bug53290 add unique index `idx` (x);
+drop table bug53290;

=== added file 'mysql-test/suite/innodb_plugin/t/innodb_bug53290.test'
--- a/mysql-test/suite/innodb_plugin/t/innodb_bug53290.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb_plugin/t/innodb_bug53290.test	2010-05-05 12:39:01 +0000
@@ -0,0 +1,22 @@
+-- source include/have_innodb_plugin.inc
+
+create table bug53290 (x bigint) engine=innodb;
+
+insert into bug53290 () values (),(),(),(),(),(),(),(),(),(),(),();
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+insert into bug53290 select * from bug53290;
+
+alter table bug53290 add unique index `idx` (x);
+
+drop table bug53290;

=== modified file 'storage/innodb_plugin/include/rem0cmp.h'
--- a/storage/innodb_plugin/include/rem0cmp.h	2009-08-06 22:04:03 +0000
+++ b/storage/innodb_plugin/include/rem0cmp.h	2010-05-05 12:39:01 +0000
@@ -148,7 +148,9 @@ cmp_rec_rec_simple(
 	const rec_t*		rec2,	/*!< in: physical record */
 	const ulint*		offsets1,/*!< in: rec_get_offsets(rec1, ...) */
 	const ulint*		offsets2,/*!< in: rec_get_offsets(rec2, ...) */
-	const dict_index_t*	index);	/*!< in: data dictionary index */
+	const dict_index_t*	index,	/*!< in: data dictionary index */
+	ibool*			null_eq);/*!< out: set to TRUE if
+					found matching null values */
 /*************************************************************//**
 This function is used to compare two physical records. Only the common
 first fields are compared, and if an externally stored field is

=== modified file 'storage/innodb_plugin/rem/rem0cmp.c'
--- a/storage/innodb_plugin/rem/rem0cmp.c	2009-08-06 22:04:03 +0000
+++ b/storage/innodb_plugin/rem/rem0cmp.c	2010-05-05 12:39:01 +0000
@@ -706,7 +706,9 @@ cmp_rec_rec_simple(
 	const rec_t*		rec2,	/*!< in: physical record */
 	const ulint*		offsets1,/*!< in: rec_get_offsets(rec1, ...) */
 	const ulint*		offsets2,/*!< in: rec_get_offsets(rec2, ...) */
-	const dict_index_t*	index)	/*!< in: data dictionary index */
+	const dict_index_t*	index,	/*!< in: data dictionary index */
+	ibool*			null_eq)/*!< out: set to TRUE if
+					found matching null values */
 {
 	ulint		rec1_f_len;	/*!< length of current field in rec1 */
 	const byte*	rec1_b_ptr;	/*!< pointer to the current byte
@@ -753,6 +755,9 @@ cmp_rec_rec_simple(
 		    || rec2_f_len == UNIV_SQL_NULL) {
 
 			if (rec1_f_len == rec2_f_len) {
+				if (null_eq) {
+					*null_eq = TRUE;
+				}
 
 				goto next_field;
 

=== modified file 'storage/innodb_plugin/row/row0merge.c'
--- a/storage/innodb_plugin/row/row0merge.c	2010-05-05 11:24:11 +0000
+++ b/storage/innodb_plugin/row/row0merge.c	2010-05-05 12:39:01 +0000
@@ -1075,11 +1075,14 @@ row_merge_cmp(
 						record to be compared */
 	const ulint*		offsets1,	/*!< in: first record offsets */
 	const ulint*		offsets2,	/*!< in: second record offsets */
-	const dict_index_t*	index)		/*!< in: index */
+	const dict_index_t*	index,		/*!< in: index */
+	ibool*			null_eq)	/*!< out: set to TRUE if
+						found matching null values */
 {
 	int	cmp;
 
-	cmp = cmp_rec_rec_simple(mrec1, mrec2, offsets1, offsets2, index);
+	cmp = cmp_rec_rec_simple(mrec1, mrec2, offsets1, offsets2, index,
+				 null_eq);
 
 #ifdef UNIV_DEBUG
 	if (row_merge_print_cmp) {
@@ -1445,11 +1448,13 @@ corrupt:
 	}
 
 	while (mrec0 && mrec1) {
+		ibool	null_eq = FALSE;
 		switch (row_merge_cmp(mrec0, mrec1,
-				      offsets0, offsets1, index)) {
+				      offsets0, offsets1, index,
+				      &null_eq)) {
 		case 0:
 			if (UNIV_UNLIKELY
-			    (dict_index_is_unique(index))) {
+			    (dict_index_is_unique(index) && !null_eq)) {
 				innobase_rec_to_mysql(table, mrec0,
 						      index, offsets0);
 				mem_heap_free(heap);

Attachment: [text/bzr-bundle] bzr/marko.makela@oracle.com-20100505123901-xjxu93h1xnbkfkq0.bundle
Thread
bzr commit into mysql-5.1-innodb branch (marko.makela:3454) marko.makela5 May