From ffad1562542a72f41912ef1edd55b3a49e7fe89d Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:01:31 +0400
Subject: [PATCH 1/8] Applying InnoDB snapshot

Detailed revision comments:

r6535 | sunny | 2010-01-30 00:08:40 +0200 (Sat, 30 Jan 2010) | 11 lines
branches/5.1: Undo the change from r6424. We need to return DB_SUCCESS even
if we were unable to initialize the tabe autoinc value. This is required for
the open to succeed. The only condition we currently treat as a hard error
is if the autoinc field instance passed in by MySQL is NULL.

Previously if the table autoinc value was 0 and the next value was requested
we had an assertion that would fail. Change that assertion and treat a value
of 0 to mean that the autoinc system is unavailable. Generation of next
value will now return failure.

rb://237
---
 storage/innobase/handler/ha_innodb.cc | 38 ++++++++++++++++++++-------
 1 file changed, 28 insertions(+), 10 deletions(-)

diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 9b6c2cf9895..e3aa5fb4f5b 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
 		auto_inc = innobase_get_int_col_max_value(field);
 	} else {
 		/* We have no idea what's been passed in to us as the
-		autoinc column. We set it to the MAX_INT of our table
-		autoinc type. */
-		auto_inc = 0xFFFFFFFFFFFFFFFFULL;
+		autoinc column. We set it to the 0, effectively disabling
+		updates to the table. */
+		auto_inc = 0;
 
 		ut_print_timestamp(stderr);
 		fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
 
 	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 		/* If the recovery level is set so high that writes
-		are disabled we force the AUTOINC counter to the MAX
+		are disabled we force the AUTOINC counter to 0
 		value effectively disabling writes to the table.
 		Secondly, we avoid reading the table in case the read
 		results in failure due to a corrupted table/index.
@@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc()
 		tables can be dumped with minimal hassle.  If an error
 		were returned in this case, the first attempt to read
 		the table would fail and subsequent SELECTs would succeed. */
+		auto_inc = 0;
 	} else if (field == NULL) {
+		/* This is a far more serious error, best to avoid
+		opening the table and return failure. */
 		my_error(ER_AUTOINC_READ_FAILED, MYF(0));
 	} else {
 		dict_index_t*	index;
@@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc()
 				"InnoDB: Unable to find the AUTOINC column "
 				"%s in the InnoDB table %s.\n"
 				"InnoDB: We set the next AUTOINC column "
-				"value to the maximum possible value,\n"
+				"value to 0,\n"
 				"InnoDB: in effect disabling the AUTOINC "
 				"next value generation.\n"
 				"InnoDB: You can either set the next "
@@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc()
 				"recreating the table.\n",
 				col_name, index->table->name);
 
-			my_error(ER_AUTOINC_READ_FAILED, MYF(0));
+			/* This will disable the AUTOINC generation. */
+			auto_inc = 0;
+
+			/* We want the open to succeed, so that the user can
+			take corrective action. ie. reads should succeed but
+			updates should fail. */
+			err = DB_SUCCESS;
 			break;
 		default:
 			/* row_search_max_autoinc() should only return
@@ -3968,11 +3977,17 @@ no_commit:
 		prebuilt->autoinc_error = DB_SUCCESS;
 
 		if ((error = update_auto_increment())) {
-
 			/* We don't want to mask autoinc overflow errors. */
-			if (prebuilt->autoinc_error != DB_SUCCESS) {
-				error = (int) prebuilt->autoinc_error;
 
+			/* Handle the case where the AUTOINC sub-system
+			failed during initialization. */
+			if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
+				error_result = ER_AUTOINC_READ_FAILED;
+				/* Set the error message to report too. */
+				my_error(ER_AUTOINC_READ_FAILED, MYF(0));
+				goto func_exit;
+			} else if (prebuilt->autoinc_error != DB_SUCCESS) {
+				error = (int) prebuilt->autoinc_error;
 				goto report_error;
 			}
 
@@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc(
 		*value = dict_table_autoinc_read(prebuilt->table);
 
 		/* It should have been initialized during open. */
-		ut_a(*value != 0);
+		if (*value == 0) {
+			prebuilt->autoinc_error = DB_UNSUPPORTED;
+			dict_table_autoinc_unlock(prebuilt->table);
+		}
 	}
   
 	return(ulong(prebuilt->autoinc_error));

From 91c42548c8685bcebecf19c960b2ab99c173b02d Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:02:05 +0400
Subject: [PATCH 2/8] Applying InnoDB snapshot

Detailed revision comments:

r6536 | sunny | 2010-01-30 00:13:42 +0200 (Sat, 30 Jan 2010) | 6 lines
branches/5.1: Check *first_value everytime against the column max
value and  set *first_value to next autoinc if it's > col max value.
ie.  not rely on what is passed in from MySQL.

[49497] Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
rb://236
---
 mysql-test/r/innodb-autoinc.result    | 83 +++++++++++++++++++++++++++
 mysql-test/t/innodb-autoinc.test      | 31 ++++++++++
 storage/innobase/handler/ha_innodb.cc | 54 +++++++----------
 3 files changed, 134 insertions(+), 34 deletions(-)

diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result
index c03daa3565e..a36b3a1a865 100644
--- a/mysql-test/r/innodb-autoinc.result
+++ b/mysql-test/r/innodb-autoinc.result
@@ -1161,3 +1161,86 @@ t1	CREATE TABLE `t1` (
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
 DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+2
+3
+4
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
+INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+4
+5
+6
+7
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+5
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test
index bb431408937..ef0359b78b0 100644
--- a/mysql-test/t/innodb-autoinc.test
+++ b/mysql-test/t/innodb-autoinc.test
@@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1);
 SELECT * FROM t1;
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
+
+##
+# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
+INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e3aa5fb4f5b..7b501a23d21 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
 		auto_inc = innobase_get_int_col_max_value(field);
 	} else {
 		/* We have no idea what's been passed in to us as the
-		autoinc column. We set it to the 0, effectively disabling
-		updates to the table. */
-		auto_inc = 0;
+		autoinc column. We set it to the MAX_INT of our table
+		autoinc type. */
+		auto_inc = 0xFFFFFFFFFFFFFFFFULL;
 
 		ut_print_timestamp(stderr);
 		fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
 
 	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 		/* If the recovery level is set so high that writes
-		are disabled we force the AUTOINC counter to 0
+		are disabled we force the AUTOINC counter to the MAX
 		value effectively disabling writes to the table.
 		Secondly, we avoid reading the table in case the read
 		results in failure due to a corrupted table/index.
@@ -2672,10 +2672,7 @@ ha_innobase::innobase_initialize_autoinc()
 		tables can be dumped with minimal hassle.  If an error
 		were returned in this case, the first attempt to read
 		the table would fail and subsequent SELECTs would succeed. */
-		auto_inc = 0;
 	} else if (field == NULL) {
-		/* This is a far more serious error, best to avoid
-		opening the table and return failure. */
 		my_error(ER_AUTOINC_READ_FAILED, MYF(0));
 	} else {
 		dict_index_t*	index;
@@ -2704,7 +2701,7 @@ ha_innobase::innobase_initialize_autoinc()
 				"InnoDB: Unable to find the AUTOINC column "
 				"%s in the InnoDB table %s.\n"
 				"InnoDB: We set the next AUTOINC column "
-				"value to 0,\n"
+				"value to the maximum possible value,\n"
 				"InnoDB: in effect disabling the AUTOINC "
 				"next value generation.\n"
 				"InnoDB: You can either set the next "
@@ -2713,13 +2710,7 @@ ha_innobase::innobase_initialize_autoinc()
 				"recreating the table.\n",
 				col_name, index->table->name);
 
-			/* This will disable the AUTOINC generation. */
-			auto_inc = 0;
-
-			/* We want the open to succeed, so that the user can
-			take corrective action. ie. reads should succeed but
-			updates should fail. */
-			err = DB_SUCCESS;
+			my_error(ER_AUTOINC_READ_FAILED, MYF(0));
 			break;
 		default:
 			/* row_search_max_autoinc() should only return
@@ -3977,17 +3968,11 @@ no_commit:
 		prebuilt->autoinc_error = DB_SUCCESS;
 
 		if ((error = update_auto_increment())) {
-			/* We don't want to mask autoinc overflow errors. */
 
