List:Commits« Previous MessageNext Message »
From:Mattias Jonsson Date:May 8 2011 9:23pm
Subject:bzr commit into mysql-5.1 branch (mattias.jonsson:3682) Bug#53775
Bug#11761296
View as plain text  
#At file:///C:/ade/mysql-bzr/b11761296-5.1/ based on revid:alexander.nozdrin@stripped

 3682 Mattias Jonsson	2011-05-08
      Bug#11761296 bug#53775:
      QUERY ON PARTITIONED TABLE RETURNS
      CACHED RESULT FROM PREVIOUS TRANSACTION
      
      Partitioned tables used the default query cache
      implementations which always allowed queries
      to be cached and never used a callback to verify
      if the query still was valid.
      
      Fixed by implementing the register_query_cache_table
      function and a matching callback in ha_partition based
      on the following:
      1) from handler.h: generic (but static) call back function
      i.e. all tables/partitions will have the same callback function
      for the same engine.
      
      2) The only two engines that have own register_query_cache_table
      functions and are supported by ha_partition (MyISAM and InnoDB)
      does both always set engine_data to 0.
      
      Due to 1) the underlying engines callback can be registered on
      the TABLE_SHARE::ha_data which can be used by a new
      ha_partition callback function.
      
      Due to 2) a partitioned table can use the engine_data to
      store which partitions that were used in the query and
      that way optimize the callbacks to only callback the partitions
      used by the original query (with the limitation of 64 bit storage).

    removed:
      mysql-test/t/cache_innodb-master.opt
    added:
      mysql-test/r/cache_myisam.result
      mysql-test/r/partition_cache_innodb.result
      mysql-test/t/cache_myisam.test
      mysql-test/t/partition_cache_innodb.test
    modified:
      mysql-test/include/query_cache.inc
      mysql-test/r/cache_innodb.result
      sql/ha_partition.cc
      sql/ha_partition.h
      sql/sql_base.cc
=== modified file 'mysql-test/include/query_cache.inc'
--- a/mysql-test/include/query_cache.inc	2009-05-15 10:15:56 +0000
+++ b/mysql-test/include/query_cache.inc	2011-05-08 21:23:01 +0000
@@ -4,6 +4,9 @@
 #     $engine_type       -- storage engine to be tested
 #     $test_foreign_keys -- 0, skip foreign key tests
 #                        -- 1, do not skip foreign key tests
+#     $partitions_a      -- partition clause for tables with column 'a'
+#     $partitions_id     -- partition clause for tables with column 'id'
+#     $partitions_s1     -- partition clause for tables with column 's1'
 # have to be set before sourcing this script.
 #
 # Last update:
@@ -12,6 +15,8 @@
 #               main code went into include/query_cache.inc
 #
 
+let $save_query_cache_size=`select @@global.query_cache_size`;
+SET GLOBAL query_cache_size = 1024 * 1024;
 eval SET SESSION STORAGE_ENGINE = $engine_type;
 
 # Initialise
@@ -24,7 +29,7 @@ drop table if exists t1,t2,t3;
 #
 flush status;
 set autocommit=0;
-create table t1 (a int not null);
+eval create table t1 (a int not null)$partitions_a;
 insert into t1 values (1),(2),(3);
 select * from t1;
 show status like "Qcache_queries_in_cache";
@@ -32,15 +37,15 @@ drop table t1;
 commit;
 set autocommit=1;
 begin;
-create table t1 (a int not null);
+eval create table t1 (a int not null)$partitions_a;
 insert into t1 values (1),(2),(3);
 select * from t1;
 show status like "Qcache_queries_in_cache";
 drop table t1;
 commit;
-create table t1 (a int not null);
-create table t2 (a int not null);
-create table t3 (a int not null);
+eval create table t1 (a int not null)$partitions_a;
+eval create table t2 (a int not null)$partitions_a;
+eval create table t3 (a int not null)$partitions_a;
 insert into t1 values (1),(2);
 insert into t2 values (1),(2);
 insert into t3 values (1),(2);
@@ -67,7 +72,7 @@ commit;
 show status like "Qcache_queries_in_cache";
 drop table t3,t2,t1;
 
-CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY  (id));
+eval CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY  (id))$partitions_id;
 select count(*) from t1;
 insert into t1 (id) values (0);
 select count(*) from t1;
@@ -78,7 +83,6 @@ if ($test_foreign_keys)
 #
 # one statement roll back inside transation
 #
-let $save_query_cache_size=`select @@global.query_cache_size`;
 set GLOBAL query_cache_size=1355776;
 CREATE TABLE t1 ( id int(10) NOT NULL auto_increment, a varchar(25) default NULL, PRIMARY KEY  (id), UNIQUE KEY a (a));
 CREATE TABLE t2 ( id int(10) NOT NULL auto_increment, b varchar(25) default NULL, PRIMARY KEY  (id), UNIQUE KEY b (b));
@@ -118,7 +122,7 @@ SET GLOBAL query_cache_size = 200000;
 flush status;
 SET @@autocommit=1;
 eval SET SESSION STORAGE_ENGINE = $engine_type;
-CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1));
+eval CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1))$partitions_s1;
 INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10));
 COMMIT;
 START TRANSACTION;

=== modified file 'mysql-test/r/cache_innodb.result'
--- a/mysql-test/r/cache_innodb.result	2009-01-31 17:55:06 +0000
+++ b/mysql-test/r/cache_innodb.result	2011-05-08 21:23:01 +0000
@@ -1,3 +1,4 @@
+SET GLOBAL query_cache_size = 1024 * 1024;
 SET SESSION STORAGE_ENGINE = InnoDB;
 drop table if exists t1,t2,t3;
 flush status;
