List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:May 13 2012 1:58am
Subject:bzr push into mysql-trunk branch (mattias.jonsson:3800 to 3801) WL#4443
View as plain text  
 3801 Mattias Jonsson	2012-05-13
      WL#4443:
      Changes for the second 1/3 of dlenevs review comments chunk 2.
      
      Test fixes in partition_locking (including in moving out tests to
      partition_default_functions.inc)
      
      Removed duplicate warnings from insert pruning.
      
      warns if PARTITION () clause is used on temporary tables.
      
      Fixed default functions in insert pruning.
      
      + some cleanups

    added:
      mysql-test/include/partition_default_functions.inc
    modified:
      include/my_time.h
      mysql-test/r/partition_datatype.result
      mysql-test/r/partition_explicit_prune.result
      mysql-test/r/partition_locking.result
      mysql-test/t/partition_explicit_prune.test
      mysql-test/t/partition_locking.test
      sql/ha_partition.cc
      sql/ha_partition.h
      sql/handler.cc
      sql/log_event.cc
      sql/opt_range.cc
      sql/opt_range.h
      sql/partition_info.cc
      sql/partition_info.h
      sql/share/errmsg-utf8.txt
      sql/sp.cc
      sql/sql_base.cc
      sql/sql_base.h
      sql/sql_class.cc
      sql/sql_delete.cc
      sql/sql_handler.cc
      sql/sql_insert.cc
      sql/sql_join_buffer.cc
      sql/sql_lex.cc
      sql/sql_lex.h
      sql/sql_optimizer.cc
      sql/sql_partition.h
      sql/sql_partition_admin.cc
      sql/sql_resolver.cc
      sql/sql_select.cc
      sql/sql_select.h
      sql/sql_show.cc
      sql/sql_tmp_table.cc
      sql/sql_union.cc
      sql/sql_update.cc
 3800 Mattias Jonsson	2012-05-09
      WL#4443:
      Changes for the first 1/3 of dlenevs review comments chunk 2.
      
      Mostly test/result changes to be more clear about what
      is tested.
      
      Fix for bitmap_get_next_set on big-endian machines.
      
      Minor cleanups.

    removed:
      mysql-test/r/grant_cache_ps_prot.result
      mysql-test/t/grant_cache_ps_prot.test
    renamed:
      mysql-test/r/grant_cache_no_prot.result => mysql-test/r/grant_cache.result
      mysql-test/t/grant_cache_no_prot.test => mysql-test/t/grant_cache.test
    modified:
      mysql-test/include/commit.inc
      mysql-test/include/grant_cache.inc
      mysql-test/include/handler.inc
      mysql-test/r/commit_1innodb.result
      mysql-test/r/handler_innodb.result
      mysql-test/r/handler_myisam.result
      mysql-test/r/partition_explicit_prune.result
      mysql-test/r/partition_locking.result
      mysql-test/r/partition_pruning.result
      mysql-test/t/partition_explicit_prune.test
      mysql-test/t/partition_locking.test
      mysql-test/t/partition_pruning.test
      mysys/my_bitmap.c
      sql/ha_partition.cc
      sql/sql_base.cc
      sql/sql_delete.cc
      sql/sql_insert.cc
      sql/sql_partition_admin.cc
      sql/sql_select.cc
      mysql-test/t/grant_cache.test
=== modified file 'include/my_time.h'
--- a/include/my_time.h	revid:mattias.jonsson@stripped51124-m3yw998dio568l9u
+++ b/include/my_time.h	revid:mattias.jonsson@stripped
@@ -180,8 +180,8 @@ void my_init_time(void);
     estimate.
 
   RETURN VALUES
-    FALSE   The value seems sane
-    TRUE    The MYSQL_TIME value is definitely out of range
+    TRUE    The value seems sane
+    FALSE   The MYSQL_TIME value is definitely out of range
 */
 
 static inline my_bool validate_timestamp_range(const MYSQL_TIME *t)

=== added file 'mysql-test/include/partition_default_functions.inc'
--- a/mysql-test/include/partition_default_functions.inc	1970-01-01 00:00:00 +0000
+++ b/mysql-test/include/partition_default_functions.inc	revid:mattias.jonsson@stripped
@@ -0,0 +1,109 @@
+# Help file for avoid duplicated tests of different DEFAULT functions
+#
+# Needs $get_handler_status_counts defined
+# normally as:
+# let $get_handler_status_counts=
+# SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+# WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+#
+# And a table t3 where a is a DATETIME/DATE/TIME/TIMESTAMP column
+# and b is a char/varchar() column.
+
+if ($null_as_now)
+{
+FLUSH STATUS;
+SET TIMESTAMP = 1234567890;
+INSERT INTO t3 (a) VALUES (NULL);
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+}
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+eval $get_handler_status_counts;
+--echo # 6 locks (1 table, 2 partition lock/unlock)
+--echo # 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+eval $get_handler_status_counts;
+if ($default_update)
+{
+--echo # 8 locks (1 table, 3 partition lock/unlock) 
+--echo # No pruning due to DEFAULT function on partitioning column
+--echo # 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+--echo # 1 delete + 1 write due to moved to different partition
+}
+if (!$default_update)
+{
+--echo # 4 locks (1 table, 1 partition lock/unlock) 
+--echo # 1 read_key + 1 update (same partition)
+--echo # 1 (failed) write
+}
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+eval $get_handler_status_counts;
+--echo # 8 locks (1 table, 3 partition lock/unlock)
+--echo # No pruning due to updating partitioning field.
+--echo # 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+--echo # 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+eval $get_handler_status_counts;
+if ($default_update)
+{
+--echo # 8 locks (1 table, 3 partition lock/unlock) 
+--echo # No pruning due to DEFAULT function on partitioning column
+--echo # 2 read_key + 1 read_rnd (1 read_key due to index lookup,
+--echo # 1 read_rnd + 1 read_key due to positioning before update)
+--echo # 1 delete + 1 write due to moved to different partition
+--echo # + 1 (failed) write
+}
+if (!$default_update)
+{
+--echo # 4 locks (1 table, 1 partition lock/unlock) 
+--echo # 1 read_key + 1 update (same partition)
+--echo # 1 (failed) write
+}
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+--echo # 1 read_key + 1 update + 1 failed write
+
+--echo #
+--echo # Test of replace of default PK (delete might be needed first)
+--echo #
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+eval $get_handler_status_counts;
+--echo # 4 locks (1 table, 1 partition lock/unlock)
+--echo # 1 read_key + 1 update + 1 failed write
+--sorted_result
+SELECT * FROM t3;

=== modified file 'mysql-test/r/partition_datatype.result'
--- a/mysql-test/r/partition_datatype.result	revid:mattias.jonsson@oracle.com-20120509151124-m3yw998dio568l9u
+++ b/mysql-test/r/partition_datatype.result	revid:mattias.jonsson@oracle.com-20120513015716-wmkf6s9fwt6zan6f
@@ -680,7 +680,6 @@ id	select_type	table	partitions	type	pos
 DELETE FROM t2 WHERE a = 0;
 INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
 Warnings:
-Warning	1292	Incorrect datetime value: '1970-01-01 00:00:00' for column 'a' at row 1
 Warning	1264	Out of range value for column 'a' at row 1
 SELECT COUNT(*) FROM t2;
 COUNT(*)
@@ -763,7 +762,6 @@ NULL	UTC
 # Test start range changes
 INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'UTC');
 Warnings:
-Warning	1292	Incorrect datetime value: '1970-01-01 00:00:00' for column 'a' at row 1
 Warning	1264	Out of range value for column 'a' at row 1
 SELECT COUNT(*) FROM t2;
 COUNT(*)
@@ -1157,7 +1155,6 @@ id	select_type	table	partitions	type	pos
 DELETE FROM t2 WHERE a = 0;
 INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
 Warnings:
-Warning	1292	Incorrect datetime value: '1970-01-01 00:00:00' for column 'a' at row 1
 Warning	1264	Out of range value for column 'a' at row 1
 SELECT COUNT(*) FROM t2;
 COUNT(*)
@@ -1242,7 +1239,6 @@ NULL	UTC
 # Test start range changes
 INSERT INTO t2 VALUES ('1970-01-01 00:00:00', 'Moscow');
 Warnings:
-Warning	1292	Incorrect datetime value: '1970-01-01 00:00:00' for column 'a' at row 1
 Warning	1264	Out of range value for column 'a' at row 1
 SELECT COUNT(*) FROM t2;
 COUNT(*)

=== modified file 'mysql-test/r/partition_explicit_prune.result'
--- a/mysql-test/r/partition_explicit_prune.result	revid:mattias.jonsson@stripped1124-m3yw998dio568l9u
+++ b/mysql-test/r/partition_explicit_prune.result	revid:mattias.jonsson@stripped015716-wmkf6s9fwt6zan6f
@@ -1916,4 +1916,11 @@ a	b
 SELECT * FROM t1 PARTITION (p2);
 a	b
 DROP TABLE t1;
+#
+# Test explicit partition selection on a non partitioned temp table
+#
+CREATE TEMPORARY TABLE t1 (a INT);
+SELECT * FROM t1 PARTITION(pNonexisting);
+ERROR HY000: PARTITION () clause on non partitioned table
+DROP TEMPORARY TABLE t1;
 SET @@default_storage_engine = @old_default_storage_engine;

=== modified file 'mysql-test/r/partition_locking.result'
--- a/mysql-test/r/partition_locking.result	revid:mattias.jonsson@strippedl9u
+++ b/mysql-test/r/partition_locking.result	revid:mattias.jonsson@stripped
@@ -11,7 +11,8 @@ ENGINE = InnoDB
 PARTITION BY HASH (a) PARTITIONS 13;
 #
 #
-# Test insert
+# Test how INSERT prune locks
+# First test, no defaults
 #
 FLUSH STATUS;
 INSERT INTO t1 VALUES (1, 'First row, p1');
@@ -56,6 +57,9 @@ HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	21
 # 4 locks (table + 1 partition lock/unlock)
 # 1 commit
+#
+# INSERT with auto increment, lock pruning
+#
 FLUSH STATUS;
 INSERT INTO t2 VALUES (NULL, 'First auto-inc row');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -79,7 +83,7 @@ HANDLER_WRITE	18
 # 28 locks (table + 13 partition lock/unlock)
 # 1 commit
 #
-# Test of pruning with secondary column auto_inc
+# Test of pruning with secondary column auto_inc INSERT
 #
 CREATE TABLE t3 (a INT, b INT AUTO_INCREMENT, PRIMARY KEY (a, b))
 ENGINE = MyISAM
@@ -137,7 +141,7 @@ a	b
 1	3
 DROP TABLE t3;
 #
-# More INSERT pruning tests
+# Test handling of INSERT INTO <table> VALUES (<all fields specified>)
 #
 CREATE TABLE t3 (a INT, b CHAR(10)) PARTITION BY HASH (a) PARTITIONS 2;
 FLUSH STATUS;
@@ -230,6 +234,10 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
+#
+# Test handling of
+# INSERT INTO <table> VALUES (<not all fields specified>)
+#
 FLUSH STATUS;
 INSERT INTO t3 (a) VALUES (1);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -341,6 +349,10 @@ SUBPARTITIONS 4
 PARTITION `p0-9` VALUES LESS THAN (9, MAXVALUE),
 PARTITION p10 VALUES LESS THAN (10, MAXVALUE),
 PARTITION `p11-100` VALUES LESS THAN (99, MAXVALUE));
+#
+# Test INSERT with
+# empty field specifier list and empty value list
+#
 FLUSH STATUS;
 INSERT INTO t3 () VALUES ();
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -350,6 +362,11 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
+#
+# Test INSERT with
+# no field specifier list and full value list, including DEFAULT
+# specifier
+#
 FLUSH STATUS;
 INSERT INTO t3 VALUES (-1, "ZZZzzzz", "yyyYYY", -1, DEFAULT);
 Warnings:
@@ -361,6 +378,10 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
+#
+# Test INSERT with
+# empty field specifier list and full value list, including NULL
+#
 FLUSH STATUS;
 INSERT INTO t3 () VALUES (0, "", "", 0, NULL);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -370,6 +391,9 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
+#
+# Test INSERT with field specifier list for only some fields
+#
 FLUSH STATUS;
 INSERT INTO t3 (a) VALUES (1);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -454,6 +478,9 @@ HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
 FLUSH STATUS;
+#
+# Test INSERT with full field specifier list and full value list
+#
 INSERT INTO t3 (a, b, c, d) VALUES (1, "Full part", "Full subpart", 1);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -462,6 +489,10 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
+#
+# Test INSERT with no field specifier list and empty value list
+# (need to delete previous inserted default row first...)
+#
 DELETE FROM t3 WHERE a = 10 AND b = 'Default' AND c = 'Default' AND D = 9;
 FLUSH STATUS;
 INSERT INTO t3 VALUES ();
@@ -472,6 +503,9 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 subpartition lock/unlock)
+#
+# Verifing result
+#
 SELECT * FROM t3;
 a	b	c	d	e
 -1	ZZZzzzz	yyyYYY	0	Default-filler.filler.filler.
@@ -526,6 +560,10 @@ HANDLER_EXTERNAL_LOCK	17
 HANDLER_WRITE	17
 # 17 locks (1 table, 16 partitions lock)
 # No further locks/unlocks until UNLOCK TABLES.
+#
+# Test INSERT with no field specifier list and empty value list
+# (need to delete previous inserted default row first...)
+#
 DELETE FROM t3 WHERE a = 10 AND b = 'Default' AND c = 'Default' AND D = 9;
 FLUSH STATUS;
 INSERT INTO t3 VALUES ();
@@ -535,6 +573,10 @@ VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
 HANDLER_WRITE	18
 FLUSH STATUS;
+#
+# Test INSERT with field specifier list for only some fields
+# (need to delete previous inserted default row first...)
+#
 DELETE FROM t3
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -553,6 +595,9 @@ VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
 HANDLER_WRITE	18
 FLUSH STATUS;