-			/* Handle the case where the AUTOINC sub-system
-			failed during initialization. */
-			if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
-				error_result = ER_AUTOINC_READ_FAILED;
-				/* Set the error message to report too. */
-				my_error(ER_AUTOINC_READ_FAILED, MYF(0));
-				goto func_exit;
-			} else if (prebuilt->autoinc_error != DB_SUCCESS) {
+			/* We don't want to mask autoinc overflow errors. */
+			if (prebuilt->autoinc_error != DB_SUCCESS) {
 				error = (int) prebuilt->autoinc_error;
+
 				goto report_error;
 			}
 
@@ -7898,10 +7883,7 @@ ha_innobase::innobase_get_autoinc(
 		*value = dict_table_autoinc_read(prebuilt->table);
 
 		/* It should have been initialized during open. */
-		if (*value == 0) {
-			prebuilt->autoinc_error = DB_UNSUPPORTED;
-			dict_table_autoinc_unlock(prebuilt->table);
-		}
+		ut_a(*value != 0);
 	}
   
 	return(ulong(prebuilt->autoinc_error));
@@ -7981,6 +7963,11 @@ ha_innobase::get_auto_increment(
 	invoking this method. So we are not sure if it's guaranteed to
 	be 0 or not. */
 
+	/* We need the upper limit of the col type to check for
+	whether we update the table autoinc counter or not. */
+	ulonglong	col_max_value = innobase_get_int_col_max_value(
+		table->next_number_field);
+
 	/* Called for the first time ? */
 	if (trx->n_autoinc_rows == 0) {
 
@@ -7997,6 +7984,11 @@ ha_innobase::get_auto_increment(
 	/* Not in the middle of a mult-row INSERT. */
 	} else if (prebuilt->autoinc_last_value == 0) {
 		set_if_bigger(*first_value, autoinc);
+	/* Check for -ve values. */
+	} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
+		/* Set to next logical value. */
+		ut_a(autoinc > trx->n_autoinc_rows);
+		*first_value = (autoinc - trx->n_autoinc_rows) - 1;
 	}
 
 	*nb_reserved_values = trx->n_autoinc_rows;
@@ -8007,12 +7999,6 @@ ha_innobase::get_auto_increment(
 		ulonglong	need;
 		ulonglong	current;
 		ulonglong	next_value;
-		ulonglong	col_max_value;
-
-		/* We need the upper limit of the col type to check for
-		whether we update the table autoinc counter or not. */
-		col_max_value = innobase_get_int_col_max_value(
-			table->next_number_field);
 
 		current = *first_value > col_max_value ? autoinc : *first_value;
 		need = *nb_reserved_values * increment;

From ac68d90faa138ced5f8441bd35874a7297a8236e Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:02:26 +0400
Subject: [PATCH 3/8] Applying InnoDB snapshot

Detailed revision comments:

r6537 | sunny | 2010-01-30 00:35:00 +0200 (Sat, 30 Jan 2010) | 2 lines
branches/5.1: Undo r6536.
---
 mysql-test/r/innodb-autoinc.result    | 83 ---------------------------
 mysql-test/t/innodb-autoinc.test      | 31 ----------
 storage/innobase/handler/ha_innodb.cc | 54 ++++++++++-------
 3 files changed, 34 insertions(+), 134 deletions(-)

diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result
index a36b3a1a865..c03daa3565e 100644
--- a/mysql-test/r/innodb-autoinc.result
+++ b/mysql-test/r/innodb-autoinc.result
@@ -1161,86 +1161,3 @@ t1	CREATE TABLE `t1` (
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
 DROP TABLE t1;
-DROP TABLE IF EXISTS t1;
-Warnings:
-Note	1051	Unknown table 't1'
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
-SELECT * FROM t1;
-c1
--685113344
-1
-2
-3
-SHOW CREATE TABLE t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `c1` int(11) NOT NULL AUTO_INCREMENT,
-  PRIMARY KEY (`c1`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
-SELECT * FROM t1;
-c1
--685113344
-2
-3
-4
-SHOW CREATE TABLE t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `c1` int(11) NOT NULL AUTO_INCREMENT,
-  PRIMARY KEY (`c1`)
-) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
-INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
-SELECT * FROM t1;
-c1
--685113344
-1
-2
-3
-4
-5
-6
-7
-SHOW CREATE TABLE t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `c1` int(11) NOT NULL AUTO_INCREMENT,
-  PRIMARY KEY (`c1`)
-) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
-SELECT * FROM t1;
-c1
--685113344
-1
-2
-5
-SHOW CREATE TABLE t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `c1` int(11) NOT NULL AUTO_INCREMENT,
-  PRIMARY KEY (`c1`)
-) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
-SELECT * FROM t1;
-c1
--685113344
-1
-2
-3
-SHOW CREATE TABLE t1;
-Table	Create Table
-t1	CREATE TABLE `t1` (
-  `c1` int(11) NOT NULL AUTO_INCREMENT,
-  PRIMARY KEY (`c1`)
-) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
-DROP TABLE t1;
diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test
index ef0359b78b0..bb431408937 100644
--- a/mysql-test/t/innodb-autoinc.test
+++ b/mysql-test/t/innodb-autoinc.test
@@ -631,34 +631,3 @@ REPLACE INTO t1 VALUES (-1);
 SELECT * FROM t1;
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
-
-##
-# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
-#
-DROP TABLE IF EXISTS t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
-INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
-CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
-INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
-SELECT * FROM t1;
-SHOW CREATE TABLE t1;
-DROP TABLE t1;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index 7b501a23d21..e3aa5fb4f5b 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -2652,9 +2652,9 @@ ha_innobase::innobase_initialize_autoinc()
 		auto_inc = innobase_get_int_col_max_value(field);
 	} else {
 		/* We have no idea what's been passed in to us as the
-		autoinc column. We set it to the MAX_INT of our table
-		autoinc type. */
-		auto_inc = 0xFFFFFFFFFFFFFFFFULL;
+		autoinc column. We set it to the 0, effectively disabling
+		updates to the table. */
+		auto_inc = 0;
 
 		ut_print_timestamp(stderr);
 		fprintf(stderr, "  InnoDB: Unable to determine the AUTOINC "
@@ -2663,7 +2663,7 @@ ha_innobase::innobase_initialize_autoinc()
 
 	if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 		/* If the recovery level is set so high that writes
-		are disabled we force the AUTOINC counter to the MAX
+		are disabled we force the AUTOINC counter to 0
 		value effectively disabling writes to the table.
 		Secondly, we avoid reading the table in case the read
 		results in failure due to a corrupted table/index.
@@ -2672,7 +2672,10 @@ ha_innobase::innobase_initialize_autoinc()
 		tables can be dumped with minimal hassle.  If an error
 		were returned in this case, the first attempt to read
 		the table would fail and subsequent SELECTs would succeed. */
+		auto_inc = 0;
 	} else if (field == NULL) {
+		/* This is a far more serious error, best to avoid
+		opening the table and return failure. */
 		my_error(ER_AUTOINC_READ_FAILED, MYF(0));
 	} else {
 		dict_index_t*	index;
@@ -2701,7 +2704,7 @@ ha_innobase::innobase_initialize_autoinc()
 				"InnoDB: Unable to find the AUTOINC column "
 				"%s in the InnoDB table %s.\n"
 				"InnoDB: We set the next AUTOINC column "
-				"value to the maximum possible value,\n"
+				"value to 0,\n"
 				"InnoDB: in effect disabling the AUTOINC "
 				"next value generation.\n"
 				"InnoDB: You can either set the next "
@@ -2710,7 +2713,13 @@ ha_innobase::innobase_initialize_autoinc()
 				"recreating the table.\n",
 				col_name, index->table->name);
 
-			my_error(ER_AUTOINC_READ_FAILED, MYF(0));
+			/* This will disable the AUTOINC generation. */
+			auto_inc = 0;
+
+			/* We want the open to succeed, so that the user can
+			take corrective action. ie. reads should succeed but
+			updates should fail. */
+			err = DB_SUCCESS;
 			break;
 		default:
 			/* row_search_max_autoinc() should only return
@@ -3968,11 +3977,17 @@ no_commit:
 		prebuilt->autoinc_error = DB_SUCCESS;
 
 		if ((error = update_auto_increment())) {
-
 			/* We don't want to mask autoinc overflow errors. */
-			if (prebuilt->autoinc_error != DB_SUCCESS) {
-				error = (int) prebuilt->autoinc_error;
 
+			/* Handle the case where the AUTOINC sub-system
+			failed during initialization. */
+			if (prebuilt->autoinc_error == DB_UNSUPPORTED) {
+				error_result = ER_AUTOINC_READ_FAILED;
+				/* Set the error message to report too. */
+				my_error(ER_AUTOINC_READ_FAILED, MYF(0));
+				goto func_exit;
+			} else if (prebuilt->autoinc_error != DB_SUCCESS) {
+				error = (int) prebuilt->autoinc_error;
 				goto report_error;
 			}
 
@@ -7883,7 +7898,10 @@ ha_innobase::innobase_get_autoinc(
 		*value = dict_table_autoinc_read(prebuilt->table);
 
 		/* It should have been initialized during open. */
-		ut_a(*value != 0);
+		if (*value == 0) {
+			prebuilt->autoinc_error = DB_UNSUPPORTED;
+			dict_table_autoinc_unlock(prebuilt->table);
+		}
 	}
   
 	return(ulong(prebuilt->autoinc_error));
@@ -7963,11 +7981,6 @@ ha_innobase::get_auto_increment(
 	invoking this method. So we are not sure if it's guaranteed to
 	be 0 or not. */
 
-	/* We need the upper limit of the col type to check for
-	whether we update the table autoinc counter or not. */
-	ulonglong	col_max_value = innobase_get_int_col_max_value(
-		table->next_number_field);
-
 	/* Called for the first time ? */
 	if (trx->n_autoinc_rows == 0) {
 
@@ -7984,11 +7997,6 @@ ha_innobase::get_auto_increment(
 	/* Not in the middle of a mult-row INSERT. */
 	} else if (prebuilt->autoinc_last_value == 0) {
 		set_if_bigger(*first_value, autoinc);
-	/* Check for -ve values. */
-	} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
-		/* Set to next logical value. */
-		ut_a(autoinc > trx->n_autoinc_rows);
-		*first_value = (autoinc - trx->n_autoinc_rows) - 1;
 	}
 
 	*nb_reserved_values = trx->n_autoinc_rows;
@@ -7999,6 +8007,12 @@ ha_innobase::get_auto_increment(
 		ulonglong	need;
 		ulonglong	current;
 		ulonglong	next_value;
+		ulonglong	col_max_value;
+
+		/* We need the upper limit of the col type to check for
+		whether we update the table autoinc counter or not. */
+		col_max_value = innobase_get_int_col_max_value(
+			table->next_number_field);
 
 		current = *first_value > col_max_value ? autoinc : *first_value;
 		need = *nb_reserved_values * increment;

From 6d4e34cabbccbfe75537060e9fafed9c041d1c8d Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:02:57 +0400
Subject: [PATCH 4/8] Applying InnoDB snapshot

Detailed revision comments:

r6538 | sunny | 2010-01-30 00:43:06 +0200 (Sat, 30 Jan 2010) | 6 lines
branches/5.1: Check *first_value every time against the column max
value and  set *first_value to next autoinc if it's > col max value.
ie.  not rely on what is passed in from MySQL.

[49497] Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
rb://236
---
 mysql-test/r/innodb-autoinc.result    | 83 +++++++++++++++++++++++++++
 mysql-test/t/innodb-autoinc.test      | 31 ++++++++++
 storage/innobase/handler/ha_innodb.cc | 16 ++++--
 3 files changed, 124 insertions(+), 6 deletions(-)

diff --git a/mysql-test/r/innodb-autoinc.result b/mysql-test/r/innodb-autoinc.result
index c03daa3565e..a36b3a1a865 100644
--- a/mysql-test/r/innodb-autoinc.result
+++ b/mysql-test/r/innodb-autoinc.result
@@ -1161,3 +1161,86 @@ t1	CREATE TABLE `t1` (
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=latin1
 DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+2
+3
+4
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
+INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+4
+5
+6
+7
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=11 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+5
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=latin1
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
+SELECT * FROM t1;
+c1
+-685113344
+1
+2
+3
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(11) NOT NULL AUTO_INCREMENT,
+  PRIMARY KEY (`c1`)
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=latin1
+DROP TABLE t1;
diff --git a/mysql-test/t/innodb-autoinc.test b/mysql-test/t/innodb-autoinc.test
index bb431408937..ef0359b78b0 100644
--- a/mysql-test/t/innodb-autoinc.test
+++ b/mysql-test/t/innodb-autoinc.test
@@ -631,3 +631,34 @@ REPLACE INTO t1 VALUES (-1);
 SELECT * FROM t1;
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
+
+##
+# 49497: Error 1467 (ER_AUTOINC_READ_FAILED) on inserting a negative value
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (1), (NULL), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (-685113344), (2), (NULL), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (NULL);
+INSERT INTO  t1 VALUES (4), (5), (6), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (NULL), (2), (-685113344), (5);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+CREATE TABLE t1  (c1 INTEGER AUTO_INCREMENT, PRIMARY KEY (c1)) ENGINE=InnoDB;
+INSERT INTO  t1 VALUES (1), (2), (-685113344), (NULL);
+SELECT * FROM t1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc
index e3aa5fb4f5b..b037fa0d0fd 100644
--- a/storage/innobase/handler/ha_innodb.cc
+++ b/storage/innobase/handler/ha_innodb.cc
@@ -7981,6 +7981,11 @@ ha_innobase::get_auto_increment(
 	invoking this method. So we are not sure if it's guaranteed to
 	be 0 or not. */
 
+	/* We need the upper limit of the col type to check for
+	whether we update the table autoinc counter or not. */
+	ulonglong	col_max_value = innobase_get_int_col_max_value(
+		table->next_number_field);
+
 	/* Called for the first time ? */
 	if (trx->n_autoinc_rows == 0) {
 
@@ -7997,6 +8002,11 @@ ha_innobase::get_auto_increment(
 	/* Not in the middle of a mult-row INSERT. */
 	} else if (prebuilt->autoinc_last_value == 0) {
 		set_if_bigger(*first_value, autoinc);
+	/* Check for -ve values. */
+	} else if (*first_value > col_max_value && trx->n_autoinc_rows > 0) {
+		/* Set to next logical value. */
+		ut_a(autoinc > trx->n_autoinc_rows);
+		*first_value = (autoinc - trx->n_autoinc_rows) - 1;
 	}
 
 	*nb_reserved_values = trx->n_autoinc_rows;
@@ -8007,12 +8017,6 @@ ha_innobase::get_auto_increment(
 		ulonglong	need;
 		ulonglong	current;
 		ulonglong	next_value;
-		ulonglong	col_max_value;
-
-		/* We need the upper limit of the col type to check for
-		whether we update the table autoinc counter or not. */
-		col_max_value = innobase_get_int_col_max_value(
-			table->next_number_field);
 
 		current = *first_value > col_max_value ? autoinc : *first_value;
 		need = *nb_reserved_values * increment;

From 167888c6c3aa8a3caea24a1325b22ff02da902ae Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:03:23 +0400
Subject: [PATCH 5/8] Applying InnoDB snapshot, fixes BUG#49001

Detailed revision comments:

r6545 | jyang | 2010-02-03 03:57:32 +0200 (Wed, 03 Feb 2010) | 8 lines
branches/5.1: Fix bug #49001, "SHOW INNODB STATUS deadlock info
incorrect when deadlock detection aborts". Print the correct
lock owner when recursive function lock_deadlock_recursive()
exceeds its maximum depth LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK.

rb://217, approved by Marko.
---
 storage/innobase/lock/lock0lock.c | 98 ++++++++++++++++++++-----------
 1 file changed, 63 insertions(+), 35 deletions(-)

diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c
index 4cc10931060..8f4b64cda96 100644
--- a/storage/innobase/lock/lock0lock.c
+++ b/storage/innobase/lock/lock0lock.c
@@ -306,6 +306,7 @@ FILE*	lock_latest_err_file;
 /* Flags for recursive deadlock search */
 #define LOCK_VICTIM_IS_START	1
 #define LOCK_VICTIM_IS_OTHER	2
+#define LOCK_EXCEED_MAX_DEPTH	3
 
 /************************************************************************
 Checks if a lock request results in a deadlock. */
@@ -332,16 +333,18 @@ lock_deadlock_recursive(
 				was found and we chose some other trx as a
 				victim: we must do the search again in this
 				last case because there may be another
-				deadlock! */
+				deadlock!
+				LOCK_EXCEED_MAX_DEPTH if the lock search
+				exceeds max steps and/or max depth. */
 	trx_t*	start,		/* in: recursion starting point */
 	trx_t*	trx,		/* in: a transaction waiting for a lock */
 	lock_t*	wait_lock,	/* in: the lock trx is waiting to be granted */
 	ulint*	cost,		/* in/out: number of calculation steps thus
 				far: if this exceeds LOCK_MAX_N_STEPS_...
-				we return LOCK_VICTIM_IS_START */
+				we return LOCK_EXCEED_MAX_DEPTH */
 	ulint	depth);		/* in: recursion depth: if this exceeds
 				LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
-				return LOCK_VICTIM_IS_START */
+				return LOCK_EXCEED_MAX_DEPTH */
 
 /*************************************************************************
 Gets the nth bit of a record lock. */
@@ -3084,8 +3087,6 @@ lock_deadlock_occurs(
 	lock_t*	lock,	/* in: lock the transaction is requesting */
 	trx_t*	trx)	/* in: transaction */
 {
-	dict_table_t*	table;
-	dict_index_t*	index;
 	trx_t*		mark_trx;
 	ulint		ret;
 	ulint		cost	= 0;
@@ -3107,31 +3108,50 @@ retry:
 
 	ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
 
-	if (ret == LOCK_VICTIM_IS_OTHER) {
+	switch (ret) {
+	case LOCK_VICTIM_IS_OTHER:
 		/* We chose some other trx as a victim: retry if there still
 		is a deadlock */
-
 		goto retry;
-	}
 
-	if (ret == LOCK_VICTIM_IS_START) {
-		if (lock_get_type(lock) & LOCK_TABLE) {
-			table = lock->un_member.tab_lock.table;
-			index = NULL;
-		} else {
-			index = lock->index;
-			table = index->table;
-		}
+	case LOCK_EXCEED_MAX_DEPTH:
+		/* If the lock search exceeds the max step
+		or the max depth, the current trx will be
+		the victim. Print its information. */
+		rewind(lock_latest_err_file);
+		ut_print_timestamp(lock_latest_err_file);
 
-		lock_deadlock_found = TRUE;
-
-		fputs("*** WE ROLL BACK TRANSACTION (2)\n",
+		fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
+		      " WAITS-FOR GRAPH, WE WILL ROLL BACK"
+		      " FOLLOWING TRANSACTION \n",
 		      lock_latest_err_file);
 
-		return(TRUE);
+		fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
+		      trx_print(lock_latest_err_file, trx, 3000);
+
+		fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
+		      lock_latest_err_file);
+
+		if (lock_get_type(lock) == LOCK_REC) {
+			lock_rec_print(lock_latest_err_file, lock);
+		} else {
+			lock_table_print(lock_latest_err_file, lock);
+		}
+		break;
+
+	case LOCK_VICTIM_IS_START:
+		fputs("*** WE ROLL BACK TRANSACTION (2)\n",
+		      lock_latest_err_file);
+		break;
+
+	default:
+		/* No deadlock detected*/
+		return(FALSE);
 	}
 
-	return(FALSE);
+	lock_deadlock_found = TRUE;
+
+	return(TRUE);
 }
 
 /************************************************************************
@@ -3147,16 +3167,18 @@ lock_deadlock_recursive(
 				was found and we chose some other trx as a
 				victim: we must do the search again in this
 				last case because there may be another
-				deadlock! */
+				deadlock!
+				LOCK_EXCEED_MAX_DEPTH if the lock search
+				exceeds max steps and/or max depth. */
 	trx_t*	start,		/* in: recursion starting point */
 	trx_t*	trx,		/* in: a transaction waiting for a lock */
 	lock_t*	wait_lock,	/* in: the lock trx is waiting to be granted */
 	ulint*	cost,		/* in/out: number of calculation steps thus
 				far: if this exceeds LOCK_MAX_N_STEPS_...
-				we return LOCK_VICTIM_IS_START */
+				we return LOCK_EXCEED_MAX_DEPTH */
 	ulint	depth)		/* in: recursion depth: if this exceeds
 				LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
-				return LOCK_VICTIM_IS_START */
+				return LOCK_EXCEED_MAX_DEPTH */
 {
 	lock_t*	lock;
 	ulint	bit_no		= ULINT_UNDEFINED;
@@ -3215,7 +3237,7 @@ lock_deadlock_recursive(
 
 			lock_trx = lock->trx;
 
-			if (lock_trx == start || too_far) {
+			if (lock_trx == start) {
 
 				/* We came back to the recursion starting
 				point: a deadlock detected; or we have
@@ -3262,19 +3284,10 @@ lock_deadlock_recursive(
 				}
 #ifdef UNIV_DEBUG
 				if (lock_print_waits) {
-					fputs("Deadlock detected"
-					      " or too long search\n",
+					fputs("Deadlock detected\n",
 					      stderr);
 				}
 #endif /* UNIV_DEBUG */
-				if (too_far) {
-
-					fputs("TOO DEEP OR LONG SEARCH"
-					      " IN THE LOCK TABLE"
-					      " WAITS-FOR GRAPH\n", ef);
-
-					return(LOCK_VICTIM_IS_START);
-				}
 
 				if (trx_weight_cmp(wait_lock->trx,
 						   start) >= 0) {
@@ -3310,6 +3323,21 @@ lock_deadlock_recursive(
 				return(LOCK_VICTIM_IS_OTHER);
 			}
 
+			if (too_far) {
+
+#ifdef UNIV_DEBUG
+				if (lock_print_waits) {
+					fputs("Deadlock search exceeds"
+					      " max steps or depth.\n",
+					      stderr);
+				}
+#endif /* UNIV_DEBUG */
+				/* The information about transaction/lock
+				to be rolled back is available in the top
+				level. Do not print anything here. */
+				return(LOCK_EXCEED_MAX_DEPTH);
+			}
+
 			if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
 
 				/* Another trx ahead has requested lock	in an

From 757a1ff33acc48f4466cc1b720a6d45356963d43 Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:03:58 +0400
Subject: [PATCH 6/8] Applying InnoDB snapshot, fixes BUG#38901

Detailed revision comments:

r6613 | inaam | 2010-02-09 20:23:09 +0200 (Tue, 09 Feb 2010) | 11 lines
branches/5.1: Fix Bug #38901
InnoDB logs error repeatedly when trying to load page into buffer pool

In buf_page_get_gen() if we are unable to read a page (because of
corruption or some other reason) we keep on retrying. This fills up
error log with millions of entries in no time and we'd eventually run
out of disk space. This patch limits the number of attempts that we
make (currently set to 100) and after that we abort with a message.

rb://241 Approved by: Heikki
---
 storage/innobase/buf/buf0buf.c     | 28 +++++++++++++++++++++++++++-
 storage/innobase/buf/buf0rea.c     | 15 ++++++---------
 storage/innobase/include/buf0rea.h |  6 ++----
 3 files changed, 35 insertions(+), 14 deletions(-)

diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c
index 901ce8e0fef..45867388a61 100644
--- a/storage/innobase/buf/buf0buf.c
+++ b/storage/innobase/buf/buf0buf.c
@@ -224,6 +224,9 @@ in the free list to the frames.
 /* Value in microseconds */
 static const int WAIT_FOR_READ	= 20000;
 
+/* Number of attemtps made to read in a page in the buffer pool */
+static const ulint BUF_PAGE_READ_MAX_RETRIES = 100;
+
 buf_pool_t*	buf_pool = NULL; /* The buffer buf_pool of the database */
 
 #ifdef UNIV_DEBUG
@@ -1160,6 +1163,7 @@ buf_page_get_gen(
 	ulint		fix_type;
 	ibool		success;
 	ibool		must_read;
+	ulint		retries = 0;
 
 	ut_ad(mtr);
 	ut_ad((rw_latch == RW_S_LATCH)
@@ -1200,7 +1204,29 @@ loop:
 			return(NULL);
 		}
 
-		buf_read_page(space, offset);
+		if (buf_read_page(space, offset)) {
+			retries = 0;
+		} else if (retries < BUF_PAGE_READ_MAX_RETRIES) {
+			++retries;
+		} else {
+			fprintf(stderr, "InnoDB: Error: Unable"
+				" to read tablespace %lu page no"
+				" %lu into the buffer pool after"
+				" %lu attempts\n"
+				"InnoDB: The most probable cause"
+				" of this error may be that the"
+				" table has been corrupted.\n"
+				"InnoDB: You can try to fix this"
+				" problem by using"
+				" innodb_force_recovery.\n"
+				"InnoDB: Please see reference manual"
+				" for more details.\n"
+				"InnoDB: Aborting...\n",
+				space, offset,
+				BUF_PAGE_READ_MAX_RETRIES);
+
+			ut_error;
+		}
 
 #ifdef UNIV_DEBUG
 		buf_dbg_counter++;
diff --git a/storage/innobase/buf/buf0rea.c b/storage/innobase/buf/buf0rea.c
index fdec0206990..451436ef75b 100644
--- a/storage/innobase/buf/buf0rea.c
+++ b/storage/innobase/buf/buf0rea.c
@@ -299,30 +299,27 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
 an exclusive lock on the buffer frame. The flag is cleared and the x-lock
 released by the i/o-handler thread. Does a random read-ahead if it seems
 sensible. */
-
-ulint
+ibool
 buf_read_page(
 /*==========*/
-			/* out: number of page read requests issued: this can
-			be > 1 if read-ahead occurred */
+			/* out: TRUE if success, FALSE otherwise */
 	ulint	space,	/* in: space id */
 	ulint	offset)	/* in: page number */
 {
 	ib_longlong	tablespace_version;
 	ulint		count;
-	ulint		count2;
 	ulint		err;
 
 	tablespace_version = fil_space_get_version(space);
 
-	count = buf_read_ahead_random(space, offset);
+	buf_read_ahead_random(space, offset);
 
 	/* We do the i/o in the synchronous aio mode to save thread
 	switches: hence TRUE */
 
-	count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
+	count = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
 				   tablespace_version, offset);
-	srv_buf_pool_reads+= count2;
+	srv_buf_pool_reads+= count;
 	if (err == DB_TABLESPACE_DELETED) {
 		ut_print_timestamp(stderr);
 		fprintf(stderr,
@@ -336,7 +333,7 @@ buf_read_page(
 	/* Flush pages from the end of the LRU list if necessary */
 	buf_flush_free_margin();
 
-	return(count + count2);
+	return(count > 0);
 }
 
 /************************************************************************
diff --git a/storage/innobase/include/buf0rea.h b/storage/innobase/include/buf0rea.h
index e4620172860..015f30fe6c2 100644
--- a/storage/innobase/include/buf0rea.h
+++ b/storage/innobase/include/buf0rea.h
@@ -18,12 +18,10 @@ buffer buf_pool if it is not already there. Sets the io_fix flag and sets
 an exclusive lock on the buffer frame. The flag is cleared and the x-lock
 released by the i/o-handler thread. Does a random read-ahead if it seems
 sensible. */
-
-ulint
+ibool
 buf_read_page(
 /*==========*/
-			/* out: number of page read requests issued: this can
-			be > 1 if read-ahead occurred */
+			/* out: TRUE if success, FALSE otherwise */
 	ulint	space,	/* in: space id */
 	ulint	offset);/* in: page number */
 /************************************************************************

From 42d56179506b8d8a289d0bfa7b112c54b15e4b6e Mon Sep 17 00:00:00 2001
From: Sergey Vojtovich <svoj@sun.com>
Date: Fri, 26 Feb 2010 13:04:24 +0400
Subject: [PATCH 7/8] Applying InnoDB snapshot, fixes BUG#50691

Detailed revision comments:

r6669 | jyang | 2010-02-11 12:24:19 +0200 (Thu, 11 Feb 2010) | 7 lines
branches/5.1: Fix bug #50691, AIX implementation of readdir_r
causes InnoDB errors. readdir_r() returns an non-NULL value
in the case of reaching the end of a directory. It should
not be treated as an error return.

rb://238 approved by Marko
---
 storage/innobase/os/os0file.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c
index 085f62daacc..7373a97cfb0 100644
--- a/storage/innobase/os/os0file.c
+++ b/storage/innobase/os/os0file.c
@@ -759,7 +759,15 @@ next_file:
 #ifdef HAVE_READDIR_R
 	ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
 
-	if (ret != 0) {
+	if (ret != 0
+#ifdef UNIV_AIX
+	    /* On AIX, only if we got non-NULL 'ent' (result) value and
+	    a non-zero 'ret' (return) value, it indicates a failed
+	    readdir_r() call. An NULL 'ent' with an non-zero 'ret'
+	    would indicate the "end of the directory" is reached. */
+	    && ent != NULL
+#endif
+	   ) {
 		fprintf(stderr,
 			"InnoDB: cannot read directory %s, error %lu\n",
 			dirname, (ulong)ret);

From fe94dec6799b81ddc6660b3d9301deff5ac82507 Mon Sep 17 00:00:00 2001
From: Sergey Glukhov <Sergey.Glukhov@sun.com>
Date: Fri, 26 Feb 2010 15:39:25 +0400
Subject: [PATCH 8/8] Bug#50995 Having clause on subquery result produces
 incorrect results. The problem is that cond->fix_fields(thd, 0) breaks
 condition(cuts off 'having'). The reason of that is that NULL valued Item
 pointer is present in the middle of Item list and it breaks the Item
 processing loop.

---
 mysql-test/r/having.result | 20 ++++++++++++++++++++
 mysql-test/t/having.test   | 26 ++++++++++++++++++++++++++
 sql/item_cmpfunc.h         | 18 +++++++++++++++---
 sql/sql_select.cc          |  8 +++++---
 4 files changed, 66 insertions(+), 6 deletions(-)

diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 9c3cc8fc89e..68ba34e353c 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -430,4 +430,24 @@ SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
 b	COUNT(DISTINCT a)
 NULL	1
 DROP TABLE t1;
+#
+# Bug#50995 Having clause on subquery result produces incorrect results.
+#
+CREATE TABLE t1
+(
+id1 INT,
+id2 INT NOT NULL,
+INDEX id1(id2)
+);
+INSERT INTO t1 SET id1=1, id2=1;
+INSERT INTO t1 SET id1=2, id2=1;
+INSERT INTO t1 SET id1=3, id2=1;
+SELECT t1.id1,
+(SELECT 0 FROM DUAL
+WHERE t1.id1=t1.id1) AS amount FROM t1
+WHERE t1.id2 = 1
+HAVING amount > 0
+ORDER BY t1.id1;
+id1	amount
+DROP TABLE t1;
 End of 5.0 tests
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index af9af4fe1fc..185ca4bdddb 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -442,4 +442,30 @@ INSERT INTO t1 VALUES (1, 1), (2,2), (3, NULL);
 SELECT b, COUNT(DISTINCT a) FROM t1 GROUP BY b HAVING b is NULL;
 DROP TABLE t1;
 
+
+--echo #
+--echo # Bug#50995 Having clause on subquery result produces incorrect results.
+--echo #
+
+CREATE TABLE t1
+(
+ id1 INT,
+ id2 INT NOT NULL,
+ INDEX id1(id2)
+);
+
+INSERT INTO t1 SET id1=1, id2=1;
+INSERT INTO t1 SET id1=2, id2=1;
+INSERT INTO t1 SET id1=3, id2=1;
+
+SELECT t1.id1,
+(SELECT 0 FROM DUAL
+ WHERE t1.id1=t1.id1) AS amount FROM t1
+WHERE t1.id2 = 1
+HAVING amount > 0
+ORDER BY t1.id1;
+
+DROP TABLE t1;
+
+
 --echo End of 5.0 tests
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 38025ff0af5..425f54fb079 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1474,9 +1474,21 @@ public:
   Item_cond(THD *thd, Item_cond *item);
   Item_cond(List<Item> &nlist)
     :Item_bool_func(), list(nlist), abort_on_null(0) {}
-  bool add(Item *item) { return list.push_back(item); }
-  bool add_at_head(Item *item) { return list.push_front(item); }
-  void add_at_head(List<Item> *nlist) { list.prepand(nlist); }
+  bool add(Item *item)
+  {
+    DBUG_ASSERT(item);
+    return list.push_back(item);
+  }
+  bool add_at_head(Item *item)
+  {
+    DBUG_ASSERT(item);
+    return list.push_front(item);
+  }
+  void add_at_head(List<Item> *nlist)
+  {
+    DBUG_ASSERT(nlist->elements);
+    list.prepand(nlist);
+  }
   bool fix_fields(THD *, Item **ref);
 
   enum Type type() const { return COND_ITEM; }
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index b9f59fac4d6..1d88343ad6d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -8200,7 +8200,8 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
   else
   {
     DBUG_ASSERT(cond->type() == Item::COND_ITEM);
-    ((Item_cond *) cond)->add_at_head(&eq_list);
+    if (eq_list.elements)
+      ((Item_cond *) cond)->add_at_head(&eq_list);
   }
 
   cond->quick_fix_field();
@@ -15657,7 +15658,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
 
   Item_cond_and *cond=new Item_cond_and();
   TABLE *table=join_tab->table;
-  int error;
+  int error= 0;
   if (!cond)
     DBUG_RETURN(TRUE);
 
@@ -15675,7 +15676,8 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
     cond->fix_fields(thd, (Item**)&cond);
   if (join_tab->select)
   {
-    error=(int) cond->add(join_tab->select->cond);
+    if (join_tab->select->cond)
+      error=(int) cond->add(join_tab->select->cond);
     join_tab->select_cond=join_tab->select->cond=cond;
   }
   else if ((join_tab->select= make_select(join_tab->table, 0, 0, cond, 0,