@@ -218,5 +219,5 @@ Qcache_queries_in_cache	1
 show status like "Qcache_hits";
 Variable_name	Value
 Qcache_hits	1
-set GLOBAL query_cache_size=1048576;
+set GLOBAL query_cache_size=0;
 drop table t2;

=== added file 'mysql-test/r/cache_myisam.result'
--- a/mysql-test/r/cache_myisam.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/cache_myisam.result	2011-05-08 21:23:01 +0000
@@ -0,0 +1,204 @@
+SET GLOBAL query_cache_size = 1024 * 1024;
+SET SESSION STORAGE_ENGINE = MyISAM;
+drop table if exists t1,t2,t3;
+flush status;
+set autocommit=0;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+drop table t1;
+commit;
+set autocommit=1;
+begin;
+create table t1 (a int not null);
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+drop table t1;
+commit;
+create table t1 (a int not null);
+create table t2 (a int not null);
+create table t3 (a int not null);
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	3
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	0
+begin;
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	6
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	0
+insert into t1 values (3);
+insert into t2 values (3);
+insert into t1 values (4);
+select * from t1;
+a
+1
+2
+3
+4
+select * from t2;
+a
+1
+2
+3
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	4
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	1
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	4
+drop table t3,t2,t1;
+CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY  (id));
+select count(*) from t1;
+count(*)
+0
+insert into t1 (id) values (0);
+select count(*) from t1;
+count(*)
+1
+drop table t1;
+SET SESSION STORAGE_ENGINE = MyISAM;
+SET @@autocommit=1;
+connection default
+SHOW VARIABLES LIKE 'have_query_cache';
+Variable_name	Value
+have_query_cache	YES
+SET GLOBAL query_cache_size = 200000;
+flush status;
+SET @@autocommit=1;
+SET SESSION STORAGE_ENGINE = MyISAM;
+CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1));
+INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10));
+COMMIT;
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+0
+UPDATE t2 SET s2 = 'w' WHERE s1 = 3;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+connection connection1
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+INSERT INTO t2 VALUES (5,'w');
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+COMMIT;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+connection default
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+COMMIT;
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+connection connection1
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+INSERT INTO t2 VALUES (6,'w');
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+3
+connection default
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+3
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+3
+DELETE from t2 WHERE s1=3;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+COMMIT;
+connection connection1
+COMMIT;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	6
+set GLOBAL query_cache_size=0;
+drop table t2;

