mirror of
https://github.com/MariaDB/server.git
synced 2025-01-22 14:54:20 +01:00
Merge spetrunia@bk-internal.mysql.com:/home/bk/mysql-5.1-new
into pylon.mylan:/home/psergey/mysql-5.1-26dec-merge
This commit is contained in:
commit
059aaa8ec8
18 changed files with 2169 additions and 62 deletions
261
mysql-test/r/partition_pruning.result
Normal file
261
mysql-test/r/partition_pruning.result
Normal file
|
@ -0,0 +1,261 @@
|
|||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
create table t1 ( a int not null) partition by hash(a) partitions 2;
|
||||
insert into t1 values (1),(2),(3);
|
||||
explain select * from t1 where a=5 and a=6;
|
||||
id select_type table type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a int(11) not null
|
||||
) partition by hash (a) partitions 2;
|
||||
insert into t1 values (1),(2),(3);
|
||||
explain partitions select * from t1 where a=1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t1 where a=2;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t1 where a=1 or a=2;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
create table t2 (
|
||||
a int not null,
|
||||
b int not null
|
||||
) partition by key(a,b) partitions 2;
|
||||
insert into t2 values (1,1),(2,2),(3,3);
|
||||
explain partitions select * from t2 where a=1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t2 where b=1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 p0,p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t2 where a=1 and b=1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t2 p0 ALL NULL NULL NULL NULL 3 Using where
|
||||
create table t3 (
|
||||
a int
|
||||
)
|
||||
partition by range (a*1) (
|
||||
partition p0 values less than (10),
|
||||
partition p1 values less than (20)
|
||||
);
|
||||
insert into t3 values (5),(15);
|
||||
explain partitions select * from t3 where a=11;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t3 where a=10;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t3 where a=20;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t3 where a=30;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
create table t4 (a int not null, b int not null) partition by LIST (a+b) (
|
||||
partition p0 values in (12),
|
||||
partition p1 values in (14)
|
||||
);
|
||||
insert into t4 values (10,2), (10,4);
|
||||
explain partitions select * from t4 where (a=10 and b=1) or (a=10 and b=2);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t4
|
||||
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t4 p0 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t4 where (a=10 and b=2) or (a=10 and b=3)
|
||||
or (a=10 and b = 4);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t4 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t4 where (a=10 and b=1) or a=11;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t4 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t4 where (a=10 and b=2) or a=11;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t4 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
drop table t1, t2, t3, t4;
|
||||
create table t5 (a int not null, b int not null,
|
||||
c int not null, d int not null)
|
||||
partition by LIST(a+b) subpartition by HASH (c+d) subpartitions 2
|
||||
(
|
||||
partition p0 values in (12),
|
||||
partition p1 values in (14)
|
||||
);
|
||||
insert into t5 values (10,2,0,0), (10,4,0,0), (10,2,0,1), (10,4,0,1);
|
||||
explain partitions select * from t5;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p0_sp1,p1_sp0,p1_sp1 ALL NULL NULL NULL NULL 4
|
||||
explain partitions select * from t5
|
||||
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p0_sp1 ALL NULL NULL NULL NULL 4 Using where
|
||||
explain partitions select * from t5 where (a=10 and b=2) or (a=10 and b=3)
|
||||
or (a=10 and b = 4);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p0_sp1,p1_sp0,p1_sp1 ALL NULL NULL NULL NULL 4 Using where
|
||||
explain partitions select * from t5 where (c=1 and d=1);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p1_sp0 ALL NULL NULL NULL NULL 4 Using where
|
||||
explain partitions select * from t5 where (c=2 and d=1);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp1,p1_sp1 ALL NULL NULL NULL NULL 4 Using where
|
||||
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
|
||||
(c=2 and d=1);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p0_sp1,p1_sp1 ALL NULL NULL NULL NULL 4 Using where
|
||||
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
|
||||
(b=2 and c=2 and d=1);
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t5 p0_sp0,p0_sp1,p1_sp1 ALL NULL NULL NULL NULL 4 Using where
|
||||
create table t6 (a int not null) partition by LIST(a) (
|
||||
partition p1 values in (1),
|
||||
partition p3 values in (3),
|
||||
partition p5 values in (5),
|
||||
partition p7 values in (7),
|
||||
partition p9 values in (9)
|
||||
);
|
||||
insert into t6 values (1),(3),(5);
|
||||
explain partitions select * from t6 where a < 1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t6 where a <= 1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a > 9;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t6 where a >= 9;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p9 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a > 0 and a < 5;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p1,p3 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a > 5 and a < 12;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p7,p9 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a > 3 and a < 8 ;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p5,p7 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a >= 0 and a <= 5;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p1,p3,p5 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a >= 5 and a <= 12;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p5,p7,p9 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a >= 3 and a <= 8;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t6 p3,p5,p7 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t6 where a > 3 and a < 5;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
create table t7 (a int not null) partition by RANGE(a) (
|
||||
partition p10 values less than (10),
|
||||
partition p30 values less than (30),
|
||||
partition p50 values less than (50),
|
||||
partition p70 values less than (70),
|
||||
partition p90 values less than (90)
|
||||
);
|
||||
insert into t7 values (10),(30),(50);
|
||||
explain partitions select * from t7 where a < 5;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p10 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t7 where a < 10;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p10 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t7 where a <= 10;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p10,p30 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t7 where a = 10;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t7 where a < 90;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p10,p30,p50,p70,p90 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t7 where a = 90;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t7 where a > 90;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t7 where a >= 90;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
explain partitions select * from t7 where a > 11 and a < 29;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t7 p30 ALL NULL NULL NULL NULL 3 Using where
|
||||
create table t8 (a date not null) partition by RANGE(YEAR(a)) (
|
||||
partition p0 values less than (1980),
|
||||
partition p1 values less than (1990),
|
||||
partition p2 values less than (2000)
|
||||
);
|
||||
insert into t8 values ('1985-05-05'),('1995-05-05');
|
||||
explain partitions select * from t8 where a < '1980-02-02';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t8 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
create table t9 (a date not null) partition by RANGE(TO_DAYS(a)) (
|
||||
partition p0 values less than (732299), -- 2004-12-19
|
||||
partition p1 values less than (732468), -- 2005-06-06
|
||||
partition p2 values less than (732664) -- 2005-12-19
|
||||
);
|
||||
insert into t9 values ('2005-05-05'), ('2005-04-04');
|
||||
explain partitions select * from t9 where a < '2004-12-19';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t9 p0 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t9 where a <= '2004-12-19';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t9 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
drop table t5,t6,t7,t8,t9;
|
||||
create table t1 (a enum('a','b','c','d') default 'a')
|
||||
partition by hash (ascii(a)) partitions 2;
|
||||
insert into t1 values ('a'),('b'),('c');
|
||||
explain partitions select * from t1 where a='b';
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 3 Using where
|
||||
drop table t1;
|
||||
create table t1 (
|
||||
a1 int not null
|
||||
)
|
||||
partition by range (a1) (
|
||||
partition p0 values less than (3),
|
||||
partition p1 values less than (6),
|
||||
partition p2 values less than (9)
|
||||
);
|
||||
insert into t1 values (1),(2),(3);
|
||||
explain partitions select * from t1 where a1 > 3;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t1 where a1 >= 3;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p1,p2 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t1 where a1 < 3 and a1 > 3;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
|
||||
drop table t1;
|
||||
create table t3 (a int, b int)
|
||||
partition by list(a) subpartition by hash(b) subpartitions 4 (
|
||||
partition p0 values in (1),
|
||||
partition p1 values in (2),
|
||||
partition p2 values in (3),
|
||||
partition p3 values in (4)
|
||||
);
|
||||
insert into t3 values (1,1),(2,2),(3,3);
|
||||
explain partitions select * from t3 where a=2 or b=1;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 p0_sp1,p1_sp0,p1_sp1,p1_sp2,p1_sp3,p2_sp1,p3_sp1 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t3 where a=4 or b=2;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 p0_sp2,p1_sp2,p2_sp2,p3_sp0,p3_sp1,p3_sp2,p3_sp3 ALL NULL NULL NULL NULL 3 Using where
|
||||
explain partitions select * from t3 where (a=2 or b=1) and (a=4 or b=2) ;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t3 p1_sp2,p3_sp1 ALL NULL NULL NULL NULL 3 Using where
|
||||
drop table t3;
|
||||
create table t1 (a int) partition by hash(a) partitions 2;
|
||||
insert into t1 values (1),(2);
|
||||
explain partitions select * from t1 where a is null;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 2 Using where
|
||||
explain partitions select * from t1 where a is not null;
|
||||
id select_type table partitions type possible_keys key key_len ref rows Extra
|
||||
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 2 Using where
|
||||
drop table t1;
|
|
@ -1,4 +1,4 @@
|
|||
drop table if exists t1,t2;
|
||||
drop table if exists t1,t2,t3,t4;
|
||||
drop database if exists client_test_db;
|
||||
create table t1
|
||||
(
|
||||
|
|
238
mysql-test/t/partition_pruning.test
Normal file
238
mysql-test/t/partition_pruning.test
Normal file
|
@ -0,0 +1,238 @@
|
|||
#
|
||||
# Partition pruning tests. Currently we only detect which partitions to
|
||||
# prune, so the test is EXPLAINs.
|
||||
#
|
||||
-- source include/have_partition.inc
|
||||
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
--enable_warnings
|
||||
|
||||
|
||||
# Check if we can infer from condition on partition fields that
|
||||
# no records will match.
|
||||
create table t1 ( a int not null) partition by hash(a) partitions 2;
|
||||
insert into t1 values (1),(2),(3);
|
||||
explain select * from t1 where a=5 and a=6;
|
||||
drop table t1;
|
||||
|
||||
# Simple HASH partitioning
|
||||
create table t1 (
|
||||
a int(11) not null
|
||||
) partition by hash (a) partitions 2;
|
||||
insert into t1 values (1),(2),(3);
|
||||
|
||||
explain partitions select * from t1 where a=1;
|
||||
explain partitions select * from t1 where a=2;
|
||||
explain partitions select * from t1 where a=1 or a=2;
|
||||
|
||||
# Partitioning over several fields
|
||||
create table t2 (
|
||||
a int not null,
|
||||
b int not null
|
||||
) partition by key(a,b) partitions 2;
|
||||
insert into t2 values (1,1),(2,2),(3,3);
|
||||
|
||||
explain partitions select * from t2 where a=1;
|
||||
explain partitions select * from t2 where b=1;
|
||||
|
||||
explain partitions select * from t2 where a=1 and b=1;
|
||||
|
||||
# RANGE(expr) partitioning
|
||||
create table t3 (
|
||||
a int
|
||||
)
|
||||
partition by range (a*1) (
|
||||
partition p0 values less than (10),
|
||||
partition p1 values less than (20)
|
||||
);
|
||||
insert into t3 values (5),(15);
|
||||
|
||||
explain partitions select * from t3 where a=11;
|
||||
explain partitions select * from t3 where a=10;
|
||||
explain partitions select * from t3 where a=20;
|
||||
|
||||
explain partitions select * from t3 where a=30;
|
||||
|
||||
# LIST(expr) partitioning
|
||||
create table t4 (a int not null, b int not null) partition by LIST (a+b) (
|
||||
partition p0 values in (12),
|
||||
partition p1 values in (14)
|
||||
);
|
||||
insert into t4 values (10,2), (10,4);
|
||||
|
||||
# empty OR one
|
||||
explain partitions select * from t4 where (a=10 and b=1) or (a=10 and b=2);
|
||||
|
||||
# empty OR one OR empty
|
||||
explain partitions select * from t4
|
||||
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
|
||||
|
||||
# one OR empty OR one
|
||||
explain partitions select * from t4 where (a=10 and b=2) or (a=10 and b=3)
|
||||
or (a=10 and b = 4);
|
||||
|
||||
# empty OR full
|
||||
explain partitions select * from t4 where (a=10 and b=1) or a=11;
|
||||
|
||||
# one OR full
|
||||
explain partitions select * from t4 where (a=10 and b=2) or a=11;
|
||||
|
||||
drop table t1, t2, t3, t4;
|
||||
|
||||
# LIST(expr)/HASH subpartitioning.
|
||||
create table t5 (a int not null, b int not null,
|
||||
c int not null, d int not null)
|
||||
partition by LIST(a+b) subpartition by HASH (c+d) subpartitions 2
|
||||
(
|
||||
partition p0 values in (12),
|
||||
partition p1 values in (14)
|
||||
);
|
||||
|
||||
insert into t5 values (10,2,0,0), (10,4,0,0), (10,2,0,1), (10,4,0,1);
|
||||
explain partitions select * from t5;
|
||||
|
||||
# empty OR one OR empty
|
||||
explain partitions select * from t5
|
||||
where (a=10 and b=1) or (a=10 and b=2) or (a=10 and b = 3);
|
||||
|
||||
# one OR empty OR one
|
||||
explain partitions select * from t5 where (a=10 and b=2) or (a=10 and b=3)
|
||||
or (a=10 and b = 4);
|
||||
|
||||
# conditions on subpartitions only
|
||||
explain partitions select * from t5 where (c=1 and d=1);
|
||||
explain partitions select * from t5 where (c=2 and d=1);
|
||||
|
||||
# mixed partition/subpartitions.
|
||||
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
|
||||
(c=2 and d=1);
|
||||
|
||||
# same as above
|
||||
explain partitions select * from t5 where (a=10 and b=2 and c=1 and d=1) or
|
||||
(b=2 and c=2 and d=1);
|
||||
|
||||
# LIST(field) partitioning, interval analysis.
|
||||
create table t6 (a int not null) partition by LIST(a) (
|
||||
partition p1 values in (1),
|
||||
partition p3 values in (3),
|
||||
partition p5 values in (5),
|
||||
partition p7 values in (7),
|
||||
partition p9 values in (9)
|
||||
);
|
||||
insert into t6 values (1),(3),(5);
|
||||
|
||||
explain partitions select * from t6 where a < 1;
|
||||
explain partitions select * from t6 where a <= 1;
|
||||
explain partitions select * from t6 where a > 9;
|
||||
explain partitions select * from t6 where a >= 9;
|
||||
|
||||
explain partitions select * from t6 where a > 0 and a < 5;
|
||||
explain partitions select * from t6 where a > 5 and a < 12;
|
||||
explain partitions select * from t6 where a > 3 and a < 8 ;
|
||||
|
||||
explain partitions select * from t6 where a >= 0 and a <= 5;
|
||||
explain partitions select * from t6 where a >= 5 and a <= 12;
|
||||
explain partitions select * from t6 where a >= 3 and a <= 8;
|
||||
|
||||
explain partitions select * from t6 where a > 3 and a < 5;
|
||||
|
||||
# RANGE(field) partitioning, interval analysis.
|
||||
create table t7 (a int not null) partition by RANGE(a) (
|
||||
partition p10 values less than (10),
|
||||
partition p30 values less than (30),
|
||||
partition p50 values less than (50),
|
||||
partition p70 values less than (70),
|
||||
partition p90 values less than (90)
|
||||
);
|
||||
insert into t7 values (10),(30),(50);
|
||||
|
||||
# leftmost intervals
|
||||
explain partitions select * from t7 where a < 5;
|
||||
explain partitions select * from t7 where a < 10;
|
||||
explain partitions select * from t7 where a <= 10;
|
||||
explain partitions select * from t7 where a = 10;
|
||||
|
||||
#rightmost intervals
|
||||
explain partitions select * from t7 where a < 90;
|
||||
explain partitions select * from t7 where a = 90;
|
||||
explain partitions select * from t7 where a > 90;
|
||||
explain partitions select * from t7 where a >= 90;
|
||||
|
||||
# misc intervals
|
||||
explain partitions select * from t7 where a > 11 and a < 29;
|
||||
|
||||
# LIST(monontonic_func) partitioning
|
||||
create table t8 (a date not null) partition by RANGE(YEAR(a)) (
|
||||
partition p0 values less than (1980),
|
||||
partition p1 values less than (1990),
|
||||
partition p2 values less than (2000)
|
||||
);
|
||||
insert into t8 values ('1985-05-05'),('1995-05-05');
|
||||
|
||||
explain partitions select * from t8 where a < '1980-02-02';
|
||||
|
||||
# LIST(strict_monotonic_func) partitioning
|
||||
create table t9 (a date not null) partition by RANGE(TO_DAYS(a)) (
|
||||
partition p0 values less than (732299), -- 2004-12-19
|
||||
partition p1 values less than (732468), -- 2005-06-06
|
||||
partition p2 values less than (732664) -- 2005-12-19
|
||||
);
|
||||
insert into t9 values ('2005-05-05'), ('2005-04-04');
|
||||
|
||||
explain partitions select * from t9 where a < '2004-12-19';
|
||||
explain partitions select * from t9 where a <= '2004-12-19';
|
||||
|
||||
drop table t5,t6,t7,t8,t9;
|
||||
|
||||
# Test the case where we can't create partitioning 'index'
|
||||
create table t1 (a enum('a','b','c','d') default 'a')
|
||||
partition by hash (ascii(a)) partitions 2;
|
||||
insert into t1 values ('a'),('b'),('c');
|
||||
explain partitions select * from t1 where a='b';
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
# Test cases for bugs found in code review:
|
||||
#
|
||||
create table t1 (
|
||||
a1 int not null
|
||||
)
|
||||
partition by range (a1) (
|
||||
partition p0 values less than (3),
|
||||
partition p1 values less than (6),
|
||||
partition p2 values less than (9)
|
||||
);
|
||||
insert into t1 values (1),(2),(3);
|
||||
explain partitions select * from t1 where a1 > 3;
|
||||
explain partitions select * from t1 where a1 >= 3;
|
||||
|
||||
explain partitions select * from t1 where a1 < 3 and a1 > 3;
|
||||
drop table t1;
|
||||
|
||||
#
|
||||
create table t3 (a int, b int)
|
||||
partition by list(a) subpartition by hash(b) subpartitions 4 (
|
||||
partition p0 values in (1),
|
||||
partition p1 values in (2),
|
||||
partition p2 values in (3),
|
||||
partition p3 values in (4)
|
||||
);
|
||||
insert into t3 values (1,1),(2,2),(3,3);
|
||||
|
||||
explain partitions select * from t3 where a=2 or b=1;
|
||||
explain partitions select * from t3 where a=4 or b=2;
|
||||
explain partitions select * from t3 where (a=2 or b=1) and (a=4 or b=2) ;
|
||||
drop table t3;
|
||||
|
||||
# Test for NULLs
|
||||
create table t1 (a int) partition by hash(a) partitions 2;
|
||||
insert into t1 values (1),(2);
|
||||
explain partitions select * from t1 where a is null;
|
||||
|
||||
# this selects both
|
||||
explain partitions select * from t1 where a is not null;
|
||||
drop table t1;
|
||||
|
||||
# No tests for NULLs in RANGE(monotonic_expr()) - they depend on BUG#15447
|
||||
# being fixed.
|
|
@ -2,7 +2,7 @@
|
|||
# SQL Syntax for Prepared Statements test
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t1,t2;
|
||||
drop table if exists t1,t2,t3,t4;
|
||||
|
||||
# Avoid wrong warnings if mysql_client_test fails
|
||||
drop database if exists client_test_db;
|
||||
|
|
|
@ -3121,7 +3121,6 @@ void ha_ndbcluster::info(uint flag)
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
int ha_ndbcluster::extra(enum ha_extra_function operation)
|
||||
{
|
||||
DBUG_ENTER("extra");
|
||||
|
@ -3130,6 +3129,8 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
|
|||
DBUG_PRINT("info", ("HA_EXTRA_RESET"));
|
||||
DBUG_PRINT("info", ("Clearing condition stack"));
|
||||
cond_clear();
|
||||
if (m_part_info)
|
||||
bitmap_clear_all(&m_part_info->used_partitions);
|
||||
break;
|
||||
case HA_EXTRA_IGNORE_DUP_KEY: /* Dup keys don't rollback everything*/
|
||||
DBUG_PRINT("info", ("HA_EXTRA_IGNORE_DUP_KEY"));
|
||||
|
|
|
@ -2799,6 +2799,8 @@ int ha_partition::reset(void)
|
|||
handler **file;
|
||||
DBUG_ENTER("ha_partition::reset");
|
||||
file= m_file;
|
||||
if (m_part_info)
|
||||
bitmap_clear_all(&m_part_info->used_partitions);
|
||||
do
|
||||
{
|
||||
if ((tmp= (*file)->reset()))
|
||||
|
|
|
@ -547,19 +547,52 @@ public:
|
|||
|
||||
List<char> part_field_list;
|
||||
List<char> subpart_field_list;
|
||||
|
||||
|
||||
/*
|
||||
If there is no subpartitioning, use only this func to get partition ids.
|
||||
If there is subpartitioning, use the this func to get partition id when
|
||||
you have both partition and subpartition fields.
|
||||
*/
|
||||
get_part_id_func get_partition_id;
|
||||
get_part_id_func get_part_partition_id;
|
||||
get_subpart_id_func get_subpartition_id;
|
||||
|
||||
/* Get partition id when we don't have subpartition fields */
|
||||
get_part_id_func get_part_partition_id;
|
||||
|
||||
/*
|
||||
Get subpartition id when we have don't have partition fields by we do
|
||||
have subpartition ids.
|
||||
Mikael said that for given constant tuple
|
||||
{subpart_field1, ..., subpart_fieldN} the subpartition id will be the
|
||||
same in all subpartitions
|
||||
*/
|
||||
get_subpart_id_func get_subpartition_id;
|
||||
|
||||
/* NULL-terminated list of fields used in partitioned expression */
|
||||
Field **part_field_array;
|
||||
/* NULL-terminated list of fields used in subpartitioned expression */
|
||||
Field **subpart_field_array;
|
||||
|
||||
/*
|
||||
Array of all fields used in partition and subpartition expression,
|
||||
without duplicates, NULL-terminated.
|
||||
*/
|
||||
Field **full_part_field_array;
|
||||
|
||||
Item *part_expr;
|
||||
Item *subpart_expr;
|
||||
|
||||
Item *item_free_list;
|
||||
|
||||
/*
|
||||
A bitmap of partitions used by the current query.
|
||||
Usage pattern:
|
||||
* It is guaranteed that all partitions are set to be unused on query start.
|
||||
* Before index/rnd_init(), partition pruning code sets the bits for used
|
||||
partitions.
|
||||
* The handler->extra(HA_EXTRA_RESET) call at query end sets all partitions
|
||||
to be unused.
|
||||
*/
|
||||
MY_BITMAP used_partitions;
|
||||
|
||||
union {
|
||||
longlong *range_int_array;
|
||||
|
@ -760,6 +793,13 @@ void get_full_part_id_from_key(const TABLE *table, byte *buf,
|
|||
bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
|
||||
uint part_info_len, TABLE *table,
|
||||
handlerton *default_db_type);
|
||||
void make_used_partitions_str(partition_info *part_info, String *parts_str);
|
||||
uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint);
|
||||
uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint);
|
||||
#endif
|
||||
|
||||
|
||||
|
|
35
sql/item.h
35
sql/item.h
|
@ -368,6 +368,28 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
This enum is used to report information about monotonicity of function
|
||||
represented by Item* tree.
|
||||
Monotonicity is defined only for Item* trees that represent table
|
||||
partitioning expressions (i.e. have no subselects/user vars/PS parameters
|
||||
etc etc). An Item* tree is assumed to have the same monotonicity properties
|
||||
as its correspoinding function F:
|
||||
|
||||
[signed] longlong F(field1, field2, ...) {
|
||||
put values of field_i into table record buffer;
|
||||
return item->val_int();
|
||||
}
|
||||
*/
|
||||
|
||||
typedef enum monotonicity_info
|
||||
{
|
||||
NON_MONOTONIC, /* none of the below holds */
|
||||
MONOTONIC_INCREASING, /* F() is unary and "x < y" => "F(x) < F(y)" */
|
||||
MONOTONIC_STRICT_INCREASING /* F() is unary and "x < y" => "F(x) <= F(y)" */
|
||||
} enum_monotonicity_info;
|
||||
|
||||
/*************************************************************************/
|
||||
|
||||
typedef bool (Item::*Item_processor)(byte *arg);
|
||||
|
@ -466,6 +488,15 @@ public:
|
|||
virtual Item_result cast_to_int_type() const { return result_type(); }
|
||||
virtual enum_field_types field_type() const;
|
||||
virtual enum Type type() const =0;
|
||||
|
||||
/*
|
||||
Return information about function monotonicity. See comment for
|
||||
enum_monotonicity_info for details. This function can only be called
|
||||
after fix_fields() call.
|
||||
*/
|
||||
virtual enum_monotonicity_info get_monotonicity_info() const
|
||||
{ return NON_MONOTONIC; }
|
||||
|
||||
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
|
||||
/*
|
||||
Return double precision floating point representation of item.
|
||||
|
@ -1140,6 +1171,10 @@ public:
|
|||
{
|
||||
return field->type();
|
||||
}
|
||||
enum_monotonicity_info get_monotonicity_info() const
|
||||
{
|
||||
return MONOTONIC_STRICT_INCREASING;
|
||||
}
|
||||
Field *get_tmp_table_field() { return result_field; }
|
||||
Field *tmp_table_field(TABLE *t_arg) { return result_field; }
|
||||
bool get_date(TIME *ltime,uint fuzzydate);
|
||||
|
|
|
@ -885,6 +885,19 @@ longlong Item_func_to_days::val_int()
|
|||
return (longlong) calc_daynr(ltime.year,ltime.month,ltime.day);
|
||||
}
|
||||
|
||||
enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
|
||||
{
|
||||
if (args[0]->type() == Item::FIELD_ITEM)
|
||||
{
|
||||
if (args[0]->field_type() == MYSQL_TYPE_DATE)
|
||||
return MONOTONIC_STRICT_INCREASING;
|
||||
if (args[0]->field_type() == MYSQL_TYPE_DATETIME)
|
||||
return MONOTONIC_INCREASING;
|
||||
}
|
||||
return NON_MONOTONIC;
|
||||
}
|
||||
|
||||
|
||||
longlong Item_func_dayofyear::val_int()
|
||||
{
|
||||
DBUG_ASSERT(fixed == 1);
|
||||
|
@ -1067,6 +1080,14 @@ longlong Item_func_year::val_int()
|
|||
return (longlong) ltime.year;
|
||||
}
|
||||
|
||||
enum_monotonicity_info Item_func_year::get_monotonicity_info() const
|
||||
{
|
||||
if (args[0]->type() == Item::FIELD_ITEM &&
|
||||
(args[0]->field_type() == MYSQL_TYPE_DATE ||
|
||||
args[0]->field_type() == MYSQL_TYPE_DATETIME))
|
||||
return MONOTONIC_INCREASING;
|
||||
return NON_MONOTONIC;
|
||||
}
|
||||
|
||||
longlong Item_func_unix_timestamp::val_int()
|
||||
{
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
|
||||
maybe_null=1;
|
||||
}
|
||||
enum_monotonicity_info get_monotonicity_info() const;
|
||||
};
|
||||
|
||||
|
||||
|
@ -234,6 +235,7 @@ public:
|
|||
Item_func_year(Item *a) :Item_int_func(a) {}
|
||||
longlong val_int();
|
||||
const char *func_name() const { return "year"; }
|
||||
enum_monotonicity_info get_monotonicity_info() const;
|
||||
void fix_length_and_dec()
|
||||
{
|
||||
decimals=0;
|
||||
|
|
1307
sql/opt_range.cc
1307
sql/opt_range.cc
File diff suppressed because it is too large
Load diff
|
@ -249,6 +249,7 @@ public:
|
|||
|
||||
|
||||
struct st_qsel_param;
|
||||
class PARAM;
|
||||
class SEL_ARG;
|
||||
|
||||
/*
|
||||
|
@ -283,12 +284,12 @@ protected:
|
|||
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
||||
struct st_table_ref *ref,
|
||||
ha_rows records);
|
||||
friend bool get_quick_keys(struct st_qsel_param *param,
|
||||
friend bool get_quick_keys(PARAM *param,
|
||||
QUICK_RANGE_SELECT *quick,KEY_PART *key,
|
||||
SEL_ARG *key_tree,
|
||||
char *min_key, uint min_key_flag,
|
||||
char *max_key, uint max_key_flag);
|
||||
friend QUICK_RANGE_SELECT *get_quick_select(struct st_qsel_param*,uint idx,
|
||||
friend QUICK_RANGE_SELECT *get_quick_select(PARAM*,uint idx,
|
||||
SEL_ARG *key_tree,
|
||||
MEM_ROOT *alloc);
|
||||
friend class QUICK_SELECT_DESC;
|
||||
|
@ -718,4 +719,8 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
|
|||
ha_rows records);
|
||||
uint get_index_for_order(TABLE *table, ORDER *order, ha_rows limit);
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -755,6 +755,13 @@ int THD::send_explain_fields(select_result *result)
|
|||
field_list.push_back(new Item_empty_string("select_type", 19, cs));
|
||||
field_list.push_back(item= new Item_empty_string("table", NAME_LEN, cs));
|
||||
item->maybe_null= 1;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if (lex->describe & DESCRIBE_PARTITIONS)
|
||||
{
|
||||
field_list.push_back(item= new Item_empty_string("partitions", 10, cs));
|
||||
item->maybe_null= 1;
|
||||
}
|
||||
#endif
|
||||
field_list.push_back(item= new Item_empty_string("type", 10, cs));
|
||||
item->maybe_null= 1;
|
||||
field_list.push_back(item=new Item_empty_string("possible_keys",
|
||||
|
|
|
@ -103,6 +103,11 @@ enum enum_sql_command {
|
|||
// describe/explain types
|
||||
#define DESCRIBE_NORMAL 1
|
||||
#define DESCRIBE_EXTENDED 2
|
||||
/*
|
||||
This is not #ifdef'ed because we want "EXPLAIN PARTITIONS ..." to produce
|
||||
additional "partitions" column even if partitioning is not compiled in.
|
||||
*/
|
||||
#define DESCRIBE_PARTITIONS 4
|
||||
|
||||
enum enum_sp_suid_behaviour
|
||||
{
|
||||
|
|
|
@ -2478,17 +2478,96 @@ bool get_partition_id_list(partition_info *part_info,
|
|||
if (list_value < part_func_value)
|
||||
min_list_index= list_index + 1;
|
||||
else if (list_value > part_func_value)
|
||||
{
|
||||
if (!list_index)
|
||||
goto notfound;
|
||||
max_list_index= list_index - 1;
|
||||
else {
|
||||
}
|
||||
else
|
||||
{
|
||||
*part_id= (uint32)list_array[list_index].partition_id;
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
}
|
||||
notfound:
|
||||
*part_id= 0;
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find the sub-array part_info->list_array that corresponds to given interval
|
||||
|
||||
SYNOPSIS
|
||||
get_list_array_idx_for_endpoint()
|
||||
part_info Partitioning info (partitioning type must be LIST)
|
||||
left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
|
||||
FALSE - the interval is (-inf; a] or (-inf; a)
|
||||
include_endpoint TRUE iff the interval includes the endpoint
|
||||
|
||||
DESCRIPTION
|
||||
This function finds the sub-array of part_info->list_array where values of
|
||||
list_array[idx].list_value are contained within the specifed interval.
|
||||
list_array is ordered by list_value, so
|
||||
1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
|
||||
sought sub-array starts at some index idx and continues till array end.
|
||||
The function returns first number idx, such that
|
||||
list_array[idx].list_value is contained within the passed interval.
|
||||
|
||||
2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
|
||||
sought sub-array starts at array start and continues till some last
|
||||
index idx.
|
||||
The function returns first number idx, such that
|
||||
list_array[idx].list_value is NOT contained within the passed interval.
|
||||
If all array elements are contained, part_info->no_list_values is
|
||||
returned.
|
||||
|
||||
NOTE
|
||||
The caller will call this function and then will run along the sub-array of
|
||||
list_array to collect partition ids. If the number of list values is
|
||||
significantly higher then number of partitions, this could be slow and
|
||||
we could invent some other approach. The "run over list array" part is
|
||||
already wrapped in a get_next()-like function.
|
||||
|
||||
RETURN
|
||||
The edge of corresponding sub-array of part_info->list_array
|
||||
*/
|
||||
|
||||
uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint)
|
||||
{
|
||||
DBUG_ENTER("get_list_array_idx_for_endpoint");
|
||||
LIST_PART_ENTRY *list_array= part_info->list_array;
|
||||
uint list_index;
|
||||
longlong list_value;
|
||||
uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
|
||||
/* Get the partitioning function value for the endpoint */
|
||||
longlong part_func_value= part_info->part_expr->val_int();
|
||||
while (max_list_index >= min_list_index)
|
||||
{
|
||||
list_index= (max_list_index + min_list_index) >> 1;
|
||||
list_value= list_array[list_index].list_value;
|
||||
if (list_value < part_func_value)
|
||||
min_list_index= list_index + 1;
|
||||
else if (list_value > part_func_value)
|
||||
{
|
||||
if (!list_index)
|
||||
goto notfound;
|
||||
max_list_index= list_index - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
|
||||
}
|
||||
}
|
||||
notfound:
|
||||
if (list_value < part_func_value)
|
||||
list_index++;
|
||||
DBUG_RETURN(list_index);
|
||||
}
|
||||
|
||||
|
||||
bool get_partition_id_range(partition_info *part_info,
|
||||
uint32 *part_id)
|
||||
{
|
||||
|
@ -2517,6 +2596,89 @@ bool get_partition_id_range(partition_info *part_info,
|
|||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Find the sub-array of part_info->range_int_array that covers given interval
|
||||
|
||||
SYNOPSIS
|
||||
get_partition_id_range_for_endpoint()
|
||||
part_info Partitioning info (partitioning type must be RANGE)
|
||||
left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
|
||||
FALSE - the interval is (-inf; a] or (-inf; a).
|
||||
include_endpoint TRUE <=> the endpoint itself is included in the
|
||||
interval
|
||||
|
||||
DESCRIPTION
|
||||
This function finds the sub-array of part_info->range_int_array where the
|
||||
elements have non-empty intersections with the given interval.
|
||||
|
||||
A range_int_array element at index idx represents the interval
|
||||
|
||||
[range_int_array[idx-1], range_int_array[idx]),
|
||||
|
||||
intervals are disjoint and ordered by their right bound, so
|
||||
|
||||
1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
|
||||
sought sub-array starts at some index idx and continues till array end.
|
||||
The function returns first number idx, such that the interval
|
||||
represented by range_int_array[idx] has non empty intersection with
|
||||
the passed interval.
|
||||
|
||||
2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
|
||||
sought sub-array starts at array start and continues till some last
|
||||
index idx.
|
||||
The function returns first number idx, such that the interval
|
||||
represented by range_int_array[idx] has EMPTY intersection with the
|
||||
passed interval.
|
||||
If the interval represented by the last array element has non-empty
|
||||
intersection with the passed interval, part_info->no_parts is
|
||||
returned.
|
||||
|
||||
RETURN
|
||||
The edge of corresponding part_info->range_int_array sub-array.
|
||||
*/
|
||||
|
||||
uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint)
|
||||
{
|
||||
DBUG_ENTER("get_partition_id_range_for_endpoint");
|
||||
longlong *range_array= part_info->range_int_array;
|
||||
uint max_partition= part_info->no_parts - 1;
|
||||
uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
|
||||
/* Get the partitioning function value for the endpoint */
|
||||
longlong part_func_value= part_info->part_expr->val_int();
|
||||
while (max_part_id > min_part_id)
|
||||
{
|
||||
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
|
||||
if (range_array[loc_part_id] < part_func_value)
|
||||
min_part_id= loc_part_id + 1;
|
||||
else
|
||||
max_part_id= loc_part_id - 1;
|
||||
}
|
||||
loc_part_id= max_part_id;
|
||||
if (loc_part_id < max_partition &&
|
||||
part_func_value >= range_array[loc_part_id+1])
|
||||
{
|
||||
loc_part_id++;
|
||||
}
|
||||
if (left_endpoint)
|
||||
{
|
||||
if (part_func_value >= range_array[loc_part_id])
|
||||
loc_part_id++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (part_func_value == range_array[loc_part_id])
|
||||
loc_part_id += test(include_endpoint);
|
||||
else if (part_func_value > range_array[loc_part_id])
|
||||
loc_part_id++;
|
||||
loc_part_id++;
|
||||
}
|
||||
DBUG_RETURN(loc_part_id);
|
||||
}
|
||||
|
||||
|
||||
bool get_partition_id_hash_nosub(partition_info *part_info,
|
||||
uint32 *part_id)
|
||||
{
|
||||
|
@ -3205,10 +3367,16 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
|
|||
*/
|
||||
uint part_func_len= part_info->part_func_len;
|
||||
uint subpart_func_len= part_info->subpart_func_len;
|
||||
uint bitmap_bits= part_info->no_subparts?
|
||||
(part_info->no_subparts* part_info->no_parts):
|
||||
part_info->no_parts;
|
||||
uint bitmap_bytes= bitmap_buffer_size(bitmap_bits);
|
||||
uint32 *bitmap_buf;
|
||||
char *part_func_string, *subpart_func_string= NULL;
|
||||
if (!((part_func_string= thd->alloc(part_func_len))) ||
|
||||
(subpart_func_len &&
|
||||
!((subpart_func_string= thd->alloc(subpart_func_len)))))
|
||||
!((subpart_func_string= thd->alloc(subpart_func_len)))) ||
|
||||
!((bitmap_buf= (uint32*)thd->alloc(bitmap_bytes))))
|
||||
{
|
||||
my_error(ER_OUTOFMEMORY, MYF(0), part_func_len);
|
||||
free_items(thd->free_list);
|
||||
|
@ -3221,6 +3389,8 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
|
|||
subpart_func_len);
|
||||
part_info->part_func_string= part_func_string;
|
||||
part_info->subpart_func_string= subpart_func_string;
|
||||
|
||||
bitmap_init(&part_info->used_partitions, bitmap_buf, bitmap_bytes*8, FALSE);
|
||||
}
|
||||
|
||||
result= FALSE;
|
||||
|
@ -3294,3 +3464,60 @@ void set_key_field_ptr(KEY *key_info, const byte *new_buf,
|
|||
} while (++i < key_parts);
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Fill the string comma-separated line of used partitions names
|
||||
SYNOPSIS
|
||||
make_used_partitions_str()
|
||||
part_info IN Partitioning info
|
||||
parts_str OUT The string to fill
|
||||
*/
|
||||
|
||||
void make_used_partitions_str(partition_info *part_info, String *parts_str)
|
||||
{
|
||||
parts_str->length(0);
|
||||
partition_element *pe;
|
||||
uint partition_id= 0;
|
||||
List_iterator<partition_element> it(part_info->partitions);
|
||||
|
||||
if (part_info->subpart_type != NOT_A_PARTITION)
|
||||
{
|
||||
partition_element *head_pe;
|
||||
while ((head_pe= it++))
|
||||
{
|
||||
List_iterator<partition_element> it2(head_pe->subpartitions);
|
||||
while ((pe= it2++))
|
||||
{
|
||||
if (bitmap_is_set(&part_info->used_partitions, partition_id))
|
||||
{
|
||||
if (parts_str->length())
|
||||
parts_str->append(',');
|
||||
parts_str->append(head_pe->partition_name,
|
||||
strlen(head_pe->partition_name),
|
||||
system_charset_info);
|
||||
parts_str->append('_');
|
||||
parts_str->append(pe->partition_name,
|
||||
strlen(pe->partition_name),
|
||||
system_charset_info);
|
||||
}
|
||||
partition_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ((pe= it++))
|
||||
{
|
||||
if (bitmap_is_set(&part_info->used_partitions, partition_id))
|
||||
{
|
||||
if (parts_str->length())
|
||||
parts_str->append(',');
|
||||
parts_str->append(pe->partition_name, strlen(pe->partition_name),
|
||||
system_charset_info);
|
||||
}
|
||||
partition_id++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -633,6 +633,21 @@ JOIN::optimize()
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
{
|
||||
TABLE_LIST *tbl;
|
||||
for (tbl= select_lex->leaf_tables; tbl; tbl= tbl->next_leaf)
|
||||
{
|
||||
if (!tbl->embedding)
|
||||
{
|
||||
Item *prune_cond= tbl->on_expr? tbl->on_expr : conds;
|
||||
tbl->table->no_partitions_used= prune_partitions(thd, tbl->table,
|
||||
prune_cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Optimize count(*), min() and max() */
|
||||
if (tables_list && tmp_table_param.sum_func_count && ! group_list)
|
||||
{
|
||||
|
@ -2018,7 +2033,11 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
|||
if (*s->on_expr_ref)
|
||||
{
|
||||
/* s is the only inner table of an outer join */
|
||||
if (!table->file->records && !embedding)
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
if ((!table->file->records || table->no_partitions_used) && !embedding)
|
||||
#else
|
||||
if (!table->file->records || && !embedding)
|
||||
#endif
|
||||
{ // Empty table
|
||||
s->dependent= 0; // Ignore LEFT JOIN depend.
|
||||
set_position(join,const_count++,s,(KEYUSE*) 0);
|
||||
|
@ -2045,8 +2064,14 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
|||
while (embedding);
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((table->s->system || table->file->records <= 1) && ! s->dependent &&
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool no_partitions_used= table->no_partitions_used;
|
||||
#else
|
||||
const bool no_partitions_used= FALSE;
|
||||
#endif
|
||||
if ((table->s->system || table->file->records <= 1 ||
|
||||
no_partitions_used) &&
|
||||
!s->dependent &&
|
||||
!(table->file->table_flags() & HA_NOT_EXACT_COUNT) &&
|
||||
!table->fulltext_searched)
|
||||
{
|
||||
|
@ -13770,6 +13795,9 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
|||
strlen(join->select_lex->type), cs));
|
||||
for (uint i=0 ; i < 7; i++)
|
||||
item_list.push_back(item_null);
|
||||
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
|
||||
item_list.push_back(item_null);
|
||||
|
||||
item_list.push_back(new Item_string(message,strlen(message),cs));
|
||||
if (result->send_data(item_list))
|
||||
join->error= 1;
|
||||
|
@ -13890,7 +13918,28 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
|
|||
item_list.push_back(new Item_string(table->alias,
|
||||
strlen(table->alias),
|
||||
cs));
|
||||
/* type */
|
||||
/* "partitions" column */
|
||||
if (join->thd->lex->describe & DESCRIBE_PARTITIONS)
|
||||
{
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
partition_info *part_info;
|
||||
if (!table->derived_select_number &&
|
||||
(part_info= table->part_info))
|
||||
{
|
||||
char parts_buff[128];
|
||||
String parts_str(parts_buff,sizeof(parts_buff),cs);
|
||||
make_used_partitions_str(part_info, &parts_str);
|
||||
item_list.push_back(new Item_string(parts_str.ptr(),
|
||||
parts_str.length(), cs));
|
||||
}
|
||||
else
|
||||
item_list.push_back(item_null);
|
||||
#else
|
||||
/* just produce empty column if partitioning is not compiled in */
|
||||
item_list.push_back(item_null);
|
||||
#endif
|
||||
}
|
||||
/* "type" column */
|
||||
item_list.push_back(new Item_string(join_type_str[tab->type],
|
||||
strlen(join_type_str[tab->type]),
|
||||
cs));
|
||||
|
|
|
@ -7419,8 +7419,10 @@ describe_command:
|
|||
opt_extended_describe:
|
||||
/* empty */ {}
|
||||
| EXTENDED_SYM { Lex->describe|= DESCRIBE_EXTENDED; }
|
||||
| PARTITIONS_SYM { Lex->describe|= DESCRIBE_PARTITIONS; }
|
||||
;
|
||||
|
||||
|
||||
opt_describe_column:
|
||||
/* empty */ {}
|
||||
| text_string { Lex->wild= $1; }
|
||||
|
|
|
@ -300,6 +300,7 @@ struct st_table {
|
|||
FILESORT_INFO sort;
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
partition_info *part_info; /* Partition related information */
|
||||
bool no_partitions_used; /* If true, all partitions have been pruned away */
|
||||
#endif
|
||||
|
||||
bool fill_item_list(List<Item> *item_list) const;
|
||||
|
|
Loading…
Add table
Reference in a new issue