List:Commits« Previous MessageNext Message »
From:Davi Arnaut Date:December 19 2008 1:26pm
Subject:bzr commit into mysql-5.1-bugteam branch (davi:2743)
View as plain text  
# At a local mysql-5.1-bugteam repository of davi

 2743 Davi Arnaut	2008-12-19 [merge]
      Merge before pushing.
added:
  mysql-test/r/innodb_bug38231.result
  mysql-test/r/innodb_bug39438.result
  mysql-test/t/innodb_bug38231.test
  mysql-test/t/innodb_bug39438-master.opt
  mysql-test/t/innodb_bug39438.test
modified:
  mysql-test/lib/mtr_report.pl
  mysql-test/r/innodb-autoinc.result
  mysql-test/r/innodb.result
  mysql-test/suite/binlog/r/binlog_innodb.result
  mysql-test/t/innodb-autoinc.test
  mysql-test/t/innodb.test
  storage/innobase/Makefile.am
  storage/innobase/btr/btr0sea.c
  storage/innobase/buf/buf0lru.c
  storage/innobase/dict/dict0dict.c
  storage/innobase/dict/dict0mem.c
  storage/innobase/handler/ha_innodb.cc
  storage/innobase/handler/ha_innodb.h
  storage/innobase/include/btr0sea.h
  storage/innobase/include/dict0dict.h
  storage/innobase/include/dict0mem.h
  storage/innobase/include/ha_prototypes.h
  storage/innobase/include/lock0lock.h
  storage/innobase/include/row0mysql.h
  storage/innobase/include/sync0sync.ic
  storage/innobase/include/ut0ut.h
  storage/innobase/lock/lock0lock.c
  storage/innobase/os/os0file.c
  storage/innobase/plug.in
  storage/innobase/row/row0mysql.c
  storage/innobase/row/row0sel.c
  storage/innobase/srv/srv0srv.c
  storage/innobase/srv/srv0start.c
  storage/innobase/ut/ut0ut.c

=== modified file 'mysql-test/lib/mtr_report.pl'
--- a/mysql-test/lib/mtr_report.pl	2008-10-02 07:46:14 +0000
+++ b/mysql-test/lib/mtr_report.pl	2008-12-14 20:31:13 +0000
@@ -412,7 +412,10 @@ sub mtr_report_stats ($) {
 
                 # When trying to set lower_case_table_names = 2
                 # on a case sensitive file system. Bug#37402.
-                /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive.  Now setting lower_case_table_names to 0 to avoid future problems./
+                /lower_case_table_names was set to 2, even though your the file system '.*' is case sensitive.  Now setting lower_case_table_names to 0 to avoid future problems./ or
+
+                # this test is expected to print warnings
+                ($testname eq 'main.innodb_bug39438')
 		)
             {
               next;                       # Skip these lines

=== modified file 'mysql-test/r/innodb-autoinc.result'
--- a/mysql-test/r/innodb-autoinc.result	2008-08-20 22:18:33 +0000
+++ b/mysql-test/r/innodb-autoinc.result	2008-12-19 00:28:51 +0000
@@ -169,3 +169,413 @@ t1	CREATE TABLE `t1` (
   PRIMARY KEY (`c1`)
 ) ENGINE=InnoDB AUTO_INCREMENT=10 DEFAULT CHARSET=latin1
 DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL, 1);
+DELETE FROM t1 WHERE c1 = 1;
+INSERT INTO t1 VALUES (2,1);
+INSERT INTO t1 VALUES (NULL,8);
+SELECT * FROM t1;
+c1	c2
+2	1
+3	8
+DROP TABLE t1;
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL, 1);
+DELETE FROM t1 WHERE c1 = 1;
+INSERT INTO t1 VALUES (2,1), (NULL, 8);
+INSERT INTO t1 VALUES (NULL,9);
+SELECT * FROM t1;
+c1	c2
+2	1
+3	8
+5	9
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	100
+auto_increment_offset	10
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL),(5),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+c1
+5
+10
+110
+250
+310
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+c1
+5
+10
+110
+250
+310
+400
+410
+1000
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0);
+SELECT * FROM t1;
+c1
+1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+c1
+-1
+1
+2
+10
+110
+250
+410
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+Got one of the listed errors
+SELECT * FROM t1;
+c1
+-1
+1
+2
+10
+110
+250
+410
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+SELECT * FROM t1;
+c1
+-1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	100
+auto_increment_offset	10
+INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+c1
+-2
+-1
+1
+2
+10
+250
+310
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+c1
+-2
+-1
+1
+2
+10
+250
+310
+400
+410
+1000
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+SELECT * FROM t1;
+c1
+1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	100
+auto_increment_offset	10
+INSERT INTO t1 VALUES (-2);
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (250);
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+c1
+1
+2
+10
+110
+210
+250
+310
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT * FROM t1;
+c1
+1
+2
+10
+110
+210
+250
+310
+400
+1000
+1010
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+SELECT * FROM t1;
+c1
+1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	100
+auto_increment_offset	10
+INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
+Warnings:
+Warning	1264	Out of range value for column 'c1' at row 1
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+c1
+1
+2
+10
+110
+210
+250
+410
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+Got one of the listed errors
+SELECT * FROM t1;
+c1
+1
+2
+10
+110
+210
+250
+410
+1000
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (9223372036854775794);
+SELECT * FROM t1;
+c1
+1
+9223372036854775794
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	2
+auto_increment_offset	10
+INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+SELECT * FROM t1;
+c1
+1
+9223372036854775794
+9223372036854775796
+9223372036854775798
+9223372036854775800
+9223372036854775802
+9223372036854775804
+9223372036854775806
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551603);
+SELECT * FROM t1;
+c1
+1
+18446744073709551603
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	2
+auto_increment_offset	10
+INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+SELECT * FROM t1;
+c1
+1
+18446744073709551603
+18446744073709551604
+18446744073709551606
+18446744073709551608
+18446744073709551610
+18446744073709551612
+18446744073709551614
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551603);
+SELECT * FROM t1;
+c1
+1
+18446744073709551603
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	5
+auto_increment_offset	7
+INSERT INTO t1 VALUES (NULL),(NULL);
+SELECT * FROM t1;
+c1
+1
+18446744073709551603
+18446744073709551607
+18446744073709551612
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES(-9223372036854775806);
+INSERT INTO t1 VALUES(-9223372036854775807);
+INSERT INTO t1 VALUES(-9223372036854775808);
+SELECT * FROM t1;
+c1
+-9223372036854775808
+-9223372036854775807
+-9223372036854775806
+1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	3
+auto_increment_offset	3
+INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
+SELECT * FROM t1;
+c1
+-9223372036854775808
+-9223372036854775807
+-9223372036854775806
+1
+3
+6
+9
+DROP TABLE t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	1
+auto_increment_offset	1
+DROP TABLE IF EXISTS t1;
+Warnings:
+Note	1051	Unknown table 't1'
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551610);
+SELECT * FROM t1;
+c1
+1
+18446744073709551610
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
+Warnings:
+Warning	1292	Truncated incorrect auto_increment_increment value: '1152921504606846976'
+Warning	1292	Truncated incorrect auto_increment_offset value: '1152921504606846976'
+SHOW VARIABLES LIKE "%auto_inc%";
+Variable_name	Value
+auto_increment_increment	65535
+auto_increment_offset	65535
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+c1
+1
+18446744073709551610
+18446744073709551615
+DROP TABLE t1;

=== modified file 'mysql-test/r/innodb.result'
--- a/mysql-test/r/innodb.result	2008-10-03 12:24:19 +0000
+++ b/mysql-test/r/innodb.result	2008-12-14 18:24:16 +0000
@@ -3295,3 +3295,11 @@ info: Records: 5  Duplicates: 0  Warning
 TRUNCATE TABLE t1;
 affected rows: 0
 DROP TABLE t1;
+Variable_name	Value
+Handler_update	0
+Variable_name	Value
+Handler_delete	0
+Variable_name	Value
+Handler_update	1
+Variable_name	Value
+Handler_delete	1

=== added file 'mysql-test/r/innodb_bug38231.result'
--- a/mysql-test/r/innodb_bug38231.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug38231.result	2008-12-14 21:26:31 +0000
@@ -0,0 +1,11 @@
+SET storage_engine=InnoDB;
+INSERT INTO bug38231 VALUES (1), (10), (300);
+SET autocommit=0;
+SELECT * FROM bug38231 FOR UPDATE;
+a
+1
+10
+300
+TRUNCATE TABLE bug38231;
+COMMIT;
+DROP TABLE bug38231;

=== added file 'mysql-test/r/innodb_bug39438.result'
--- a/mysql-test/r/innodb_bug39438.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/innodb_bug39438.result	2008-12-14 20:31:13 +0000
@@ -0,0 +1 @@
+SET storage_engine=InnoDB;

=== modified file 'mysql-test/suite/binlog/r/binlog_innodb.result'
--- a/mysql-test/suite/binlog/r/binlog_innodb.result	2008-08-27 14:17:55 +0000
+++ b/mysql-test/suite/binlog/r/binlog_innodb.result	2008-12-15 22:58:16 +0000
@@ -115,14 +115,14 @@ master-bin.000001	#	Xid	#	#	COMMIT /* XI
 DROP TABLE t1;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	15
+Binlog_cache_use	13
 show status like "binlog_cache_disk_use";
 Variable_name	Value
 Binlog_cache_disk_use	0
 create table t1 (a int) engine=innodb;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	16
+Binlog_cache_use	14
 show status like "binlog_cache_disk_use";
 Variable_name	Value
 Binlog_cache_disk_use	1
@@ -131,7 +131,7 @@ delete from t1;
 commit;
 show status like "binlog_cache_use";
 Variable_name	Value
-Binlog_cache_use	17
+Binlog_cache_use	15
 show status like "binlog_cache_disk_use";
 Variable_name	Value
 Binlog_cache_disk_use	1

=== modified file 'mysql-test/t/innodb-autoinc.test'
--- a/mysql-test/t/innodb-autoinc.test	2008-08-20 22:18:33 +0000
+++ b/mysql-test/t/innodb-autoinc.test	2008-12-19 00:28:51 +0000
@@ -139,3 +139,262 @@ SELECT c1 FROM t1;
 SHOW CREATE TABLE t1;
 DROP TABLE t1;
 
