summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMattias Jonsson <mattias.jonsson@sun.com>2009-12-15 23:47:04 +0100
committerMattias Jonsson <mattias.jonsson@sun.com>2009-12-15 23:47:04 +0100
commita39a91112eb541788ea2346fc6793320ba9ba82c (patch)
tree1aa7c04d9e07d76518286c7d94fd6662a5a5bb93
parent0b1a15e9a73126254d23f3c15576e8496b2efdbc (diff)
parentdd46365a0bf752766a71ffc871dcedd29ff02200 (diff)
downloadmariadb-git-a39a91112eb541788ea2346fc6793320ba9ba82c.tar.gz
merge (and including the fix for bug#48939 since that was not included in mysql-trunk-bugfixing).
-rw-r--r--mysql-test/include/check_key_reads.inc6
-rw-r--r--mysql-test/include/check_key_req.inc9
-rw-r--r--mysql-test/r/partition_key_cache.result420
-rw-r--r--mysql-test/t/partition_key_cache.test252
-rw-r--r--sql/protocol.cc4
5 files changed, 689 insertions, 2 deletions
diff --git a/mysql-test/include/check_key_reads.inc b/mysql-test/include/check_key_reads.inc
new file mode 100644
index 00000000000..cfb754bccd4
--- /dev/null
+++ b/mysql-test/include/check_key_reads.inc
@@ -0,0 +1,6 @@
+# include file for checking if variable key_reads is zero
+let $key_reads= query_get_value(SHOW STATUS LIKE 'key_reads',Value,1);
+--disable_query_log
+eval SELECT IF($key_reads = 0, "Yes!", "No!") as 'Zero key reads?';
+FLUSH STATUS;
+--enable_query_log
diff --git a/mysql-test/include/check_key_req.inc b/mysql-test/include/check_key_req.inc
new file mode 100644
index 00000000000..92a81f09d91
--- /dev/null
+++ b/mysql-test/include/check_key_req.inc
@@ -0,0 +1,9 @@
+# include file for checking if variable key_reads = key_read_requests
+let $key_reads= query_get_value(SHOW STATUS LIKE 'key_reads',Value,1);
+let $key_r_req= query_get_value(SHOW STATUS LIKE 'key_read_requests',Value,1);
+let $key_writes= query_get_value(SHOW STATUS LIKE 'key_writes',Value,1);
+let $key_w_req= query_get_value(SHOW STATUS LIKE 'key_write_requests',Value,1);
+--disable_query_log
+eval SELECT IF($key_reads = $key_r_req, "reads == requests", "reads != requests") as 'reads vs requests';
+eval SELECT IF($key_writes = $key_w_req, "writes == requests", "writes != requests") as 'writes vs requests';
+--enable_query_log
diff --git a/mysql-test/r/partition_key_cache.result b/mysql-test/r/partition_key_cache.result
new file mode 100644
index 00000000000..c09f277840b
--- /dev/null
+++ b/mysql-test/r/partition_key_cache.result
@@ -0,0 +1,420 @@
+DROP TABLE IF EXISTS t1, t2, v, x;
+# Actual test of key caches
+# Verifing that reads/writes use the key cache correctly
+SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size;
+@org_key_cache_buffer_size:= @@global.default.key_buffer_size
+1048576
+# Minimize default key cache (almost disabled).
+SET @@global.default.key_buffer_size = 1;
+Warnings:
+Warning 1292 Truncated incorrect key_buffer_size value: '1'
+SELECT @@global.default.key_buffer_size;
+@@global.default.key_buffer_size
+36
+CREATE TABLE t1 (
+a INT,
+b INT,
+c INT NOT NULL,
+PRIMARY KEY (a),
+KEY `inx_b` (b))
+PARTITION BY RANGE (a)
+SUBPARTITION BY HASH (a)
+(PARTITION p0 VALUES LESS THAN (1167602410)
+(SUBPARTITION sp0,
+SUBPARTITION sp1),
+PARTITION p1 VALUES LESS THAN MAXVALUE
+(SUBPARTITION sp2,
+SUBPARTITION sp3));
+CREATE TABLE t2 (
+a INT,
+b INT,
+c INT NOT NULL,
+PRIMARY KEY (a),
+KEY `inx_b` (b));
+FLUSH TABLES;
+FLUSH STATUS;
+SET @a:=1167602400;
+CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4;
+CREATE VIEW x AS SELECT 1 FROM v,v a,v b;
+FLUSH STATUS;
+INSERT t1 SELECT @a, @a * (1 - ((@a % 2) * 2)) , 1167612400 - (@a:=@a+1) FROM x, x y;
+reads vs requests
+reads == requests
+writes vs requests
+writes == requests
+# row distribution:
+SELECT PARTITION_NAME, SUBPARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' and TABLE_NAME='t1';
+PARTITION_NAME SUBPARTITION_NAME TABLE_ROWS
+p0 sp0 5
+p0 sp1 5
+p1 sp2 2043
+p1 sp3 2043
+DROP VIEW x;
+DROP VIEW v;
+FLUSH TABLES;
+FLUSH STATUS;
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+INSERT t2 SELECT a,b,c FROM t1;
+reads vs requests
+reads == requests
+writes vs requests
+writes == requests
+FLUSH STATUS;
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+FLUSH TABLES;
+# Setting the default key cache to 1M
+SET GLOBAL key_buffer_size = 1024*1024;
+FLUSH STATUS;
+# All these have to read the indexes
+LOAD INDEX INTO CACHE t1 PARTITION (p1);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+Zero key reads?
+No!
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+# All these should be able to use the key cache
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+Yes!
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+Yes!
+FLUSH TABLES;
+LOAD INDEX INTO CACHE t1 PARTITION (p1,p0);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+Zero key reads?
+No!
+# should not be zero
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+Yes!
+LOAD INDEX INTO CACHE t2;
+Table Op Msg_type Msg_text
+test.t2 preload_keys status OK
+Zero key reads?
+No!
+# should not be zero
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+Yes!
+FLUSH TABLES;
+LOAD INDEX INTO CACHE t1 PARTITION (p1,p0) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+Zero key reads?
+No!
+# should not be zero
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+LOAD INDEX INTO CACHE t2 IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys status OK
+Zero key reads?
+No!
+# should not be zero
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+COUNT(b)
+2048
+Zero key reads?
+No!
+TRUNCATE TABLE t2;
+INSERT t2 SELECT a,b,c FROM t1;
+reads vs requests
+reads != requests
+writes vs requests
+writes != requests
+DROP TABLE t1,t2;
+SET GLOBAL hot_cache.key_buffer_size = 1024*1024;
+SET GLOBAL warm_cache.key_buffer_size = 1024*1024;
+SET @@global.cold_cache.key_buffer_size = 1024*1024;
+SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d;
+a b c d
+1048576 1024 300 100
+SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d;
+a b c d
+1048576 1024 300 100
+SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d;
+a b c d
+1048576 1024 300 100
+SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d;
+a b c d
+1048576 1024 300 100
+CREATE TABLE t1 (
+a INT,
+b VARCHAR(257),
+c INT NOT NULL,
+PRIMARY KEY (a),
+KEY `inx_b` (b),
+KEY `inx_c`(c))
+PARTITION BY RANGE (a)
+SUBPARTITION BY HASH (a)
+(PARTITION p0 VALUES LESS THAN (10)
+(SUBPARTITION sp0,
+SUBPARTITION sp1),
+PARTITION p1 VALUES LESS THAN MAXVALUE
+(SUBPARTITION sp2,
+SUBPARTITION sp3));
+CREATE TABLE t2 (
+a INT,
+b VARCHAR(257),
+c INT NOT NULL,
+PRIMARY KEY (a),
+KEY `inx_b` (b),
+KEY `inx_c`(c));
+SET @a:=1167602400;
+CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4;
+CREATE VIEW x AS SELECT 1 FROM v,v a,v b;
+INSERT t1 SELECT @a, CONCAT('X_', @a, ' MySQL'), 1167612400 - (@a:=@a+1) FROM x, x a;
+DROP VIEW x;
+DROP VIEW v;
+INSERT t2 SELECT a, b, c FROM t1;
+SELECT COUNT(*) FROM t1;
+COUNT(*)
+4096
+SELECT COUNT(*) FROM t2;
+COUNT(*)
+4096
+FLUSH TABLES;
+# Restrict partitioned commands to partitioned tables only
+CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+ERROR HY000: Partition management on a not partitioned table is not possible
+CACHE INDEX t2 PARTITION (p0,`p1`) INDEX (`PRIMARY`) IN hot_cache;
+ERROR HY000: Partition management on a not partitioned table is not possible
+CACHE INDEX t2 PARTITION (`p1`) INDEX (`PRIMARY`,`inx_b`) IN hot_cache;
+ERROR HY000: Partition management on a not partitioned table is not possible
+CACHE INDEX t2 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN hot_cache;
+ERROR HY000: Partition management on a not partitioned table is not possible
+# Basic key cache testing
+# The manual correctly says: "The syntax of CACHE INDEX enables you to
+# specify that only particular indexes from a table should be assigned
+# to the cache. The current implementation assigns all the table's
+# indexes to the cache, so there is no reason to specify anything
+# other than the table name."
+# So the most of the test only tests the syntax
+CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t2 KEY (`PRIMARY`) IN warm_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t2 KEY (`PRIMARY`,`inx_b`) IN cold_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t2 INDEX (inx_b,`PRIMARY`) IN default;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN cold_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 PARTITIONS (p0) KEY (`inx_b`) IN cold_cache;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITIONS (p0) KEY (`inx_b`) IN cold_cache' at line 1
+# only one table at a time if specifying partitions
+CACHE INDEX t1,t2 PARTITION (p0) KEY (`inx_b`) IN cold_cache;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITION (p0) KEY (`inx_b`) IN cold_cache' at line 1
+CACHE INDEX t1 PARTITION (`p0`,p1) INDEX (`PRIMARY`) IN warm_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 PARTITION (`p1`) INDEX (`PRIMARY`,inx_b) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN default;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 PARTITION (ALL) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 INDEX (`inx_b`) IN default;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 KEY (`PRIMARY`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 KEY (`PRIMARY`,`inx_b`) IN warm_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 INDEX (`inx_b`,`PRIMARY`) IN cold_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+CACHE INDEX t1 IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+# Test of non existent key cache:
+CACHE INDEX t1 IN non_existent_key_cache;
+ERROR HY000: Unknown key cache 'non_existent_key_cache'
+# Basic testing of LOAD INDEX
+LOAD INDEX INTO CACHE t2;
+Table Op Msg_type Msg_text
+test.t2 preload_keys status OK
+# PRIMARY and secondary keys have different block sizes
+LOAD INDEX INTO CACHE t2 ignore leaves;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+# Must have INDEX or KEY before the index list
+LOAD INDEX INTO CACHE t2 (`PRIMARY`);
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '(`PRIMARY`)' at line 1
+# Test of IGNORE LEAVES
+LOAD INDEX INTO CACHE t2 INDEX (`PRIMARY`);
+Table Op Msg_type Msg_text
+test.t2 preload_keys status OK
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+CACHE INDEX t2 IN warm_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t1 IN cold_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache status OK
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+CACHE INDEX t2 INDEX (`inx_b`, `inx_c`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+LOAD INDEX INTO CACHE t2 KEY (`inx_b`, `inx_c`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+CACHE INDEX t2 IN warm_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+CACHE INDEX t2 INDEX (`PRIMARY`, `inx_c`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_c`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+CACHE INDEX t2 INDEX (`inx_b`,`PRIMARY`) IN default;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`);
+Table Op Msg_type Msg_text
+test.t2 preload_keys status OK
+CACHE INDEX t2 IN default;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache status OK
+LOAD INDEX INTO CACHE t2 IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t2 preload_keys error Indexes use different block sizes
+test.t2 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t2 PARTITION (p1) INDEX (`PRIMARY`);
+ERROR HY000: Partition management on a not partitioned table is not possible
+LOAD INDEX INTO CACHE t1, t2;
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+test.t2 preload_keys status OK
+# only one table at a time if specifying partitions
+LOAD INDEX INTO CACHE t1 PARTITION (p0), t2;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ' t2' at line 1
+LOAD INDEX INTO CACHE t1 IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t1 INDEX (`inx_b`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+LOAD INDEX INTO CACHE t1 PARTITION (p1) INDEX (`PRIMARY`);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+LOAD INDEX INTO CACHE t1 PARTITION (`p1`,p0) KEY (`PRIMARY`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+LOAD INDEX INTO CACHE t1 PARTITION (ALL);
+Table Op Msg_type Msg_text
+test.t1 preload_keys status OK
+LOAD INDEX INTO CACHE t1 PARTITIONS ALL;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'PARTITIONS ALL' at line 1
+LOAD INDEX INTO CACHE t1 PARTITION (p1,`p0`) IGNORE LEAVES;
+Table Op Msg_type Msg_text
+test.t1 preload_keys error Indexes use different block sizes
+test.t1 preload_keys error Subpartition sp2 returned error
+test.t1 preload_keys status Operation failed
+DROP INDEX `inx_b` on t1;
+DROP INDEX `inx_b` on t2;
+CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+ERROR HY000: Partition management on a not partitioned table is not possible
+CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t2 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't2'
+test.t2 assign_to_keycache status Operation failed
+CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache error Subpartition sp0 returned error
+test.t1 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't1'
+test.t1 assign_to_keycache status Operation failed
+CACHE INDEX t1 INDEX (`inx_b`) IN hot_cache;
+Table Op Msg_type Msg_text
+test.t1 assign_to_keycache error Subpartition sp0 returned error
+test.t1 assign_to_keycache Error Key 'inx_b' doesn't exist in table 't1'
+test.t1 assign_to_keycache status Operation failed
+DROP TABLE t1,t2;
+SET GLOBAL hot_cache.key_buffer_size = 0;
+SET GLOBAL warm_cache.key_buffer_size = 0;
+SET @@global.cold_cache.key_buffer_size = 0;
+SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d;
+a b c d
+1048576 1024 300 100
+SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d;
+a b c d
+0 1024 300 100
+SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d;
+a b c d
+0 1024 300 100
+SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d;
+a b c d
+0 1024 300 100
+SET @@global.default.key_buffer_size = @org_key_cache_buffer_size;
diff --git a/mysql-test/t/partition_key_cache.test b/mysql-test/t/partition_key_cache.test
new file mode 100644
index 00000000000..34f3d4de19c
--- /dev/null
+++ b/mysql-test/t/partition_key_cache.test
@@ -0,0 +1,252 @@
+# Test of key cache with partitions
+--source include/have_partition.inc
+
+--disable_warnings
+DROP TABLE IF EXISTS t1, t2, v, x;
+--enable_warnings
+
+--echo # Actual test of key caches
+--echo # Verifing that reads/writes use the key cache correctly
+SELECT @org_key_cache_buffer_size:= @@global.default.key_buffer_size;
+--echo # Minimize default key cache (almost disabled).
+SET @@global.default.key_buffer_size = 1;
+SELECT @@global.default.key_buffer_size;
+CREATE TABLE t1 (
+ a INT,
+ b INT,
+ c INT NOT NULL,
+ PRIMARY KEY (a),
+ KEY `inx_b` (b))
+PARTITION BY RANGE (a)
+SUBPARTITION BY HASH (a)
+(PARTITION p0 VALUES LESS THAN (1167602410)
+ (SUBPARTITION sp0,
+ SUBPARTITION sp1),
+ PARTITION p1 VALUES LESS THAN MAXVALUE
+ (SUBPARTITION sp2,
+ SUBPARTITION sp3));
+CREATE TABLE t2 (
+ a INT,
+ b INT,
+ c INT NOT NULL,
+ PRIMARY KEY (a),
+ KEY `inx_b` (b));
+FLUSH TABLES;
+FLUSH STATUS;
+
+# Genereate 4096 rows. Idea from:
+# http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.html
+SET @a:=1167602400;
+CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4;
+CREATE VIEW x AS SELECT 1 FROM v,v a,v b;
+# due to I_S performance, this was substituted with include files which
+# uses SHOW STATUS
+#DELIMITER |;
+#CREATE PROCEDURE was_zero_reads()
+#BEGIN
+# SELECT IF(VARIABLE_VALUE = 0,"Yes!","No!") as 'Was zero reads?'
+# FROM INFORMATION_SCHEMA.SESSION_STATUS
+# WHERE VARIABLE_NAME = 'KEY_READS';
+# FLUSH STATUS;
+#END|
+#DELIMITER ;|
+
+FLUSH STATUS;
+INSERT t1 SELECT @a, @a * (1 - ((@a % 2) * 2)) , 1167612400 - (@a:=@a+1) FROM x, x y;
+--source include/check_key_req.inc
+--echo # row distribution:
+SELECT PARTITION_NAME, SUBPARTITION_NAME, TABLE_ROWS FROM INFORMATION_SCHEMA.PARTITIONS WHERE TABLE_SCHEMA='test' and TABLE_NAME='t1';
+DROP VIEW x;
+DROP VIEW v;
+FLUSH TABLES;
+FLUSH STATUS;
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+--source include/check_key_reads.inc
+INSERT t2 SELECT a,b,c FROM t1;
+--source include/check_key_req.inc
+FLUSH STATUS;
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+--source include/check_key_reads.inc
+FLUSH TABLES;
+--echo # Setting the default key cache to 1M
+SET GLOBAL key_buffer_size = 1024*1024;
+FLUSH STATUS;
+--echo # All these have to read the indexes
+LOAD INDEX INTO CACHE t1 PARTITION (p1);
+--source include/check_key_reads.inc
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+--source include/check_key_reads.inc
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+--source include/check_key_reads.inc
+--echo # All these should be able to use the key cache
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+--source include/check_key_reads.inc
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+--source include/check_key_reads.inc
+FLUSH TABLES;
+LOAD INDEX INTO CACHE t1 PARTITION (p1,p0);
+--source include/check_key_reads.inc
+--echo # should not be zero
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+--source include/check_key_reads.inc
+LOAD INDEX INTO CACHE t2;
+--source include/check_key_reads.inc
+--echo # should not be zero
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+--source include/check_key_reads.inc
+FLUSH TABLES;
+LOAD INDEX INTO CACHE t1 PARTITION (p1,p0) IGNORE LEAVES;
+--source include/check_key_reads.inc
+--echo # should not be zero
+SELECT COUNT(b) FROM t1 WHERE b >= 0;
+--source include/check_key_reads.inc
+LOAD INDEX INTO CACHE t2 IGNORE LEAVES;
+--source include/check_key_reads.inc
+--echo # should not be zero
+SELECT COUNT(b) FROM t2 WHERE b >= 0;
+--source include/check_key_reads.inc
+TRUNCATE TABLE t2;
+INSERT t2 SELECT a,b,c FROM t1;
+--source include/check_key_req.inc
+DROP TABLE t1,t2;
+
+SET GLOBAL hot_cache.key_buffer_size = 1024*1024;
+SET GLOBAL warm_cache.key_buffer_size = 1024*1024;
+SET @@global.cold_cache.key_buffer_size = 1024*1024;
+SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d;
+SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d;
+SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d;
+SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d;
+CREATE TABLE t1 (
+ a INT,
+ b VARCHAR(257),
+ c INT NOT NULL,
+ PRIMARY KEY (a),
+ KEY `inx_b` (b),
+ KEY `inx_c`(c))
+PARTITION BY RANGE (a)
+SUBPARTITION BY HASH (a)
+(PARTITION p0 VALUES LESS THAN (10)
+ (SUBPARTITION sp0,
+ SUBPARTITION sp1),
+ PARTITION p1 VALUES LESS THAN MAXVALUE
+ (SUBPARTITION sp2,
+ SUBPARTITION sp3));
+CREATE TABLE t2 (
+ a INT,
+ b VARCHAR(257),
+ c INT NOT NULL,
+ PRIMARY KEY (a),
+ KEY `inx_b` (b),
+ KEY `inx_c`(c));
+SET @a:=1167602400;
+# Genereate 4096 rows. Idea from:
+# http://datacharmer.blogspot.com/2007/12/data-from-nothing-solution-to-pop-quiz.html
+CREATE VIEW v AS SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4;
+CREATE VIEW x AS SELECT 1 FROM v,v a,v b;
+INSERT t1 SELECT @a, CONCAT('X_', @a, ' MySQL'), 1167612400 - (@a:=@a+1) FROM x, x a;
+DROP VIEW x;
+DROP VIEW v;
+INSERT t2 SELECT a, b, c FROM t1;
+SELECT COUNT(*) FROM t1;
+SELECT COUNT(*) FROM t2;
+FLUSH TABLES;
+
+--echo # Restrict partitioned commands to partitioned tables only
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+CACHE INDEX t2 PARTITION (p0,`p1`) INDEX (`PRIMARY`) IN hot_cache;
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+CACHE INDEX t2 PARTITION (`p1`) INDEX (`PRIMARY`,`inx_b`) IN hot_cache;
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+CACHE INDEX t2 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN hot_cache;
+--echo # Basic key cache testing
+--echo # The manual correctly says: "The syntax of CACHE INDEX enables you to
+--echo # specify that only particular indexes from a table should be assigned
+--echo # to the cache. The current implementation assigns all the table's
+--echo # indexes to the cache, so there is no reason to specify anything
+--echo # other than the table name."
+--echo # So the most of the test only tests the syntax
+CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache;
+CACHE INDEX t2 KEY (`PRIMARY`) IN warm_cache;
+CACHE INDEX t2 KEY (`PRIMARY`,`inx_b`) IN cold_cache;
+CACHE INDEX t2 INDEX (inx_b,`PRIMARY`) IN default;
+CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN cold_cache;
+--error ER_PARSE_ERROR
+CACHE INDEX t1 PARTITIONS (p0) KEY (`inx_b`) IN cold_cache;
+--echo # only one table at a time if specifying partitions
+--error ER_PARSE_ERROR
+CACHE INDEX t1,t2 PARTITION (p0) KEY (`inx_b`) IN cold_cache;
+CACHE INDEX t1 PARTITION (`p0`,p1) INDEX (`PRIMARY`) IN warm_cache;
+CACHE INDEX t1 PARTITION (`p1`) INDEX (`PRIMARY`,inx_b) IN hot_cache;
+CACHE INDEX t1 PARTITION (ALL) KEY (`inx_b`,`PRIMARY`) IN default;
+CACHE INDEX t1 PARTITION (ALL) IN hot_cache;
+CACHE INDEX t1 INDEX (`inx_b`) IN default;
+CACHE INDEX t1 KEY (`PRIMARY`) IN hot_cache;
+CACHE INDEX t1 KEY (`PRIMARY`,`inx_b`) IN warm_cache;
+CACHE INDEX t1 INDEX (`inx_b`,`PRIMARY`) IN cold_cache;
+CACHE INDEX t1 IN hot_cache;
+--echo # Test of non existent key cache:
+--error ER_UNKNOWN_KEY_CACHE
+CACHE INDEX t1 IN non_existent_key_cache;
+--echo # Basic testing of LOAD INDEX
+LOAD INDEX INTO CACHE t2;
+--echo # PRIMARY and secondary keys have different block sizes
+LOAD INDEX INTO CACHE t2 ignore leaves;
+--echo # Must have INDEX or KEY before the index list
+--error ER_PARSE_ERROR
+LOAD INDEX INTO CACHE t2 (`PRIMARY`);
+
+--echo # Test of IGNORE LEAVES
+LOAD INDEX INTO CACHE t2 INDEX (`PRIMARY`);
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`) IGNORE LEAVES;
+CACHE INDEX t2 IN warm_cache;
+CACHE INDEX t1 IN cold_cache;
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`) IGNORE LEAVES;
+CACHE INDEX t2 INDEX (`inx_b`, `inx_c`) IN hot_cache;
+LOAD INDEX INTO CACHE t2 KEY (`inx_b`, `inx_c`) IGNORE LEAVES;
+CACHE INDEX t2 IN warm_cache;
+CACHE INDEX t2 INDEX (`PRIMARY`, `inx_c`) IN hot_cache;
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_c`) IGNORE LEAVES;
+CACHE INDEX t2 INDEX (`inx_b`,`PRIMARY`) IN default;
+LOAD INDEX INTO CACHE t2 KEY (`PRIMARY`,`inx_b`);
+CACHE INDEX t2 IN default;
+LOAD INDEX INTO CACHE t2 IGNORE LEAVES;
+
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+LOAD INDEX INTO CACHE t2 PARTITION (p1) INDEX (`PRIMARY`);
+LOAD INDEX INTO CACHE t1, t2;
+--echo # only one table at a time if specifying partitions
+--error ER_PARSE_ERROR
+LOAD INDEX INTO CACHE t1 PARTITION (p0), t2;
+LOAD INDEX INTO CACHE t1 IGNORE LEAVES;
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`);
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`) IGNORE LEAVES;
+LOAD INDEX INTO CACHE t1 INDEX (`inx_b`) IGNORE LEAVES;
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`) IGNORE LEAVES;
+LOAD INDEX INTO CACHE t1 INDEX (`PRIMARY`,`inx_b`);
+LOAD INDEX INTO CACHE t1 PARTITION (p1) INDEX (`PRIMARY`);
+LOAD INDEX INTO CACHE t1 PARTITION (`p1`,p0) KEY (`PRIMARY`) IGNORE LEAVES;
+LOAD INDEX INTO CACHE t1 PARTITION (ALL);
+--error ER_PARSE_ERROR
+LOAD INDEX INTO CACHE t1 PARTITIONS ALL;
+LOAD INDEX INTO CACHE t1 PARTITION (p1,`p0`) IGNORE LEAVES;
+DROP INDEX `inx_b` on t1;
+DROP INDEX `inx_b` on t2;
+--error ER_PARTITION_MGMT_ON_NONPARTITIONED
+CACHE INDEX t2 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+CACHE INDEX t2 INDEX (`inx_b`) IN hot_cache;
+CACHE INDEX t1 PARTITION (p0) KEY (`inx_b`) IN hot_cache;
+CACHE INDEX t1 INDEX (`inx_b`) IN hot_cache;
+DROP TABLE t1,t2;
+SET GLOBAL hot_cache.key_buffer_size = 0;
+SET GLOBAL warm_cache.key_buffer_size = 0;
+SET @@global.cold_cache.key_buffer_size = 0;
+SELECT @@global.default.key_buffer_size a, @@global.default.key_cache_block_size b, @@global.default.key_cache_age_threshold c, @@global.default.key_cache_division_limit d;
+SELECT @@global.hot_cache.key_buffer_size a, @@global.hot_cache.key_cache_block_size b, @@global.hot_cache.key_cache_age_threshold c, @@global.hot_cache.key_cache_division_limit d;
+SELECT @@global.warm_cache.key_buffer_size a, @@global.warm_cache.key_cache_block_size b, @@global.warm_cache.key_cache_age_threshold c, @@global.warm_cache.key_cache_division_limit d;
+SELECT @@global.cold_cache.key_buffer_size a, @@global.cold_cache.key_cache_block_size b, @@global.cold_cache.key_cache_age_threshold c, @@global.cold_cache.key_cache_division_limit d;
+--disable_warnings
+SET @@global.default.key_buffer_size = @org_key_cache_buffer_size;
+--enable_warnings
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 5990f0f001a..ca6aa3a6052 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -411,8 +411,8 @@ bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
thd->variables.character_set_results,
err, strlen(err),
system_charset_info, &error);
- length= (uint) (strmake((char*) pos, (char*)converted_err, MYSQL_ERRMSG_SIZE) -
- (char*) buff);
+ length= (uint) (strmake((char*) pos, (char*)converted_err,
+ MYSQL_ERRMSG_SIZE - 1) - (char*) buff);
err= (char*) buff;
DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
length));