List:Commits« Previous MessageNext Message »
From:marko.makela Date:May 31 2012 12:48pm
Subject:bzr push into mysql-trunk-wl6255 branch (marko.makela:3916 to 3917) WL#6255
View as plain text  
 3917 Marko Mäkelä	2012-05-31
      WL#6255 duplicate key error reporting
      
      When an error occurs during online rebuild apply, convert the buffered row
      into the MySQL record buffer, so that it can be used in error messages,
      such as duplicate key error.
      
      row_log_table_apply_insert(), row_log_table_apply_update(): Invoke
      innobase_rec_to_mysql() on error.
      
      When delete fails, we will not invoke the conversion, because the buffered
      record contains the PRIMARY KEY in the new table, which could differ from
      the old table (different columns).

    modified:
      mysql-test/suite/innodb/r/innodb-table-online.result
      storage/innobase/row/row0log.cc
 3916 Marko Mäkelä	2012-05-31 [merge]
      Merge mysql-trunk to mysql-trunk-wl6255.

    added:
      mysql-test/include/wl6301.inc
      mysql-test/r/wl6301_1_not_windows.result
      mysql-test/r/wl6301_2_not_windows.result
      mysql-test/r/wl6301_3.result
      mysql-test/t/wl6301_1_not_windows-master.opt
      mysql-test/t/wl6301_1_not_windows.test
      mysql-test/t/wl6301_2_not_windows-master.opt
      mysql-test/t/wl6301_2_not_windows.test
      mysql-test/t/wl6301_3-master.opt
      mysql-test/t/wl6301_3.test
    modified:
      mysql-test/r/ipv6.result
      mysql-test/r/mysqld--help-notwin.result
      mysql-test/r/mysqld--help-win.result
      mysql-test/t/ipv6.test
      sql/mysqld.cc
      sql/sys_vars.cc
      storage/innobase/buf/buf0flu.cc
=== modified file 'mysql-test/suite/innodb/r/innodb-table-online.result'
--- a/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@stripped120531102447-4oeg3lbfe1rd819e
+++ b/mysql-test/suite/innodb/r/innodb-table-online.result	revid:marko.makela@oracle.com-20120531124240-feea5g2n2x5gjsei
@@ -89,7 +89,7 @@ ddl_pending_alter_table	1
 BEGIN;
 INSERT INTO t1 VALUES(4,7,2);
 SET DEBUG_SYNC = 'now SIGNAL insert_done';
-ERROR 23000: Duplicate entry '0' for key 'PRIMARY'
+ERROR 23000: Duplicate entry '4' for key 'PRIMARY'
 ROLLBACK;
 SHOW CREATE TABLE t1;
 Table	Create Table

=== modified file 'storage/innobase/row/row0log.cc'
--- a/storage/innobase/row/row0log.cc	revid:marko.makela@stripped7-4oeg3lbfe1rd819e
+++ b/storage/innobase/row/row0log.cc	revid:marko.makela@strippedjsei
@@ -30,6 +30,7 @@ Created 2011-05-26 Marko Makela
 #include "row0merge.h"
 #include "data0data.h"
 #include "que0que.h"
+#include "handler0alter.h"
 
 #include<set>
 
@@ -1103,10 +1104,6 @@ row_log_table_apply_insert_low(
 	case DB_SUCCESS_LOCKED_REC:
 		/* The row had already been copied to the table. */
 		return(DB_SUCCESS);
-	case DB_DUPLICATE_KEY:
-		/* TODO: report the duplicate key unless the record is
-		a full match of what we tried to insert */
-		/* fall through */
 	default:
 		return(error);
 	}
@@ -1122,10 +1119,6 @@ row_log_table_apply_insert_low(
 			index, offsets_heap, heap, entry, thr);
 	} while (error == DB_SUCCESS);
 
-	if (error == DB_DUPLICATE_KEY) {
-		/* TODO: report a duplicate */
-	}
-
 	return(error);
 }
 
@@ -1149,10 +1142,18 @@ row_log_table_apply_insert(
 	row_merge_dup_t*	dup)		/*!< in/out: for reporting
 						duplicate key errors */
 {
-	const dtuple_t*	row = row_log_table_apply_convert_mrec(
+	const dtuple_t*	row	= row_log_table_apply_convert_mrec(
 		mrec, offsets, heap, new_table, altered_table, dup);
-	return(row_log_table_apply_insert_low(thr, row, offsets_heap, heap,
-					      new_table, altered_table, dup));
+	dberr_t		error	= row_log_table_apply_insert_low(
+		thr, row, offsets_heap, heap, new_table, altered_table, dup);
+
+	if (error != DB_SUCCESS) {
+		/* Report the erroneous row using the old
+		version of the table. */
+		innobase_rec_to_mysql(dup->table, mrec, dup->index, offsets);
+	}
+
+	return(error);
 }
 
 /******************************************************//**
@@ -1330,6 +1331,10 @@ all_done:
 		}
 	}
 
+	/* We cannot invoke innobase_rec_to_mysql() to convert an
+	erroneous mrec to a MySQL row if a PRIMARY KEY is being created.
+	Error messages on delete should not need the row, though. Only
+	messages about duplicates or failed conversions use the row. */
 	return(row_log_table_apply_delete_low(&pcur, offsets, heap, &mtr));
 }
 
@@ -1367,6 +1372,7 @@ row_log_table_apply_update(
 	dict_index_t*	index = dict_table_get_first_index(new_table);
 	mtr_t		mtr;
 	btr_pcur_t	pcur;
+	dberr_t		error;
 
 	ut_ad(dtuple_get_n_fields_cmp(old_pk)
 	      == dict_index_get_n_unique(index));
@@ -1399,9 +1405,19 @@ row_log_table_apply_update(
 		mtr_commit(&mtr);
 insert:
 		/* The row was not found. Insert it. */
-		return(row_log_table_apply_insert_low(
-			       thr, row, offsets_heap, heap,
-			       new_table, altered_table, dup));
+		error = row_log_table_apply_insert_low(
+			thr, row, offsets_heap, heap,
+			new_table, altered_table, dup);
+
+		if (error != DB_SUCCESS) {
+err_exit:
+			/* Report the erroneous row using the old
+			version of the table. */
+			innobase_rec_to_mysql(
+				dup->table, mrec, dup->index, offsets);
+		}
+
+		return(error);
 	}
 
 	/* Update the record. */
@@ -1414,7 +1430,8 @@ insert:
 	const upd_t*	update	= row_upd_build_difference_binary(
 		index, entry, btr_pcur_get_rec(&pcur), cur_offsets,
 		false, NULL, heap);
-	dberr_t		error	= DB_SUCCESS;
+
+	error = DB_SUCCESS;
 
 	if (!update->n_fields) {
 		/* Nothing to do. */
@@ -1433,7 +1450,7 @@ delete_insert:
 		ut_ad(mtr.state == MTR_COMMITTED);
 
 		if (error != DB_SUCCESS) {
-			return(error);
+			goto err_exit;
 		}
 
 		goto insert;
@@ -1568,6 +1585,10 @@ delete_insert:
 
 func_exit:
 	mtr_commit(&mtr);
+	if (error != DB_SUCCESS) {
+		goto err_exit;
+	}
+
 	return(error);
 }
 

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk-wl6255 branch (marko.makela:3916 to 3917) WL#6255marko.makela31 May