+#
+# Bug 38839
+# Reset the last value generated at end of statement
+#
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL, 1);
+DELETE FROM t1 WHERE c1 = 1;
+INSERT INTO t1 VALUES (2,1); 
+INSERT INTO t1 VALUES (NULL,8);
+SELECT * FROM t1;
+DROP TABLE t1;
+# Bug 38839 -- same as above but for multi value insert
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, c2 INT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL, 1);
+DELETE FROM t1 WHERE c1 = 1;
+INSERT INTO t1 VALUES (2,1), (NULL, 8);
+INSERT INTO t1 VALUES (NULL,9);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Test changes to AUTOINC next value calculation
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (NULL),(5),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test with SIGNED INT column, by inserting a 0 for the first column value
+# 0 is treated in the same was NULL.
+# Reset the AUTOINC session variables
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(0);
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+INSERT INTO t1 VALUES (-1), (NULL),(2),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+SET @@INSERT_ID=400;
+# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
+-- error ER_DUP_ENTRY,1062
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test with SIGNED INT column
+# Reset the AUTOINC session variables
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+INSERT INTO t1 VALUES (-2), (NULL),(2),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test with UNSIGNED INT column, single insert
+# The sign in the value is ignored and a new column value is generated
+# Reset the AUTOINC session variables
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+INSERT INTO t1 VALUES (-2);
+INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (NULL);
+INSERT INTO t1 VALUES (250);
+INSERT INTO t1 VALUES (NULL);
+SELECT * FROM t1;
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Test with UNSIGNED INT column, multi-value inserts
+# The sign in the value is ignored and a new column value is generated
+# Reset the AUTOINC session variables
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 INT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+INSERT INTO t1 VALUES(-1);
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=100, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+INSERT INTO t1 VALUES (-2),(NULL),(2),(NULL);
+INSERT INTO t1 VALUES (250),(NULL);
+SELECT * FROM t1;
+INSERT INTO t1 VALUES (1000);
+SET @@INSERT_ID=400;
+# Duplicate error expected here for autoinc_lock_mode != TRADITIONAL
+-- error ER_DUP_ENTRY,1062
+INSERT INTO t1 VALUES(NULL),(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Check for overflow handling when increment is > 1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+# TODO: Fix the autoinc init code
+# We have to do this because of a bug in the AUTOINC init code.
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (9223372036854775794); -- 2^63 - 14
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+# This should just fit
+INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Check for overflow handling when increment and offser are > 1
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+# TODO: Fix the autoinc init code
+# We have to do this because of a bug in the AUTOINC init code.
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=2, @@SESSION.AUTO_INCREMENT_OFFSET=10;
+SHOW VARIABLES LIKE "%auto_inc%";
+# This should fail because of overflow but it doesn't, it seems to be
+# a MySQL server bug. It wraps around to 0 for the last value.
+# See MySQL Bug# 39828
+#
+# Instead of wrapping around, it asserts when MySQL is compiled --with-debug
+# (see sql/handler.cc:handler::update_auto_increment()).  Don't test for
+# overflow until Bug #39828 is fixed.
+#
+# Since this asserts when compiled --with-debug, we can't properly test this
+# until Bug #39828 is fixed.  For now, this test is meaningless.
+#if Bug #39828 is fixed
+#INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+#else
+INSERT INTO t1 VALUES (NULL),(NULL),(NULL),(NULL),(NULL),(NULL);
+#endif
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Check for overflow handling when increment and offset are odd numbers
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+# TODO: Fix the autoinc init code
+# We have to do this because of a bug in the AUTOINC init code.
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551603); -- 2^64 - 13
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=5, @@SESSION.AUTO_INCREMENT_OFFSET=7;
+SHOW VARIABLES LIKE "%auto_inc%";
+# This should fail because of overflow but it doesn't. It fails with
+# a duplicate entry message because of a MySQL server bug, it wraps
+# around.  See MySQL Bug# 39828, once MySQL fix the bug we can replace
+# the ER_DUP_ENTRY, 1062 below with the appropriate error message
+#
+# Since this asserts when compiled --with-debug, we can't properly test this
+# until Bug #39828 is fixed.  For now, this test is meaningless.
+#if Bug #39828 is fixed
+# Still need to fix this error code, error should mention overflow
+#-- error ER_DUP_ENTRY,1062
+#INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
+#else
+INSERT INTO t1 VALUES (NULL),(NULL);
+#endif
+SELECT * FROM t1;
+DROP TABLE t1;
+
+# Check for overflow handling when increment and offset are odd numbers
+# and check for large -ve numbers
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 BIGINT AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+# TODO: Fix the autoinc init code
+# We have to do this because of a bug in the AUTOINC init code.
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES(-9223372036854775806); -- -2^63 + 2
+INSERT INTO t1 VALUES(-9223372036854775807); -- -2^63 + 1
+INSERT INTO t1 VALUES(-9223372036854775808); -- -2^63
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=3, @@SESSION.AUTO_INCREMENT_OFFSET=3;
+SHOW VARIABLES LIKE "%auto_inc%";
+INSERT INTO t1 VALUES (NULL),(NULL), (NULL);
+SELECT * FROM t1;
+DROP TABLE t1;
+#
+# Check for overflow handling when increment and offset are very
+# large numbers 2^60
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1, @@SESSION.AUTO_INCREMENT_OFFSET=1;
+SET @@INSERT_ID=1;
+SHOW VARIABLES LIKE "%auto_inc%";
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1 (c1 BIGINT UNSIGNED AUTO_INCREMENT, PRIMARY KEY(c1)) ENGINE=InnoDB;
+# TODO: Fix the autoinc init code
+# We have to do this because of a bug in the AUTOINC init code.
+INSERT INTO t1 VALUES(NULL);
+INSERT INTO t1 VALUES (18446744073709551610); -- 2^64 - 2
+SELECT * FROM t1;
+SET @@SESSION.AUTO_INCREMENT_INCREMENT=1152921504606846976, @@SESSION.AUTO_INCREMENT_OFFSET=1152921504606846976;
+SHOW VARIABLES LIKE "%auto_inc%";
+# This should fail because of overflow but it doesn't. It wraps around
+# and the autoinc values look bogus too.
+# See MySQL Bug# 39828, once MySQL fix the bug we can enable the error
+# code expected test.
+# -- error ER_AUTOINC_READ_FAILED,1467
+#
+# Since this asserts when compiled --with-debug, we can't properly test this
+# until Bug #39828 is fixed.  For now, this test is meaningless.
+#if Bug #39828 is fixed
+#-- error ER_AUTOINC_READ_FAILED,1467
+#INSERT INTO t1 VALUES (NULL),(NULL);
+#else
+INSERT INTO t1 VALUES (NULL);
+#endif
+SELECT * FROM t1;
+DROP TABLE t1;

=== modified file 'mysql-test/t/innodb.test'
--- a/mysql-test/t/innodb.test	2008-10-03 12:24:19 +0000
+++ b/mysql-test/t/innodb.test	2008-12-14 18:24:16 +0000
@@ -2475,6 +2475,7 @@ SELECT AUTO_INCREMENT FROM INFORMATION_S
 DROP TABLE t2;
 DROP TABLE t1;
 # End 34920 test
+#
 # Bug #29507 TRUNCATE shows to many rows effected
 #
 CONNECTION default;
@@ -2491,6 +2492,36 @@ TRUNCATE TABLE t1;
 --disable_info
 DROP TABLE t1;
 #
+# Bug#35537 Innodb doesn't increment handler_update and handler_delete.
+#
+-- disable_query_log
+-- disable_result_log
+
+CONNECT (c1,localhost,root,,);
+
+DROP TABLE IF EXISTS bug35537;
+CREATE TABLE bug35537 (
+  c1 int
+) ENGINE=InnoDB;
+
+INSERT INTO bug35537 VALUES (1);
+
+-- enable_result_log
+
+SHOW SESSION STATUS LIKE 'Handler_update%';
+SHOW SESSION STATUS LIKE 'Handler_delete%';
+
+UPDATE bug35537 SET c1 = 2 WHERE c1 = 1;
+DELETE FROM bug35537 WHERE c1 = 2;
+
+SHOW SESSION STATUS LIKE 'Handler_update%';
+SHOW SESSION STATUS LIKE 'Handler_delete%';
+
+DROP TABLE bug35537;
+
+DISCONNECT c1;
+CONNECTION default;
+
 #######################################################################
 #                                                                     #
 # Please, DO NOT TOUCH this file as well as the innodb.result file.   #

=== added file 'mysql-test/t/innodb_bug38231.test'
--- a/mysql-test/t/innodb_bug38231.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug38231.test	2008-12-14 21:26:31 +0000
@@ -0,0 +1,83 @@
+#
+# Bug#38231 Innodb crash in lock_reset_all_on_table() on TRUNCATE + LOCK / UNLOCK
+# http://bugs.mysql.com/38231
+#
+
+-- source include/have_innodb.inc
+
+SET storage_engine=InnoDB;
+
+# we care only that the following SQL commands do not crash the server
+-- disable_query_log
+-- disable_result_log
+
+DROP TABLE IF EXISTS bug38231;
+CREATE TABLE bug38231 (a INT);
+
+-- connect (con1,localhost,root,,)
+-- connect (con2,localhost,root,,)
+-- connect (con3,localhost,root,,)
+
+-- connection con1
+SET autocommit=0;
+LOCK TABLE bug38231 WRITE;
+
+-- connection con2
+SET autocommit=0;
+-- send
+LOCK TABLE bug38231 WRITE;
+
+-- connection con3
+SET autocommit=0;
+-- send
+LOCK TABLE bug38231 WRITE;
+
+-- connection default
+-- send
+TRUNCATE TABLE bug38231;
+
+-- connection con1
+# give time to TRUNCATE and others to be executed; without sleep, sometimes
+# UNLOCK executes before TRUNCATE
+-- sleep 0.2
+# this crashes the server if the bug is present
+UNLOCK TABLES;
+
+# clean up
+
+-- connection con2
+UNLOCK TABLES;
+
+-- connection con3
+UNLOCK TABLES;
+
+-- connection default
+
+-- disconnect con1
+-- disconnect con2
+-- disconnect con3
+
+# test that TRUNCATE works with with row-level locks
+
+-- enable_query_log
+-- enable_result_log
+
+INSERT INTO bug38231 VALUES (1), (10), (300);
+
+-- connect (con4,localhost,root,,)
+
+-- connection con4
+SET autocommit=0;
+SELECT * FROM bug38231 FOR UPDATE;
+
+-- connection default
+TRUNCATE TABLE bug38231;
+
+-- connection con4
+COMMIT;
+
+-- connection default
+
+-- disconnect con4
+
+DROP TABLE bug38231;

=== added file 'mysql-test/t/innodb_bug39438-master.opt'
--- a/mysql-test/t/innodb_bug39438-master.opt	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug39438-master.opt	2008-12-14 20:31:13 +0000
@@ -0,0 +1 @@
+--innodb-file-per-table=1

=== added file 'mysql-test/t/innodb_bug39438.test'
--- a/mysql-test/t/innodb_bug39438.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/innodb_bug39438.test	2008-12-14 20:31:13 +0000
@@ -0,0 +1,27 @@
+#
+# Bug#39438 Testcase for Bug#39436 crashes on 5.1 in fil_space_get_latch
+# http://bugs.mysql.com/39438
+#
+# This test must be run with innodb_file_per_table=1 because the crash
+# only occurs if that option is turned on and DISCARD TABLESPACE only
+# works with innodb_file_per_table.
+#
+
+-- source include/have_innodb.inc
+
+SET storage_engine=InnoDB;
+
+# we care only that the following SQL commands do not crash the server
+-- disable_query_log
+-- disable_result_log
+
+DROP TABLE IF EXISTS bug39438;
+
+CREATE TABLE bug39438 (id INT) ENGINE=INNODB;
+
+ALTER TABLE bug39438 DISCARD TABLESPACE;
+
+# this crashes the server if the bug is present
+SHOW TABLE STATUS;
+
+DROP TABLE bug39438;

=== modified file 'storage/innobase/Makefile.am'
--- a/storage/innobase/Makefile.am	2008-06-19 04:44:22 +0000
+++ b/storage/innobase/Makefile.am	2008-12-14 18:54:01 +0000
@@ -15,21 +15,21 @@
 
 # Process this file with automake to create Makefile.in
 
-MYSQLDATAdir =          $(localstatedir)
-MYSQLSHAREdir =         $(pkgdatadir)
-MYSQLBASEdir=           $(prefix)
-MYSQLLIBdir=            $(pkglibdir)
-pkgplugindir =		$(pkglibdir)/plugin
-INCLUDES =              -I$(top_srcdir)/include -I$(top_builddir)/include \
+MYSQLDATAdir=		$(localstatedir)
+MYSQLSHAREdir=		$(pkgdatadir)
+MYSQLBASEdir=		$(prefix)
+MYSQLLIBdir=		$(pkglibdir)
+pkgplugindir=		$(pkglibdir)/plugin
+INCLUDES=		-I$(top_srcdir)/include -I$(top_builddir)/include \
 			-I$(top_srcdir)/regex \
 			-I$(top_srcdir)/storage/innobase/include \
 			-I$(top_srcdir)/sql \
-                        -I$(srcdir)
+			-I$(srcdir)
 
-DEFS =			@DEFS@
+DEFS=			@DEFS@
 
 
-noinst_HEADERS = include/btr0btr.h include/btr0btr.ic			\
+noinst_HEADERS=		include/btr0btr.h include/btr0btr.ic		\
 			include/btr0cur.h include/btr0cur.ic		\
 			include/btr0pcur.h include/btr0pcur.ic		\
 			include/btr0sea.h include/btr0sea.ic		\
@@ -121,9 +121,9 @@ noinst_HEADERS = include/btr0btr.h inclu
 			include/ut0list.ic include/ut0wqueue.h		\
 			include/ha_prototypes.h handler/ha_innodb.h
 
