mariadb/mysql-test/t/partition_pruning.test
unknown 457510903f Fix for BUG#18025: Wrong query results because of bugs in partition pruning:
- Fix typo bug in SEL_ARG::is_singlepoint()
 - In set_up_range_analysis_info(), treat MEDIUMINT as enumerable type just like other integer types


mysql-test/r/partition_pruning.result:
  Testcase for BUG#18025
mysql-test/t/partition_pruning.test:
  Testcase for BUG#18025
sql/opt_range.cc:
  BUG#18025: Fix a typo bug in SEL_ARG::is_singlepoint()
sql/sql_partition.cc:
  BUG#18025: In set_up_range_analysis_info(), treat MEDIUMINT as enumerable type just like other integer types.
2006-03-31 15:17:15 +04:00

483 lines
15 KiB
Text

#
# 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 uses both partitions
explain partitions select * from t1 where a is not null;
drop table t1;
# Join tests
create table t1 (a int not null, b int not null, key(a), key(b))
partition by hash(a) partitions 4;
insert into t1 values (1,1),(2,2),(3,3),(4,4);
explain partitions
select * from t1 X, t1 Y
where X.b = Y.b and (X.a=1 or X.a=2) and (Y.a=2 or Y.a=3);
explain partitions
select * from t1 X, t1 Y where X.a = Y.a and (X.a=1 or X.a=2);
drop table t1;
# Tests for "short ranges"
create table t1 (a int) partition by hash(a) partitions 20;
insert into t1 values (1),(2),(3);
explain partitions select * from t1 where a > 1 and a < 3;
explain partitions select * from t1 where a >= 1 and a < 3;
explain partitions select * from t1 where a > 1 and a <= 3;
explain partitions select * from t1 where a >= 1 and a <= 3;
drop table t1;
create table t1 (a int, b int)
partition by list(a) subpartition by hash(b) subpartitions 20
(
partition p0 values in (0),
partition p1 values in (1),
partition p2 values in (2),
partition p3 values in (3)
);
insert into t1 values (1,1),(2,2),(3,3);
explain partitions select * from t1 where b > 1 and b < 3;
explain partitions select * from t1 where b > 1 and b < 3 and (a =1 or a =2);
drop table t1;
# Test partition pruning for single-table UPDATE/DELETE.
# TODO: Currently we test only "all partitions pruned away" case. Add more
# tests when the patch that makes use of partition pruning results at
# execution phase is pushed.
create table t1 (a int) partition by list(a) (
partition p0 values in (1,2),
partition p1 values in (3,4)
);
insert into t1 values (1),(1),(2),(2),(3),(4),(3),(4);
# This won't do any table access
flush status;
update t1 set a=100 where a=5;
show status like 'Handler_read_rnd_next';
# ... as compared to this, which will scan both partitions
flush status;
update t1 set a=100 where a+1=5+1;
show status like 'Handler_read_rnd_next';
# Same as above for DELETE:
flush status;
delete from t1 where a=5;
show status like 'Handler_read_rnd_next';
flush status;
delete from t1 where a+1=5+1;
show status like 'Handler_read_rnd_next';
# Same as above multi-table UPDATE/DELETE
create table t2 like t1;
insert into t2 select * from t2;
flush status;
update t1,t2 set t1.a=1000, t2.a=1000 where t1.a=5 and t2.a=5;
show status like 'Handler_read_rnd_next';
# ^ This shows 3 accesses, these are caused by const table reads.
# They should vanish when partition pruning results are used.
flush status;
delete t1,t2 from t1, t2 where t1.a=5 and t2.a=5;
show status like 'Handler_read_rnd_next';
drop table t1,t2;
#
# WL#2986 Tests (Checking if partition pruning results are used at query
# execution phase)
#
CREATE TABLE `t1` (
`a` int(11) default NULL
);
INSERT INTO t1 VALUES (0),(1),(2),(3),(4),(5),(6),(7),(8),(9);
CREATE TABLE `t2` (
`a` int(11) default NULL,
KEY `a` (`a`)
) ;
insert into t2 select A.a + 10*(B.a + 10* C.a) from t1 A, t1 B, t1 C ;
insert into t1 select a from t2;
drop table t2;
CREATE TABLE `t2` (
`a` int(11) default NULL,
`b` int(11) default NULL
)
PARTITION BY RANGE (a) (
PARTITION p0 VALUES LESS THAN (200),
PARTITION p1 VALUES LESS THAN (400),
PARTITION p2 VALUES LESS THAN (600),
PARTITION p3 VALUES LESS THAN (800),
PARTITION p4 VALUES LESS THAN (1001));
insert into t2 select a,1 from t1 where a < 200;
insert into t2 select a,2 from t1 where a >= 200 and a < 400;
insert into t2 select a,3 from t1 where a >= 400 and a < 600;
insert into t2 select a,4 from t1 where a >= 600 and a < 800;
insert into t2 select a,5 from t1 where a >= 800 and a < 1001;
explain partitions select * from t2;
explain partitions select * from t2 where a < 801 and a > 200;
explain partitions select * from t2 where a < 801 and a > 800;
explain partitions select * from t2 where a > 600;
explain partitions select * from t2 where a > 600 and b = 1;
explain partitions select * from t2 where a > 600 and b = 4;
explain partitions select * from t2 where a > 600 and b = 5;
explain partitions select * from t2 where b = 5;
flush status;
update t2 set b = 100 where b = 6;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set a = 1002 where a = 1001;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set b = 6 where a = 600;
show status like 'Handler_read_rnd_next';
flush status;
update t2 set b = 6 where a > 600 and a < 800;
show status like 'Handler_read_rnd_next';
flush status;
delete from t2 where a > 600;
show status like 'Handler_read_rnd_next';
drop table t2;
CREATE TABLE `t2` (
`a` int(11) default NULL,
`b` int(11) default NULL,
index (b)
)
PARTITION BY RANGE (a) (
PARTITION p0 VALUES LESS THAN (200),
PARTITION p1 VALUES LESS THAN (400),
PARTITION p2 VALUES LESS THAN (600),
PARTITION p3 VALUES LESS THAN (800),
PARTITION p4 VALUES LESS THAN (1001));
insert into t2 select a,1 from t1 where a < 100;
insert into t2 select a,2 from t1 where a >= 200 and a < 300;
insert into t2 select a,3 from t1 where a >= 300 and a < 400;
insert into t2 select a,4 from t1 where a >= 400 and a < 500;
insert into t2 select a,5 from t1 where a >= 500 and a < 600;
insert into t2 select a,6 from t1 where a >= 600 and a < 700;
insert into t2 select a,7 from t1 where a >= 700 and a < 800;
insert into t2 select a,8 from t1 where a >= 800 and a < 900;
insert into t2 select a,9 from t1 where a >= 900 and a < 1001;
explain partitions select * from t2;
# not using indexes
explain partitions select * from t2 where a = 101;
explain partitions select * from t2 where a = 550;
explain partitions select * from t2 where a = 833;
explain partitions select * from t2 where (a = 100 OR a = 900);
explain partitions select * from t2 where (a > 100 AND a < 600);
explain partitions select * from t2 where b = 4;
explain partitions select * from t2 where b = 6;
explain partitions select * from t2 where b in (1,3,5);
explain partitions select * from t2 where b in (2,4,6);
explain partitions select * from t2 where b in (7,8,9);
explain partitions select * from t2 where b > 5;
explain partitions select * from t2 where b > 5 and b < 8;
explain partitions select * from t2 where b > 5 and b < 7;
explain partitions select * from t2 where b > 0 and b < 5;
flush status;
update t2 set a = 111 where b = 10;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
update t2 set a = 111 where b in (5,6);
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
update t2 set a = 222 where b = 7;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
delete from t2 where b = 7;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
flush status;
delete from t2 where b > 5;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
show status like 'Handler_read_prev';
show status like 'Handler_read_next';
flush status;
delete from t2 where b < 5 or b > 3;
show status like 'Handler_read_rnd_next';
show status like 'Handler_read_key';
show status like 'Handler_read_prev';
show status like 'Handler_read_next';
drop table t1, t2;
# BUG#18025
# part1: mediumint columns
create table t1 ( f_int1 mediumint, f_int2 integer)
partition by list(mod(f_int1,4)) (
partition p_3 values in (-3),
partition p_2 values in (-2),
partition p_1 values in (-1),
partition p0 values in (0),
partition p1 values in (1),
partition p2 values in (2),
partition p3 values in (3)
);
insert into t1 values (9, 9), (8, 8), (7, 7), (6, 6), (5, 5),
(4, 4), (3, 3), (2, 2), (1, 1);
select * from t1 where f_int1 between 5 and 15 order by f_int1;
drop table t1;
# part2: bug in pruning code
create table t1 (a char(10)) partition by list(length(a)) (
partition p1 values in (1),
partition p2 values in (2),
partition p3 values in (3),
partition p4 values in (4),
partition p5 values in (5)
);
insert into t1 values ('a'),('bb'),('ccc'),('dddd'),('eeEee');
select * from t1 where a>='a' and a <= 'dddd';
explain partitions select * from t1 where a>='a' and a <= 'dddd';
drop table t1;
# No tests for NULLs in RANGE(monotonic_expr()) - they depend on BUG#15447
# being fixed.