=== added file 'mysql-test/r/partition_cache_innodb.result'
--- a/mysql-test/r/partition_cache_innodb.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/r/partition_cache_innodb.result	2011-05-08 21:23:01 +0000
@@ -0,0 +1,331 @@
+SET GLOBAL query_cache_size = 1024 * 1024;
+SET SESSION STORAGE_ENGINE = InnoDB;
+drop table if exists t1,t2,t3;
+flush status;
+set autocommit=0;
+create table t1 (a int not null) PARTITION BY HASH (a) PARTITIONS 7;
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	0
+drop table t1;
+commit;
+set autocommit=1;
+begin;
+create table t1 (a int not null) PARTITION BY HASH (a) PARTITIONS 7;
+insert into t1 values (1),(2),(3);
+select * from t1;
+a
+1
+2
+3
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+drop table t1;
+commit;
+create table t1 (a int not null) PARTITION BY HASH (a) PARTITIONS 7;
+create table t2 (a int not null) PARTITION BY HASH (a) PARTITIONS 7;
+create table t3 (a int not null) PARTITION BY HASH (a) PARTITIONS 7;
+insert into t1 values (1),(2);
+insert into t2 values (1),(2);
+insert into t3 values (1),(2);
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	3
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	0
+begin;
+select * from t1;
+a
+1
+2
+select * from t2;
+a
+1
+2
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	6
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	0
+insert into t1 values (3);
+insert into t2 values (3);
+insert into t1 values (4);
+select * from t1;
+a
+1
+2
+3
+4
+select * from t2;
+a
+1
+2
+3
+select * from t3;
+a
+1
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	1
+commit;
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	2
+drop table t3,t2,t1;
+CREATE TABLE t1 (id int(11) NOT NULL auto_increment, PRIMARY KEY  (id)) PARTITION BY HASH (id) PARTITIONS 7;
+select count(*) from t1;
+count(*)
+0
+insert into t1 (id) values (0);
+select count(*) from t1;
+count(*)
+1
+drop table t1;
+SET SESSION STORAGE_ENGINE = InnoDB;
+SET @@autocommit=1;
+connection default
+SHOW VARIABLES LIKE 'have_query_cache';
+Variable_name	Value
+have_query_cache	YES
+SET GLOBAL query_cache_size = 200000;
+flush status;
+SET @@autocommit=1;
+SET SESSION STORAGE_ENGINE = InnoDB;
+CREATE TABLE t2 (s1 int, s2 varchar(1000), key(s1)) PARTITION BY HASH (s1) PARTITIONS 7;
+INSERT INTO t2 VALUES (1,repeat('a',10)),(2,repeat('a',10)),(3,repeat('a',10)),(4,repeat('a',10));
+COMMIT;
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+0
+UPDATE t2 SET s2 = 'w' WHERE s1 = 3;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	0
+connection connection1
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+0
+INSERT INTO t2 VALUES (5,'w');
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+COMMIT;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	0
+connection default
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+COMMIT;
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	0
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+connection connection1
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+INSERT INTO t2 VALUES (6,'w');
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+3
+connection default
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+START TRANSACTION;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+DELETE from t2 WHERE s1=3;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+1
+COMMIT;
+connection connection1
+COMMIT;
+SELECT sql_cache count(*) FROM t2 WHERE s2 = 'w';
+count(*)
+2
+show status like "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+show status like "Qcache_hits";
+Variable_name	Value
+Qcache_hits	1
+set GLOBAL query_cache_size=0;
+drop table t2;
+SET GLOBAL query_cache_size = 1024 * 1024;
+create table t1
+(name varchar(128), 
+dept int, 
+primary key(dept,name))
+ENGINE=InnoDB
+PARTITION BY RANGE (`dept`) 
+(
+PARTITION d0 VALUES LESS THAN (1),
+PARTITION d1 VALUES LESS THAN (2), 
+PARTITION d2 VALUES LESS THAN (3),
+PARTITION d_other VALUES LESS THAN MAXVALUE);
+set autocommit=0;
+start transaction;
+insert into t1(name,dept) values('a',1);
+insert into t1(name,dept) values('b',1);
+insert into t1(name,dept) values('c',1);
+select count(*) from t1;
+count(*)
+3
+# expecting 3
+rollback;
+select count(*) from t1;
+count(*)
+0
+# expecting 0, and seeing 0
+select count(*) from t1;
+count(*)
+0
+# expecting 0, and seeing 3 before fix!
+drop table t1;
+CREATE TABLE `t1`
+(`id` int(11) NOT NULL ,
+`created_at` datetime NOT NULL,
+`cool` tinyint default 0
+) ENGINE=InnoDB;
+ALTER TABLE t1
+PARTITION BY RANGE (TO_DAYS(created_at))
+(PARTITION month_2010_4 VALUES LESS THAN (734258),
+PARTITION month_2010_5 VALUES LESS THAN (734289),
+PARTITION month_max VALUES LESS THAN MAXVALUE);
+INSERT INTO t1 VALUES (1, now(), 0);
+BEGIN;
+UPDATE `t1` SET `cool` = 1 WHERE `id` = 1;
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+cool
+1
+ROLLBACK;
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+cool
+0
+BEGIN;
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+cool
+0
+ROLLBACK;
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+cool
+0
+DROP TABLE `t1`;
+CREATE TABLE t1 (a INT, b VARCHAR(64))
+ENGINE = InnoDB
+PARTITION BY HASH (a)
+PARTITIONS 5;
+INSERT INTO t1 VALUES (11, 'Eleven'), (1, 'One'), (2, 'Two'), (12, 'aslasdrfa'), (7, 'sdfae'), (4, 'asdfees'), (14, '3asdf3'), (9, 'asdfeea');
+set autocommit=1;
+FLUSH STATUS;
+SELECT * FROM t1;
+a	b
+11	Eleven
+1	One
+2	Two
+12	aslasdrfa
+7	sdfae
+4	asdfees
+14	3asdf3
+9	asdfeea
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+SHOW STATUS LIKE "Qcache_inserts";
+Variable_name	Value
+Qcache_inserts	1
+SHOW STATUS LIKE "Qcache_hits";
+Variable_name	Value
+Qcache_hits	0
+SELECT * FROM t1;
+a	b
+11	Eleven
+1	One
+2	Two
+12	aslasdrfa
+7	sdfae
+4	asdfees
+14	3asdf3
+9	asdfeea
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+SHOW STATUS LIKE "Qcache_inserts";
+Variable_name	Value
+Qcache_inserts	1
+SHOW STATUS LIKE "Qcache_hits";
+Variable_name	Value
+Qcache_hits	1
+FLUSH TABLES;
+SELECT * FROM t1;
+a	b
+11	Eleven
+1	One
+2	Two
+12	aslasdrfa
+7	sdfae
+4	asdfees
+14	3asdf3
+9	asdfeea
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+Variable_name	Value
+Qcache_queries_in_cache	1
+SHOW STATUS LIKE "Qcache_inserts";
+Variable_name	Value
+Qcache_inserts	2
+SHOW STATUS LIKE "Qcache_hits";
+Variable_name	Value
+Qcache_hits	1
+DROP TABLE t1;
+set GLOBAL query_cache_size=0;

=== removed file 'mysql-test/t/cache_innodb-master.opt'
--- a/mysql-test/t/cache_innodb-master.opt	2006-08-16 12:58:49 +0000
+++ b/mysql-test/t/cache_innodb-master.opt	1970-01-01 00:00:00 +0000
@@ -1 +0,0 @@
---set-variable=query_cache_size=1M

=== added file 'mysql-test/t/cache_myisam.test'
--- a/mysql-test/t/cache_myisam.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/cache_myisam.test	2011-05-08 21:23:01 +0000
@@ -0,0 +1,7 @@
+--source include/have_query_cache.inc
+
+let $engine_type= MyISAM;
+# MyISAM does NOT supports FOREIGN KEYs
+let $test_foreign_keys= 0;
+
+--source include/query_cache.inc