-EXTRA_LIBRARIES =	libinnobase.a
-noinst_LIBRARIES =	@plugin_innobase_static_target@
-libinnobase_a_SOURCES =	btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c	\
+EXTRA_LIBRARIES=	libinnobase.a
+noinst_LIBRARIES=	@plugin_innobase_static_target@
+libinnobase_a_SOURCES=	btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c	\
 			btr/btr0sea.c buf/buf0buf.c buf/buf0flu.c	\
 			buf/buf0lru.c buf/buf0rea.c data/data0data.c	\
 			data/data0type.c dict/dict0boot.c		\
@@ -156,17 +156,17 @@ libinnobase_a_SOURCES =	btr/btr0btr.c bt
 			handler/ha_innodb.cc
 
 libinnobase_a_CXXFLAGS=	$(AM_CFLAGS)
-libinnobase_a_CFLAGS  =	$(AM_CFLAGS)
+libinnobase_a_CFLAGS=	$(AM_CFLAGS)
 
-EXTRA_LTLIBRARIES =	ha_innodb.la
+EXTRA_LTLIBRARIES=	ha_innodb.la
 pkgplugin_LTLIBRARIES=	@plugin_innobase_shared_target@
 
-ha_innodb_la_LDFLAGS =	-module -rpath $(pkgplugindir)
-ha_innodb_la_CXXFLAGS=	$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_innodb_la_CFLAGS  =	$(AM_CFLAGS) -DMYSQL_DYNAMIC_PLUGIN
-ha_innodb_la_SOURCES =	$(libinnobase_a_SOURCES)
+ha_innodb_la_LDFLAGS=	-module -rpath $(pkgplugindir)
+ha_innodb_la_CXXFLAGS=	$(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
+ha_innodb_la_CFLAGS=	$(AM_CFLAGS) $(INNODB_DYNAMIC_CFLAGS)
+ha_innodb_la_SOURCES=	$(libinnobase_a_SOURCES)
 
-EXTRA_DIST =		CMakeLists.txt plug.in \
+EXTRA_DIST=		CMakeLists.txt plug.in \
 			pars/make_bison.sh pars/make_flex.sh \
 			pars/pars0grm.y pars/pars0lex.l
 

=== modified file 'storage/innobase/btr/btr0sea.c'
--- a/storage/innobase/btr/btr0sea.c	2006-09-21 07:39:09 +0000
+++ b/storage/innobase/btr/btr0sea.c	2008-12-14 19:25:33 +0000
@@ -161,6 +161,7 @@ btr_search_info_create(
 	info->magic_n = BTR_SEARCH_MAGIC_N;
 #endif /* UNIV_DEBUG */
 
+	info->ref_count = 0;
 	info->root_guess = NULL;
 
 	info->hash_analysis = 0;
@@ -184,6 +185,31 @@ btr_search_info_create(
 	return(info);
 }
 
+/*********************************************************************
+Returns the value of ref_count. The value is protected by
+btr_search_latch. */
+ulint
+btr_search_info_get_ref_count(
+/*==========================*/
+				/* out: ref_count value. */
+	btr_search_t*   info)	/* in: search info. */
+{
+	ulint ret;
+
+	ut_ad(info);
+
+#ifdef UNIV_SYNC_DEBUG
+	ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_SHARED));
+	ut_ad(!rw_lock_own(&btr_search_latch, RW_LOCK_EX));
+#endif /* UNIV_SYNC_DEBUG */
+
+	rw_lock_s_lock(&btr_search_latch);
+	ret = info->ref_count;
+	rw_lock_s_unlock(&btr_search_latch);
+
+	return(ret);
+}
+
 /*************************************************************************
 Updates the search info of an index about hash successes. NOTE that info
 is NOT protected by any semaphore, to save CPU time! Do not assume its fields
@@ -1022,8 +1048,12 @@ next_rec:
 		ha_remove_all_nodes_to_page(table, folds[i], page);
 	}
 
+	ut_a(index->search_info->ref_count > 0);
+	index->search_info->ref_count--;
+
 	block->is_hashed = FALSE;
 	block->index = NULL;
+	
 cleanup:
 	if (UNIV_UNLIKELY(block->n_pointers)) {
 		/* Corruption */
@@ -1244,6 +1274,15 @@ btr_search_build_page_hash_index(
 		goto exit_func;
 	}
 
+	/* This counter is decremented every time we drop page
+	hash index entries and is incremented here. Since we can
+	rebuild hash index for a page that is already hashed, we
+	have to take care not to increment the counter in that
+	case. */
+	if (!block->is_hashed) {
+		index->search_info->ref_count++;
+	}
+
 	block->is_hashed = TRUE;
 	block->n_hash_helps = 0;
 

=== modified file 'storage/innobase/buf/buf0lru.c'
--- a/storage/innobase/buf/buf0lru.c	2008-02-01 10:55:39 +0000
+++ b/storage/innobase/buf/buf0lru.c	2008-12-14 20:47:17 +0000
@@ -42,6 +42,11 @@ initial segment in buf_LRU_get_recent_li
 
 #define BUF_LRU_INITIAL_RATIO	8
 
+/* When dropping the search hash index entries before deleting an ibd
+file, we build a local array of pages belonging to that tablespace
+in the buffer pool. Following is the size of that array. */
+#define BUF_LRU_DROP_SEARCH_HASH_SIZE	1024
+
 /* If we switch on the InnoDB monitor because there are too few available
 frames in the buffer pool, we set this to TRUE */
 ibool	buf_lru_switched_on_innodb_mon	= FALSE;