+#
+# Test UPDATE of non PK field in default row
+#
 UPDATE t3
 SET e = CONCAT(e, ", updated")
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
@@ -565,6 +610,9 @@ HANDLER_READ_NEXT	1
 HANDLER_UPDATE	1
 HANDLER_WRITE	17
 FLUSH STATUS;
+#
+# Test UPDATE of PK field + non PK field in default row
+#
 UPDATE t3
 SET a = DEFAULT, b = "Not DEFAULT!", e = CONCAT(e, ", updated2")
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
@@ -578,6 +626,9 @@ HANDLER_READ_RND	1
 HANDLER_UPDATE	1
 HANDLER_WRITE	17
 FLUSH STATUS;
+#
+# Test REPLACE of default row (INSERT, since not duplicate)
+#
 REPLACE INTO t3 (e) VALUES ("New default row");
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -607,6 +658,9 @@ HANDLER_COMMIT	1
 HANDLER_READ_KEY	1
 HANDLER_WRITE	17
 FLUSH STATUS;
+#
+# Test REPLACE of default row (REPLACE, since duplicate exists)
+#
 REPLACE INTO t3 (e) VALUES ("Newest default row");
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -615,17 +669,20 @@ HANDLER_COMMIT	1
 HANDLER_READ_KEY	1
 HANDLER_UPDATE	1
 HANDLER_WRITE	18
+#
+# Test SELECT with explicit partition selection
+#
 FLUSH STATUS;
 SELECT * FROM t3 PARTITION (p10);
 a	b	c	d	e
-10	Half part	Full subpart	1	Default-filler.filler.filler.
 10	Default	Default	1	Default-filler.filler.filler.
+10	Default	Default	2	Default-filler.filler.filler.
 10	Default	Default	9	Newest default row
+10	Default	Subpart expr fulfilled	1	Default-filler.filler.filler.
 10	Full part, half subpart	Default	1	Default-filler.filler.filler.
+10	Half part	Full subpart	1	Default-filler.filler.filler.
 10	Not DEFAULT!	Default	9	All default!, updated, updated2
 10	Part expr fulfilled	Default	9	Default-filler.filler.filler.
-10	Default	Default	2	Default-filler.filler.filler.
-10	Default	Subpart expr fulfilled	1	Default-filler.filler.filler.
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -653,19 +710,27 @@ HANDLER_WRITE	17
 # 17 locks (1 table, 16 partitions unlock)
 DROP TABLE t3;
 #
-# Test insert with timestamp column
+# End of LOCK TABLE test.
+#
+#
+# Test INSERT with timestamp column NO default function
 #