=== added file 'mysql-test/t/partition_cache_innodb.test'
--- a/mysql-test/t/partition_cache_innodb.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/partition_cache_innodb.test	2011-05-08 21:23:01 +0000
@@ -0,0 +1,110 @@
+--source include/have_query_cache.inc
+
+--source include/have_innodb.inc
+--source include/have_partition.inc
+let $engine_type= InnoDB;
+# partitioned InnoDB does NOT supports FOREIGN KEYs
+let $test_foreign_keys= 0;
+
+# Using SELECT to get a space as first character.
+let $partitions_a= `SELECT ' PARTITION BY HASH (a) PARTITIONS 7'`;
+let $partitions_id= `SELECT ' PARTITION BY HASH (id) PARTITIONS 7'`;
+let $partitions_s1= `SELECT ' PARTITION BY HASH (s1) PARTITIONS 7'`;
+
+--source include/query_cache.inc
+
+let $save_query_cache_size=`select @@global.query_cache_size`;
+SET GLOBAL query_cache_size = 1024 * 1024;
+create table t1
+(name varchar(128), 
+ dept int, 
+ primary key(dept,name))
+ENGINE=InnoDB
+PARTITION BY RANGE (`dept`) 
+(
+ PARTITION d0 VALUES LESS THAN (1),
+ PARTITION d1 VALUES LESS THAN (2), 
+ PARTITION d2 VALUES LESS THAN (3),
+ PARTITION d_other VALUES LESS THAN MAXVALUE);
+
+set autocommit=0;
+start transaction;
+
+insert into t1(name,dept) values('a',1);
+insert into t1(name,dept) values('b',1);
+insert into t1(name,dept) values('c',1);
+
+select count(*) from t1;
+--echo # expecting 3
+rollback;
+
+select count(*) from t1;
+--echo # expecting 0, and seeing 0
+
+select count(*) from t1;
+--echo # expecting 0, and seeing 3 before fix!
+
+drop table t1;
+
+
+
+CREATE TABLE `t1`
+(`id` int(11) NOT NULL ,
+ `created_at` datetime NOT NULL,
+ `cool` tinyint default 0
+) ENGINE=InnoDB;
+
+ALTER TABLE t1
+PARTITION BY RANGE (TO_DAYS(created_at))
+(PARTITION month_2010_4 VALUES LESS THAN (734258),
+ PARTITION month_2010_5 VALUES LESS THAN (734289),
+ PARTITION month_max VALUES LESS THAN MAXVALUE);
+
+INSERT INTO t1 VALUES (1, now(), 0);
+
+BEGIN;
+
+UPDATE `t1` SET `cool` = 1 WHERE `id` = 1;
+
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+
+ROLLBACK;
+
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+
+BEGIN;
+
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+
+ROLLBACK;
+
+SELECT cool FROM `t1` WHERE (`t1`.id = 1) LIMIT 1;
+
+DROP TABLE `t1`;
+
+CREATE TABLE t1 (a INT, b VARCHAR(64))
+ENGINE = InnoDB
+PARTITION BY HASH (a)
+PARTITIONS 5;
+INSERT INTO t1 VALUES (11, 'Eleven'), (1, 'One'), (2, 'Two'), (12, 'aslasdrfa'), (7, 'sdfae'), (4, 'asdfees'), (14, '3asdf3'), (9, 'asdfeea');
+set autocommit=1;
+FLUSH STATUS;
+SELECT * FROM t1;
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+SHOW STATUS LIKE "Qcache_inserts";
+SHOW STATUS LIKE "Qcache_hits";
+SELECT * FROM t1;
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+SHOW STATUS LIKE "Qcache_inserts";
+SHOW STATUS LIKE "Qcache_hits";
+FLUSH TABLES;
+SELECT * FROM t1;
+SHOW STATUS LIKE "Qcache_queries_in_cache";
+SHOW STATUS LIKE "Qcache_inserts";
+SHOW STATUS LIKE "Qcache_hits";
+DROP TABLE t1;
+eval set GLOBAL query_cache_size=$save_query_cache_size;
+--echo # TODO: Add tests of partition pruning of
+--echo #       64, 65, 255, 256 and 1024 partitions
+--echo #       0-64, 0-9+65, 0-9+255, 0-5+256 and 0-5+1024
+--echo #       non pruned partitions)