@@ -66,6 +71,120 @@ buf_LRU_block_free_hashed_page(
 				be in a state where it can be freed */
 
 /**********************************************************************
+Attempts to drop page hash index on a batch of pages belonging to a
+particular space id. */
+static
+void
+buf_LRU_drop_page_hash_batch(
+/*=========================*/
+	ulint		id,	/* in: space id */
+	const ulint*	arr,	/* in: array of page_no */
+	ulint		count)	/* in: number of entries in array */
+{
+	ulint	i;
+
+	ut_ad(arr != NULL);
+	ut_ad(count <= BUF_LRU_DROP_SEARCH_HASH_SIZE);
+
+	for (i = 0; i < count; ++i) {
+		btr_search_drop_page_hash_when_freed(id, arr[i]);
+	}
+}
+
+/**********************************************************************
+When doing a DROP TABLE/DISCARD TABLESPACE we have to drop all page
+hash index entries belonging to that table. This function tries to
+do that in batch. Note that this is a 'best effort' attempt and does
+not guarantee that ALL hash entries will be removed. */
+static
+void
+buf_LRU_drop_page_hash_for_tablespace(
+/*==================================*/
+	ulint	id)	/* in: space id */
+{
+	buf_block_t*	block;
+	ulint*		page_arr;
+	ulint		num_entries;
+
+	page_arr = ut_malloc(sizeof(ulint)
+			     * BUF_LRU_DROP_SEARCH_HASH_SIZE);
+	mutex_enter(&buf_pool->mutex);
+
+scan_again:
+	num_entries = 0;
+	block = UT_LIST_GET_LAST(buf_pool->LRU);
+
+	while (block != NULL) {
+		buf_block_t*	prev_block;
+
+		mutex_enter(&block->mutex);
+		prev_block = UT_LIST_GET_PREV(LRU, block);
+
+		ut_a(block->state == BUF_BLOCK_FILE_PAGE);
+
+		if (block->space != id
+		    || block->buf_fix_count > 0
+		    || block->io_fix != 0) {
+			/* We leave the fixed pages as is in this scan.
+			To be dealt with later in the final scan. */
+			mutex_exit(&block->mutex);
+			goto next_page;
+		}
+
+		ut_ad(block->space == id);
+		if (block->is_hashed) {
+
+			/* Store the offset(i.e.: page_no) in the array
+			so that we can drop hash index in a batch
+			later. */
+			page_arr[num_entries] = block->offset;
+			mutex_exit(&block->mutex);
+			ut_a(num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE);
+			++num_entries;
+
+			if (num_entries < BUF_LRU_DROP_SEARCH_HASH_SIZE) {
+				goto next_page;
+			}
+			/* Array full. We release the buf_pool->mutex to
+			obey the latching order. */
+			mutex_exit(&buf_pool->mutex);
+
+			buf_LRU_drop_page_hash_batch(id, page_arr,
+						     num_entries);
+			num_entries = 0;
+			mutex_enter(&buf_pool->mutex);
+		} else {
+			mutex_exit(&block->mutex);
+		}
+
+next_page:
+		/* Note that we may have released the buf_pool->mutex
+		above after reading the prev_block during processing
+		of a page_hash_batch (i.e.: when the array was full).
+		This means that prev_block can change in LRU list.
+		This is OK because this function is a 'best effort'
+		to drop as many search hash entries as possible and
+		it does not guarantee that ALL such entries will be
+		dropped. */
+		block = prev_block;
+
+		/* If, however, block has been removed from LRU list
+		to the free list then we should restart the scan.
+		block->state is protected by buf_pool->mutex. */
+		if (block && block->state != BUF_BLOCK_FILE_PAGE) {
+			ut_a(num_entries == 0);
+			goto scan_again;
+		}
+	}
+
+	mutex_exit(&buf_pool->mutex);
+
+	/* Drop any remaining batch of search hashed pages. */
+	buf_LRU_drop_page_hash_batch(id, page_arr, num_entries);
+	ut_free(page_arr);
+}
+
+/**********************************************************************
 Invalidates all pages belonging to a given tablespace when we are deleting
 the data file(s) of that tablespace. */
 
@@ -78,6 +197,14 @@ buf_LRU_invalidate_tablespace(
 	ulint		page_no;
 	ibool		all_freed;
 
+	/* Before we attempt to drop pages one by one we first
+	attempt to drop page hash index entries in batches to make
+	it more efficient. The batching attempt is a best effort
+	attempt and does not guarantee that all pages hash entries
+	will be dropped. We get rid of remaining page hash entries
+	one by one below. */
+	buf_LRU_drop_page_hash_for_tablespace(id);
+
 scan_again:
 	mutex_enter(&(buf_pool->mutex));
 

=== modified file 'storage/innobase/dict/dict0dict.c'
--- a/storage/innobase/dict/dict0dict.c	2008-08-08 00:33:12 +0000
+++ b/storage/innobase/dict/dict0dict.c	2008-12-14 20:59:50 +0000
@@ -422,8 +422,7 @@ dict_table_autoinc_lock(
 }
 
 /************************************************************************
-Initializes the autoinc counter. It is not an error to initialize an already
-initialized counter. */
+Unconditionally set the autoinc counter. */
 
 void
 dict_table_autoinc_initialize(
@@ -433,7 +432,6 @@ dict_table_autoinc_initialize(
 {
 	ut_ad(mutex_own(&table->autoinc_mutex));
 
-	table->autoinc_inited = TRUE;
 	table->autoinc = value;
 }
 
@@ -447,32 +445,25 @@ dict_table_autoinc_read(
 				/* out: value for a new row, or 0 */
 	dict_table_t*	table)	/* in: table */
 {
-	ib_longlong	value;
-
 	ut_ad(mutex_own(&table->autoinc_mutex));
 
-	if (!table->autoinc_inited) {
-
-		value = 0;
-	} else {
-		value = table->autoinc;
-	}
-
-	return(value);
+	return(table->autoinc);
 }
 
 /************************************************************************
 Updates the autoinc counter if the value supplied is greater than the
-current value. If not inited, does nothing. */
+current value. */
 
 void
-dict_table_autoinc_update(
-/*======================*/
+dict_table_autoinc_update_if_greater(
+/*=================================*/
 
 	dict_table_t*	table,	/* in: table */
 	ib_ulonglong	value)	/* in: value which was assigned to a row */
 {
-	if (table->autoinc_inited && value > table->autoinc) {
+	ut_ad(mutex_own(&table->autoinc_mutex));
+
+	if (value > table->autoinc) {
 
 		table->autoinc = value;
 	}
@@ -1394,12 +1385,59 @@ dict_index_remove_from_cache(
 	dict_index_t*	index)	/* in, own: index */
 {
 	ulint		size;
+	ulint		retries = 0;
+	btr_search_t*	info;
 
 	ut_ad(table && index);
 	ut_ad(table->magic_n == DICT_TABLE_MAGIC_N);
 	ut_ad(index->magic_n == DICT_INDEX_MAGIC_N);
 	ut_ad(mutex_own(&(dict_sys->mutex)));
 
+	/* We always create search info whether or not adaptive
+	hash index is enabled or not. */
+	info = index->search_info;
+	ut_ad(info);
+
+	/* We are not allowed to free the in-memory index struct
+ 	dict_index_t until all entries in the adaptive hash index
+	that point to any of the page belonging to his b-tree index
+	are dropped. This is so because dropping of these entries
+	require access to dict_index_t struct. To avoid such scenario
+	We keep a count of number of such pages in the search_info and
+	only free the dict_index_t struct when this count drops to
+	zero. */
+
+	for (;;) {
+		ulint ref_count = btr_search_info_get_ref_count(info);
+		if (ref_count == 0) {
+			break;
+		}
+
+		/* Sleep for 10ms before trying again. */
+		os_thread_sleep(10000);
+		++retries;
+
+		if (retries % 500 == 0) {
+			/* No luck after 5 seconds of wait. */
+			fprintf(stderr, "InnoDB: Error: Waited for"
+					" %lu secs for hash index"
+					" ref_count (%lu) to drop"
+					" to 0.\n"
+					"index: \"%s\""
+					" table: \"%s\"\n",
+					retries/100,
+					ref_count,
+					index->name,
+					table->name);
+		}
+
+		/* To avoid a hang here we commit suicide if the
+		ref_count doesn't drop to zero in 600 seconds. */
+		if (retries >= 60000) {
+			ut_error;
+		}
+	}
+
 	rw_lock_free(&index->lock);
 
 	/* Remove the index from the list of indexes of the table */

=== modified file 'storage/innobase/dict/dict0mem.c'
--- a/storage/innobase/dict/dict0mem.c	2007-08-28 00:18:14 +0000
+++ b/storage/innobase/dict/dict0mem.c	2008-12-14 20:59:50 +0000
@@ -89,11 +89,7 @@ dict_mem_table_create(
 
 	mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX);
 
-	table->autoinc_inited = FALSE;
-
-	/* The actual increment value will be set by MySQL, we simply
-	default to 1 here.*/
-	table->autoinc_increment = 1;
+	table->autoinc = 0;
 
 	/* The number of transactions that are either waiting on the
 	AUTOINC lock or have been granted the lock. */

=== modified file 'storage/innobase/handler/ha_innodb.cc'
--- a/storage/innobase/handler/ha_innodb.cc	2008-08-20 22:18:33 +0000
+++ b/storage/innobase/handler/ha_innodb.cc	2008-12-14 20:59:50 +0000
@@ -507,6 +507,18 @@ thd_has_edited_nontrans_tables(
 	return((ibool) thd_non_transactional_update((THD*) thd));
 }
 
+/**********************************************************************
+Returns true if the thread is executing a SELECT statement. */
+extern "C"
+ibool
+thd_is_select(
+/*==========*/
+				/* out: true if thd is executing SELECT */
+	const void*	thd)	/* in: thread handle (THD*) */
+{
+	return(thd_sql_command((const THD*) thd) == SQLCOM_SELECT);
+}
+
 /************************************************************************
 Obtain the InnoDB transaction of a MySQL thread. */
 inline
@@ -910,6 +922,81 @@ innobase_convert_string(
 }
 
 /*************************************************************************
+Compute the next autoinc value.
+
+For MySQL replication the autoincrement values can be partitioned among
+the nodes. The offset is the start or origin of the autoincrement value
+for a particular node. For n nodes the increment will be n and the offset
+will be in the interval [1, n]. The formula tries to allocate the next
+value for a particular node.
+
+Note: This function is also called with increment set to the number of
+values we want to reserve for multi-value inserts e.g.,
+
+	INSERT INTO T VALUES(), (), ();
+
+innobase_next_autoinc() will be called with increment set to
+n * 3 where autoinc_lock_mode != TRADITIONAL because we want
+to reserve 3 values for the multi-value INSERT above. */
+static
+ulonglong
+innobase_next_autoinc(
+/*==================*/
+					/* out: the next value */
+	ulonglong	current,	/* in: Current value */
+	ulonglong	increment,	/* in: increment current by */
+	ulonglong	offset,		/* in: AUTOINC offset */
+	ulonglong	max_value)	/* in: max value for type */
+{
+	ulonglong	next_value;
+
+	/* Should never be 0. */
+	ut_a(increment > 0);
+
+	if (max_value <= current) {
+		next_value = max_value;
+	} else if (offset <= 1) {
+		/* Offset 0 and 1 are the same, because there must be at
+		least one node in the system. */
+		if (max_value - current <= increment) {
+			next_value = max_value;
+		} else {
+			next_value = current + increment;
+		}
+	} else {
+		if (current > offset) {
+			next_value = ((current - offset) / increment) + 1;
+		} else {
+			next_value = ((offset - current) / increment) + 1;
+		}
+
+		ut_a(increment > 0);
+		ut_a(next_value > 0);
+
+		/* Check for multiplication overflow. */
+		if (increment > (max_value / next_value)) {
+
+			next_value = max_value;
+		} else {
+			next_value *= increment;
+
+			ut_a(max_value >= next_value);
+
+			/* Check for overflow. */
+			if (max_value - next_value <= offset) {
+				next_value = max_value;
+			} else {
+				next_value += offset;
+			}
+		}
+	}
+
+	ut_a(next_value <= max_value);
+
+	return(next_value);
+}
+
+/*************************************************************************
 Gets the InnoDB transaction handle for a MySQL handler object, creates
 an InnoDB transaction struct if the corresponding MySQL thread struct still
 lacks one. */
@@ -2262,6 +2349,44 @@ normalize_table_name(
 #endif
 }
 
+/************************************************************************
+Set the autoinc column max value. This should only be called once from
+ha_innobase::open(). Therefore there's no need for a covering lock. */
+
+ulong
+ha_innobase::innobase_initialize_autoinc()
+/*======================================*/
+{
+	dict_index_t*	index;
+	ulonglong	auto_inc;
+	const char*	col_name;
+	ulint		error = DB_SUCCESS;
+	dict_table_t*	innodb_table = prebuilt->table;
+
+	col_name = table->found_next_number_field->field_name;
+	index = innobase_get_index(table->s->next_number_index);
+
+	/* Execute SELECT MAX(col_name) FROM TABLE; */
+	error = row_search_max_autoinc(index, col_name, &auto_inc);
+
+	if (error == DB_SUCCESS) {
+
+		/* At the this stage we dont' know the increment
+		or the offset, so use default inrement of 1. */
+		++auto_inc;
+
+		dict_table_autoinc_initialize(innodb_table, auto_inc);
+
+	} else {
+		ut_print_timestamp(stderr);
+		fprintf(stderr, "  InnoDB: Error: (%lu) Couldn't read "
+			"the MAX(%s) autoinc value from the "
+			"index (%s).\n", error, col_name, index->name);
+	}
+
+	return(ulong(error));
+}
+
 /*********************************************************************
 Creates and opens a handle to a table which already exists in an InnoDB
 database. */
@@ -2286,6 +2411,14 @@ ha_innobase::open(
 	UT_NOT_USED(test_if_locked);
 
 	thd = ha_thd();
+
+	/* Under some cases MySQL seems to call this function while
+	holding btr_search_latch. This breaks the latching order as
+	we acquire dict_sys->mutex below and leads to a deadlock. */
+	if (thd != NULL) {
+		innobase_release_temporary_latches(ht, thd);
+	}
+
 	normalize_table_name(norm_name, name);
 
 	user_thd = NULL;
@@ -2445,6 +2578,26 @@ retry:
 
 	info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 
+	/* Only if the table has an AUTOINC column. */
+	if (prebuilt->table != NULL && table->found_next_number_field != NULL) {
+		ulint	error;
+
+		dict_table_autoinc_lock(prebuilt->table);
+
+		/* Since a table can already be "open" in InnoDB's internal
+		data dictionary, we only init the autoinc counter once, the
+		first time the table is loaded. We can safely reuse the
+		autoinc value from a previous MySQL open. */
+		if (dict_table_autoinc_read(prebuilt->table) == 0) {
+
+			error = innobase_initialize_autoinc();
+			/* Should always succeed! */
+			ut_a(error == DB_SUCCESS);
+		}
+
+		dict_table_autoinc_unlock(prebuilt->table);
+	}
+
 	DBUG_RETURN(0);
 }
 
@@ -3252,6 +3405,59 @@ skip_field:
 }
 
 /************************************************************************
+Get the upper limit of the MySQL integral type. */
+
+ulonglong
+ha_innobase::innobase_get_int_col_max_value(
+/*========================================*/
+	const Field*	field)
+{
+	ulonglong	max_value = 0;
+
+	switch(field->key_type()) {
+	/* TINY */
+        case HA_KEYTYPE_BINARY:
+		max_value = 0xFFULL;
+		break;
+	case HA_KEYTYPE_INT8:
+		max_value = 0x7FULL;
+		break;
+	/* SHORT */
+	case HA_KEYTYPE_USHORT_INT:
+		max_value = 0xFFFFULL;
+		break;
+	case HA_KEYTYPE_SHORT_INT:
+		max_value = 0x7FFFULL;
+		break;
+	/* MEDIUM */
+    	case HA_KEYTYPE_UINT24:
+		max_value = 0xFFFFFFULL;
+		break;
+	case HA_KEYTYPE_INT24:
+		max_value = 0x7FFFFFULL;
+		break;
+	/* LONG */
+	case HA_KEYTYPE_ULONG_INT:
+		max_value = 0xFFFFFFFFULL;
+		break;
+	case HA_KEYTYPE_LONG_INT:
+		max_value = 0x7FFFFFFFULL;
+		break;
+	/* BIG */
+    	case HA_KEYTYPE_ULONGLONG:
+		max_value = 0xFFFFFFFFFFFFFFFFULL;
+		break;
+	case HA_KEYTYPE_LONGLONG:
+		max_value = 0x7FFFFFFFFFFFFFFFULL;
+		break;
+	default:
+		ut_error;
+	}
+
+	return(max_value);
+}
+
+/************************************************************************
 This special handling is really to overcome the limitations of MySQL's
 binlogging. We need to eliminate the non-determinism that will arise in
 INSERT ... SELECT type of statements, since MySQL binlog only stores the
@@ -3259,7 +3465,7 @@ min value of the autoinc interval. Once 
 the special lock handling.*/
 
 ulong
-ha_innobase::innobase_autoinc_lock(void)
+ha_innobase::innobase_lock_autoinc(void)
 /*====================================*/
 					/* out: DB_SUCCESS if all OK else
 					error code */
@@ -3324,7 +3530,7 @@ ha_innobase::innobase_reset_autoinc(
 {
 	ulint		error;
 
-	error = innobase_autoinc_lock();
+	error = innobase_lock_autoinc();
 
 	if (error == DB_SUCCESS) {
 
@@ -3349,11 +3555,11 @@ ha_innobase::innobase_set_max_autoinc(
 {
 	ulint		error;
 
-	error = innobase_autoinc_lock();
+	error = innobase_lock_autoinc();
 
 	if (error == DB_SUCCESS) {
 
-		dict_table_autoinc_update(prebuilt->table, auto_inc);
+		dict_table_autoinc_update_if_greater(prebuilt->table, auto_inc);
 
 		dict_table_autoinc_unlock(prebuilt->table);
 	}
@@ -3473,8 +3679,20 @@ no_commit:
 	/* This is the case where the table has an auto-increment column */
 	if (table->next_number_field && record == table->record[0]) {
 
+		/* Reset the error code before calling
+		innobase_get_auto_increment(). */
+		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 = prebuilt->autoinc_error;
+
+				goto report_error;
+			}
+
+			/* MySQL errors are passed straight back. */
 			goto func_exit;
 		}
 
@@ -3498,6 +3716,7 @@ no_commit:
 	if (auto_inc_used) {
 		ulint		err;
 		ulonglong	auto_inc;
+		ulonglong	col_max_value;
 
 		/* Note the number of rows processed for this statement, used
 		by get_auto_increment() to determine the number of AUTO-INC
@@ -3507,6 +3726,11 @@ no_commit:
 			--trx->n_autoinc_rows;
 		}
 
+		/* 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);
+
 		/* Get the value that MySQL attempted to store in the table.*/
 		auto_inc = table->next_number_field->val_int();
 
@@ -3545,22 +3769,19 @@ no_commit:
 			update the table upper limit. Note: last_value
 			will be 0 if get_auto_increment() was not called.*/
 
-			if (auto_inc > prebuilt->last_value) {
+			if (auto_inc <= col_max_value
+			    && auto_inc > prebuilt->autoinc_last_value) {
 set_max_autoinc:
-				ut_a(prebuilt->table->autoinc_increment > 0);
+				ut_a(prebuilt->autoinc_increment > 0);
 
-				ulonglong	have;
 				ulonglong	need;
+				ulonglong	offset;
 
-				/* Check for overflow conditions. */
-				need = prebuilt->table->autoinc_increment;
-				have = ~0x0ULL - auto_inc;
+				offset = prebuilt->autoinc_offset;
+				need = prebuilt->autoinc_increment;
 
-				if (have < need) {
-					need = have;
-				}
-
-				auto_inc += need;
+				auto_inc = innobase_next_autoinc(
+					auto_inc, need, offset, col_max_value);
 
 				err = innobase_set_max_autoinc(auto_inc);
 
@@ -3574,6 +3795,7 @@ set_max_autoinc:
 
 	innodb_srv_conc_exit_innodb(prebuilt->trx);
 
+report_error:
 	error = convert_error_code_to_mysql(error, user_thd);
 
 func_exit:
@@ -3755,6 +3977,8 @@ ha_innobase::update_row(
 
 	ut_a(prebuilt->trx == trx);
 
+	ha_statistic_increment(&SSV::ha_update_count);
+
 	if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 		table->timestamp_field->set_time();
 
@@ -3795,12 +4019,26 @@ ha_innobase::update_row(
 	    && (trx->duplicates & (TRX_DUP_IGNORE | TRX_DUP_REPLACE))
 		== TRX_DUP_IGNORE)  {
 
-		longlong	auto_inc;
+		ulonglong	auto_inc;
+		ulonglong	col_max_value;
 
 		auto_inc = table->next_number_field->val_int();
 
-		if (auto_inc != 0) {
-			auto_inc += prebuilt->table->autoinc_increment;
+		/* 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);
+
+		if (auto_inc <= col_max_value && auto_inc != 0) {
+
+			ulonglong	need;
+			ulonglong	offset;
+
+			offset = prebuilt->autoinc_offset;
+			need = prebuilt->autoinc_increment;
+
+			auto_inc = innobase_next_autoinc(
+				auto_inc, need, offset, col_max_value);
 
 			error = innobase_set_max_autoinc(auto_inc);
 		}
@@ -3844,29 +4082,7 @@ ha_innobase::delete_row(
 
 	ut_a(prebuilt->trx == trx);
 
-	/* Only if the table has an AUTOINC column */
-	if (table->found_next_number_field && record == table->record[0]) {
-		ulonglong	dummy = 0;
-
-		/* First check whether the AUTOINC sub-system has been
-		initialized using the AUTOINC mutex. If not then we
-		do it the "proper" way, by acquiring the heavier locks. */
-		dict_table_autoinc_lock(prebuilt->table);
-
-		if (!prebuilt->table->autoinc_inited) {
-			dict_table_autoinc_unlock(prebuilt->table);
-
-			error = innobase_get_auto_increment(&dummy);
-
-			if (error == DB_SUCCESS) {
-				dict_table_autoinc_unlock(prebuilt->table);
-			} else {
-				goto error_exit;
-			}
-		} else  {
-			dict_table_autoinc_unlock(prebuilt->table);
-		}
-	}
+	ha_statistic_increment(&SSV::ha_delete_count);
 
 	if (!prebuilt->upd_node) {
 		row_get_prebuilt_update_vector(prebuilt);
@@ -3882,7 +4098,6 @@ ha_innobase::delete_row(
 
 	innodb_srv_conc_exit_innodb(trx);
 
-error_exit:
 	error = convert_error_code_to_mysql(error, user_thd);
 
 	/* Tell the InnoDB server that there might be work for
@@ -4986,6 +5201,29 @@ ha_innobase::create(
 	DBUG_ENTER("ha_innobase::create");
 
 	DBUG_ASSERT(thd != NULL);
+	DBUG_ASSERT(create_info != NULL);
+
+#ifdef __WIN__
+	/* Names passed in from server are in two formats:
+	1. <database_name>/<table_name>: for normal table creation
+	2. full path: for temp table creation, or sym link
+
+	When srv_file_per_table is on, check for full path pattern, i.e.
+	X:\dir\...,		X is a driver letter, or
+	\\dir1\dir2\...,	UNC path
+	returns error if it is in full path format, but not creating a temp.
+	table. Currently InnoDB does not support symbolic link on Windows. */
+
+	if (srv_file_per_table
+	    && (!create_info->options & HA_LEX_CREATE_TMP_TABLE)) {
+
+		if ((name[1] == ':')
+		    || (name[0] == '\\' && name[1] == '\\')) {
+			sql_print_error("Cannot create table %s\n", name);
+			DBUG_RETURN(HA_ERR_GENERIC);
+		}
+	}
+#endif
 
 	if (form->s->fields > 1000) {
 		/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
@@ -5216,7 +5454,8 @@ ha_innobase::delete_all_rows(void)
 	if (thd_sql_command(user_thd) != SQLCOM_TRUNCATE) {
 	fallback:
 		/* We only handle TRUNCATE TABLE t as a special case.
-		DELETE FROM t will have to use ha_innobase::delete_row(). */
+		DELETE FROM t will have to use ha_innobase::delete_row(),
+		because DELETE is transactional while TRUNCATE is not. */
 		DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
 	}
 
@@ -5797,7 +6036,7 @@ ha_innobase::info(
 			not be updated. This will force write_row() into
 			attempting an update of the table's AUTOINC counter. */
 
-			prebuilt->last_value = 0;
+			prebuilt->autoinc_last_value = 0;
 		}
 
 		stats.records = (ha_rows)n_rows;
@@ -5818,9 +6057,39 @@ ha_innobase::info(
 		so the "old" value can remain. delete_length is initialized
 		to 0 in the ha_statistics' constructor. */
 		if (!(flag & HA_STATUS_NO_LOCK)) {
-			stats.delete_length =
-				fsp_get_available_space_in_free_extents(
-					ib_table->space) * 1024;
+
+			/* lock the data dictionary to avoid races with
+			ibd_file_missing and tablespace_discarded */
+			row_mysql_lock_data_dictionary(prebuilt->trx);
+
+			/* ib_table->space must be an existent tablespace */
+			if (!ib_table->ibd_file_missing
+			    && !ib_table->tablespace_discarded) {
+
+				stats.delete_length =
+					fsp_get_available_space_in_free_extents(
+						ib_table->space) * 1024;
+			} else {
+
+				THD*	thd;
+
+				thd = ha_thd();
+
+				push_warning_printf(
+					thd,
+					MYSQL_ERROR::WARN_LEVEL_WARN,
+					ER_CANT_GET_STAT,
+					"InnoDB: Trying to get the free "
+					"space for table %s but its "
+					"tablespace has been discarded or "
+					"the .ibd file is missing. Setting "
+					"the free space to zero.",
+					ib_table->name);
+
+				stats.delete_length = 0;
+			}
+
+			row_mysql_unlock_data_dictionary(prebuilt->trx);
 		}
 
 		stats.check_time = 0;
@@ -5905,29 +6174,7 @@ ha_innobase::info(
 	}
 
 	if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
-		ulonglong	auto_inc;
-		int		ret;
-
-		/* The following function call can the first time fail in
-		a lock wait timeout error because it reserves the auto-inc
-		lock on the table. If it fails, then someone is already initing
-		the auto-inc counter, and the second call is guaranteed to
-		succeed. */
-
-		ret = innobase_read_and_init_auto_inc(&auto_inc);
-
-		if (ret != 0) {
-			ret = innobase_read_and_init_auto_inc(&auto_inc);
-
-			if (ret != 0) {
-				sql_print_error("Cannot get table %s auto-inc"
-						"counter value in ::info\n",
-						ib_table->name);
-				auto_inc = 0;
-			}
-		}
-
-		stats.auto_increment_value = auto_inc;
+ 		stats.auto_increment_value = innobase_peek_autoinc();
 	}
 
 	prebuilt->trx->op_info = (char*)"";
@@ -6390,15 +6637,26 @@ ha_innobase::extra(
 	return(0);
 }
 
+/**********************************************************************
+Reset state of file to after 'open'.
+This function is called after every statement for all tables used
+by that statement.  */
 int ha_innobase::reset()
 {
-  if (prebuilt->blob_heap) {
-    row_mysql_prebuilt_free_blob_heap(prebuilt);
-  }
-  reset_template(prebuilt);
-  return 0;
-}
+	if (prebuilt->blob_heap) {
+		row_mysql_prebuilt_free_blob_heap(prebuilt);
+	}
 
+	reset_template(prebuilt);
+
+	/* TODO: This should really be reset in reset_template() but for now
+	it's safer to do it explicitly here. */
+
+	/* This is a statement level counter. */
+	prebuilt->autoinc_last_value = 0;
+
+	return(0);
+}
 
 /**********************************************************************
 MySQL calls this function at the start of each SQL statement inside LOCK
@@ -7247,169 +7505,59 @@ ha_innobase::store_lock(
 	return(to);
 }
 
-/***********************************************************************
-This function initializes the auto-inc counter if it has not been
-initialized yet. This function does not change the value of the auto-inc
-counter if it already has been initialized. In parameter ret returns
-the value of the auto-inc counter. */
-
-int
-ha_innobase::innobase_read_and_init_auto_inc(
-/*=========================================*/
-						/* out: 0 or generic MySQL
-						error code */
-        ulonglong*	value)			/* out: the autoinc value */
-{
-	ulonglong	auto_inc;
-	ibool		stmt_start;
-	int		mysql_error = 0;
-	dict_table_t*	innodb_table = prebuilt->table;
-	ibool		trx_was_not_started	= FALSE;
-
-	ut_a(prebuilt);
-	ut_a(prebuilt->table);
-
-	/* Remember if we are in the beginning of an SQL statement.
-	This function must not change that flag. */
-	stmt_start = prebuilt->sql_stat_start;
-
-	/* Prepare prebuilt->trx in the table handle */
-	update_thd(ha_thd());
-
-	if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
-		trx_was_not_started = TRUE;
-	}
-
-	/* In case MySQL calls this in the middle of a SELECT query, release
-	possible adaptive hash latch to avoid deadlocks of threads */
-
-	trx_search_latch_release_if_reserved(prebuilt->trx);
-
-	dict_table_autoinc_lock(prebuilt->table);
-
-	auto_inc = dict_table_autoinc_read(prebuilt->table);
-
-	/* Was the AUTOINC counter reset during normal processing, if
-	so then we simply start count from 1. No need to go to the index.*/
-	if (auto_inc == 0 && innodb_table->autoinc_inited) {
-		++auto_inc;
-		dict_table_autoinc_initialize(innodb_table, auto_inc);
-	}
-
-	if (auto_inc == 0) {
-		dict_index_t* index;
-		ulint error;
-		const char* autoinc_col_name;
-
-		ut_a(!innodb_table->autoinc_inited);
-
-		index = innobase_get_index(table->s->next_number_index);
-
-		autoinc_col_name = table->found_next_number_field->field_name;
-
-		error = row_search_max_autoinc(
-			index, autoinc_col_name, &auto_inc);
-
-		if (error == DB_SUCCESS) {
-			if (auto_inc < ~0x0ULL) {
-				++auto_inc;
-			}
-			dict_table_autoinc_initialize(innodb_table, auto_inc);
-		} else {
-			ut_print_timestamp(stderr);
-			fprintf(stderr, "  InnoDB: Error: (%lu) Couldn't read "
-				"the max AUTOINC value from the index (%s).\n",
-				error, index->name);
-
-			mysql_error = 1;
-		}
-	}
-
-	*value = auto_inc;
-
-	dict_table_autoinc_unlock(prebuilt->table);
-
-	/* Since MySQL does not seem to call autocommit after SHOW TABLE
-	STATUS (even if we would register the trx here), we commit our
-	transaction here if it was started here. This is to eliminate a
-	dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
-	TABLE STATUS does leave a dangling transaction if the user does not
-	himself call COMMIT. */
-
-	if (trx_was_not_started) {
-
-		innobase_commit_low(prebuilt->trx);
-	}
-
-	prebuilt->sql_stat_start = stmt_start;
-
-	return(mysql_error);
-}
-
 /*******************************************************************************
-Read the next autoinc value, initialize the table if it's not initialized.
-On return if there is no error then the tables AUTOINC lock is locked.*/
+Read the next autoinc value. Acquire the relevant locks before reading
+the AUTOINC value. If SUCCESS then the table AUTOINC mutex will be locked
+on return and all relevant locks acquired. */
 
 ulong
-ha_innobase::innobase_get_auto_increment(
-/*=====================================*/
+ha_innobase::innobase_get_autoinc(
+/*==============================*/
+					/* out: DB_SUCCESS or error code */
 	ulonglong*	value)		/* out: autoinc value */
 {
-	ulong		error;
-
-	*value = 0;
-
-	/* Note: If the table is not initialized when we attempt the
-	read below. We initialize the table's auto-inc counter  and
-	always do a reread of the AUTOINC value. */
-	do {
-		error = innobase_autoinc_lock();
-
-		if (error == DB_SUCCESS) {
-			ulonglong	autoinc;
+ 	*value = 0;
+ 
+	prebuilt->autoinc_error = innobase_lock_autoinc();
 
-			/* Determine the first value of the interval */
-			autoinc = dict_table_autoinc_read(prebuilt->table);
+	if (prebuilt->autoinc_error == DB_SUCCESS) {
 
-			/* We need to initialize the AUTO-INC value, for
-			that we release all locks.*/
-			if (autoinc == 0) {
-				trx_t*		trx;
+		/* Determine the first value of the interval */
+		*value = dict_table_autoinc_read(prebuilt->table);
 
-				trx = prebuilt->trx;
-				dict_table_autoinc_unlock(prebuilt->table);
+		/* It should have been initialized during open. */
+		ut_a(*value != 0);
+	}
+  
+	return(ulong(prebuilt->autoinc_error));
+}
 
-				/* If we had reserved the AUTO-INC
-				lock in this SQL statement we release
-				it before retrying.*/
-				row_unlock_table_autoinc_for_mysql(trx);
+/***********************************************************************
+This function reads the global auto-inc counter. It doesn't use the 
+AUTOINC lock even if the lock mode is set to TRADITIONAL. */
 
-				/* Just to make sure */
-				ut_a(!trx->auto_inc_lock);
+ulonglong
+ha_innobase::innobase_peek_autoinc()
+/*================================*/
+					/* out: the autoinc value */
+{
+	ulonglong	auto_inc;
+	dict_table_t*	innodb_table;
 
-				int	mysql_error;
+	ut_a(prebuilt != NULL);
+	ut_a(prebuilt->table != NULL);
 
-				mysql_error = innobase_read_and_init_auto_inc(
-					&autoinc);
+	innodb_table = prebuilt->table;
 
-				if (mysql_error) {
-					error = DB_ERROR;
-				}
-			} else {
-				*value = autoinc;
-			}
-		/* A deadlock error during normal processing is OK
-		and can be ignored. */
-		} else if (error != DB_DEADLOCK) {
+	dict_table_autoinc_lock(innodb_table);
 
-			sql_print_error("InnoDB: Error: %lu in "
-					"::innobase_get_auto_increment()",
-					error);
-		}
+	auto_inc = dict_table_autoinc_read(innodb_table);
 
-	} while (*value == 0 && error == DB_SUCCESS);
+	ut_a(auto_inc > 0);
 
-	return(error);
+	dict_table_autoinc_unlock(innodb_table);
+ 
+	return(auto_inc);
 }
 
 /*******************************************************************************
@@ -7436,7 +7584,7 @@ ha_innobase::get_auto_increment(
 	/* Prepare prebuilt->trx in the table handle */
 	update_thd(ha_thd());
 
-	error = innobase_get_auto_increment(&autoinc);
+	error = innobase_get_autoinc(&autoinc);
 
 	if (error != DB_SUCCESS) {
 		*first_value = (~(ulonglong) 0);
@@ -7472,7 +7620,7 @@ ha_innobase::get_auto_increment(
 
 		set_if_bigger(*first_value, autoinc);
 	/* Not in the middle of a mult-row INSERT. */
-	} else if (prebuilt->last_value == 0) {
+	} else if (prebuilt->autoinc_last_value == 0) {
 		set_if_bigger(*first_value, autoinc);
 	}
 
@@ -7481,35 +7629,40 @@ ha_innobase::get_auto_increment(
 	/* With old style AUTOINC locking we only update the table's
 	AUTOINC counter after attempting to insert the row. */
 	if (innobase_autoinc_lock_mode != AUTOINC_OLD_STYLE_LOCKING) {
-		ulonglong	have;
 		ulonglong	need;
+		ulonglong	next_value;
+		ulonglong	col_max_value;
 
-		/* Check for overflow conditions. */
-		need = *nb_reserved_values * increment;
-		have = ~0x0ULL - *first_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);
 
-		if (have < need) {
-			need = have;
-		}
+		need = *nb_reserved_values * increment;
 
 		/* Compute the last value in the interval */
-		prebuilt->last_value = *first_value + need;
+		next_value = innobase_next_autoinc(
+			*first_value, need, offset, col_max_value);
 
-		ut_a(prebuilt->last_value >= *first_value);
+		prebuilt->autoinc_last_value = next_value;
+
+		ut_a(prebuilt->autoinc_last_value >= *first_value);
 
 		/* Update the table autoinc variable */
-		dict_table_autoinc_update(
-			prebuilt->table, prebuilt->last_value);
+		dict_table_autoinc_update_if_greater(
+			prebuilt->table, prebuilt->autoinc_last_value);
 	} else {
 		/* This will force write_row() into attempting an update
 		of the table's AUTOINC counter. */
-		prebuilt->last_value = 0;
+		prebuilt->autoinc_last_value = 0;
 	}
 
 	/* The increment to be used to increase the AUTOINC value, we use
 	this in write_row() and update_row() to increase the autoinc counter
-	for columns that are filled by the user.*/
-	prebuilt->table->autoinc_increment = increment;
+	for columns that are filled by the user. We need the offset and
+	the increment. */
+	prebuilt->autoinc_offset = offset;
+	prebuilt->autoinc_increment = increment;
 
 	dict_table_autoinc_unlock(prebuilt->table);
 }
@@ -7534,6 +7687,11 @@ ha_innobase::reset_auto_increment(
 		DBUG_RETURN(error);
 	}
 
+	/* The next value can never be 0. */
+	if (value == 0) {
+		value = 1;
+	}
+
 	innobase_reset_autoinc(value);
 
 	DBUG_RETURN(0);

=== modified file 'storage/innobase/handler/ha_innodb.h'
--- a/storage/innobase/handler/ha_innodb.h	2008-03-27 01:40:45 +0000
+++ b/storage/innobase/handler/ha_innodb.h	2008-12-14 20:59:50 +0000
@@ -72,12 +72,15 @@ class ha_innobase: public handler
 	int update_thd(THD* thd);
 	int change_active_index(uint keynr);
 	int general_fetch(uchar* buf, uint direction, uint match_mode);
-	int innobase_read_and_init_auto_inc(ulonglong* ret);
-	ulong innobase_autoinc_lock();
+	ulong innobase_lock_autoinc();
+	ulonglong innobase_peek_autoinc();
 	ulong innobase_set_max_autoinc(ulonglong auto_inc);
 	ulong innobase_reset_autoinc(ulonglong auto_inc);
-	ulong innobase_get_auto_increment(ulonglong* value);
+	ulong innobase_get_autoinc(ulonglong* value);
+	ulong innobase_update_autoinc(ulonglong	auto_inc);
+	ulong innobase_initialize_autoinc();
 	dict_index_t* innobase_get_index(uint keynr);
+ 	ulonglong innobase_get_int_col_max_value(const Field* field);
 
 	/* Init values for the class: */
  public:

=== modified file 'storage/innobase/include/btr0sea.h'
--- a/storage/innobase/include/btr0sea.h	2007-01-05 02:51:34 +0000
+++ b/storage/innobase/include/btr0sea.h	2008-12-14 19:25:33 +0000
@@ -40,6 +40,14 @@ btr_search_info_create(
 /*===================*/
 				/* out, own: search info struct */
 	mem_heap_t*	heap);	/* in: heap where created */
+/*********************************************************************
+Returns the value of ref_count. The value is protected by
+btr_search_latch. */
+ulint
+btr_search_info_get_ref_count(
+/*==========================*/
+				/* out: ref_count value. */
+	btr_search_t*   info);	/* in: search info. */
 /*************************************************************************
 Updates the search info. */
 UNIV_INLINE
@@ -137,6 +145,13 @@ btr_search_validate(void);
 /* The search info struct in an index */
 
 struct btr_search_struct{
+	ulint	ref_count;	/* Number of blocks in this index tree
+				that have search index built
+				i.e. block->index points to this index.
+				Protected by btr_search_latch except
+				when during initialization in
+				btr_search_info_create(). */
+
 	/* The following fields are not protected by any latch.
 	Unfortunately, this means that they must be aligned to
 	the machine word, i.e., they cannot be turned into bit-fields. */

=== modified file 'storage/innobase/include/dict0dict.h'
--- a/storage/innobase/include/dict0dict.h	2008-03-27 01:40:45 +0000
+++ b/storage/innobase/include/dict0dict.h	2008-12-14 20:59:50 +0000
@@ -178,8 +178,7 @@ dict_table_autoinc_lock(
 /*====================*/
 	dict_table_t*	table);	/* in: table */
 /************************************************************************
-Initializes the autoinc counter. It is not an error to initialize an already
-initialized counter. */
+Unconditionally set the autoinc counter. */
 
 void
 dict_table_autoinc_initialize(
@@ -196,12 +195,12 @@ dict_table_autoinc_read(
 				/* out: value for a new row, or 0 */
 	dict_table_t*	table);	/* in: table */
 /************************************************************************
-Updates the autoinc counter if the value supplied is equal or bigger than the
-current value. If not inited, does nothing. */
+Updates the autoinc counter if the value supplied is greater than the
+current value. */
 
 void
-dict_table_autoinc_update(
-/*======================*/
+dict_table_autoinc_update_if_greater(
+/*=================================*/
 
 	dict_table_t*	table,	/* in: table */
 	ib_ulonglong	value);	/* in: value which was assigned to a row */

=== modified file 'storage/innobase/include/dict0mem.h'
--- a/storage/innobase/include/dict0mem.h	2008-03-27 01:40:45 +0000
+++ b/storage/innobase/include/dict0mem.h	2008-12-14 20:59:50 +0000
@@ -405,17 +405,8 @@ struct dict_table_struct{
 	mutex_t		autoinc_mutex;
 				/* mutex protecting the autoincrement
 				counter */
-	ibool		autoinc_inited;
-				/* TRUE if the autoinc counter has been
-				inited; MySQL gets the init value by executing
-				SELECT MAX(auto inc column) */
 	ib_ulonglong	autoinc;/* autoinc counter value to give to the
 				next inserted row */
-
-	ib_longlong	autoinc_increment;
-				/* The increment step of the auto increment
-				column. Value must be greater than or equal
-				to 1 */
 	ulong		n_waiting_or_granted_auto_inc_locks;
 				/* This counter is used to track the number
 				of granted and pending autoinc locks on this
@@ -425,6 +416,7 @@ struct dict_table_struct{
 				acquired the AUTOINC lock or not. Of course
 				only one transaction can be granted the
 				lock but there can be multiple waiters. */
+	/*----------------------*/
 
 #ifdef UNIV_DEBUG
 	ulint		magic_n;/* magic number */

=== modified file 'storage/innobase/include/ha_prototypes.h'
--- a/storage/innobase/include/ha_prototypes.h	2007-11-06 22:42:58 +0000
+++ b/storage/innobase/include/ha_prototypes.h	2008-12-14 19:28:19 +0000
@@ -63,5 +63,14 @@ thd_has_edited_nontrans_tables(
 			been edited */
 	void*	thd);	/* in: thread handle (THD*) */
 
+/**********************************************************************
+Returns true if the thread is executing a SELECT statement. */
+
+ibool
+thd_is_select(
+/*==========*/
+				/* out: true if thd is executing SELECT */
+	const void*	thd);	/* in: thread handle (THD*) */
+
 #endif
 #endif

=== modified file 'storage/innobase/include/lock0lock.h'
--- a/storage/innobase/include/lock0lock.h	2007-08-25 01:14:52 +0000
+++ b/storage/innobase/include/lock0lock.h	2008-12-14 20:00:37 +0000
@@ -463,14 +463,21 @@ void
 lock_cancel_waiting_and_release(
 /*============================*/
 	lock_t*	lock);	/* in: waiting lock request */
+
 /*************************************************************************
-Resets all locks, both table and record locks, on a table to be dropped.
-No lock is allowed to be a wait lock. */
+Removes locks on a table to be dropped or truncated.
+If remove_also_table_sx_locks is TRUE then table-level S and X locks are
+also removed in addition to other table-level and record-level locks.
+No lock, that is going to be removed, is allowed to be a wait lock. */
 
 void
-lock_reset_all_on_table(
-/*====================*/
-	dict_table_t*	table);	/* in: table to be dropped */
+lock_remove_all_on_table(
+/*=====================*/
+	dict_table_t*	table,			/* in: table to be dropped
+						or truncated */
+	ibool		remove_also_table_sx_locks);/* in: also removes
+						table S and X locks */
+
 /*************************************************************************
 Calculates the fold value of a page file address: used in inserting or
 searching for a lock in the hash table. */

=== modified file 'storage/innobase/include/row0mysql.h'
--- a/storage/innobase/include/row0mysql.h	2008-03-27 14:13:10 +0000
+++ b/storage/innobase/include/row0mysql.h	2008-12-14 20:56:33 +0000
@@ -683,7 +683,21 @@ struct row_prebuilt_struct {
 					to this heap */
 	mem_heap_t*	old_vers_heap;	/* memory heap where a previous
 					version is built in consistent read */
-	ulonglong	last_value;	/* last value of AUTO-INC interval */
+	/*----------------------*/
+	ulonglong	autoinc_last_value;/* last value of AUTO-INC interval */
+	ulonglong	autoinc_increment;/* The increment step of the auto 
+					increment column. Value must be
+					greater than or equal to 1. Required to
+					calculate the next value */
+	ulonglong	autoinc_offset; /* The offset passed to
+					get_auto_increment() by MySQL. Required
+					to calculate the next value */
+	ulint		autoinc_error;	/* The actual error code encountered
+					while trying to init or read the
+					autoinc value from the table. We
+					store it here so that we can return
+					it to MySQL */
+	/*----------------------*/
 	ulint		magic_n2;	/* this should be the same as
 					magic_n */
 };

=== modified file 'storage/innobase/include/sync0sync.ic'
--- a/storage/innobase/include/sync0sync.ic	2008-02-19 16:44:09 +0000
+++ b/storage/innobase/include/sync0sync.ic	2008-12-14 20:27:13 +0000
@@ -197,7 +197,7 @@ mutex_exit(
 {
 	ut_ad(mutex_own(mutex));
 
-	ut_d(mutex->thread_id = ULINT_UNDEFINED);
+	ut_d(mutex->thread_id = (os_thread_id_t) ULINT_UNDEFINED);
 
 #ifdef UNIV_SYNC_DEBUG
 	sync_thread_reset_level(mutex);

=== modified file 'storage/innobase/include/ut0ut.h'
--- a/storage/innobase/include/ut0ut.h	2007-11-06 22:42:58 +0000
+++ b/storage/innobase/include/ut0ut.h	2008-12-14 19:18:59 +0000
@@ -145,11 +145,15 @@ ib_time_t
 ut_time(void);
 /*=========*/
 /**************************************************************
-Returns system time. */
+Returns system time.
+Upon successful completion, the value 0 is returned; otherwise the
+value -1 is returned and the global variable errno is set to indicate the
+error. */
 
-void
+int
 ut_usectime(
 /*========*/
+			/* out: 0 on success, -1 otherwise */
 	ulint*	sec,	/* out: seconds since the Epoch */
 	ulint*	ms);	/* out: microseconds since the Epoch+*sec */
 /**************************************************************

=== modified file 'storage/innobase/lock/lock0lock.c'
--- a/storage/innobase/lock/lock0lock.c	2008-08-20 22:18:33 +0000
+++ b/storage/innobase/lock/lock0lock.c	2008-12-14 20:00:37 +0000
@@ -3920,15 +3920,25 @@ lock_cancel_waiting_and_release(
 	trx_end_lock_wait(lock->trx);
 }
 
+/* True if a lock mode is S or X */
+#define IS_LOCK_S_OR_X(lock) \
+	(lock_get_mode(lock) == LOCK_S \
+	 || lock_get_mode(lock) == LOCK_X)
+
+
 /*************************************************************************
-Resets all record and table locks of a transaction on a table to be dropped.
-No lock is allowed to be a wait lock. */
+Removes locks of a transaction on a table to be dropped.
+If remove_also_table_sx_locks is TRUE then table-level S and X locks are
+also removed in addition to other table-level and record-level locks.
+No lock, that is going to be removed, is allowed to be a wait lock. */
 static
 void
-lock_reset_all_on_table_for_trx(
-/*============================*/
-	dict_table_t*	table,	/* in: table to be dropped */
-	trx_t*		trx)	/* in: a transaction */
+lock_remove_all_on_table_for_trx(
+/*=============================*/
+	dict_table_t*	table,			/* in: table to be dropped */
+	trx_t*		trx,			/* in: a transaction */
+	ibool		remove_also_table_sx_locks)/* in: also removes
+						table S and X locks */
 {
 	lock_t*	lock;
 	lock_t*	prev_lock;
@@ -3946,7 +3956,9 @@ lock_reset_all_on_table_for_trx(
 
 			lock_rec_discard(lock);
 		} else if (lock_get_type(lock) & LOCK_TABLE
-			   && lock->un_member.tab_lock.table == table) {
+			   && lock->un_member.tab_lock.table == table
+			   && (remove_also_table_sx_locks
+			       || !IS_LOCK_S_OR_X(lock))) {
 
 			ut_a(!lock_get_wait(lock));
 
@@ -3958,26 +3970,65 @@ lock_reset_all_on_table_for_trx(
 }
 
 /*************************************************************************
-Resets all locks, both table and record locks, on a table to be dropped.
-No lock is allowed to be a wait lock. */
+Removes locks on a table to be dropped or truncated.
+If remove_also_table_sx_locks is TRUE then table-level S and X locks are
+also removed in addition to other table-level and record-level locks.
+No lock, that is going to be removed, is allowed to be a wait lock. */
 
 void
-lock_reset_all_on_table(
-/*====================*/
-	dict_table_t*	table)	/* in: table to be dropped */
+lock_remove_all_on_table(
+/*=====================*/
+	dict_table_t*	table,			/* in: table to be dropped
+						or truncated */
+	ibool		remove_also_table_sx_locks)/* in: also removes
+						table S and X locks */
 {
 	lock_t*	lock;
+	lock_t*	prev_lock;
 
 	mutex_enter(&kernel_mutex);
 
 	lock = UT_LIST_GET_FIRST(table->locks);
 
-	while (lock) {
-		ut_a(!lock_get_wait(lock));
+	while (lock != NULL) {
+
+		prev_lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
+					     lock);
 
-		lock_reset_all_on_table_for_trx(table, lock->trx);
+		/* If we should remove all locks (remove_also_table_sx_locks
+		is TRUE), or if the lock is not table-level S or X lock,
+		then check we are not going to remove a wait lock. */
+		if (remove_also_table_sx_locks
+		    || !(lock_get_type(lock) == LOCK_TABLE
+			 && IS_LOCK_S_OR_X(lock))) {
 
-		lock = UT_LIST_GET_FIRST(table->locks);
+			ut_a(!lock_get_wait(lock));
+		}
+
+		lock_remove_all_on_table_for_trx(table, lock->trx,
+						 remove_also_table_sx_locks);
+
+		if (prev_lock == NULL) {
+			if (lock == UT_LIST_GET_FIRST(table->locks)) {
+				/* lock was not removed, pick its successor */
+				lock = UT_LIST_GET_NEXT(
+					un_member.tab_lock.locks, lock);
+			} else {
+				/* lock was removed, pick the first one */
+				lock = UT_LIST_GET_FIRST(table->locks);
+			}
+		} else if (UT_LIST_GET_NEXT(un_member.tab_lock.locks,
+					    prev_lock) != lock) {
+			/* If lock was removed by
+			lock_remove_all_on_table_for_trx() then pick the
+			successor of prev_lock ... */
+			lock = UT_LIST_GET_NEXT(
+				un_member.tab_lock.locks, prev_lock);
+		} else {
+			/* ... otherwise pick the successor of lock. */
+			lock = UT_LIST_GET_NEXT(
+				un_member.tab_lock.locks, lock);
+		}
 	}
 
 	mutex_exit(&kernel_mutex);

=== modified file 'storage/innobase/os/os0file.c'
--- a/storage/innobase/os/os0file.c	2008-03-27 14:13:10 +0000
+++ b/storage/innobase/os/os0file.c	2008-12-14 19:15:12 +0000
@@ -1267,9 +1267,19 @@ try_again:
 	if (file == INVALID_HANDLE_VALUE) {
 		*success = FALSE;
 
-		retry = os_file_handle_error(name,
-					     create_mode == OS_FILE_CREATE ?
-					     "create" : "open");
+		/* When srv_file_per_table is on, file creation failure may not
+		be critical to the whole instance. Do not crash the server in
+		case of unknown errors. */
+		if (srv_file_per_table) {
+			retry = os_file_handle_error_no_exit(name,
+						create_mode == OS_FILE_CREATE ?
+						"create" : "open");
+		} else {
+			retry = os_file_handle_error(name,
+						create_mode == OS_FILE_CREATE ?
+						"create" : "open");
+		}
+
 		if (retry) {
 			goto try_again;
 		}
@@ -1344,9 +1354,19 @@ try_again:
 	if (file == -1) {
 		*success = FALSE;
 
-		retry = os_file_handle_error(name,
-					     create_mode == OS_FILE_CREATE ?
-					     "create" : "open");
+		/* When srv_file_per_table is on, file creation failure may not
+		be critical to the whole instance. Do not crash the server in
+		case of unknown errors. */
+		if (srv_file_per_table) {
+			retry = os_file_handle_error_no_exit(name,
+						create_mode == OS_FILE_CREATE ?
+						"create" : "open");
+		} else {
+			retry = os_file_handle_error(name,
+						create_mode == OS_FILE_CREATE ?
+						"create" : "open");
+		}
+
 		if (retry) {
 			goto try_again;
 		} else {

=== modified file 'storage/innobase/plug.in'
--- a/storage/innobase/plug.in	2008-05-14 08:45:32 +0000
+++ b/storage/innobase/plug.in	2008-12-14 18:54:01 +0000
@@ -15,25 +15,30 @@ MYSQL_PLUGIN_ACTIONS(innobase,  [
   AC_CHECK_FUNCS(localtime_r)
   AC_C_BIGENDIAN
   case "$target_os" in
-         lin*)
-           CFLAGS="$CFLAGS -DUNIV_LINUX";;
-         hpux10*)
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
-         hp*)
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
-         aix*)
-           CFLAGS="$CFLAGS -DUNIV_AIX";;
-         irix*)
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
-         osf*)
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
-	 *solaris*|*SunOS*)
-           CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
-         sysv5uw7*)
-           # Problem when linking on SCO
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
-         openbsd*)
-           CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
+	lin*)
+		CFLAGS="$CFLAGS -DUNIV_LINUX";;
+	hpux10*)
+		CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX -DUNIV_HPUX10";;
+	hp*)
+		CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE -DUNIV_HPUX";;
+	aix*)
+		CFLAGS="$CFLAGS -DUNIV_AIX";;
+	irix*|osf*|sysv5uw7*|openbsd*)
+		CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
+	*solaris*|*SunOS*)
+		CFLAGS="$CFLAGS -DUNIV_SOLARIS";;
   esac
+  INNODB_DYNAMIC_CFLAGS="-DMYSQL_DYNAMIC_PLUGIN"
+  case "$target_cpu" in
+	x86_64)
+		# The AMD64 ABI forbids absolute addresses in shared libraries
+		;;
+	*86)
+		# Use absolute addresses on IA-32
+		INNODB_DYNAMIC_CFLAGS="$INNODB_DYNAMIC_CFLAGS -prefer-non-pic"
+		;;
+  esac
+  AC_SUBST(INNODB_DYNAMIC_CFLAGS)
   ])
 
+# vim: set ft=config:

=== modified file 'storage/innobase/row/row0mysql.c'
--- a/storage/innobase/row/row0mysql.c	2008-05-14 08:45:32 +0000
+++ b/storage/innobase/row/row0mysql.c	2008-12-14 20:59:50 +0000
@@ -661,7 +661,14 @@ row_create_prebuilt(
 
 	prebuilt->old_vers_heap = NULL;
 
-	prebuilt->last_value = 0;
+	prebuilt->autoinc_error = 0;
+	prebuilt->autoinc_offset = 0;
+
+	/* Default to 1, we will set the actual value later in 
+	ha_innobase::get_auto_increment(). */
+	prebuilt->autoinc_increment = 1;
+
+	prebuilt->autoinc_last_value = 0;
 
 	return(prebuilt);
 }
@@ -1963,6 +1970,7 @@ row_create_index_for_mysql(
 	ulint		err;
 	ulint		i, j;
 	ulint		len;
+	char*		table_name;
 
 #ifdef UNIV_SYNC_DEBUG
 	ut_ad(rw_lock_own(&dict_operation_lock, RW_LOCK_EX));
@@ -1972,6 +1980,11 @@ row_create_index_for_mysql(
 
 	trx->op_info = "creating index";
 
+	/* Copy the table name because we may want to drop the
+	table later, after the index object is freed (inside
+	que_run_threads()) and thus index->table_name is not available. */
+	table_name = mem_strdup(index->table_name);
+
 	trx_start_if_not_started(trx);
 
 	/* Check that the same column does not appear twice in the index.
@@ -2044,13 +2057,15 @@ error_handling:
 
 		trx_general_rollback_for_mysql(trx, FALSE, NULL);
 
-		row_drop_table_for_mysql(index->table_name, trx, FALSE);
+		row_drop_table_for_mysql(table_name, trx, FALSE);
 
 		trx->error_state = DB_SUCCESS;
 	}
 
 	trx->op_info = "";
 
+	mem_free(table_name);
+
 	return((int) err);
 }
 
@@ -2443,8 +2458,8 @@ row_discard_tablespace_for_mysql(
 
 	new_id = dict_hdr_get_new_id(DICT_HDR_TABLE_ID);
 
-	/* Remove any locks there are on the table or its records */
-	lock_reset_all_on_table(table);
+	/* Remove all locks except the table-level S and X locks. */
+	lock_remove_all_on_table(table, FALSE);
 
 	info = pars_info_create();
 
@@ -2779,9 +2794,8 @@ row_truncate_table_for_mysql(
 		goto funct_exit;
 	}
 
-	/* Remove any locks there are on the table or its records */
-
-	lock_reset_all_on_table(table);
+	/* Remove all locks except the table-level S and X locks. */
+	lock_remove_all_on_table(table, FALSE);
 
 	trx->table_id = table->id;
 
@@ -2896,7 +2910,7 @@ next_rec:
 	/* MySQL calls ha_innobase::reset_auto_increment() which does
 	the same thing. */
 	dict_table_autoinc_lock(table);
-	dict_table_autoinc_initialize(table, 0);
+	dict_table_autoinc_initialize(table, 1);
 	dict_table_autoinc_unlock(table);
 	dict_update_statistics(table);
 
@@ -3131,9 +3145,8 @@ check_next_foreign:
 		goto funct_exit;
 	}
 
-	/* Remove any locks there are on the table or its records */
-
-	lock_reset_all_on_table(table);
+	/* Remove all locks there are on the table or its records */
+	lock_remove_all_on_table(table, TRUE);
 
 	trx->dict_operation = TRUE;
 	trx->table_id = table->id;
@@ -3429,8 +3442,6 @@ loop:
 
 		err = row_drop_table_for_mysql(table_name, trx, TRUE);
 
-		mem_free(table_name);
-
 		if (err != DB_SUCCESS) {
 			fputs("InnoDB: DROP DATABASE ", stderr);
 			ut_print_name(stderr, trx, TRUE, name);
@@ -3438,8 +3449,11 @@ loop:
 				(ulint) err);
 			ut_print_name(stderr, trx, TRUE, table_name);
 			putc('\n', stderr);
+			mem_free(table_name);
 			break;
 		}
+
+		mem_free(table_name);
 	}
 
 	if (err == DB_SUCCESS) {

=== modified file 'storage/innobase/row/row0sel.c'
--- a/storage/innobase/row/row0sel.c	2008-08-20 00:37:41 +0000
+++ b/storage/innobase/row/row0sel.c	2008-12-14 19:28:19 +0000
@@ -32,6 +32,7 @@ Created 12/19/1997 Heikki Tuuri
 #include "row0mysql.h"
 #include "read0read.h"
 #include "buf0lru.h"
+#include "ha_prototypes.h"
 
 /* Maximum number of rows to prefetch; MySQL interface has another parameter */
 #define SEL_MAX_N_PREFETCH	16
@@ -3577,20 +3578,12 @@ shortcut_fails_too_big_rec:
 
 	if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 	    && prebuilt->select_lock_type != LOCK_NONE
-	    && trx->mysql_query_str != NULL
-	    && *trx->mysql_query_str != NULL
-	    && trx->mysql_thd != NULL) {
-
-		/* Scan the MySQL query string; check if SELECT is the first
-		word there */
-
-		if (dict_str_starts_with_keyword(
-			    trx->mysql_thd, *trx->mysql_query_str, "SELECT")) {
-			/* It is a plain locking SELECT and the isolation
-			level is low: do not lock gaps */
+	    && trx->mysql_thd != NULL
+	    && thd_is_select(trx->mysql_thd)) {
+		/* It is a plain locking SELECT and the isolation
+		level is low: do not lock gaps */
 
-			set_also_gap_locks = FALSE;
-		}
+		set_also_gap_locks = FALSE;
 	}
 
 	/* Note that if the search mode was GE or G, then the cursor

=== modified file 'storage/innobase/srv/srv0srv.c'
--- a/storage/innobase/srv/srv0srv.c	2008-08-20 00:37:41 +0000
+++ b/storage/innobase/srv/srv0srv.c	2008-12-14 19:18:59 +0000
@@ -1453,8 +1453,11 @@ srv_suspend_mysql_thread(
 		srv_n_lock_wait_count++;
 		srv_n_lock_wait_current_count++;
 
-		ut_usectime(&sec, &ms);
-		start_time = (ib_longlong)sec * 1000000 + ms;
+		if (ut_usectime(&sec, &ms) == -1) {
+			start_time = -1;
+		} else {
+			start_time = (ib_longlong)sec * 1000000 + ms;
+		}
 	}
 	/* Wake the lock timeout monitor thread, if it is suspended */
 
@@ -1508,14 +1511,20 @@ srv_suspend_mysql_thread(
 	wait_time = ut_difftime(ut_time(), slot->suspend_time);
 
 	if (thr->lock_state == QUE_THR_LOCK_ROW) {
-		ut_usectime(&sec, &ms);
-		finish_time = (ib_longlong)sec * 1000000 + ms;
+		if (ut_usectime(&sec, &ms) == -1) {
+			finish_time = -1;
+		} else {
+			finish_time = (ib_longlong)sec * 1000000 + ms;
+		}
 
 		diff_time = (ulint) (finish_time - start_time);
 
 		srv_n_lock_wait_current_count--;
 		srv_n_lock_wait_time = srv_n_lock_wait_time + diff_time;
-		if (diff_time > srv_n_lock_max_wait_time) {
+		if (diff_time > srv_n_lock_max_wait_time &&
+		    /* only update the variable if we successfully
+		    retrieved the start and finish times. See Bug#36819. */
+		    start_time != -1 && finish_time != -1) {
 			srv_n_lock_max_wait_time = diff_time;
 		}
 	}

=== modified file 'storage/innobase/srv/srv0start.c'
--- a/storage/innobase/srv/srv0start.c	2008-03-27 14:13:10 +0000
+++ b/storage/innobase/srv/srv0start.c	2008-12-14 19:21:24 +0000
@@ -202,13 +202,13 @@ srv_parse_data_file_paths_and_sizes(
 
 		str = srv_parse_megabytes(str, &size);
 
-		if (0 == memcmp(str, ":autoextend",
-				(sizeof ":autoextend") - 1)) {
+		if (0 == strncmp(str, ":autoextend",
+				 (sizeof ":autoextend") - 1)) {
 
 			str += (sizeof ":autoextend") - 1;
 
-			if (0 == memcmp(str, ":max:",
-					(sizeof ":max:") - 1)) {
+			if (0 == strncmp(str, ":max:",
+					 (sizeof ":max:") - 1)) {
 
 				str += (sizeof ":max:") - 1;
 
@@ -290,14 +290,15 @@ srv_parse_data_file_paths_and_sizes(
 		(*data_file_names)[i] = path;
 		(*data_file_sizes)[i] = size;
 
-		if (0 == memcmp(str, ":autoextend",
-				(sizeof ":autoextend") - 1)) {
+		if (0 == strncmp(str, ":autoextend",
+				 (sizeof ":autoextend") - 1)) {
 
 			*is_auto_extending = TRUE;
 
 			str += (sizeof ":autoextend") - 1;
 
-			if (0 == memcmp(str, ":max:", (sizeof ":max:") - 1)) {
+			if (0 == strncmp(str, ":max:",
+					 (sizeof ":max:") - 1)) {
 
 				str += (sizeof ":max:") - 1;
 

=== modified file 'storage/innobase/ut/ut0ut.c'
--- a/storage/innobase/ut/ut0ut.c	2007-11-06 22:42:58 +0000
+++ b/storage/innobase/ut/ut0ut.c	2008-12-14 19:18:59 +0000
@@ -112,19 +112,45 @@ ut_time(void)
 }
 
 /**************************************************************
-Returns system time. */
+Returns system time.
+Upon successful completion, the value 0 is returned; otherwise the
+value -1 is returned and the global variable errno is set to indicate the
+error. */
 
-void
+int
 ut_usectime(
 /*========*/
+			/* out: 0 on success, -1 otherwise */
 	ulint*	sec,	/* out: seconds since the Epoch */
 	ulint*	ms)	/* out: microseconds since the Epoch+*sec */
 {
 	struct timeval	tv;
+	int		ret;
+	int		errno_gettimeofday;
+	int		i;
+
+	for (i = 0; i < 10; i++) {
+
+		ret = ut_gettimeofday(&tv, NULL);
+
+		if (ret == -1) {
+			errno_gettimeofday = errno;
+			ut_print_timestamp(stderr);
+			fprintf(stderr, "  InnoDB: gettimeofday(): %s\n",
+				strerror(errno_gettimeofday));
+			os_thread_sleep(100000);  /* 0.1 sec */
+			errno = errno_gettimeofday;
+		} else {
+			break;
+		}
+	}
+
+	if (ret != -1) {
+		*sec = (ulint) tv.tv_sec;
+		*ms  = (ulint) tv.tv_usec;
+	}
 
-	ut_gettimeofday(&tv, NULL);
-	*sec = (ulint) tv.tv_sec;
-	*ms  = (ulint) tv.tv_usec;
+	return(ret);
 }
 
 /**************************************************************

Thread
bzr commit into mysql-5.1-bugteam branch (davi:2743) Davi Arnaut19 Dec