+SELECT UNIX_TIMESTAMP('2011-01-01 00:00:00') as time_t,
+UNIX_TIMESTAMP('2011-01-01 00:00:00') % 3 as part,
+1234567890 % 3 as part2;
+time_t	part	part2
+1293829200	0	0
 CREATE TABLE t3
 (a timestamp DEFAULT 0,
 b char(10),
-PRIMARY KEY (a, b))
+PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
 Table	Create Table
 t3	CREATE TABLE `t3` (
   `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
-  `b` char(10) NOT NULL DEFAULT '',
-  PRIMARY KEY (`a`,`b`)
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 /*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
 PARTITIONS 3 */
@@ -680,6 +745,7 @@ HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
 INSERT INTO t3 VALUES ();
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -715,9 +781,89 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	6
 HANDLER_WRITE	19
 # 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
 FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
 INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -727,26 +873,31 @@ HANDLER_READ_KEY	1
 HANDLER_UPDATE	1
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
 SELECT * FROM t3;
 a	b
-0000-00-00 00:00:00	
-2009-02-14 02:31:30	
-2011-01-01 00:00:00	, DUP_KEY
-2011-01-01 00:00:03	
-2011-01-01 00:00:01	
-2011-01-01 00:00:02	
+0000-00-00 00:00:00	Replace4
+2009-02-14 02:31:30	NULL
+2011-01-01 00:00:00	DUP_KEY
+2011-01-01 00:00:02	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
 DROP TABLE t3;
+#
+# Test INSERT with timestamp column DEFAULT INSERT + UPDATE
+#
 CREATE TABLE t3
 (a timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 b char(10),
-PRIMARY KEY (a, b))
+PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
 Table	Create Table
 t3	CREATE TABLE `t3` (
   `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-  `b` char(10) NOT NULL DEFAULT '',
-  PRIMARY KEY (`a`,`b`)
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 /*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
 PARTITIONS 3 */
@@ -760,7 +911,16 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
-# TODO Fix the bug in INSERT INTO t3 VALUES () and enable the test
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
 INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
@@ -788,10 +948,26 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	6
 HANDLER_WRITE	19
 # 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
 FLUSH STATUS;
 SET TIMESTAMP = 1234567892;
 INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -801,29 +977,105 @@ HANDLER_EXTERNAL_LOCK	8
 HANDLER_READ_KEY	1
 HANDLER_WRITE	19
 # 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	2
+HANDLER_READ_RND	1
+HANDLER_WRITE	18
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 2 read_key + 1 read_rnd (1 read_key due to index lookup,
+# 1 read_rnd + 1 read_key due to positioning before update)
+# 1 delete + 1 write due to moved to different partition
+# + 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
 SELECT * FROM t3;
 a	b
-2009-02-14 02:31:30	
-2011-01-01 00:00:03	
-2011-01-01 00:00:01	
-2009-02-14 02:31:32	, DUP_KEY
-2011-01-01 00:00:02	
+2009-02-14 02:31:30	NULL
+2009-02-14 02:31:31	NULL
+2009-02-14 02:31:32	DUP_KEY
+2009-02-14 02:31:33	Updated
+2009-02-14 02:31:34	Replace4
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
 DROP TABLE t3;
+#
+# Test INSERT with timestamp column DEFAULT UPDATE
+#
 CREATE TABLE t3
 (a timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
 b char(10),
-PRIMARY KEY (a, b))
+PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
 Table	Create Table
 t3	CREATE TABLE `t3` (
   `a` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
-  `b` char(10) NOT NULL DEFAULT '',
-  PRIMARY KEY (`a`,`b`)
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
 ) ENGINE=InnoDB DEFAULT CHARSET=latin1
 /*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
 PARTITIONS 3 */
 FLUSH STATUS;
+SET TIMESTAMP = 1234567890;
 INSERT INTO t3 (a) VALUES (NULL);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -833,6 +1085,16 @@ HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
 INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
@@ -859,43 +1121,58 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	6
 HANDLER_WRITE	19
 # 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
 FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
 INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
-# May change partition, so gives different UPDATE/DELETE/WRITE count
-SHOW STATUS LIKE 'Handler_external_lock';
-Variable_name	Value
-Handler_external_lock	8
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
 # 8 locks (1 table, 3 partition lock/unlock)
-SELECT COUNT(*) FROM t3;
-COUNT(*)
-5
-DROP TABLE t3;
-CREATE TABLE t3
-(a timestamp DEFAULT CURRENT_TIMESTAMP,
-b char(10),
-PRIMARY KEY (a, b))
-PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
-SHOW CREATE TABLE t3;
-Table	Create Table
-t3	CREATE TABLE `t3` (
-  `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
-  `b` char(10) NOT NULL DEFAULT '',
-  PRIMARY KEY (`a`,`b`)
-) ENGINE=InnoDB DEFAULT CHARSET=latin1
-/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
-PARTITIONS 3 */
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
 FLUSH STATUS;
-INSERT INTO t3 (a) VALUES (NULL);
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
-HANDLER_EXTERNAL_LOCK	4
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	2
+HANDLER_READ_RND	1
 HANDLER_WRITE	18
-# 4 locks (1 table, 1 partition lock/unlock)
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 2 read_key + 1 read_rnd (1 read_key due to index lookup,
+# 1 read_rnd + 1 read_key due to positioning before update)
+# 1 delete + 1 write due to moved to different partition
+# + 1 (failed) write
 FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -904,26 +1181,34 @@ HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
 FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
-HANDLER_EXTERNAL_LOCK	6
-HANDLER_WRITE	19
-# 6 locks (1 table, 2 partition lock/unlock)
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -933,26 +1218,837 @@ HANDLER_READ_KEY	1
 HANDLER_UPDATE	1
 HANDLER_WRITE	18
 # 4 locks (1 table, 1 partition lock/unlock)
-SELECT COUNT(*) FROM t3;
-COUNT(*)
-5
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+0000-00-00 00:00:00	Replace4
+2009-02-14 02:31:30	NULL
+2009-02-14 02:31:32	DUP_KEY
+2009-02-14 02:31:33	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
 DROP TABLE t3;
 #
-# Test insert select
+# Test INSERT with timestamp column DEFAULT INSERT
 #
+CREATE TABLE t3
+(a timestamp DEFAULT CURRENT_TIMESTAMP,
+b char(10),
+PRIMARY KEY (a))
+PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `a` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY HASH (UNIX_TIMESTAMP(a))
+PARTITIONS 3 */
 FLUSH STATUS;
-TRUNCATE TABLE t2;
+SET TIMESTAMP = 1234567890;
+INSERT INTO t3 (a) VALUES (NULL);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_COMMIT	1
-HANDLER_EXTERNAL_LOCK	28
-HANDLER_WRITE	17
-# All partitions needs to be locked
-# 28 locks (table + 13 partition lock/unlock)
-# 1 commit
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
 FLUSH STATUS;
-INSERT INTO t2 SELECT a, b FROM t1 WHERE a IN (1,4);
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	6
+HANDLER_WRITE	19
+# 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+2009-02-14 02:31:30	NULL
+2009-02-14 02:31:31	NULL
+2009-02-14 02:31:34	Replace4
+2011-01-01 00:00:00	DUP_KEY
+2011-01-01 00:00:02	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
+DROP TABLE t3;
+#
+# Test INSERT with DATETIME column NO default function
+#
+CREATE TABLE t3
+(a DATETIME DEFAULT 0,
+b char(10),
+PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `a` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY KEY (a)
+PARTITIONS 3 */
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	6
+HANDLER_WRITE	19
+# 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+0000-00-00 00:00:00	Replace4
+2011-01-01 00:00:00	DUP_KEY
+2011-01-01 00:00:02	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
+DROP TABLE t3;
+#
+# Test INSERT with DATETIME column DEFAULT INSERT + UPDATE
+#
+CREATE TABLE t3
+(a DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+b char(10),
+PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `a` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY KEY (a)
+PARTITIONS 3 */
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	6
+HANDLER_WRITE	19
+# 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	2
+HANDLER_READ_RND	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 2 read_key + 1 read_rnd (1 read_key due to index lookup,
+# 1 read_rnd + 1 read_key due to positioning before update)
+# 1 delete + 1 write due to moved to different partition
+# + 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+2009-02-14 02:31:31	NULL
+2009-02-14 02:31:32	DUP_KEY
+2009-02-14 02:31:33	Updated
+2009-02-14 02:31:34	Replace4
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
+DROP TABLE t3;
+#
+# Test INSERT with DATETIME column DEFAULT UPDATE
+#
+CREATE TABLE t3
+(a DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
+b char(10),
+PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `a` datetime NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY KEY (a)
+PARTITIONS 3 */
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	6
+HANDLER_WRITE	19
+# 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	2
+HANDLER_READ_RND	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 8 locks (1 table, 3 partition lock/unlock) 
+# No pruning due to DEFAULT function on partitioning column
+# 2 read_key + 1 read_rnd (1 read_key due to index lookup,
+# 1 read_rnd + 1 read_key due to positioning before update)
+# 1 delete + 1 write due to moved to different partition
+# + 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+0000-00-00 00:00:00	Replace4
+2009-02-14 02:31:32	DUP_KEY
+2009-02-14 02:31:33	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
+DROP TABLE t3;
+#
+# Test INSERT with DATETIME column DEFAULT INSERT
+#
+CREATE TABLE t3
+(a DATETIME DEFAULT CURRENT_TIMESTAMP,
+b char(10),
+PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+Table	Create Table
+t3	CREATE TABLE `t3` (
+  `a` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `b` char(10) DEFAULT NULL,
+  PRIMARY KEY (`a`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+/*!50100 PARTITION BY KEY (a)
+PARTITIONS 3 */
+FLUSH STATUS;
+SET TIMESTAMP = 1234567891;
+INSERT INTO t3 VALUES ();
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	6
+HANDLER_WRITE	19
+# 6 locks (1 table, 2 partition lock/unlock)
+# 2 writes
+FLUSH STATUS;
+SET TIMESTAMP = 1234567892;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
+ON DUPLICATE KEY UPDATE b = "DUP_KEY";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01')
+ON DUPLICATE KEY UPDATE a = '2011-01-01 00:00:05', b = "DUP_KEY2";
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_DELETE	1
+HANDLER_EXTERNAL_LOCK	8
+HANDLER_READ_KEY	1
+HANDLER_WRITE	19
+# 8 locks (1 table, 3 partition lock/unlock)
+# No pruning due to updating partitioning field.
+# 1 read_key + 1 delete + 2 write (1 failed + 1 ok)
+# 1 delete + 1 write due to moved to different partition
+FLUSH STATUS;
+SET TIMESTAMP = 1234567893;
+UPDATE t3 SET b = 'Updated' WHERE a = '2011-01-01 00:00:02';
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	17
+# 4 locks (1 table, 1 partition lock/unlock) 
+# 1 read_key + 1 update (same partition)
+# 1 (failed) write
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace1');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+REPLACE INTO t3 VALUES ('2011-01-01 00:00:04', 'Replace2');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+#
+# Test of replace of default PK (delete might be needed first)
+#
+DELETE FROM t3 WHERE a = 0;
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace3');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
+SET TIMESTAMP = 1234567894;
+REPLACE INTO t3 (b) VALUES ('Replace4');
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	4
+HANDLER_READ_KEY	1
+HANDLER_UPDATE	1
+HANDLER_WRITE	18
+# 4 locks (1 table, 1 partition lock/unlock)
+# 1 read_key + 1 update + 1 failed write
+SELECT * FROM t3;
+a	b
+2009-02-14 02:31:31	NULL
+2009-02-14 02:31:34	Replace4
+2011-01-01 00:00:00	DUP_KEY
+2011-01-01 00:00:02	Updated
+2011-01-01 00:00:03	NULL
+2011-01-01 00:00:04	Replace2
+2011-01-01 00:00:05	DUP_KEY2
+DROP TABLE t3;
+#
+# Test INSERT SELECT
+#
+FLUSH STATUS;
+TRUNCATE TABLE t2;
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	28
+HANDLER_WRITE	17
+# All partitions needs to be locked
+# 28 locks (table + 13 partition lock/unlock)
+# 1 commit
+FLUSH STATUS;
+INSERT INTO t2 SELECT a, b FROM t1 WHERE a IN (1,4);
 SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
 WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
 VARIABLE_NAME	VARIABLE_VALUE
@@ -979,7 +2075,16 @@ HANDLER_COMMIT	1
 HANDLER_EXTERNAL_LOCK	4
 HANDLER_WRITE	17
 # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
 INSERT INTO t2 SELECT a, b FROM t1 WHERE a = 1;
+SELECT * FROM INFORMATION_SCHEMA.SESSION_STATUS
+WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND VARIABLE_VALUE > 0;
+VARIABLE_NAME	VARIABLE_VALUE
+HANDLER_COMMIT	1
+HANDLER_EXTERNAL_LOCK	32
+HANDLER_READ_KEY	1
+HANDLER_WRITE	18
+# 32 locks (2 table + 13 + 1 partitions)
 #
 # Test insert on duplicated key update
 #
@@ -1169,7 +2274,7 @@ HANDLER_WRITE	18
 # 1 update (NOTE: write_record() may cheat instead of delete/insert!)
 # 1 rollback
 #
-# Test select
+# Test SELECT
 #
 FLUSH STATUS;
 SELECT * FROM t1 ORDER BY a;
@@ -1272,7 +2377,7 @@ HANDLER_WRITE	17
 # 13 read_key
 # 5 read_next
 #
-# Test EXPLAIN select
+# Test EXPLAIN SELECT
 #
 FLUSH STATUS;
 EXPLAIN SELECT * FROM t1;
@@ -1388,7 +2493,7 @@ HANDLER_WRITE	17
 # 28 locks (1 table + 13 partition lock/unlock)
 #
 # Test pruning of non static values
-# They will need to lock all partitions, but will allow pruning
+# They will need to lock all partitions, but will allow scan pruning
 # due to a second pruning call in optimize.
 #
 CREATE TABLE t3 (a INT);
@@ -1534,7 +2639,7 @@ id	select_type	table	partitions	type	pos
 DROP TABLE t3;
 DROP TABLE t4;
 #
-# Test select * from (select * from ...)
+# Test derived tables like SELECT * FROM (SELECT * FROM ...)
 #
 FLUSH STATUS;
 SELECT * FROM (SELECT * FROM t1 WHERE a IN (0,2,3,13,26)) t3;
@@ -1581,7 +2686,7 @@ HANDLER_WRITE	27
 # 11 read_next
 # 12 read_rnd_next (tmp table)
 #
-# Test EXPLAIN select * from (select * from ...)
+# Test EXPLAIN SELECT * FROM (SELECT * FROM ...)
 #
 FLUSH STATUS;
 EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a IN (0,2,3,13,26)) t3;
@@ -1634,7 +2739,7 @@ HANDLER_EXTERNAL_LOCK	8
 HANDLER_WRITE	17
 # 8 locks (1 table + 3 partitions lock/unlock)
 #
-# Test select ... UNION select ...
+# Test SELECT ... UNION SELECT ...
 #
 FLUSH STATUS;
 SELECT * FROM t1 UNION SELECT * FROM t2;
@@ -1774,7 +2879,7 @@ HANDLER_READ_RND_NEXT	16
 HANDLER_WRITE	30
 # 12 locks (2 tables, 3 + 1 partitions lock/unlock)
 #
-# Test EXPLAIN select ... UNION select ...
+# Test EXPLAIN SELECT ... UNION SELECT ...
 #
 FLUSH STATUS;
 EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
@@ -1978,7 +3083,7 @@ HANDLER_READ_KEY	1
 HANDLER_WRITE	17
 # 12 locks (2 tables, 3 + 1 partitions lock/unlock)
 #
-# Test update
+# Test UPDATE
 #
 SELECT * FROM t1 ORDER BY a;
 a	b
@@ -2097,7 +3202,7 @@ HANDLER_UPDATE	1
 HANDLER_WRITE	17
 # 32 locks (2 tables, 1 + 13 partitions lock/unlock)
 #
-# Test multi table update
+# Test multi table UPDATE
 #
 SELECT * FROM t1 ORDER BY a;
 a	b
@@ -2312,9 +3417,6 @@ WHERE VARIABLE_NAME LIKE 'HANDLER_%' AND
 VARIABLE_NAME	VARIABLE_VALUE
 HANDLER_WRITE	17
 # 0 locks, impossible where!
-# TODO: See if the reviewer in optimizer notices the difference :)
-# I.e. EXPLAIN DELETE for non partitioned tables does not optimize this
-# as SELECT would!
 EXPLAIN EXTENDED DELETE FROM v1_9_check WHERE a = 8;
 id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
 1	SIMPLE	NULL	NULL	NULL	NULL	NULL	NULL	NULL	NULL	No matching rows after partition pruning
@@ -2646,7 +3748,7 @@ DROP PROCEDURE sp_select_partition;
 DROP PROCEDURE sp_select_range;
 DROP PROCEDURE sp_select_exact;
 #
-# Test EXPLAIN delete
+# Test EXPLAIN DELETE
 #
 SELECT * FROM t1 ORDER BY a;
 a	b
@@ -2769,7 +3871,7 @@ id	select_type	table	partitions	type	pos
 1	PRIMARY	t1	p0	range	PRIMARY,b	PRIMARY	4	NULL	1	Using where
 2	SUBQUERY	t2	p1	const	PRIMARY	PRIMARY	4	const	1	Using index
 #
-# Test multi table delete
+# Test multi table DELETE
 #
 SELECT * FROM t1 ORDER BY a;
 a	b

=== modified file 'mysql-test/t/partition_explicit_prune.test'
--- a/mysql-test/t/partition_explicit_prune.test	revid:mattias.jonsson@stripped998dio568l9u
+++ b/mysql-test/t/partition_explicit_prune.test	revid:mattias.jonsson@stripped6s9fwt6zan6f
@@ -835,4 +835,12 @@ SELECT * FROM t1 PARTITION (p2);
 
 DROP TABLE t1;
 
+--echo #
+--echo # Test explicit partition selection on a non partitioned temp table
+--echo #
+CREATE TEMPORARY TABLE t1 (a INT);
+--error ER_PARTITION_CLAUSE_ON_NONPARTITIONED
+SELECT * FROM t1 PARTITION(pNonexisting);
+DROP TEMPORARY TABLE t1;
+
 SET @@default_storage_engine = @old_default_storage_engine;

=== modified file 'mysql-test/t/partition_locking.test'
--- a/mysql-test/t/partition_locking.test	revid:mattias.jonsson@stripped
+++ b/mysql-test/t/partition_locking.test	revid:mattias.jonsson@oracle.com-20120513015716-wmkf6s9fwt6zan6f
@@ -29,7 +29,8 @@ PARTITION BY HASH (a) PARTITIONS 13;
 
 --echo #
 --echo #
---echo # Test insert
+--echo # Test how INSERT prune locks
+--echo # First test, no defaults
 --echo #
 FLUSH STATUS;
 INSERT INTO t1 VALUES (1, 'First row, p1');
@@ -54,6 +55,10 @@ INSERT INTO t1 VALUES (1 * 13, 'Second r
 eval $get_handler_status_counts;
 --echo # 4 locks (table + 1 partition lock/unlock)
 --echo # 1 commit
+
+--echo #
+--echo # INSERT with auto increment, lock pruning
+--echo #
 FLUSH STATUS;
 INSERT INTO t2 VALUES (NULL, 'First auto-inc row');
 eval $get_handler_status_counts;
@@ -69,7 +74,7 @@ eval $get_handler_status_counts;
 --echo # 1 commit
 
 --echo #
---echo # Test of pruning with secondary column auto_inc
+--echo # Test of pruning with secondary column auto_inc INSERT
 --echo #
 CREATE TABLE t3 (a INT, b INT AUTO_INCREMENT, PRIMARY KEY (a, b))
 ENGINE = MyISAM
@@ -101,7 +106,7 @@ SELECT * FROM t3;
 DROP TABLE t3;
 
 --echo #
---echo # More INSERT pruning tests
+--echo # Test handling of INSERT INTO <table> VALUES (<all fields specified>)
 --echo #
 CREATE TABLE t3 (a INT, b CHAR(10)) PARTITION BY HASH (a) PARTITIONS 2;
 FLUSH STATUS;
@@ -144,6 +149,11 @@ FLUSH STATUS;
 INSERT INTO t3 (a, b) VALUES (0, "Test 0");
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 partition lock/unlock)
+
+--echo #
+--echo # Test handling of
+--echo # INSERT INTO <table> VALUES (<not all fields specified>)
+--echo #
 FLUSH STATUS;
 INSERT INTO t3 (a) VALUES (1);
 eval $get_handler_status_counts;
@@ -190,18 +200,37 @@ SUBPARTITIONS 4
  PARTITION `p0-9` VALUES LESS THAN (9, MAXVALUE),
  PARTITION p10 VALUES LESS THAN (10, MAXVALUE),
  PARTITION `p11-100` VALUES LESS THAN (99, MAXVALUE));
+--echo #
+--echo # Test INSERT with
+--echo # empty field specifier list and empty value list
+--echo #
 FLUSH STATUS;
 INSERT INTO t3 () VALUES ();
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
+
+--echo #
+--echo # Test INSERT with
+--echo # no field specifier list and full value list, including DEFAULT
+--echo # specifier
+--echo #
 FLUSH STATUS;
 INSERT INTO t3 VALUES (-1, "ZZZzzzz", "yyyYYY", -1, DEFAULT);
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
+
+--echo #
+--echo # Test INSERT with
+--echo # empty field specifier list and full value list, including NULL
+--echo #
 FLUSH STATUS;
 INSERT INTO t3 () VALUES (0, "", "", 0, NULL);
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
+
+--echo #
+--echo # Test INSERT with field specifier list for only some fields
+--echo #
 FLUSH STATUS;
 INSERT INTO t3 (a) VALUES (1);
 eval $get_handler_status_counts;
@@ -246,15 +275,27 @@ INSERT INTO t3 (b, c, d) VALUES ("Half p
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
 FLUSH STATUS;
+
+--echo #
+--echo # Test INSERT with full field specifier list and full value list
+--echo #
 INSERT INTO t3 (a, b, c, d) VALUES (1, "Full part", "Full subpart", 1);
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
+
+--echo #
+--echo # Test INSERT with no field specifier list and empty value list
+--echo # (need to delete previous inserted default row first...)
+--echo #
 DELETE FROM t3 WHERE a = 10 AND b = 'Default' AND c = 'Default' AND D = 9;
 FLUSH STATUS;
 INSERT INTO t3 VALUES ();
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 subpartition lock/unlock)
 
+--echo #
+--echo # Verifing result
+--echo #
 --sorted_result
 SELECT * FROM t3;
 --sorted_result
@@ -276,11 +317,21 @@ LOCK TABLES t3 WRITE;
 eval $get_handler_status_counts;
 --echo # 17 locks (1 table, 16 partitions lock)
 --echo # No further locks/unlocks until UNLOCK TABLES.
+
+--echo #
+--echo # Test INSERT with no field specifier list and empty value list
+--echo # (need to delete previous inserted default row first...)
+--echo #
 DELETE FROM t3 WHERE a = 10 AND b = 'Default' AND c = 'Default' AND D = 9;
 FLUSH STATUS;
 INSERT INTO t3 VALUES ();
 eval $get_handler_status_counts;
 FLUSH STATUS;
+
+--echo #
+--echo # Test INSERT with field specifier list for only some fields
+--echo # (need to delete previous inserted default row first...)
+--echo #
 DELETE FROM t3
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
 eval $get_handler_status_counts;
@@ -288,16 +339,28 @@ FLUSH STATUS;
 INSERT INTO t3 (b, d, e) VALUES (DEFAULT, DEFAULT, "All default!");
 eval $get_handler_status_counts;
 FLUSH STATUS;
+
+--echo #
+--echo # Test UPDATE of non PK field in default row
+--echo #
 UPDATE t3
 SET e = CONCAT(e, ", updated")
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
 eval $get_handler_status_counts;
 FLUSH STATUS;
+
+--echo #
+--echo # Test UPDATE of PK field + non PK field in default row
+--echo #
 UPDATE t3
 SET a = DEFAULT, b = "Not DEFAULT!", e = CONCAT(e, ", updated2")
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
 eval $get_handler_status_counts;
 FLUSH STATUS;
+
+--echo #
+--echo # Test REPLACE of default row (INSERT, since not duplicate)
+--echo #
 REPLACE INTO t3 (e) VALUES ("New default row");
 eval $get_handler_status_counts;
 FLUSH STATUS;
@@ -309,9 +372,18 @@ EXPLAIN PARTITIONS SELECT * FROM t3
 WHERE a = 10 AND b = "Default" AND c = "Default" AND d = 9;
 eval $get_handler_status_counts;
 FLUSH STATUS;
+
+--echo #
+--echo # Test REPLACE of default row (REPLACE, since duplicate exists)
+--echo #
 REPLACE INTO t3 (e) VALUES ("Newest default row");
 eval $get_handler_status_counts;
+
+--echo #
+--echo # Test SELECT with explicit partition selection
+--echo #
 FLUSH STATUS;
+--sorted_result
 SELECT * FROM t3 PARTITION (p10);
 eval $get_handler_status_counts;
 FLUSH STATUS;
@@ -323,146 +395,123 @@ UNLOCK TABLES;
 eval $get_handler_status_counts;
 --echo # 17 locks (1 table, 16 partitions unlock)
 DROP TABLE t3;
+--echo #
+--echo # End of LOCK TABLE test.
+--echo #
 
+# Only TIMESTAMP auto converts NULL to NOW().
+--let $null_as_now= 1;
+--let $default_update= 0;
 --echo #
---echo # Test insert with timestamp column
+--echo # Test INSERT with timestamp column NO default function
 --echo #
+SELECT UNIX_TIMESTAMP('2011-01-01 00:00:00') as time_t,
+       UNIX_TIMESTAMP('2011-01-01 00:00:00') % 3 as part,
+       1234567890 % 3 as part2;
 CREATE TABLE t3
 (a timestamp DEFAULT 0,
  b char(10),
- PRIMARY KEY (a, b))
+ PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
-FLUSH STATUS;
-SET TIMESTAMP = 1234567890;
-INSERT INTO t3 (a) VALUES (NULL);
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 VALUES ();
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
-eval $get_handler_status_counts;
---echo # 6 locks (1 table, 2 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-SELECT * FROM t3;
+--source include/partition_default_functions.inc
 DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with timestamp column DEFAULT INSERT + UPDATE
+--echo #
+--let $default_update= 1;
 CREATE TABLE t3
 (a timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  b char(10),
- PRIMARY KEY (a, b))
+ PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
-FLUSH STATUS;
-SET TIMESTAMP = 1234567890;
-INSERT INTO t3 (a) VALUES (NULL);
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
---echo # TODO Fix the bug in INSERT INTO t3 VALUES () and enable the test
-#FLUSH STATUS;
-#SET TIMESTAMP = 1234567891;
-#INSERT INTO t3 VALUES ();
-#eval $get_handler_status_counts;
-#--echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
-eval $get_handler_status_counts;
---echo # 6 locks (1 table, 2 partition lock/unlock)
-FLUSH STATUS;
-SET TIMESTAMP = 1234567892;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
-eval $get_handler_status_counts;
-#--echo # May change partition, so gives different UPDATE/DELETE/WRITE count
-#SHOW STATUS LIKE 'Handler_external_lock';
---echo # 8 locks (1 table, 3 partition lock/unlock)
-SELECT * FROM t3;
+--source include/partition_default_functions.inc
 DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with timestamp column DEFAULT UPDATE
+--echo #
+--let $default_update= 1;
 CREATE TABLE t3
 (a timestamp DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
  b char(10),
- PRIMARY KEY (a, b))
+ PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES (NULL);
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
-eval $get_handler_status_counts;
---echo # 6 locks (1 table, 2 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
-#eval $get_handler_status_counts;
---echo # May change partition, so gives different UPDATE/DELETE/WRITE count
-SHOW STATUS LIKE 'Handler_external_lock';
---echo # 8 locks (1 table, 3 partition lock/unlock)
-SELECT COUNT(*) FROM t3;
+--source include/partition_default_functions.inc
 DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with timestamp column DEFAULT INSERT
+--echo #
+--let $default_update= 0;
 CREATE TABLE t3
 (a timestamp DEFAULT CURRENT_TIMESTAMP,
  b char(10),
- PRIMARY KEY (a, b))
+ PRIMARY KEY (a))
 PARTITION BY HASH (UNIX_TIMESTAMP(a)) PARTITIONS 3;
 SHOW CREATE TABLE t3;
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES (NULL);
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:01');
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:02'), ('2011-01-01 00:00:03');
-eval $get_handler_status_counts;
---echo # 6 locks (1 table, 2 partition lock/unlock)
-FLUSH STATUS;
-INSERT INTO t3 (a) VALUES ('2011-01-01 00:00:00')
-ON DUPLICATE KEY UPDATE b = CONCAT(b, ", DUP_KEY");
-eval $get_handler_status_counts;
---echo # 4 locks (1 table, 1 partition lock/unlock)
-SELECT COUNT(*) FROM t3;
+--source include/partition_default_functions.inc
 DROP TABLE t3;
 
+# Only TIMESTAMP auto converts NULL to NOW().
+--let $null_as_now= 0;
+--let $default_update= 0;
 --echo #
---echo # Test insert select
+--echo # Test INSERT with DATETIME column NO default function
+--echo #
+CREATE TABLE t3
+(a DATETIME DEFAULT 0,
+ b char(10),
+ PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+--source include/partition_default_functions.inc
+DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with DATETIME column DEFAULT INSERT + UPDATE
+--echo #
+--let $default_update= 1;
+CREATE TABLE t3
+(a DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+ b char(10),
+ PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+--source include/partition_default_functions.inc
+DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with DATETIME column DEFAULT UPDATE
+--echo #
+--let $default_update= 1;
+CREATE TABLE t3
+(a DATETIME DEFAULT 0 ON UPDATE CURRENT_TIMESTAMP,
+ b char(10),
+ PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+--source include/partition_default_functions.inc
+DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT with DATETIME column DEFAULT INSERT
+--echo #
+--let $default_update= 0;
+CREATE TABLE t3
+(a DATETIME DEFAULT CURRENT_TIMESTAMP,
+ b char(10),
+ PRIMARY KEY (a))
+PARTITION BY KEY (a) PARTITIONS 3;
+SHOW CREATE TABLE t3;
+--source include/partition_default_functions.inc
+DROP TABLE t3;
+
+--echo #
+--echo # Test INSERT SELECT
 --echo #
 FLUSH STATUS;
 TRUNCATE TABLE t2;
@@ -486,7 +535,10 @@ FLUSH STATUS;
 ALTER TABLE t2 TRUNCATE PARTITION p1;
 eval $get_handler_status_counts;
 --echo # 4 locks (1 table, 1 partition lock/unlock)
+FLUSH STATUS;
 INSERT INTO t2 SELECT a, b FROM t1 WHERE a = 1;
+eval $get_handler_status_counts;
+--echo # 32 locks (2 table + 13 + 1 partitions)
 
 --echo #
 --echo # Test insert on duplicated key update
@@ -611,7 +663,7 @@ eval $get_handler_status_counts;
 --echo # 1 rollback
 
 --echo #
---echo # Test select
+--echo # Test SELECT
 --echo #
 FLUSH STATUS;
 SELECT * FROM t1 ORDER BY a;
@@ -647,7 +699,7 @@ eval $get_handler_status_counts;
 --echo # 5 read_next
 
 --echo #
---echo # Test EXPLAIN select
+--echo # Test EXPLAIN SELECT
 --echo #
 FLUSH STATUS;
 --sorted_result
@@ -698,7 +750,7 @@ eval $get_handler_status_counts;
 
 --echo #
 --echo # Test pruning of non static values
---echo # They will need to lock all partitions, but will allow pruning
+--echo # They will need to lock all partitions, but will allow scan pruning
 --echo # due to a second pruning call in optimize.
 --echo #
 CREATE TABLE t3 (a INT);
@@ -762,7 +814,7 @@ DROP TABLE t4;
 
 
 --echo #
---echo # Test select * from (select * from ...)
+--echo # Test derived tables like SELECT * FROM (SELECT * FROM ...)
 --echo #
 FLUSH STATUS;
 SELECT * FROM (SELECT * FROM t1 WHERE a IN (0,2,3,13,26)) t3;
@@ -781,7 +833,7 @@ eval $get_handler_status_counts;
 
 
 --echo #
---echo # Test EXPLAIN select * from (select * from ...)
+--echo # Test EXPLAIN SELECT * FROM (SELECT * FROM ...)
 --echo #
 FLUSH STATUS;
 EXPLAIN SELECT * FROM (SELECT * FROM t1 WHERE a IN (0,2,3,13,26)) t3;
@@ -803,7 +855,7 @@ eval $get_handler_status_counts;
 
 
 --echo #
---echo # Test select ... UNION select ...
+--echo # Test SELECT ... UNION SELECT ...
 --echo #
 FLUSH STATUS;
 --sorted_result
@@ -837,7 +889,7 @@ eval $get_handler_status_counts;
 
 
 --echo #
---echo # Test EXPLAIN select ... UNION select ...
+--echo # Test EXPLAIN SELECT ... UNION SELECT ...
 --echo #
 FLUSH STATUS;
 EXPLAIN SELECT * FROM t1 UNION SELECT * FROM t2;
@@ -898,7 +950,7 @@ eval $get_handler_status_counts;
 
 
 --echo #
---echo # Test update
+--echo # Test UPDATE
 --echo #
 SELECT * FROM t1 ORDER BY a;
 --echo # This should be prunable (does not change the partitioning key)
@@ -955,7 +1007,7 @@ eval $get_handler_status_counts;
 --echo # 32 locks (2 tables, 1 + 13 partitions lock/unlock)
 
 --echo #
---echo # Test multi table update
+--echo # Test multi table UPDATE
 --echo #
 SELECT * FROM t1 ORDER BY a;
 SELECT * FROM t2 ORDER BY a;
@@ -1067,9 +1119,6 @@ FLUSH STATUS;
 DELETE FROM v1_9_check WHERE a = 8;
 eval $get_handler_status_counts;
 --echo # 0 locks, impossible where!
---echo # TODO: See if the reviewer in optimizer notices the difference :)
---echo # I.e. EXPLAIN DELETE for non partitioned tables does not optimize this
---echo # as SELECT would!
 EXPLAIN EXTENDED DELETE FROM v1_9_check WHERE a = 8;
 EXPLAIN EXTENDED SELECT * FROM v1_9_check WHERE a = 8;
 SELECT * FROM t1 WHERE a = 8;
@@ -1221,7 +1270,7 @@ DROP PROCEDURE sp_select_range;
 DROP PROCEDURE sp_select_exact;
 
 --echo #
---echo # Test EXPLAIN delete
+--echo # Test EXPLAIN DELETE
 --echo #
 SELECT * FROM t1 ORDER BY a;
 FLUSH STATUS;
@@ -1270,7 +1319,7 @@ eval $get_handler_status_counts;
 EXPLAIN PARTITIONS DELETE FROM t1 WHERE a = (SELECT a + 90 FROM t2 WHERE a = 1);
 
 --echo #
---echo # Test multi table delete
+--echo # Test multi table DELETE
 --echo #
 SELECT * FROM t1 ORDER BY a;
 SELECT * FROM t2 ORDER BY a;

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	revid:mattias.jonsson@oracle.com-20120509151124-m3yw998dio568l9u
+++ b/sql/ha_partition.cc	revid:mattias.jonsson@strippedkf6s9fwt6zan6f
@@ -2937,7 +2937,7 @@ void ha_partition::free_partition_bitmap
   /* Initialize the bitmap we use to minimize ha_start_bulk_insert calls */
   bitmap_free(&m_bulk_insert_started);
   bitmap_free(&m_locked_partitions);
-  bitmap_free(&m_started_partitions);
+  bitmap_free(&m_partitions_to_reset);
 }
 
 
@@ -2961,14 +2961,17 @@ bool ha_partition::init_partition_bitmap
   }
   bitmap_clear_all(&m_locked_partitions);
 
-  /* Initialize the bitmap we use to keep track of started partitions */
-  if (bitmap_init(&m_started_partitions, NULL, m_tot_parts, FALSE))
+  /*
+    Initialize the bitmap we use to keep track of partitions which may have
+    something to reset in ha_reset().
+  */
+  if (bitmap_init(&m_partitions_to_reset, NULL, m_tot_parts, FALSE))
   {
     bitmap_free(&m_bulk_insert_started);
     bitmap_free(&m_locked_partitions);
     DBUG_RETURN(true);
   }
-  bitmap_clear_all(&m_started_partitions);
+  bitmap_clear_all(&m_partitions_to_reset);
 
   /* Initialize the bitmap for read/lock_partitions */
   if (!m_is_clone_of)
@@ -2976,9 +2979,7 @@ bool ha_partition::init_partition_bitmap
     DBUG_ASSERT(!m_clone_mem_root);
     if (m_part_info->set_partition_bitmaps(NULL))
     {
-      bitmap_free(&m_bulk_insert_started);
-      bitmap_free(&m_locked_partitions);
-      bitmap_free(&m_started_partitions);
+      free_partition_bitmaps();
       DBUG_RETURN(true);
     }
   }
@@ -3388,7 +3389,7 @@ int ha_partition::external_lock(THD *thd
       Only clear this when a new lock is taken or start_stmt is called,
       leave it as is after unlocking to be able to prune ::reset() calls.
     */
-    DBUG_ASSERT(bitmap_is_clear_all(&m_started_partitions));
+    DBUG_ASSERT(bitmap_is_clear_all(&m_partitions_to_reset));
     used_partitions= &(m_part_info->lock_partitions);
   }
   first_used_partition= bitmap_get_first_set(used_partitions);
@@ -3413,7 +3414,7 @@ int ha_partition::external_lock(THD *thd
   }
   else
   {
-    bitmap_copy(&m_started_partitions, used_partitions);
+    bitmap_copy(&m_partitions_to_reset, used_partitions);
   }
 
   if (m_added_file && m_added_file[0])
@@ -3436,7 +3437,7 @@ err_handler:
     (void) m_file[j]->ha_external_lock(thd, F_UNLCK);
   }
   bitmap_clear_all(&m_locked_partitions);
-  bitmap_clear_all(&m_started_partitions);
+  bitmap_clear_all(&m_partitions_to_reset);
   DBUG_RETURN(error);
 }
 
@@ -3528,20 +3529,24 @@ int ha_partition::start_stmt(THD *thd, t
   /* Assert that read_partitions is included in lock_partitions */
   DBUG_ASSERT(bitmap_is_subset(&m_part_info->read_partitions,
                                &m_part_info->lock_partitions));
-  /* and all partitions are previously locked and bound */
+  /*
+    m_locked_partitions is set in previous external_lock/LOCK TABLES.
+    Current statement's lock requests must not include any partitions
+    not previously locked.
+  */
   DBUG_ASSERT(bitmap_is_subset(&m_part_info->lock_partitions,
                                &m_locked_partitions));
   DBUG_ENTER("ha_partition::start_stmt");
 
   /* Needed to clear all bits from the LOCK TABLES statement. */
-  bitmap_clear_all(&m_started_partitions);
+  bitmap_clear_all(&m_partitions_to_reset);
   for (i= bitmap_get_first_set(&(m_part_info->read_partitions));
        i < m_tot_parts;
        i= bitmap_get_next_set(&m_part_info->read_partitions, i))
   {
-    bitmap_set_bit(&m_started_partitions, i);
     if ((error= m_file[i]->start_stmt(thd, lock_type)))
       break;
+    bitmap_set_bit(&m_partitions_to_reset, i);
   }
   DBUG_RETURN(error);
 }
@@ -3564,6 +3569,10 @@ uint ha_partition::lock_count() const
   DBUG_ENTER("ha_partition::lock_count");
   DBUG_PRINT("info", ("m_num_locks %d total %d", m_num_locks,
              bitmap_bits_set(&m_part_info->lock_partitions) * m_num_locks));
+  /*
+    We choose to return the exact count to avoid allocating unused memory,
+    even if the cpu cost of bitmap_bits_set is linear: O(number of partitions).
+  */
   DBUG_RETURN(bitmap_bits_set(&m_part_info->lock_partitions) * m_num_locks);
 }
 
@@ -5027,12 +5036,15 @@ int ha_partition::index_read_idx_map(uch
       or no matching partitions (start_part > end_part)
     */
     DBUG_ASSERT(m_part_spec.start_part >= m_part_spec.end_part);
+    /* The start part is must be marked as used. */
+    DBUG_ASSERT(m_part_spec.start_part > m_part_spec.end_part ||
+                bitmap_is_set(&(m_part_info->read_partitions),
+                              m_part_spec.start_part));
 
     for (part= m_part_spec.start_part;
          part <= m_part_spec.end_part;
          part= bitmap_get_next_set(&m_part_info->read_partitions, part))
     {
-      DBUG_ASSERT(bitmap_is_set(&(m_part_info->read_partitions), part));
       error= m_file[part]->ha_index_read_idx_map(buf, index, key,
                                                  keypart_map, find_flag);
       if (error != HA_ERR_KEY_NOT_FOUND &&
@@ -6536,14 +6548,16 @@ int ha_partition::reset(void)
     int tmp;
     uint i;
 
-    for (i= bitmap_get_first_set(&m_started_partitions);
+    DBUG_ASSERT(bitmap_is_subset(&m_partitions_to_reset,
+                                 &m_part_info->lock_partitions));
+    for (i= bitmap_get_first_set(&m_partitions_to_reset);
          i < m_tot_parts;
-         i= bitmap_get_next_set(&m_started_partitions, i))
+         i= bitmap_get_next_set(&m_partitions_to_reset, i))
     {
       if ((tmp= m_file[i]->ha_reset()))
         result= tmp;
     }
-    bitmap_clear_all(&m_started_partitions);
+    bitmap_clear_all(&m_partitions_to_reset);
   }
   DBUG_RETURN(result);
 }

=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h	revid:mattias.jonsson@stripped20509151124-m3yw998dio568l9u
+++ b/sql/ha_partition.h	revid:mattias.jonsson@strippedan6f
@@ -255,8 +255,8 @@ private:
   static int compare_number_of_records(ha_partition *me,
                                        const uint32 *a,
                                        const uint32 *b);
-  /** keep track of started partitions */
-  MY_BITMAP m_started_partitions;
+  /** keep track of partitions to call ha_reset */
+  MY_BITMAP m_partitions_to_reset;
 public:
   Partition_share *get_part_share() { return part_share; }
   handler *clone(const char *name, MEM_ROOT *mem_root);

=== modified file 'sql/handler.cc'
--- a/sql/handler.cc	revid:mattias.jonsson@stripped
+++ b/sql/handler.cc	revid:mattias.jonsson@stripped15716-wmkf6s9fwt6zan6f
@@ -6770,19 +6770,6 @@ int handler::ha_external_lock(THD *thd, 
                lock_type == F_UNLCK));
   /* SQL HANDLER call locks/unlock while scanning (RND/INDEX). */
   DBUG_ASSERT(inited == NONE || table->open_by_handler);
-#ifndef DBUG_OFF
-  /*
-    If this handler is cloned, then table->file is not this handler!
-    TODO: have an indicator in the handler to show that it is clone,
-    since table->file may point to ha_partition too...
-  */
-  if (table->key_read != 0 && table->file == this)
-  {
-    DBUG_PRINT("error", ("key_read != 0 (%d)", table->key_read));
-    table->key_read= 0;
-    DBUG_ASSERT(0);
-  }
-#endif
 
   if (MYSQL_HANDLER_RDLOCK_START_ENABLED() ||
       MYSQL_HANDLER_WRLOCK_START_ENABLED() ||

=== modified file 'sql/log_event.cc'
--- a/sql/log_event.cc	revid:mattias.jonsson@stripped0509151124-m3yw998dio568l9u
+++ b/sql/log_event.cc	revid:mattias.jonsson@strippedf
@@ -6286,7 +6286,6 @@ int Load_log_event::do_apply_event(NET* 
         update it inside mysql_load().
       */
       List<Item> tmp_list;
-      thd->lex->query_tables= &tables;
       if (open_temporary_tables(thd, &tables) ||
           mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
                      handle_dup, ignore, net != 0))

=== modified file 'sql/opt_range.cc'
--- a/sql/opt_range.cc	revid:mattias.jonsson@stripped20509151124-m3yw998dio568l9u
+++ b/sql/opt_range.cc	revid:mattias.jonsson@stripped6f
@@ -3035,13 +3035,12 @@ static void dbug_print_singlepoint_range
 #endif
 
 
-/*
+/**
   Perform partition pruning for a given table and condition.
 
   @param      thd            Thread handle
   @param      table          Table to perform partition pruning for
   @param      pprune_cond    Condition to use for partition pruning
-  @param      is_prepare     Is prepare stage
   
   @note This function assumes that lock_partitions are setup when it
   is invoked. The function analyzes the condition, finds partitions that
@@ -3058,8 +3057,7 @@ static void dbug_print_singlepoint_range
     @retval false Success
 */
 
-bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond,
-                      bool is_prepare)
+bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
 {
   partition_info *part_info = table->part_info;
   DBUG_ENTER("prune_partitions");
@@ -3089,7 +3087,7 @@ bool prune_partitions(THD *thd, TABLE *t
     Since it will not be able to prune anything more than the previous call
     from the prepare step.
   */
-  if (part_info->is_const_pruned() &&
+  if (part_info->is_const_item_pruned &&
       !pprune_cond->has_subquery())
     DBUG_RETURN(false);
 
@@ -3223,7 +3221,7 @@ end:
   }
   if (bitmap_is_clear_all(&(prune_param.part_info->read_partitions)))
     table->all_partitions_pruned_away= true;
-  part_info->set_prune_state(is_prepare, pprune_cond->const_item());
+  part_info->is_const_item_pruned= pprune_cond->const_item();
   DBUG_RETURN(false);
 }
 
@@ -6600,7 +6598,6 @@ get_mm_leaf(RANGE_OPT_PARAM *param, Item
 
   if (!value->can_be_evaluated_now())
   {
-    tree= 0;
     field->table->in_use->variables.sql_mode= orig_sql_mode;
     goto end;
   }

=== modified file 'sql/opt_range.h'
--- a/sql/opt_range.h	revid:mattias.jonsson@stripped4-m3yw998dio568l9u
+++ b/sql/opt_range.h	revid:mattias.jonsson@stripped
@@ -984,8 +984,7 @@ SQL_SELECT *make_select(TABLE *head, tab
                         bool allow_null_cond,  int *error);
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
-bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond,
-                      bool is_prepare);
+bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
 void store_key_image_to_rec(Field *field, uchar *ptr, uint len);
 #endif
 

=== modified file 'sql/partition_info.cc'
--- a/sql/partition_info.cc	revid:mattias.jonsson@stripped509151124-m3yw998dio568l9u
+++ b/sql/partition_info.cc	revid:mattias.jonsson@strippedzan6f
@@ -171,15 +171,8 @@ bool partition_info::prune_partition_bit
   List_iterator<String> partition_names_it(*(table_list->partition_names));
   uint num_names= table_list->partition_names->elements;
   uint i= 0;
-  HASH *part_name_hash;
-  Partition_share *part_share;
   DBUG_ENTER("partition_info::prune_partition_bitmaps");
 
-  DBUG_ASSERT(table && table->s && table->s->ha_share);
-  part_share= static_cast<Partition_share*>((table->s->ha_share));
-  DBUG_ASSERT(part_share->partition_name_hash_initialized);
-  part_name_hash= &part_share->partition_name_hash;
-  DBUG_ASSERT(part_name_hash->records);
   if (num_names < 1)
     DBUG_RETURN(true);
 
@@ -223,7 +216,7 @@ bool partition_info::set_partition_bitma
 
   DBUG_ASSERT(bitmaps_are_initialized);
   DBUG_ASSERT(table);
-  prune_state= NOT_PRUNED;
+  is_const_item_pruned= false;
   if (!bitmaps_are_initialized)
     DBUG_RETURN(TRUE);
 
@@ -248,23 +241,40 @@ bool partition_info::set_partition_bitma
 /**
   Checks if possible to do prune partitions on insert.
 
+  @param thd           Thread context
   @param duplic        How to handle duplicates
+  @param update        In case of ON DUPLICATE UPDATE, default function fields
   @param update_fields In case of ON DUPLICATE UPDATE, which fields to update
   @param fields        Listed fields
   @param empty_values  True if values is empty (only defaults)
   @param[out] prune_needs_default_values  Set on return if copying of default
                                           values is needed
+  @param[out] can_prune_partitions        Enum showing if possible to prune
+  @param[inout] used_partitions           If possible to prune the bitmap
+                                          is initialized and cleared
+
+  @return Operation status
+    @retval false  Success
+    @retval true   Failure
 */
 
-partition_info::enum_can_prune
-partition_info::can_prune_insert(enum_duplicates duplic,
-                                 COPY_INFO &update,
-                                 List<Item> &update_fields,
-                                 List<Item> &fields,
-                                 bool empty_values,
-                                 bool *prune_needs_default_values)
-{
+bool partition_info::can_prune_insert(THD* thd,
+                                      enum_duplicates duplic,
+                                      COPY_INFO &update,
+                                      List<Item> &update_fields,
+                                      List<Item> &fields,
+                                      bool empty_values,
+                                      enum_can_prune *can_prune_partitions,
+                                      bool *prune_needs_default_values,
+                                      MY_BITMAP *used_partitions)
+{
+  uint32 *bitmap_buf;
+  uint bitmap_bytes;
+  uint num_partitions= 0;
+  *can_prune_partitions= PRUNE_NO;
+  DBUG_ASSERT(bitmaps_are_initialized);
   DBUG_ENTER("partition_info::can_prune_insert");
+
   /*
     If under LOCK TABLES pruning will skip start_stmt instead of external_lock
     for unused partitions.
@@ -274,16 +284,8 @@ partition_info::can_prune_insert(enum_du
   */
   if (table->triggers &&
       table->triggers->has_triggers(TRG_EVENT_INSERT, TRG_ACTION_BEFORE))
-    DBUG_RETURN(PRUNE_NO);
+    DBUG_RETURN(false);
 
-  /*
-    Note: It makes no sense to prune on partition/subpartition level when
-    only partition/subpartition fields are affected.
-    For subpartitioned tables, there makes little sense to prune only on
-    partition level or subpartition level. Since it is only possible in
-    few cases (update/auto_inc fields only in part OR subpart fields).
-    Cannot be INSERT SELECT.
-  */
   if (table->found_next_number_field)
   {
     /*
@@ -291,9 +293,9 @@ partition_info::can_prune_insert(enum_du
       TODO: If all rows have not null values and
       is not 0 (with NO_AUTO_VALUE_ON_ZERO sql_mode), then pruning is possible!
     */
-    if (bitmap_is_set(&table->part_info->full_part_field_set,
+    if (bitmap_is_set(&full_part_field_set,
         table->found_next_number_field->field_index))
-      DBUG_RETURN(PRUNE_NO);
+      DBUG_RETURN(false);
   }
 
   /*
@@ -311,15 +313,14 @@ partition_info::can_prune_insert(enum_du
       Cannot prune if any field in the partitioning expression can
       be updated by ON DUPLICATE UPDATE.
     */
-    if (update.function_defaults_apply_on_columns(&table->part_info->
-                                                  full_part_field_set))
-      DBUG_RETURN(PRUNE_NO);
+    if (update.function_defaults_apply_on_columns(&full_part_field_set))
+      DBUG_RETURN(false);
  
     /*
       TODO: add check for static update values, which can be pruned.
     */
     if (is_field_in_part_expr(update_fields))
-      DBUG_RETURN(PRUNE_NO);
+      DBUG_RETURN(false);
 
     /*
       Cannot prune if there are BEFORE UPDATE triggers,
@@ -328,7 +329,7 @@ partition_info::can_prune_insert(enum_du
     if (table->triggers &&
         table->triggers->has_triggers(TRG_EVENT_UPDATE,
                                       TRG_ACTION_BEFORE))
-      DBUG_RETURN(PRUNE_NO);
+      DBUG_RETURN(false);
   }
 
   /*
@@ -351,24 +352,51 @@ partition_info::can_prune_insert(enum_du
   {
     *prune_needs_default_values= true; // like 'INSERT INTO t () VALUES ()'
   }
+  else
+  {
+     /*
+       In case of INSERT INTO t VALUES (...) we must get values for
+       all fields in table from VALUES (...) part, so no defaults
+       are needed.
+     */
+  }
 
+  /* Pruning possible, have to initialize the used_partitions bitmap. */
+  num_partitions= lock_partitions.n_bits;
+  bitmap_bytes= bitmap_buffer_size(num_partitions);
+  if (!(bitmap_buf= (uint32*) thd->alloc(bitmap_bytes)))
+  {
+    mem_alloc_error(bitmap_bytes);
+    DBUG_RETURN(true);
+  }
+  /* Also clears all bits. */
+  if (bitmap_init(used_partitions, bitmap_buf, num_partitions, false))
+  {
+    /* Cannot happen, due to pre-alloc, purecov: begin deadcode */
+    mem_alloc_error(bitmap_bytes);
+    DBUG_RETURN(true);
+    /* purecov: end */
+  }
   /*
     If no partitioning field in set (e.g. defaults) check pruning only once.
   */
   if (fields.elements &&
       !is_field_in_part_expr(fields))
-    DBUG_RETURN(PRUNE_DEFAULTS);
+    *can_prune_partitions= PRUNE_DEFAULTS;
+  else
+    *can_prune_partitions= PRUNE_YES;
 
-  DBUG_RETURN(PRUNE_YES);
+  DBUG_RETURN(false);
 }
 
 
 /**
   Mark the partition, the record belongs to, as used.
 
-  @param table            Table to use
   @param fields           Fields to set
   @param values           Values to use
+  @param info             COPY_INFO used for default values handling
+  @param copy_default_values  True if we should copy default values
   @param used_partitions  Bitmap to set
 
   @returns Operational status
@@ -378,43 +406,62 @@ partition_info::can_prune_insert(enum_du
 
 bool partition_info::set_used_partition(List<Item> &fields,
                                         List<Item> &values,
+                                        COPY_INFO &info,
                                         bool copy_default_values,
                                         MY_BITMAP *used_partitions)
 {
   THD *thd= table->in_use;
   uint32 part_id;
   longlong func_value;
+  Dummy_error_handler error_handler;
+  bool ret= true;
   DBUG_ENTER("set_partition");
   DBUG_ASSERT(thd);
 
   /* Only allow checking of constant values */
   List_iterator_fast<Item> v(values);
   Item *item;
+  thd->push_internal_handler(&error_handler);
   while ((item= v++))
   {
     if (!item->const_item())
-      DBUG_RETURN(true);
+      goto err;
   }
 
-  default_record(copy_default_values, table);
+  if (copy_default_values)
+    restore_record(table,s->default_values);
 
   if (fields.elements || !values.elements)
   {
     if (fill_record(thd, fields, values, false, &full_part_field_set))
-      DBUG_RETURN(true);
+      goto err;
   }
   else
   {
     if (fill_record(thd, table->field, values, false, &full_part_field_set))
-      DBUG_RETURN(true);
+      goto err;
   }
+  DBUG_ASSERT(!table->auto_increment_field_not_null);
+
+  /*
+    Evaluate DEFAULT functions like CURRENT_TIMESTAMP.
+    TODO: avoid setting non partitioning fields default value, to avoid
+    overhead. Not yet done, since mostly only one DEFAULT function per
+    table, or at least very few such columns.
+  */
+  if (info.function_defaults_apply_on_columns(&full_part_field_set))
+    info.set_function_defaults(table);
 
   if (get_partition_id(this, &part_id, &func_value))
-    DBUG_RETURN(true);
+    goto err;
 
   DBUG_PRINT("info", ("Insert into partition %u", part_id));
   bitmap_set_bit(used_partitions, part_id);
-  DBUG_RETURN(false);
+  ret= false;
+
+err:
+  thd->pop_internal_handler();
+  DBUG_RETURN(ret);
 }
 
 
@@ -2097,7 +2144,8 @@ bool partition_info::is_field_in_part_ex
     }
     else
     {
-      DBUG_ASSERT(0); // Should already be checked
+      /* Some non-updateable entity. Should have been checked already. */
+      DBUG_ASSERT(0);
       DBUG_RETURN(true);
     }
   }
@@ -2130,7 +2178,8 @@ bool partition_info::is_full_part_expr_i
     {
       if (!(field= item->field_for_view_update()))
       {
-        DBUG_ASSERT(0); // Should already be checked
+        /* Some non-updateable entity. Should have been checked already. */
+        DBUG_ASSERT(0);
         DBUG_RETURN(false);
       }
       else
@@ -2733,39 +2782,6 @@ bool partition_info::fix_parser_data(THD
 }
 
 
-/**
-  Is the table pruned when cond->const_item() was true.
-*/
-
-bool partition_info::is_const_pruned() const
-{
-  if (prune_state >= PREPARE_CONST_PRUNED)
-    return true;
-  return false;
-}
-
-
-/**
-  Set prune_state.
-
-  @param  is_prepare  Is in prepare stage.
-  @param  is_const    Is the pruning condition const_item.
-*/
-
-void partition_info::set_prune_state(bool is_prepare, bool is_const)
-{
-  if (is_prepare)
-  {
-    if (is_const)
-      prune_state= PREPARE_CONST_PRUNED;
-    else
-      prune_state= PREPARE_PRUNED;
-  }
-  else
-    prune_state= OPTIMIZE_PRUNED;
-}
-
-
 void partition_info::print_debug(const char *str, uint *value)
 {
   DBUG_ENTER("print_debug");

=== modified file 'sql/partition_info.h'
--- a/sql/partition_info.h	revid:mattias.jonsson@stripped0509151124-m3yw998dio568l9u
+++ b/sql/partition_info.h	revid:mattias.jonsson@strippedzan6f
@@ -223,9 +223,8 @@ public:
   bool from_openfrm;
   bool has_null_value;
   bool column_list;                          // COLUMNS PARTITIONING, 5.5+
-  enum enum_prune_state { NOT_PRUNED= 0, PREPARE_PRUNED, PREPARE_CONST_PRUNED,
-                          OPTIMIZE_PRUNED };
-  enum_prune_state prune_state;
+  /** True if pruning has been done with cond->const_item(). */
+  bool is_const_item_pruned;
 
   partition_info()
   : get_partition_id(NULL), get_part_partition_id(NULL),
@@ -258,7 +257,7 @@ public:
     list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
     linear_hash_ind(FALSE), fixed(FALSE),
     is_auto_partitioned(FALSE), from_openfrm(FALSE),
-    has_null_value(FALSE), column_list(FALSE), prune_state(NOT_PRUNED)
+    has_null_value(FALSE), column_list(FALSE), is_const_item_pruned(false)
   {
     partitions.empty();
     temp_partitions.empty();
@@ -319,21 +318,21 @@ public:
                                    char *file_name,
                                    uint32 *part_id);
   void report_part_expr_error(bool use_subpart_expr);
-  bool is_field_in_part_expr(List<Item> &fields);
-  bool is_full_part_expr_in_fields(List<Item> &fields);
   bool set_used_partition(List<Item> &fields,
                           List<Item> &values,
+                          COPY_INFO &info,
                           bool copy_default_values,
                           MY_BITMAP *used_partitions);
   enum enum_can_prune {PRUNE_NO=0, PRUNE_DEFAULTS, PRUNE_YES};
-  enum_can_prune can_prune_insert(enum_duplicates duplic,
-                                  COPY_INFO &update,
-                                  List<Item> &update_fields,
-                                  List<Item> &fields,
-                                  bool empty_values,
-                                  bool *prune_needs_default_values);
-  bool is_const_pruned() const;
-  void set_prune_state(bool is_prepare, bool is_const);
+  bool can_prune_insert(THD *thd,
+                        enum_duplicates duplic,
+                        COPY_INFO &update,
+                        List<Item> &update_fields,
+                        List<Item> &fields,
+                        bool empty_values,
+                        enum_can_prune *can_prune_partitions,
+                        bool *prune_needs_default_values,
+                        MY_BITMAP *used_partitions);
 private:
   static int list_part_cmp(const void* a, const void* b);
   bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
@@ -345,6 +344,8 @@ private:
                                          const char *part_name);
   bool prune_partition_bitmaps(TABLE_LIST *table_list);
   bool add_named_partition(const char *part_name, uint length);
+  bool is_field_in_part_expr(List<Item> &fields);
+  bool is_full_part_expr_in_fields(List<Item> &fields);
 };
 
 uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	revid:mattias.jonsson@stripped
+++ b/sql/share/errmsg-utf8.txt	revid:mattias.jonsson@oracle.com-20120513015716-wmkf6s9fwt6zan6f
@@ -6574,7 +6574,8 @@ ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SE
   swe "Hittade en rad som inte passar i någon given partition"
 
 # Not used any longer, use ER_UNKNOWN_PARTITION which includes the tablename.
-ER_NO_SUCH_PARTITION 
+# was ER_NO_SUCH_PARTITION
+ER_NO_SUCH_PARTITION__UNUSED
   cze "partion '%-.64s' neexistuje"
   dan "partition '%-.64s' eksisterer ikke"
   nla "partition '%-.64s' bestaat niet"

=== modified file 'sql/sp.cc'
--- a/sql/sp.cc	revid:mattias.jonsson@stripped
+++ b/sql/sp.cc	revid:mattias.jonsson@stripped6-wmkf6s9fwt6zan6f
@@ -1519,6 +1519,9 @@ bool lock_db_routines(THD *thd, char *db
 
   @note Close the thread tables, the calling code might want to
   delete from other system tables afterwards.
+
+  @todo We need to change this function to call a my_error()/print_error()
+  once we stop ignoring return value of sp_drop_db_routines().
 */
 
 int

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	revid:mattias.jonsson@strippedm3yw998dio568l9u
+++ b/sql/sql_base.cc	revid:mattias.jonsson@stripped
@@ -3198,15 +3198,14 @@ retry_share:
   table_list->table= table;
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
-  /* Set all [named] partitions as used. */
   if (table->part_info)
   {
+
+    /* Set all [named] partitions as used. */
     if (table->part_info->set_partition_bitmaps(table_list))
       DBUG_RETURN(true);
   }
-  else if (table_list &&
-           table_list->partition_names &&
-           table_list->partition_names->elements)
+  else if (table_list->partition_names)
   {
     /* Don't allow PARTITION () clause on a nonpartitioned table */
     my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
@@ -5650,24 +5649,6 @@ end:
 
 
 /**
-  Cleanup failed open or lock tables.
-
-  @param thd            Thread context.
-  @param mdl_savepoint  Savepoint for rollback.
-*/
-
-void open_and_lock_tables_cleanup(THD *thd,
-                                  const MDL_savepoint &mdl_savepoint)
-{
-  if (!thd->in_sub_stmt)
-    trans_rollback_stmt(thd);  /* Necessary if derived handling failed. */
-  close_thread_tables(thd);
-  /* Don't keep locks for a failed statement. */
-  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
-}
-
-
-/**
   Open all tables in list, locks them and optionally process derived tables.
 
   @param thd		      Thread context.
@@ -5714,7 +5695,11 @@ bool open_and_lock_tables(THD *thd, TABL
 
   DBUG_RETURN(FALSE);
 err:
-  open_and_lock_tables_cleanup(thd, mdl_savepoint);
+  if (! thd->in_sub_stmt)
+    trans_rollback_stmt(thd);  /* Necessary if derived handling failed. */
+  close_thread_tables(thd);
+  /* Don't keep locks for a failed statement. */
+  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
   DBUG_RETURN(TRUE);
 }
 
@@ -6378,6 +6363,16 @@ bool open_temporary_table(THD *thd, TABL
     DBUG_RETURN(FALSE);
   }
 
+#ifdef WITH_PARTITION_STORAGE_ENGINE
+  if (tl->partition_names)
+  {
+    /* Partitioned temporary tables is not supported. */
+    DBUG_ASSERT(!table->part_info);
+    my_error(ER_PARTITION_CLAUSE_ON_NONPARTITIONED, MYF(0));
+    DBUG_RETURN(true);
+  }
+#endif
+
   if (table->query_id)
   {
     /*

=== modified file 'sql/sql_base.h'
--- a/sql/sql_base.h	revid:mattias.jonsson@oracle.com-20120509151124-m3yw998dio568l9u
+++ b/sql/sql_base.h	revid:mattias.jonsson@strippedf6s9fwt6zan6f
@@ -242,8 +242,6 @@ bool lock_table_names(THD *thd, TABLE_LI
                       uint flags);
 bool open_tables(THD *thd, TABLE_LIST **tables, uint *counter, uint flags,
                  Prelocking_strategy *prelocking_strategy);
-void open_and_lock_tables_cleanup(THD *thd,
-                                  const MDL_savepoint &mdl_savepoint);
 /* open_and_lock_tables with optional derived handling */
 bool open_and_lock_tables(THD *thd, TABLE_LIST *tables,
                           bool derived, uint flags,

=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc	revid:mattias.jonsson@stripped-20120509151124-m3yw998dio568l9u
+++ b/sql/sql_class.cc	revid:mattias.jonsson@stripped6zan6f
@@ -4479,7 +4479,7 @@ void xid_cache_delete(XID_STATE *xid_sta
    @retval true Memory allocation error.
 */
 
-bool allocate_column_bitmap(TABLE *table, MY_BITMAP **bitmap)
+static bool allocate_column_bitmap(TABLE *table, MY_BITMAP **bitmap)
 {
   DBUG_ENTER("allocate_column_bitmap");
   const uint number_bits= table->s->fields;
@@ -4558,24 +4558,21 @@ void COPY_INFO::set_function_defaults(TA
 
   DBUG_ASSERT(m_function_default_columns != NULL);
 
-  /* Quick reject test for checking the case when no defaults are invoked. */
-  if (bitmap_is_clear_all(m_function_default_columns))
-    DBUG_VOID_RETURN;
-
-  for (uint i= 0; i < table->s->fields; ++i)
-    if (bitmap_is_set(m_function_default_columns, i))
+  for (uint i= bitmap_get_first_set(m_function_default_columns);
+       i < table->s->fields;
+       i= bitmap_get_next_set(m_function_default_columns, i))
+  {
+    DBUG_ASSERT(bitmap_is_set(table->write_set, i));
+    switch (m_optype)
     {
-      DBUG_ASSERT(bitmap_is_set(table->write_set, i));
-      switch (m_optype)
-      {
-      case INSERT_OPERATION:
-        table->field[i]->evaluate_insert_default_function();
-        break;
-      case UPDATE_OPERATION:
-        table->field[i]->evaluate_update_default_function();
-        break;
-      }
+    case INSERT_OPERATION:
+      table->field[i]->evaluate_insert_default_function();
+      break;
+    case UPDATE_OPERATION:
+      table->field[i]->evaluate_update_default_function();
+      break;
     }
+  }
   DBUG_VOID_RETURN;
 }
 

=== modified file 'sql/sql_delete.cc'
--- a/sql/sql_delete.cc	revid:mattias.jonsson@strippedu
+++ b/sql/sql_delete.cc	revid:mattias.jonsson@strippedm-20120513015716-wmkf6s9fwt6zan6f
@@ -108,7 +108,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
     Non delete tables are pruned in JOIN::prepare,
     only the delete table needs this.
   */
-  if (prune_partitions(thd, table, conds, true))
+  if (prune_partitions(thd, table, conds))
     DBUG_RETURN(true);
   if (table->all_partitions_pruned_away)
     goto exit_all_parts_pruned_away;
@@ -209,7 +209,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   /* Prune a second time to be able to prune on subqueries in WHERE clause. */
-  if (prune_partitions(thd, table, conds, false))
+  if (prune_partitions(thd, table, conds))
     DBUG_RETURN(true);
   if (table->all_partitions_pruned_away)
     goto exit_all_parts_pruned_away;

=== modified file 'sql/sql_handler.cc'
--- a/sql/sql_handler.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_handler.cc	revid:mattias.jonsson@stripped716-wmkf6s9fwt6zan6f
@@ -683,18 +683,23 @@ retry:
         error= table->file->ha_rnd_next(table->record[0]);
         break;
       }
-      /* else fall through */
+      /*
+        Fall through to HANDLER ... READ ... FIRST case if we are trying
+        to read next row in index order after starting reading rows in
+        natural order, or, vice versa, trying to read next row in natural
+        order after reading previous rows in index order.
+      */
     case RFIRST:
       if (m_key_name)
       {
-        table->file->ha_index_or_rnd_end();
-        if (!(error= table->file->ha_index_init(keyno, 1)))
+        if (!(error= table->file->ha_index_or_rnd_end()) &&
+            !(error= table->file->ha_index_init(keyno, 1)))
           error= table->file->ha_index_first(table->record[0]);
       }
       else
       {
-        table->file->ha_index_or_rnd_end();
-	if (!(error= table->file->ha_rnd_init(1)))
+        if (!(error= table->file->ha_index_or_rnd_end()) &&
+            !(error= table->file->ha_rnd_init(1)))
           error= table->file->ha_rnd_next(table->record[0]);
       }
       mode=RNEXT;
@@ -708,7 +713,7 @@ retry:
         error= table->file->ha_index_prev(table->record[0]);
         break;
       }
-      /* else fall through */
+      /* else fall through, for more info, see comment before 'case RFIRST'. */
     case RLAST:
       DBUG_ASSERT(m_key_name != 0);
       if (!(error= table->file->ha_index_or_rnd_end()) &&
@@ -718,15 +723,8 @@ retry:
       break;
     case RNEXT_SAME:
       /* Continue scan on "(keypart1,keypart2,...)=(c1, c2, ...)  */
-      DBUG_ASSERT(m_key_name != 0);
-      /* Continue scan, or start a new scan if no previous index scan */
-      if (table->file->inited == handler::INDEX ||
-          (!(error= table->file->ha_index_or_rnd_end()) &&
-           !(error= table->file->ha_index_init(keyno, 1))))
-      {
-        DBUG_ASSERT((uint) keyno == table->file->get_index());
-        error= table->file->ha_index_next_same(table->record[0], key, key_len);
-      }
+      DBUG_ASSERT(table->file->inited == handler::INDEX);
+      error= table->file->ha_index_next_same(table->record[0], key, key_len);
       break;
     case RKEY:
     {

=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc	revid:mattias.jonsson@stripped-m3yw998dio568l9u
+++ b/sql/sql_insert.cc	revid:mattias.jonsson@stripped
@@ -60,7 +60,6 @@
 #include "unireg.h"                    // REQUIRED: for other includes
 #include "sql_insert.h"
 #include "sql_update.h"                         // compare_record
-#include "sql_derived.h"                        // mysql_derived_*
 #include "sql_base.h"                           // close_thread_tables
 #include "sql_cache.h"                          // query_cache_*
 #include "key.h"                                // key_copy
@@ -767,6 +766,13 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   /* mysql_prepare_insert set table_list->table if it was not set */
   table= table_list->table;
 
+  /* Must be done before can_prune_insert, due to internal initialization. */
+  if (info.add_function_default_columns(table, table->write_set))
+    goto exit_without_my_ok;
+  if (duplic == DUP_UPDATE &&
+      update.add_function_default_columns(table, table->write_set))
+    goto exit_without_my_ok;
+
   context= &thd->lex->select_lex.context;
   /*
     These three asserts test the hypothesis that the resetting of the name
@@ -787,53 +793,34 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
   table_list->next_local= 0;
   context->resolve_in_table_list_only(table_list);
 
-  /* Must be done before can_prune_insert, due to internal initialization. */
-  if (info.add_function_default_columns(table, table->write_set))
-    goto exit_without_my_ok;
-  if (duplic == DUP_UPDATE &&
-      update.add_function_default_columns(table, table->write_set))
-    goto exit_without_my_ok;
-
 #ifdef WITH_PARTITION_STORAGE_ENGINE
   if (!is_locked && table->part_info)
   {
-    can_prune_partitions=
-      table->part_info->can_prune_insert(duplic,
-                                         update,
-                                         update_fields,
-                                         fields,
-                                         !test(values->elements),
-                                         &prune_needs_default_values);
+    if (table->part_info->can_prune_insert(thd,
+                                           duplic,
+                                           update,
+                                           update_fields,
+                                           fields,
+                                           !test(values->elements),
+                                           &can_prune_partitions,
+                                           &prune_needs_default_values,
+                                           &used_partitions))
+      goto exit_without_my_ok;
+
     if (can_prune_partitions != partition_info::PRUNE_NO)
     {
-      uint32 *bitmap_buf;
-      uint bitmap_bytes;
-      DBUG_ASSERT(table->part_info->bitmaps_are_initialized);
-
-      /*
-        Pruning probably possible, must unmark all partitions for read/lock,
-        and add them on row by row basis.
-      */
       num_partitions= table->part_info->lock_partitions.n_bits;
-      bitmap_bytes= bitmap_buffer_size(num_partitions);
-      if (!(bitmap_buf= (uint32*) thd->alloc(bitmap_bytes)))
-      {
-        mem_alloc_error(bitmap_bytes);
-        goto exit_without_my_ok;
-      }
-      /* Also clears all bits. */
-      if (bitmap_init(&used_partitions, bitmap_buf, num_partitions, false))
-      {
-        mem_alloc_error(bitmap_bytes);   /* Cannot happen, due to pre-alloc */
-        goto exit_without_my_ok;
-      }
       /*
+        Pruning probably possible, all partitions is unmarked for read/lock,
+        and we must now add them on row by row basis.
+
         Check the first INSERT value.
         Do not fail here, since that would break MyISAM behavior of inserting
         all rows before the failing row.
       */
       if (table->part_info->set_used_partition(fields,
                                                *values,
+                                               info,
                                                prune_needs_default_values,
                                                &used_partitions))
         can_prune_partitions= partition_info::PRUNE_NO;
@@ -854,7 +841,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
 
 #ifdef WITH_PARTITION_STORAGE_ENGINE
     /*
-      To make it possible to increase concurrancy on table level locking
+      To make it possible to increase concurrency on table level locking
       engines such as MyISAM, we check pruning for each row until we will use
       all partitions, Even if the number of rows is much higher than the
       number of partitions.
@@ -865,17 +852,24 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
     {
       if (table->part_info->set_used_partition(fields,
                                                *values,
+                                               info,
                                                prune_needs_default_values,
                                                &used_partitions))
         can_prune_partitions= partition_info::PRUNE_NO;
       if (!(counter % num_partitions))
       {
+        /*
+          Check if we using all partitions in table after adding partition
+          for current row to the set of used partitions. Do it only from
+          time to time to avoid overhead from bitmap_is_set_all() call.
+        */
         if (bitmap_is_set_all(&used_partitions))
           can_prune_partitions= partition_info::PRUNE_NO;
       }
     }
 #endif /* WITH_PARTITION_STORAGE_ENGINE */
   }
+  table->auto_increment_field_not_null= false;
   its.rewind ();
  
   /* Restore the current context. */
@@ -902,6 +896,10 @@ bool mysql_insert(THD *thd,TABLE_LIST *t
       the new set of read/lock partitions is the intersection of read/lock
       partitions and used partitions, i.e only the partitions that exists in
       both sets will be marked for read/lock.
+      It is also safe for REPLACE, since all potentially conflicting records
+      always belong to the same partition as the one which we try to
+      insert a row. This is because ALL unique/primary keys must
+      include ALL partitioning columns.
     */
     bitmap_intersect(&table->part_info->read_partitions,
                      &used_partitions);
@@ -3795,8 +3793,11 @@ void select_insert::abort_result_set() {
   {
     bool changed, transactional_table;
     /*
-      If we are not in prelocked mode, we end the bulk insert started
-      before.
+      Try to end the bulk insert which might have been started before.
+      We don't need to do this if we are in prelocked mode (since we
+      don't use bulk insert in this case). Also we should not do this
+      if tables are not locked yet (bulk insert is not started yet
+      in this case).
     */
     if (thd->locked_tables_mode <= LTM_LOCK_TABLES &&
         thd->lex->is_query_tables_locked())

=== modified file 'sql/sql_join_buffer.cc'
--- a/sql/sql_join_buffer.cc	revid:mattias.jonsson@strippedom-20120509151124-m3yw998dio568l9u
+++ b/sql/sql_join_buffer.cc	revid:mattias.jonsson@strippedkf6s9fwt6zan6f
@@ -2384,7 +2384,7 @@ enum_nested_loop_state JOIN_CACHE_BKA::j
 enum_nested_loop_state 
 JOIN_CACHE_BKA::init_join_matching_records(RANGE_SEQ_IF *seq_funcs, uint ranges)
 {
-  int error= 0;
+  int error;
   handler *file= join_tab->table->file;
   enum_nested_loop_state rc= NESTED_LOOP_OK;
 

=== modified file 'sql/sql_lex.cc'
--- a/sql/sql_lex.cc	revid:mattias.jonsson@stripped0120509151124-m3yw998dio568l9u
+++ b/sql/sql_lex.cc	revid:mattias.jonsson@stripped6f
@@ -3334,6 +3334,9 @@ TABLE_LIST *LEX::unlink_first_table(bool
       query_tables_last= &query_tables;
     first->next_global= 0;
 
+    if (query_tables_own_last == &first->next_global)
+      query_tables_own_last= &query_tables;
+
     /*
       and from local list if it is not empty
     */
@@ -3416,6 +3419,10 @@ void LEX::link_first_table_back(TABLE_LI
       query_tables->prev_global= &first->next_global;
     else
       query_tables_last= &first->next_global;
+
+    if (query_tables_own_last == &query_tables)
+      query_tables_own_last= &first->next_global;
+
     query_tables= first;
 
     if (link_to_local)

=== modified file 'sql/sql_lex.h'
--- a/sql/sql_lex.h	revid:mattias.jonsson@stripped98dio568l9u
+++ b/sql/sql_lex.h	revid:mattias.jonsson@oracle.com-20120513015716-wmkf6s9fwt6zan6f
@@ -1135,26 +1135,7 @@ public:
   /* Return pointer to first not-own table in query-tables or 0 */
   TABLE_LIST* first_not_own_table()
   {
-    /*
-      Note: query_tables_own_last may be set to &first_table->next_global
-      which might be removed by unlink_first_table.
-      So if query_tables_own_last is set, but *query_tables_own_last is NULL,
-      Then it might be not own tables left any way.
-      This can be checked by comparing query_tables_own_last with
-      query_tables_last and if they is not the same, then
-      first_not_own_table is query_tables.
-    */
-    if (query_tables_own_last)
-    {
-      if (*query_tables_own_last)
-        return *query_tables_own_last;
-      else
-      {
-        if (query_tables_own_last != query_tables_last)
-          return query_tables;
-      }
-    }
-    return NULL;
+    return ( query_tables_own_last ? *query_tables_own_last : 0);
   }
   void chop_off_not_own_tables()
   {

=== modified file 'sql/sql_optimizer.cc'
--- a/sql/sql_optimizer.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_optimizer.cc	revid:mattias.jonsson@stripped3015716-wmkf6s9fwt6zan6f
@@ -270,10 +270,13 @@ JOIN::optimize()
         This will try to prune non-static conditions, which can
         be used after the tables are locked.
       */
+      //DBUG_ASSERT(!tbl->embedding);
+#ifndef TODO_INVESTIGATE
       if (!tbl->embedding)
+#endif
       {
         Item *prune_cond= tbl->join_cond()? tbl->join_cond() : conds;
-        if (prune_partitions(thd, tbl->table, prune_cond, false))
+        if (prune_partitions(thd, tbl->table, prune_cond))
         {
           error= 1;
           DBUG_PRINT("error", ("Error from prune_partitions"));

=== modified file 'sql/sql_partition.h'
--- a/sql/sql_partition.h	revid:mattias.jonsson@oracle.com-20120509151124-m3yw998dio568l9u
+++ b/sql/sql_partition.h	revid:mattias.jonsson@strippedkf6s9fwt6zan6f
@@ -77,9 +77,6 @@ struct st_partition_iter;
 bool is_partition_in_list(char *part_name, List<char> list_part_names);
 char *are_partitions_in_table(partition_info *new_part_info,
                               partition_info *old_part_info);
-bool check_reorganise_list(partition_info *new_part_info,
-                           partition_info *old_part_info,
-                           List<char> list_part_names);
 handler *get_ha_partition(partition_info *part_info);
 int get_parts_for_update(const uchar *old_data, uchar *new_data,
                          const uchar *rec0, partition_info *part_info,

=== modified file 'sql/sql_partition_admin.cc'
--- a/sql/sql_partition_admin.cc	revid:mattias.jonsson@stripped120509151124-m3yw998dio568l9u
+++ b/sql/sql_partition_admin.cc	revid:mattias.jonsson@strippedf6s9fwt6zan6f
@@ -149,6 +149,13 @@ static bool check_exchange_partition(TAB
     DBUG_RETURN(TRUE);
   }
 
+  /* The table cannot have foreign keys constraints or be referenced */
+  if(!table->file->can_switch_engines())
+  {
+    my_error(ER_PARTITION_EXCHANGE_FOREIGN_KEY, MYF(0),
+             table->s->table_name.str);
+    DBUG_RETURN(TRUE);
+  }
   DBUG_RETURN(FALSE);
 }
 
@@ -481,7 +488,6 @@ bool Sql_cmd_alter_table_exchange_partit
   handlerton *table_hton;
   partition_element *part_elem;
   char *partition_name;
-  List<String> partition_names_list;
   char temp_name[FN_REFLEN+1];
   char part_file_name[FN_REFLEN+1];
   char swap_file_name[FN_REFLEN+1];
@@ -526,10 +532,7 @@ bool Sql_cmd_alter_table_exchange_partit
   table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
   if (open_tables(thd, &table_list, &table_counter, 0,
                   &alter_prelocking_strategy))
-  {
-    open_and_lock_tables_cleanup(thd, mdl_savepoint);
-    DBUG_RETURN(TRUE);
-  }
+    DBUG_RETURN(true);
 
   part_table= table_list->table;
   swap_table= swap_table_list->table;
@@ -544,21 +547,8 @@ bool Sql_cmd_alter_table_exchange_partit
     DBUG_RETURN(true);
 
   if (lock_tables(thd, table_list, table_counter, 0))
-  {
-    open_and_lock_tables_cleanup(thd, mdl_savepoint);
     DBUG_RETURN(true);
-  }
 
-  /*
-    The table cannot have foreign keys constraints or be referenced.
-    This can only be checked after locking the table.
-  */
-  if(!swap_table->file->can_switch_engines())
-  {
-    my_error(ER_PARTITION_EXCHANGE_FOREIGN_KEY, MYF(0),
-             swap_table->s->table_name.str);
-    DBUG_RETURN(true);
-  }
 
   table_hton= swap_table->file->ht;
 
@@ -781,10 +771,7 @@ bool Sql_cmd_alter_table_truncate_partit
 
   mdl_savepoint= thd->mdl_context.mdl_savepoint();
   if (open_tables(thd, &first_table, &table_counter, 0))
-  {
-    open_and_lock_tables_cleanup(thd, mdl_savepoint);
     DBUG_RETURN(true);
-  }
 
   /*
     TODO: Add support for TRUNCATE PARTITION for NDB and other
@@ -814,10 +801,7 @@ bool Sql_cmd_alter_table_truncate_partit
     DBUG_RETURN(true);
 
   if (lock_tables(thd, first_table, table_counter, 0))
-  {
-    open_and_lock_tables_cleanup(thd, mdl_savepoint);
     DBUG_RETURN(true);
-  }
 
   /*
     Under locked table modes this might still not be an exclusive

=== modified file 'sql/sql_resolver.cc'
--- a/sql/sql_resolver.cc	revid:mattias.jonsson@strippedl9u
+++ b/sql/sql_resolver.cc	revid:mattias.jonsson@oracle.com-20120513015716-wmkf6s9fwt6zan6f
@@ -385,12 +385,16 @@ JOIN::prepare(TABLE_LIST *tables_init,
     TABLE_LIST *tbl;
     for (tbl= select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
     {
+#ifdef TODO_INVESTIGATE
+      if (tbl->embedding)
+        continue;
+#endif
       /* 
         This will only prune constant conditions, which will be used for
         lock pruning.
       */
       Item *prune_cond= tbl->join_cond() ? tbl->join_cond() : conds;
-      if (prune_partitions(thd, tbl->table, prune_cond, true))
+      if (prune_partitions(thd, tbl->table, prune_cond))
         goto err;
     }
   }

=== modified file 'sql/sql_select.cc'
--- a/sql/sql_select.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_select.cc	revid:mattias.jonsson@stripped-20120513015716-wmkf6s9fwt6zan6f
@@ -973,7 +973,8 @@ void JOIN::cleanup_item_list(List<Item> 
                               SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2)
                               has 2 unions.
   @param select_lex           the only SELECT_LEX of this query
-  @param[out] free_join       if returned JOIN should be freed     
+  @param[out] free_join       Will be set to false if select_lex->join does
+                              not need to be freed.
 
   @retval
     false  success
@@ -983,7 +984,7 @@ void JOIN::cleanup_item_list(List<Item> 
   @note tables must be opened before calling mysql_prepare_select.
 */
 
-bool
+static bool
 mysql_prepare_select(THD *thd,
                      TABLE_LIST *tables, uint wild_num, List<Item> &fields,
                      Item *conds, uint og_num,  ORDER *order, ORDER *group,
@@ -1030,7 +1031,7 @@ mysql_prepare_select(THD *thd,
           DBUG_RETURN(true);
       }
     }
-    *free_join= 0;
+    *free_join= false;
     join->select_options= select_options;
   }
   else
@@ -1064,16 +1065,14 @@ mysql_prepare_select(THD *thd,
   @note tables must be opened and locked before calling mysql_execute_select.
 */
 
-bool
+static bool
 mysql_execute_select(THD *thd, SELECT_LEX *select_lex, bool free_join)
 {
   bool err;
   JOIN* join= select_lex->join;
 
   DBUG_ENTER("mysql_execute_select");
-
-  if (!join)
-    DBUG_RETURN(false);
+  DBUG_ASSERT(join);
 
   if ((err= join->optimize()))
   {
@@ -1086,7 +1085,7 @@ mysql_execute_select(THD *thd, SELECT_LE
   if (join->select_options & SELECT_DESCRIBE)
   {
     join->explain();
-    free_join= 0;
+    free_join= false;
   }
   else
     join->exec();
@@ -1119,8 +1118,6 @@ err:
                               for a, b and c in this list.
   @param conds                top level item of an expression representing
                               WHERE clause of the top level select
-  @param og_num               total number of ORDER BY and GROUP BY clauses
-                              arguments
   @param order                linked list of ORDER BY agruments
   @param group                linked list of GROUP BY arguments
   @param having               top level item of HAVING expression
@@ -1137,13 +1134,6 @@ err:
                               SELECT * FROM t1 WHERE a1 IN (SELECT * FROM t2)
                               has 2 unions.
   @param select_lex           the only SELECT_LEX of this query
-  @param tables_to_open_and_lock  Tables to open and lock
-                                  (NULL if already locked)
-  @param open_tables_is_done  All tables are already opened
-  @param tables_to_lock       If open_tables_is_done, not null means we should
-                              also lock tables
-  @param open_mdl_savepoint   If open_tables_is_done, savepoint to use on
-                              failure
 
   @retval
     false  success
@@ -1159,7 +1149,7 @@ mysql_select(THD *thd,
              select_result *result, SELECT_LEX_UNIT *unit,
              SELECT_LEX *select_lex)
 {
-  bool free_join= 1;
+  bool free_join= true;
   uint og_num= 0;
   ORDER *first_order= NULL;
   ORDER *first_group= NULL;
@@ -1183,7 +1173,7 @@ mysql_select(THD *thd,
   {
     if (free_join)
     {
-      thd_proc_info(thd, "end");
+      THD_STAGE_INFO(thd, stage_end);
       (void) select_lex->cleanup();
     }
     DBUG_RETURN(true);
@@ -1204,7 +1194,7 @@ mysql_select(THD *thd,
     {
       if (free_join)
       {
-        thd_proc_info(thd, "end");
+        THD_STAGE_INFO(thd, stage_end);
         (void) select_lex->cleanup();
       }
       DBUG_RETURN(true);
@@ -1220,10 +1210,7 @@ mysql_select(THD *thd,
     query_cache_store_query(thd, thd->lex->query_tables);
   }
 
-  if (mysql_execute_select(thd, select_lex, free_join))
-    DBUG_RETURN(true);
-
-  DBUG_RETURN(false);
+  DBUG_RETURN(mysql_execute_select(thd, select_lex, free_join));
 }
 
 /*****************************************************************************

=== modified file 'sql/sql_select.h'
--- a/sql/sql_select.h	revid:mattias.jonsson@stripped4-m3yw998dio568l9u
+++ b/sql/sql_select.h	revid:mattias.jonsson@stripped
@@ -1111,14 +1111,6 @@ protected:  
 bool error_if_full_join(JOIN *join);
 bool handle_select(THD *thd, select_result *result,
                    ulong setup_tables_done_option);
-bool mysql_prepare_select(THD *thd,
-                          TABLE_LIST *tables, uint wild_num, List<Item> &fields,
-                          Item *conds, uint og_num,  ORDER *order, ORDER *group,
-                          Item *having, ORDER *proc_param,
-                          ulonglong select_options, select_result *result,
-                          SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex,
-                          bool *free_join);
-bool mysql_execute_select(THD *thd, SELECT_LEX *select_lex, bool free_join);
 bool mysql_select(THD *thd,
                   TABLE_LIST *tables, uint wild_num,  List<Item> &list,
                   Item *conds, SQL_I_List<ORDER> *order,

=== modified file 'sql/sql_show.cc'
--- a/sql/sql_show.cc	revid:mattias.jonsson@stripped1124-m3yw998dio568l9u
+++ b/sql/sql_show.cc	revid:mattias.jonsson@stripped
@@ -5230,7 +5230,7 @@ int fill_schema_proc(THD *thd, TABLE_LIS
   TABLE *proc_table;
   TABLE_LIST proc_tables;
   const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
-  int res= 0;
+  int error, res= 0;
   TABLE *table= tables->table;
   bool full_access;
   char definer[USER_HOST_BUFF_SIZE];
@@ -5254,14 +5254,17 @@ int fill_schema_proc(THD *thd, TABLE_LIS
   {
     DBUG_RETURN(1);
   }
-  if (proc_table->file->ha_index_init(0, 1))
+  if ((error= proc_table->file->ha_index_init(0, 1)))
   {
+    proc_table->file->print_error(error, MYF(0));
     res= 1;
     goto err;
   }
-  if ((res= proc_table->file->ha_index_first(proc_table->record[0])))
+  if ((error= proc_table->file->ha_index_first(proc_table->record[0])))
   {
-    res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
+    res= (error == HA_ERR_END_OF_FILE) ? 0 : 1;
+    if (res)
+      proc_table->file->print_error(error, MYF(0));
     goto err;
   }
 

=== modified file 'sql/sql_tmp_table.cc'
--- a/sql/sql_tmp_table.cc	revid:mattias.jonsson@stripped20120509151124-m3yw998dio568l9u
+++ b/sql/sql_tmp_table.cc	revid:mattias.jonsson@strippedfwt6zan6f
@@ -1918,7 +1918,7 @@ bool create_myisam_from_heap(THD *thd, T
   TABLE new_table;
   TABLE_SHARE share;
   const char *save_proc_info;
-  int write_err= 0;
+  int write_err;
   DBUG_ENTER("create_myisam_from_heap");
 
   if (table->s->db_type() != heap_hton || 

=== modified file 'sql/sql_union.cc'
--- a/sql/sql_union.cc	revid:mattias.jonsson@stripped
+++ b/sql/sql_union.cc	revid:mattias.jonsson@stripped0120513015716-wmkf6s9fwt6zan6f
@@ -41,29 +41,26 @@ bool mysql_union(THD *thd, LEX *lex, sel
   if (res)
     goto err;
 
-  if (! thd->lex->is_query_tables_locked())
-  {
-    /*
-      If tables are not locked at this point, it means that we have delayed
-      this step until after prepare stage (i.e. this moment). This allows to
-      do better partition pruning and avoid locking unused partitions.
-      As a consequence, in such a case, prepare stage can rely only on
-      metadata about tables used and not data from them.
-      We need to lock tables now in order to proceed with the remaning
-      stages of query optimization and execution.
-    */
-    if (lock_tables(thd, lex->query_tables, lex->table_count, 0))
-      goto err;
 
-    /*
-      Only register query in cache if it tables were locked above.
+  /*
+    Tables are not locked at this point, it means that we have delayed
+    this step until after prepare stage (i.e. this moment). This allows to
+    do better partition pruning and avoid locking unused partitions.
+    As a consequence, in such a case, prepare stage can rely only on
+    metadata about tables used and not data from them.
+    We need to lock tables now in order to proceed with the remaning
+    stages of query optimization and execution.
+  */
+  DBUG_ASSERT(! thd->lex->is_query_tables_locked());
+  if (lock_tables(thd, lex->query_tables, lex->table_count, 0))
+    goto err;
 
-      Tables must be locked before storing the query in the query cache.
-      Transactional engines must been signalled that the statement started,
-      which external_lock signals.
-    */
-    query_cache_store_query(thd, thd->lex->query_tables);
-  }
+  /*
+    Tables must be locked before storing the query in the query cache.
+    Transactional engines must been signalled that the statement started,
+    which external_lock signals.
+  */
+  query_cache_store_query(thd, thd->lex->query_tables);
 
   res= unit->optimize() || unit->exec();
   res|= unit->cleanup();

=== modified file 'sql/sql_update.cc'
--- a/sql/sql_update.cc	revid:mattias.jonsson@oracle.com-20120509151124-m3yw998dio568l9u
+++ b/sql/sql_update.cc	revid:mattias.jonsson@stripped6s9fwt6zan6f
@@ -418,7 +418,7 @@ int mysql_update(THD *thd,
       bitmap_copy(&lock_partitions, &table->part_info->lock_partitions);
     }
 
-    if (prune_partitions(thd, table, conds, true))
+    if (prune_partitions(thd, table, conds))
       DBUG_RETURN(1);
     if (table->all_partitions_pruned_away)
     {

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (mattias.jonsson:3800 to 3801) WL#4443Mattias Jonsson20 May