=== modified file 'sql/ha_partition.cc'
--- a/sql/ha_partition.cc	2011-04-29 07:48:26 +0000
+++ b/sql/ha_partition.cc	2011-05-08 21:23:01 +0000
@@ -392,7 +392,7 @@ bool ha_partition::initialize_partition(
     DBUG_RETURN(0);
   }
   else if (get_from_handler_file(table_share->normalized_path.str,
-                                 mem_root, false))
+                                 mem_root, false, NULL))
   {
     my_message(ER_UNKNOWN_ERROR, "Failed to read from the .par file", MYF(0));
     DBUG_RETURN(1);
@@ -1881,7 +1881,7 @@ uint ha_partition::del_ren_cre_table(con
     DBUG_RETURN(TRUE);
   }
 
-  if (get_from_handler_file(from, ha_thd()->mem_root, false))
+  if (get_from_handler_file(from, ha_thd()->mem_root, false, NULL))
     DBUG_RETURN(TRUE);
   DBUG_ASSERT(m_file_buffer);
   DBUG_PRINT("enter", ("from: (%s) to: (%s)", from, to));
@@ -2385,7 +2385,8 @@ error_end:
 /**
   Read the .par file to get the partitions engines and names
 
-  @param name  Name of table file (without extention)
+  @param      name                Name of table file (without extention)
+  @param[out] name_buffer_length  Length of the m_name_buffer
 
   @return Operation status
     @retval true   Failure
@@ -2395,7 +2396,7 @@ error_end:
   freed by the caller. m_name_buffer_ptr and m_tot_parts is also set.
 */
 
-bool ha_partition::read_par_file(const char *name)
+bool ha_partition::read_par_file(const char *name, uint *name_buffer_length)
 {
   char buff[FN_REFLEN], *tot_name_len_offset;
   File file;
@@ -2443,6 +2444,8 @@ bool ha_partition::read_par_file(const c
     goto err2;
   VOID(my_close(file, MYF(0)));
   m_file_buffer= file_buffer;          // Will be freed in clear_handler_file()
+  if (name_buffer_length)
+    *name_buffer_length= uint4korr(tot_name_len_offset);
   m_name_buffer_ptr= tot_name_len_offset + PAR_WORD_SIZE;
 
   DBUG_RETURN(false);
@@ -2524,16 +2527,22 @@ err:
   partitions.
 */
 
-bool ha_partition::get_from_handler_file(const char *name, MEM_ROOT *mem_root,
-                                         bool is_clone)
+bool ha_partition::get_from_handler_file(const char *name,
+                                         MEM_ROOT *mem_root,
+                                         bool is_clone,
+                                         uint *name_buffer_length)
 {
   DBUG_ENTER("ha_partition::get_from_handler_file");
   DBUG_PRINT("enter", ("table name: '%s'", name));
 
   if (m_file_buffer)
+  {
+    if (name_buffer_length)
+      *name_buffer_length= uint4korr(m_name_buffer_ptr - PAR_WORD_SIZE);
     DBUG_RETURN(false);
+  }
 
-  if (read_par_file(name))
+  if (read_par_file(name, name_buffer_length))
     DBUG_RETURN(true);
 
   if (!is_clone && setup_engine_array(mem_root))
@@ -2588,7 +2597,7 @@ int ha_partition::open(const char *name,
 {
   char *name_buffer_ptr;
   int error= HA_ERR_INITIALIZATION;
-  uint alloc_len;
+  uint alloc_len, name_buffer_length;
   handler **file;
   char name_buff[FN_REFLEN];
   bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
@@ -2600,7 +2609,8 @@ int ha_partition::open(const char *name,
   m_mode= mode;
   m_open_test_lock= test_if_locked;
   m_part_field_array= m_part_info->full_part_field_array;
-  if (get_from_handler_file(name, &table->mem_root, test(m_is_clone_of)))
+  if (get_from_handler_file(name, &table->mem_root, test(m_is_clone_of),
+                            &name_buffer_length))
     DBUG_RETURN(error);
   name_buffer_ptr= m_name_buffer_ptr;
   m_start_key.length= 0;
@@ -2633,6 +2643,48 @@ int ha_partition::open(const char *name,
     }
   }
 
+  /*
+    Use table_share->ha_data to:
+    - share auto_increment_value among all handlers for the same table.
+    - store a copy of all partition names.
+  */
+  if (is_not_tmp_table)
+    pthread_mutex_lock(&table_share->mutex);
+  if (!table_share->ha_data)
+  {
+    HA_DATA_PARTITION *ha_data;
+    /* currently only needed for auto_increment */
+    table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
+                                   alloc_root(&table_share->mem_root,
+                                              sizeof(HA_DATA_PARTITION));
+    if (!ha_data)
+    {
+      if (is_not_tmp_table)
+        pthread_mutex_unlock(&table_share->mutex);
+      DBUG_RETURN(HA_ERR_INITIALIZATION);
+    }
+    DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
+    bzero(ha_data, sizeof(HA_DATA_PARTITION));
+    table_share->ha_data_destroy= ha_data_partition_destroy;
+    VOID(pthread_mutex_init(&ha_data->LOCK_auto_inc, MY_MUTEX_INIT_FAST));
+    ha_data->num_tot_parts= m_tot_parts;
+    /* Allocate space for all partition names + one extra '\0' at the end */
+    ha_data->partition_names= (char*) alloc_root(&table_share->mem_root,
+                                                 name_buffer_length + 1);
+                                        
+    if (!ha_data->partition_names)
+    {
+      if (is_not_tmp_table)
+        pthread_mutex_unlock(&table_share->mutex);
+      DBUG_RETURN(HA_ERR_INITIALIZATION);
+    }
+    memcpy((void *) ha_data->partition_names, (void *) m_name_buffer_ptr,
+           name_buffer_length);
+    memset((void *) (ha_data->partition_names + name_buffer_length), 0, 1);
+  }
+  if (is_not_tmp_table)
+    pthread_mutex_unlock(&table_share->mutex);
+
   /* Initialize the bitmap we use to minimize ha_start_bulk_insert calls */
   if (bitmap_init(&m_bulk_insert_started, NULL, m_tot_parts + 1, FALSE))
     DBUG_RETURN(error);
@@ -2735,32 +2787,6 @@ int ha_partition::open(const char *name,
     goto err_handler;
 
   /*
-    Use table_share->ha_data to share auto_increment_value among all handlers
-    for the same table.
-  */
-  if (is_not_tmp_table)
-    pthread_mutex_lock(&table_share->mutex);
-  if (!table_share->ha_data)
-  {
-    HA_DATA_PARTITION *ha_data;
-    /* currently only needed for auto_increment */
-    table_share->ha_data= ha_data= (HA_DATA_PARTITION*)
-                                   alloc_root(&table_share->mem_root,
-                                              sizeof(HA_DATA_PARTITION));
-    if (!ha_data)
-    {
-      if (is_not_tmp_table)
-        pthread_mutex_unlock(&table_share->mutex);
-      goto err_handler;
-    }
-    DBUG_PRINT("info", ("table_share->ha_data 0x%p", ha_data));
-    bzero(ha_data, sizeof(HA_DATA_PARTITION));
-    table_share->ha_data_destroy= ha_data_partition_destroy;
-    VOID(pthread_mutex_init(&ha_data->LOCK_auto_inc, MY_MUTEX_INIT_FAST));
-  }
-  if (is_not_tmp_table)
-    pthread_mutex_unlock(&table_share->mutex);
-  /*
     Some handlers update statistics as part of the open call. This will in
     some cases corrupt the statistics of the partition handler and thus
     to ensure we have correct statistics we call info from open after
@@ -6339,6 +6365,9 @@ bool ha_partition::can_switch_engines()
 }
 
 
+/****************************************************************************
+                MODULE query cache
+****************************************************************************/
 /*
   Is table cache supported
 
@@ -6355,6 +6384,302 @@ uint8 ha_partition::table_cache_type()
 }
 
 
+/**
+  Callback for verifying that the partitioned table has not changed.
+  
+    @param thd          THD
+    @param key          table key (db\0table)
+    @param len          length of key
+    @param engine_data  Engine specific data
+
+  @return True if result still is valid.
+*/
+
+static my_bool partition_qc_check_callback(THD *thd,
+                                           char *key,
+                                           uint len,
+                                           ulonglong *engine_data)
+{
+  TABLE_SHARE *share;
+  int dummy, is_still_valid= 0;
+  uint tot_parts, part_id= 0;
+  HA_DATA_PARTITION *ha_data;
+  const char *part_name= NULL;
+
+  DBUG_ENTER("partition_qc_check_callback");
+  share= get_table_share(thd, NULL, key, len, 0, &dummy);
+  if (!share)
+  {
+    DBUG_PRINT("info", ("db: %s table: %s no share found (qc_check_callback)",
+                        key, key + strlen(key) + 1));
+    DBUG_RETURN(FALSE);
+  }
+
+  /*
+    Since ha_data->partition_names and ha_data->static_qc_callback
+    only are set once and never reset or changed it is safe to check
+    first without holding a mutex.
+  */
+  ha_data= (HA_DATA_PARTITION*) share->ha_data;
+  if (ha_data && ha_data->static_qc_callback)
+  {
+    part_name= ha_data->partition_names;
+    tot_parts= ha_data->num_tot_parts;
+  }
+  else
+  {
+    pthread_mutex_lock(&share->mutex);
+    if (ha_data && ha_data->static_qc_callback)
+    {
+      part_name= ha_data->partition_names;
+      tot_parts= ha_data->num_tot_parts;
+    }
+    pthread_mutex_unlock(&share->mutex);
+  }
+  
+  /* Remove this if hit, might be possible right after a FLUSH TABLES? */
+  DBUG_ASSERT(part_name && tot_parts);
+  
+
+  /* loop through all names and their callbacks */
+  if (part_name)
+  {
+    char part_name_key[FN_REFLEN], *part_name_start;
+    uint part_id= 0, part_count= 0;
+    memcpy(part_name_key, key, len);
+    part_name_start= part_name_key + len - 1;
+    while (*part_name)
+    {
+      if (*engine_data)
+      {
+         /*
+          Check if it is pruning was used (engine_data).
+          See register function below.
+        */
+        if (tot_parts <= 64)
+        {
+          ulonglong pruned_engine_data= *engine_data;
+          if (!(pruned_engine_data & (1ULL << part_id)))
+            goto next_part;
+        }
+        else if (tot_parts <= 255)
+        {
+          uint8 *pruned_engine_data= (uint8*) engine_data;
+          DBUG_ASSERT(part_count < 8);
+          if (!pruned_engine_data[part_count])
+            break;
+          if ((part_id + 1) != pruned_engine_data[part_count])
+            goto next_part;
+        }
+        else
+        {
+          uint16 *pruned_engine_data= (uint16*) engine_data;
+          DBUG_ASSERT(part_count < 4);
+          if (!pruned_engine_data[part_count])
+            break;
+          if ((part_id + 1) != pruned_engine_data[part_count])
+            goto next_part;
+        }
+      }
+      /* create new key + lenght */
+      create_partition_name(part_name_start, "",
+                            part_name, NORMAL_PART_NAME, FALSE);
+      if (!ha_data->static_qc_callback(thd, part_name_key,
+                                       len + strlen(part_name_start),
+                                       engine_data))
+      {
+        DBUG_PRINT("info", ("part: %s callback does not allow cached result",
+                          part_name_start));
+        goto err;
+      }
+      part_count++;
+next_part:
+      part_name+= strlen(part_name) + 1;
+      part_id++;
+    }
+    is_still_valid= 1;
+  }
+err:
+  release_table_share(share, RELEASE_NORMAL);
+  DBUG_RETURN(test(is_still_valid));
+}
+
+
+/**
+  Register a table to be cached with a query.
+
+    @param thd              Thread
+    @param table_key        dbname\0tablename\0
+    @param key_length       Lenght of table_key
+    @param engine_callback  Function callback for checking if table is changed
+    @param engine_data      Engine specific data
+
+  @return True if the query can be cached
+    @retval TRUE   OK to cache query
+    @retval FALSE  can not cache query
+
+  @note Since partitioning does not support foreign keys, there will not be any
+  internal invalidations by InnoDB.
+
+  Implemented by forward the call to every partition, with its unique partition
+  name. If not all partitions return the same callback and engine_data we
+  cannot succeed (both MyISAM and InnoDB have a static callback and don't use
+  the engine_data).
+*/
+
+my_bool ha_partition::register_query_cache_table(THD *thd, char *table_key,
+                                                 uint key_length,
+                                                 qc_engine_callback
+                                                 *engine_callback,
+                                                 ulonglong *engine_data)
+{
+  qc_engine_callback first_callback, part_callback;
+  ulonglong first_data= 0, part_engine_data, pruned_engine_data= 0;
+  bool first_set= false;
+  handler **file;
+  char part_name_key[FN_REFLEN], *part_name_start;
+  const char *part_name=
+                ((HA_DATA_PARTITION*) table_share->ha_data)->partition_names;
+  DBUG_ENTER("ha_partition::register_query_cache_table");
+
+  /*
+    Check if it is possible to use pruning by using
+    the unused engine_data.
+    Like:
+    TODO: Fix this scheme, fails if only first partition is used!
+    Solve by moving part_id range with one -> 1..m_tot_parts instead
+    of 0..(m_tot_parts - 1)
+    If <= 64 parts use as bitmap.
+    If (> 64 parts && <= 255 parts && max 8 partitions used) use
+    each byte as (partition id + 1) (uint8).
+    If (> 255 parts && max 4 partitions used) use
+    each pair of byte as (partition id + 1) (uint16).
+  */
+  if (m_tot_parts <= 64)
+  {
+    uint part_id= bitmap_get_first_set(&m_part_info->used_partitions);
+    for (;part_id < m_tot_parts; part_id++)
+    {
+      if (bitmap_is_set(&m_part_info->used_partitions, part_id))
+        pruned_engine_data|= 1ULL << part_id;
+    }
+  }
+  else if (m_tot_parts <= 255)
+  {
+    if (bitmap_bits_set(&m_part_info->used_partitions) <= 8)
+    {
+      uint part_id= bitmap_get_first_set(&m_part_info->used_partitions);
+      uint part_count= 0;
+      uint8 *pruned_engine_data_array= (uint8*) &pruned_engine_data;
+      for (;part_id < m_tot_parts; part_id++)
+      {
+        if (bitmap_is_set(&m_part_info->used_partitions, part_id))
+          pruned_engine_data_array[part_count++]= (part_id + 1);
+        DBUG_ASSERT(part_count <= 8);
+      }
+    }
+  }
+  else
+  {
+    if (bitmap_bits_set(&m_part_info->used_partitions) <= 4)
+    {
+      uint part_id= bitmap_get_first_set(&m_part_info->used_partitions);
+      uint part_count= 0;
+      uint16 *pruned_engine_data_array= (uint16*) &pruned_engine_data;
+      for (;part_id < m_tot_parts; part_id++)
+      {
+        if (bitmap_is_set(&m_part_info->used_partitions, part_id))
+          pruned_engine_data_array[part_count++]= (part_id + 1);
+        DBUG_ASSERT(part_count <= 4);
+      }
+    }
+  }
+  file= m_file;
+  memcpy(part_name_key, table_key, key_length);
+  part_name_start= part_name_key + key_length - 1;
+  do
+  {
+    if (!pruned_engine_data || bitmap_is_set(&m_part_info->used_partitions,
+                                             file - m_file))
+    {
+      create_partition_name(part_name_start, "",
+                            part_name, NORMAL_PART_NAME, FALSE);  
+      if (!(*file)->register_query_cache_table(thd, part_name_key,
+                                               key_length +
+                                               strlen(part_name_start),
+                                               &part_callback,
+                                               &part_engine_data))
+      {
+        DBUG_PRINT("info", ("part: %s failed register_query_cache_table",
+                            part_name_start));
+        DBUG_RETURN(FALSE);
+      }
+
+      /*
+        All partitions must have same callback function and engine_data.
+        MyISAM sets both callback and data = 0.
+        InnoDB uses a static function for callback and sets data = 0.
+      */
+      if (!first_set)
+      {
+        first_callback= part_callback;
+        first_data= part_engine_data;
+        first_set= true;
+      }
+      if (first_callback != part_callback || first_data != part_engine_data)
+      {
+        DBUG_PRINT("info", ("part: %s different callback function/engine data",
+                            part_name_start));
+        DBUG_RETURN(FALSE);
+      }
+    }
+    part_name+= strlen(part_name) + 1;
+
+  } while (*(++file));
+  
+  if (first_callback)
+  {
+    HA_DATA_PARTITION *ha_data= (HA_DATA_PARTITION*) table_share->ha_data;
+    /*
+      Verify if it is the same as ha_data->qc_callback.
+      Or register if never set.
+      This is only set by the first call from the first instance
+      and never reset or changed, so it is safe to check first without
+      taking the table_share->mutex.
+    */
+    DBUG_ASSERT(ha_data);
+    if (!ha_data->static_qc_callback)
+    {
+      pthread_mutex_lock(&table_share->mutex);
+      ha_data->static_qc_callback= first_callback;
+      pthread_mutex_unlock(&table_share->mutex);
+    }
+    
+    if (ha_data->static_qc_callback != first_callback)
+    {
+      /* If this is hit, the underlying engine have changed the callback! */
+      DBUG_ASSERT(0);
+      DBUG_RETURN(FALSE);
+    }
+
+    *engine_callback= partition_qc_check_callback;
+  }
+
+  /*
+    Neither InnoDB or MyISAM use engine_data.
+    If set, we must remove the pruning optimization!
+  */
+  DBUG_ASSERT(!first_data);
+  if (first_data)
+  {
+    DBUG_RETURN(FALSE);
+  }
+
+  *engine_data= pruned_engine_data;
+
+  DBUG_RETURN(TRUE);
+}
+
 /****************************************************************************
                 MODULE print messages
 ****************************************************************************/
@@ -6898,128 +7223,6 @@ int ha_partition::indexes_are_disabled(v
   return error;
 }
 
-
-/****************************************************************************
-                MODULE Partition Share
-****************************************************************************/
-/*
-  Service routines for ... methods.
--------------------------------------------------------------------------
-  Variables for partition share methods. A hash used to track open tables.
-  A mutex for the hash table and an init variable to check if hash table
-  is initialized.
-  There is also a constant ending of the partition handler file name.
-*/
-
-#ifdef NOT_USED
-static HASH partition_open_tables;
-static pthread_mutex_t partition_mutex;
-static int partition_init= 0;
-
-
-/*
-  Function we use in the creation of our hash to get key.
-*/
-
-static uchar *partition_get_key(PARTITION_SHARE *share, size_t *length,
-			       my_bool not_used __attribute__ ((unused)))
-{
-  *length= share->table_name_length;
-  return (uchar *) share->table_name;
-}
-
-/*
-  Example of simple lock controls. The "share" it creates is structure we
-  will pass to each partition handler. Do you have to have one of these?
-  Well, you have pieces that are used for locking, and they are needed to
-  function.
-*/
-
-static PARTITION_SHARE *get_share(const char *table_name, TABLE *table)
-{
-  PARTITION_SHARE *share;
-  uint length;
-  char *tmp_name;
-
-  /*
-    So why does this exist? There is no way currently to init a storage
-    engine.
-    Innodb and BDB both have modifications to the server to allow them to
-    do this. Since you will not want to do this, this is probably the next
-    best method.
-  */
-  if (!partition_init)
-  {
-    /* Hijack a mutex for init'ing the storage engine */
-    pthread_mutex_lock(&LOCK_mysql_create_db);
-    if (!partition_init)
-    {
-      partition_init++;
-      VOID(pthread_mutex_init(&partition_mutex, MY_MUTEX_INIT_FAST));
-      (void) hash_init(&partition_open_tables, system_charset_info, 32, 0, 0,
-		       (hash_get_key) partition_get_key, 0, 0);
-    }
-    pthread_mutex_unlock(&LOCK_mysql_create_db);
-  }
-  pthread_mutex_lock(&partition_mutex);
-  length= (uint) strlen(table_name);
-
-  if (!(share= (PARTITION_SHARE *) hash_search(&partition_open_tables,
-					       (uchar *) table_name, length)))
-  {
-    if (!(share= (PARTITION_SHARE *)
-	  my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
-			  &share, (uint) sizeof(*share),
-			  &tmp_name, (uint) length + 1, NullS)))
-    {
-      pthread_mutex_unlock(&partition_mutex);
-      return NULL;
-    }
-
-    share->use_count= 0;
-    share->table_name_length= length;
-    share->table_name= tmp_name;
-    strmov(share->table_name, table_name);
-    if (my_hash_insert(&partition_open_tables, (uchar *) share))
-      goto error;
-    thr_lock_init(&share->lock);
-    pthread_mutex_init(&share->mutex, MY_MUTEX_INIT_FAST);
-  }
-  share->use_count++;
-  pthread_mutex_unlock(&partition_mutex);
-
-  return share;
-
-error:
-  pthread_mutex_unlock(&partition_mutex);
-  my_free((uchar*) share, MYF(0));
-
-  return NULL;
-}
-
-
-/*
-  Free lock controls. We call this whenever we close a table. If the table
-  had the last reference to the share then we free memory associated with
-  it.
-*/
-
-static int free_share(PARTITION_SHARE *share)
-{
-  pthread_mutex_lock(&partition_mutex);
-  if (!--share->use_count)
-  {
-    hash_delete(&partition_open_tables, (uchar *) share);
-    thr_lock_delete(&share->lock);
-    pthread_mutex_destroy(&share->mutex);
-    my_free((uchar*) share, MYF(0));
-  }
-  pthread_mutex_unlock(&partition_mutex);
-
-  return 0;
-}
-#endif /* NOT_USED */
-
 struct st_mysql_storage_engine partition_storage_engine=
 { MYSQL_HANDLERTON_INTERFACE_VERSION };
 

=== modified file 'sql/ha_partition.h'
--- a/sql/ha_partition.h	2011-04-20 15:52:33 +0000
+++ b/sql/ha_partition.h	2011-05-08 21:23:01 +0000
@@ -22,20 +22,6 @@ enum partition_keywords
   PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR
 };
 
-/*
-  PARTITION_SHARE is a structure that will be shared amoung all open handlers
-  The partition implements the minimum of what you will probably need.
-*/
-
-#ifdef NOT_USED
-typedef struct st_partition_share
-{
-  char *table_name;
-  uint table_name_length, use_count;
-  pthread_mutex_t mutex;
-  THR_LOCK lock;
-} PARTITION_SHARE;
-#endif
 
 /**
   Partition specific ha_data struct.
@@ -46,6 +32,13 @@ typedef struct st_ha_data_partition
   ulonglong next_auto_inc_val;                 /**< first non reserved value */
   pthread_mutex_t LOCK_auto_inc;
   bool auto_inc_initialized;
+  /*
+    All partition names in file-name format with '\0' in between and two
+    '\0' at the end.
+  */
+  const char *partition_names;
+  qc_engine_callback static_qc_callback;
+  uint num_tot_parts;
 } HA_DATA_PARTITION;
 
 #define PARTITION_BYTES_IN_POS 2
@@ -292,9 +285,9 @@ private:
   */
   bool create_handler_file(const char *name);
   bool setup_engine_array(MEM_ROOT *mem_root);
-  bool read_par_file(const char *name);
+  bool read_par_file(const char *name, uint *name_buffer_length);
   bool get_from_handler_file(const char *name, MEM_ROOT *mem_root,
-                             bool is_clone);
+                             bool is_clone, uint *name_buffer_length);
   bool new_handlers_from_part_info(MEM_ROOT *mem_root);
   bool create_handlers(MEM_ROOT *mem_root);
   void clear_handler_file();
@@ -627,6 +620,11 @@ public:
     underlying handlers must have the same implementation for it to work.
   */
   virtual uint8 table_cache_type();
+  virtual my_bool register_query_cache_table(THD *thd, char *table_key,
+                                             uint key_length,
+                                             qc_engine_callback
+                                             *engine_callback,
+                                             ulonglong *engine_data);
   virtual ha_rows records();
 
   /*

=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc	2011-03-29 08:09:05 +0000
+++ b/sql/sql_base.cc	2011-05-08 21:23:01 +0000
@@ -345,7 +345,7 @@ TABLE_SHARE *get_table_share(THD *thd, T
                                          key_length)))
     goto found;
 
-  if (!(share= alloc_table_share(table_list, key, key_length)))
+  if (!table_list || !(share= alloc_table_share(table_list, key, key_length)))
   {
     DBUG_RETURN(0);
   }


Attachment: [text/bzr-bundle] bzr/mattias.jonsson@oracle.com-20110508212301-mgo9udm02i4ug584.bundle
Thread
bzr commit into mysql-5.1 branch (mattias.jonsson:3682) Bug#53775Bug#11761296Mattias Jonsson8 May