Merged WL#3352 into mysql-next-mr

This commit is contained in:
Mikael Ronstrom 2009-10-28 18:22:36 +01:00
commit 072c13d939
48 changed files with 4922 additions and 1365 deletions

View File

@ -420,14 +420,12 @@ create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
ERROR 42000: VALUES value must be of same type as partition function near '),
partition p1 values less than (10))' at line 3
ERROR HY000: VALUES value must be of same type as partition function
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
partition p1 values in (10));
ERROR 42000: VALUES value must be of same type as partition function near '),
partition p1 values in (10))' at line 3
ERROR HY000: VALUES value must be of same type as partition function
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (100),
@ -1421,7 +1419,7 @@ DROP TABLE t1;
CREATE TABLE t1 (a int)
PARTITION BY RANGE(a)
(PARTITION p0 VALUES LESS THAN (NULL));
ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '))' at line 3
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
create table t1 (s1 int auto_increment primary key)
partition by list (s1)
(partition p1 values in (1),

View File

@ -0,0 +1,524 @@
drop table if exists t1;
create table t1 (a varchar(1500), b varchar(1570))
partition by list column_list(a,b)
( partition p0 values in (('a','b')));
ERROR HY000: The total length of the partitioning fields is too large
create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
partition by range column_list(a)
( partition p0 values less than ('CZ'),
partition p1 values less than ('CH'),
partition p2 values less than ('D'));
insert into t1 values ('czz'),('chi'),('ci'),('cg');
select * from t1 where a between 'cg' AND 'ci';
a
ci
cg
drop table t1;
set @@sql_mode=allow_invalid_dates;
create table t1 (a char, b char, c date)
partition by range column_list (a,b,c)
( partition p0 values less than (0,0,to_days('3000-11-31')));
ERROR HY000: Partition column values of incorrect type
create table t1 (a char, b char, c date)
partition by range column_list (a,b,c)
( partition p0 values less than (0,0,'3000-11-31'));
ERROR HY000: Partition column values of incorrect type
set @@sql_mode='';
create table t1 (a varchar(2) character set ucs2)
partition by list column_list (a)
(partition p0 values in (0x2020),
partition p1 values in (''));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` varchar(2) CHARACTER SET ucs2 DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST COLUMN_LIST(a)
(PARTITION p0 VALUES IN (_ucs2' ') ENGINE = MyISAM,
PARTITION p1 VALUES IN (_ucs2'') ENGINE = MyISAM) */
insert into t1 values ('');
insert into t1 values (_ucs2 0x2020);
drop table t1;
create table t1 (a int, b char(10), c varchar(25), d datetime)
partition by range column_list(a,b,c,d)
subpartition by hash (to_seconds(d))
subpartitions 4
( partition p0 values less than (1, 0, MAXVALUE, 0),
partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
RANGE COLUMN_LIST a,b,c,d 1,'0',MAXVALUE,0
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,730120
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,'a',MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
RANGE COLUMN_LIST a,b,c,d 1,MAXVALUE,MAXVALUE,MAXVALUE
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` char(10) DEFAULT NULL,
`c` varchar(25) DEFAULT NULL,
`d` datetime DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE COLUMN_LIST(a,b,c,d)
SUBPARTITION BY HASH (to_seconds(d))
SUBPARTITIONS 4
(PARTITION p0 VALUES LESS THAN (1,_latin1'0',MAXVALUE,0) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1,_latin1'a',MAXVALUE,730120) ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (1,_latin1'a',MAXVALUE,MAXVALUE) ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (1,MAXVALUE,MAXVALUE,MAXVALUE) ENGINE = MyISAM) */
drop table t1;
create table t1 (a int, b int)
partition by range column_list (a,b)
(partition p0 values less than (NULL, maxvalue));
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in ((maxvalue, 0)));
Got one of the listed errors
create table t1 (a int, b int)
partition by list column_list (a,b)
( partition p0 values in ((0,0)));
alter table t1 add partition
(partition p1 values in (maxvalue, maxvalue));
Got one of the listed errors
drop table t1;
create table t1 (a int, b int)
partition by key (a,a);
ERROR HY000: Duplicate partition field name 'a'
create table t1 (a int, b int)
partition by list column_list(a,a)
( partition p values in ((1,1)));
ERROR HY000: Duplicate partition field name 'a'
create table t1 (a int signed)
partition by list (a)
( partition p0 values in (1, 3, 5, 7, 9, NULL),
partition p1 values in (2, 4, 6, 8, 0));
insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
select * from t1 where NULL <= a;
a
select * from t1 where a is null;
a
NULL
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 10 Using where
select * from t1 where a <= 1;
a
1
0
drop table t1;
create table t1 (a int signed)
partition by list column_list(a)
( partition p0 values in (1, 3, 5, 7, 9, NULL),
partition p1 values in (2, 4, 6, 8, 0));
insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
select * from t1 where a <= NULL;
a
select * from t1 where a is null;
a
NULL
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
select * from t1 where a <= 1;
a
1
0
drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in ((1, NULL), (2, NULL), (NULL, NULL)),
partition p1 values in ((1,1), (2,2)),
partition p2 values in ((3, NULL), (NULL, 1)));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
LIST COLUMN_LIST a,b (1,NULL),(2,NULL),(NULL,NULL)
LIST COLUMN_LIST a,b (1,1),(2,2)
LIST COLUMN_LIST a,b (3,NULL),(NULL,1)
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST COLUMN_LIST(a,b)
(PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM,
PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM,
PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */
insert into t1 values (3, NULL);
insert into t1 values (NULL, 1);
insert into t1 values (NULL, NULL);
insert into t1 values (1, NULL);
insert into t1 values (2, NULL);
insert into t1 values (1,1);
insert into t1 values (2,2);
select * from t1 where a = 1;
a b
1 NULL
1 1
select * from t1 where a = 2;
a b
2 NULL
2 2
select * from t1 where a > 8;
a b
select * from t1 where a not between 8 and 8;
a b
2 NULL
2 2
3 NULL
1 NULL
1 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST COLUMN_LIST(a,b)
(PARTITION p0 VALUES IN ((1,NULL),(2,NULL),(NULL,NULL)) ENGINE = MyISAM,
PARTITION p1 VALUES IN ((1,1),(2,2)) ENGINE = MyISAM,
PARTITION p2 VALUES IN ((3,NULL),(NULL,1)) ENGINE = MyISAM) */
drop table t1;
create table t1 (a int)
partition by list (a)
( partition p0 values in (1),
partition p1 values in (1));
ERROR HY000: Multiple definition of same constant in list partitioning
create table t1 (a int)
partition by list (a)
( partition p0 values in (2, 1),
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
LIST a 2,1
LIST a NULL,4,3
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST (a)
(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
PARTITION p1 VALUES IN (NULL,4,3) ENGINE = MyISAM) */
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
insert into t1 values (4);
insert into t1 values (NULL);
insert into t1 values (5);
ERROR HY000: Table has no partition for value 5
drop table t1;
create table t1 (a int)
partition by list column_list(a)
( partition p0 values in (2, 1),
partition p1 values in ((4), (NULL), (3)));
ERROR 42000: Row expressions in VALUES IN only allowed for multi-field column partitioning near '))' at line 4
create table t1 (a int)
partition by list column_list(a)
( partition p0 values in (2, 1),
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
LIST COLUMN_LIST a 2,1
LIST COLUMN_LIST a 4,NULL,3
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST COLUMN_LIST(a)
(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
insert into t1 values (4);
insert into t1 values (NULL);
insert into t1 values (5);
ERROR HY000: Table has no partition for value from column_list
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY LIST COLUMN_LIST(a)
(PARTITION p0 VALUES IN (2,1) ENGINE = MyISAM,
PARTITION p1 VALUES IN (4,NULL,3) ENGINE = MyISAM) */
drop table t1;
create table t1 (a int, b char(10), c varchar(5), d int)
partition by range column_list(a,b,c)
subpartition by key (c,d)
subpartitions 3
( partition p0 values less than (1,'abc','abc'),
partition p1 values less than (2,'abc','abc'),
partition p2 values less than (3,'abc','abc'),
partition p3 values less than (4,'abc','abc'));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
RANGE COLUMN_LIST a,b,c 1,'abc','abc'
RANGE COLUMN_LIST a,b,c 1,'abc','abc'
RANGE COLUMN_LIST a,b,c 1,'abc','abc'
RANGE COLUMN_LIST a,b,c 2,'abc','abc'
RANGE COLUMN_LIST a,b,c 2,'abc','abc'
RANGE COLUMN_LIST a,b,c 2,'abc','abc'
RANGE COLUMN_LIST a,b,c 3,'abc','abc'
RANGE COLUMN_LIST a,b,c 3,'abc','abc'
RANGE COLUMN_LIST a,b,c 3,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
RANGE COLUMN_LIST a,b,c 4,'abc','abc'
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` char(10) DEFAULT NULL,
`c` varchar(5) DEFAULT NULL,
`d` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE COLUMN_LIST(a,b,c)
SUBPARTITION BY KEY (c,d)
SUBPARTITIONS 3
(PARTITION p0 VALUES LESS THAN (1,_latin1'abc',_latin1'abc') ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (2,_latin1'abc',_latin1'abc') ENGINE = MyISAM,
PARTITION p2 VALUES LESS THAN (3,_latin1'abc',_latin1'abc') ENGINE = MyISAM,
PARTITION p3 VALUES LESS THAN (4,_latin1'abc',_latin1'abc') ENGINE = MyISAM) */
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
insert into t1 values (1,'c','d',1),(2,'c','d',2),(3,'c','d',3);
insert into t1 values (1,'d','e',1),(2,'d','e',2),(3,'d','e',3);
select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
a b c d
1 a b 1
1 b c 1
drop table t1;
create table t1 (a int, b varchar(2), c int)
partition by range column_list (a, b, c)
(partition p0 values less than (1, 'A', 1),
partition p1 values less than (1, 'B', 1));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
RANGE COLUMN_LIST a,b,c 1,'A',1
RANGE COLUMN_LIST a,b,c 1,'B',1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) DEFAULT NULL,
`b` varchar(2) DEFAULT NULL,
`c` int(11) DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
/*!50100 PARTITION BY RANGE COLUMN_LIST(a,b,c)
(PARTITION p0 VALUES LESS THAN (1,_latin1'A',1) ENGINE = MyISAM,
PARTITION p1 VALUES LESS THAN (1,_latin1'B',1) ENGINE = MyISAM) */
insert into t1 values (1, 'A', 1);
explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 system NULL NULL NULL NULL 1
select * from t1 where a = 1 AND b <= 'A' and c = 1;
a b c
1 A 1
drop table t1;
create table t1 (a char, b char, c char)
partition by list column_list(a)
( partition p0 values in ('a'));
insert into t1 (a) values ('a');
select * from t1 where a = 'a';
a b c
a NULL NULL
drop table t1;
create table t1 (d time)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
ERROR HY000: Partition column values of incorrect type
create table t1 (d timestamp)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
create table t1 (d bit(1))
partition by range column_list(d)
( partition p0 values less than (0),
partition p1 values less than (1));
ERROR HY000: Field 'd' is of a not allowed type for this type of partitioning
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue, 10));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2009-01-01'));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('1999-01-01'),
partition p1 values less than ('2000-01-01'));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('3000-01-01'));
drop table t1;
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p2 values less than (99,99),
partition p1 values less than (99,999));
insert into t1 values (99,998);
select * from t1 where b = 998;
a b
99 998
drop table t1;
create table t1 as select to_seconds(null) as to_seconds;
select data_type from information_schema.columns
where column_name='to_seconds';
data_type
int
drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
(partition p0 values in ((maxvalue,maxvalue)));
ERROR 42000: Cannot use MAXVALUE as value in VALUES IN near 'maxvalue,maxvalue)))' at line 3
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue,maxvalue));
drop table t1;
create table t1 (a int)
partition by list column_list(a)
(partition p0 values in (0));
select partition_method from information_schema.partitions where table_name='t1';
partition_method
LIST COLUMN_LIST
drop table t1;
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than ('H23456'),
partition p1 values less than ('M23456'));
insert into t1 values ('F23456');
select * from t1;
a
F23456
drop table t1;
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than (H23456),
partition p1 values less than (M23456));
ERROR 42S22: Unknown column 'H23456' in 'field list'
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than (23456),
partition p1 values less than (23456));
ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (10));
ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (1,1,1);
ERROR HY000: Inconsistency in usage of column lists for partitioning
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (1, 0),
partition p1 values less than (2, maxvalue),
partition p2 values less than (3, 3),
partition p3 values less than (10, maxvalue));
insert into t1 values (11,0);
ERROR HY000: Table has no partition for value from column_list
insert into t1 values (0,1),(1,1),(2,1),(3,1),(3,4),(4,9),(9,1);
select * from t1;
a b
0 1
1 1
2 1
3 1
3 4
4 9
9 1
alter table t1
partition by range column_list(b,a)
(partition p0 values less than (1,2),
partition p1 values less than (3,3),
partition p2 values less than (9,5));
explain partitions select * from t1 where b < 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 7 Using where
select * from t1 where b < 2;
a b
0 1
1 1
2 1
3 1
9 1
explain partitions select * from t1 where b < 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1,p2 ALL NULL NULL NULL NULL 7 Using where
select * from t1 where b < 4;
a b
0 1
1 1
2 1
3 1
9 1
alter table t1 reorganize partition p1 into
(partition p11 values less than (2,2),
partition p12 values less than (3,3));
alter table t1 reorganize partition p0 into
(partition p01 values less than (0,3),
partition p02 values less than (1,1));
ERROR HY000: Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
alter table t1 reorganize partition p2 into
(partition p2 values less than(9,6,1));
ERROR HY000: Inconsistency in usage of column lists for partitioning
alter table t1 reorganize partition p2 into
(partition p2 values less than (10));
ERROR HY000: Inconsistency in usage of column lists for partitioning
alter table t1 reorganize partition p2 into
(partition p21 values less than (4,7),
partition p22 values less than (9,5));
explain partitions select * from t1 where b < 4;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p11,p12,p21 ALL NULL NULL NULL NULL 7 Using where
select * from t1 where b < 4;
a b
0 1
1 1
2 1
3 1
9 1
drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
subpartition by hash (b)
subpartitions 2
(partition p0 values in ((0,0), (1,1)),
partition p1 values in ((1000,1000)));
insert into t1 values (1000,1000);
drop table t1;
create table t1 (a char, b char, c char)
partition by range column_list(a,b,c)
( partition p0 values less than ('a','b','c'));
alter table t1 add partition
(partition p1 values less than ('b','c','d'));
drop table t1;

View File

@ -0,0 +1,66 @@
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
create table t1 (a char, b char, c char)
partition by range column_list(a,b,c)
( partition p0 values less than ('a','b','c'));
insert into t1 values ('a', NULL, 'd');
explain partitions select * from t1 where a = 'a' AND c = 'd';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
select * from t1 where a = 'a' AND c = 'd';
a b c
a NULL d
drop table t1;
create table t1 (a int not null) partition by range column_list(a) (
partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (40),
partition p4 values less than (50),
partition p5 values less than (60),
partition p6 values less than (70)
);
insert into t1 values (5),(15),(25),(35),(45),(55),(65);
insert into t1 values (5),(15),(25),(35),(45),(55),(65);
create table t2 (a int not null) partition by range(a) (
partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (40),
partition p4 values less than (50),
partition p5 values less than (60),
partition p6 values less than (70)
);
insert into t2 values (5),(15),(25),(35),(45),(55),(65);
insert into t2 values (5),(15),(25),(35),(45),(55),(65);
explain partitions select * from t1 where a > 35 and a < 45;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p3,p4 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t2 where a > 35 and a < 45;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t2 p3,p4 ALL NULL NULL NULL NULL 4 Using where
drop table t1, t2;
create table t1 (a int not null, b int not null )
partition by range column_list(a,b) (
partition p01 values less than (2,10),
partition p02 values less than (2,20),
partition p03 values less than (2,30),
partition p11 values less than (4,10),
partition p12 values less than (4,20),
partition p13 values less than (4,30),
partition p21 values less than (6,10),
partition p22 values less than (6,20),
partition p23 values less than (6,30)
);
insert into t1 values (2,5), (2,15), (2,25),
(4,5), (4,15), (4,25), (6,5), (6,15), (6,25);
insert into t1 select * from t1;
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 p01,p02,p03,p11 ALL NULL NULL NULL NULL 13 Using where
explain partitions select * from t1 where a=4;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p11,p12,p13,p21 ALL NULL NULL NULL NULL 16 Using where
explain partitions select * from t1 where a=2 and b < 22;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p01,p02,p03 ALL NULL NULL NULL NULL 16 Using where
drop table t1;

View File

@ -273,7 +273,7 @@ select * from t1 where a = 'y';
a
y
drop table t1;
create table t1 (a varchar(65531)) partition by key (a);
create table t1 (a varchar(3068)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@ -286,7 +286,7 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
create table t1 (a varchar(65532)) partition by key (a);
create table t1 (a varchar(3069)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@ -299,7 +299,7 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
create table t1 (a varchar(65533) not null) partition by key (a);
create table t1 (a varchar(3070) not null) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
@ -312,6 +312,8 @@ select * from t1 where a = 'bbbb';
a
bbbb
drop table t1;
create table t1 (a varchar(3070)) partition by key (a);
ERROR HY000: The total length of the partitioning fields is too large
create table t1 (a varchar(65533)) partition by key (a);
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
create table t1 (a varchar(65534) not null) partition by key (a);

View File

@ -361,8 +361,7 @@ partition by range (a)
partitions 2
(partition x1 values less than (4.0) tablespace ts1,
partition x2 values less than (8) tablespace ts2);
ERROR 42000: VALUES value must be of same type as partition function near ') tablespace ts1,
partition x2 values less than (8) tablespace ts2)' at line 8
ERROR HY000: VALUES value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,
@ -412,8 +411,7 @@ partition by list (a)
partitions 2
(partition x1 values less than 4,
partition x2 values less than (5));
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 '4,
partition x2 values less than (5))' at line 8
ERROR HY000: Only RANGE PARTITIONING can use VALUES LESS THAN in partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@ -423,7 +421,7 @@ partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than (5));
ERROR 42000: MAXVALUE can only be used in last partition definition near '))' at line 9
ERROR HY000: MAXVALUE can only be used in last partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@ -433,7 +431,7 @@ partition by range (a)
partitions 2
(partition x1 values less than maxvalue,
partition x2 values less than maxvalue);
ERROR 42000: MAXVALUE can only be used in last partition definition near 'maxvalue)' at line 9
ERROR HY000: MAXVALUE can only be used in last partition definition
CREATE TABLE t1 (
a int not null,
b int not null,
@ -602,8 +600,7 @@ partition by list (a)
partitions 2
(partition x1 values in (4.0, 12+8),
partition x2 values in (3, 21));
ERROR 42000: VALUES value must be of same type as partition function near ' 12+8),
partition x2 values in (3, 21))' at line 8
ERROR HY000: VALUES value must be of same type as partition function
CREATE TABLE t1 (
a int not null,
b int not null,

View File

@ -1,4 +1,28 @@
drop table if exists t1;
create table t1 (a varchar(5))
engine=memory
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
create table t1 (a varchar(5))
engine=myisam
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
create table t1 (a varchar(5))
engine=innodb
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
create table t1 (a int not null,
b datetime not null,
primary key (a,b))

View File

@ -54,6 +54,17 @@ subpartitions 2
partition p1 values in (1),
partition pnull values in (null, 2),
partition p3 values in (3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
LIST a 0
LIST a 0
LIST a 1
LIST a 1
LIST a NULL,2
LIST a NULL,2
LIST a 3
LIST a 3
insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1);
insert into t1 values (2,0),(2,1),(3,0),(3,1);
explain partitions select * from t1 where a is null;

View File

@ -41,7 +41,7 @@ ERROR HY000: Reorganize of range partitions cannot change total ranges except fo
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (4),
PARTITION x11 VALUES LESS THAN (2));
ERROR HY000: Reorganize of range partitions cannot change total ranges except for last partition where it can extend the range
ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (6),
PARTITION x11 VALUES LESS THAN (4));

View File

@ -656,6 +656,335 @@ EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
DROP TABLE t1;
# TO_SECONDS, test of LIST and index
CREATE TABLE t1 (a DATE, KEY(a))
PARTITION BY LIST (TO_SECONDS(a))
(PARTITION `p0001-01-01` VALUES IN (TO_SECONDS('0001-01-01')),
PARTITION `p2001-01-01` VALUES IN (TO_SECONDS('2001-01-01')),
PARTITION `pNULL` VALUES IN (NULL),
PARTITION `p0000-01-02` VALUES IN (TO_SECONDS('0000-01-02')),
PARTITION `p1001-01-01` VALUES IN (TO_SECONDS('1001-01-01')));
INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
SELECT * FROM t1 WHERE a < '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
SELECT * FROM t1 WHERE a <= '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
SELECT * FROM t1 WHERE a >= '1001-01-01';
a
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a > '1001-01-01';
a
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a = '1001-01-01';
a
1001-01-01
SELECT * FROM t1 WHERE a < '1001-00-00';
a
0000-00-00
0000-01-02
0001-01-01
SELECT * FROM t1 WHERE a <= '1001-00-00';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
SELECT * FROM t1 WHERE a >= '1001-00-00';
a
1001-00-00
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a > '1001-00-00';
a
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a = '1001-00-00';
a
1001-00-00
# Disabling warnings for the invalid date
SELECT * FROM t1 WHERE a < '1999-02-31';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a <= '1999-02-31';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a >= '1999-02-31';
a
2001-01-01
SELECT * FROM t1 WHERE a > '1999-02-31';
a
2001-01-01
SELECT * FROM t1 WHERE a = '1999-02-31';
a
SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
a
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
a
0001-01-01
1001-00-00
1001-01-01
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 3 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1001-01-01 system a NULL NULL NULL 1
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 range a a 4 NULL 3 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 range a a 4 NULL 4 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
# Disabling warnings for the invalid date
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL range a a 4 NULL 2 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL ref a a 4 const 1 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 5 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 range a a 4 NULL 4 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL,p1001-01-01 range a a 4 NULL 2 Using where; Using index
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 range a a 4 NULL 3 Using where; Using index
# test without index
ALTER TABLE t1 DROP KEY a;
SELECT * FROM t1 WHERE a < '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
SELECT * FROM t1 WHERE a <= '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
SELECT * FROM t1 WHERE a >= '1001-01-01';
a
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a > '1001-01-01';
a
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a = '1001-01-01';
a
1001-01-01
SELECT * FROM t1 WHERE a < '1001-00-00';
a
0000-00-00
0000-01-02
0001-01-01
SELECT * FROM t1 WHERE a <= '1001-00-00';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
SELECT * FROM t1 WHERE a >= '1001-00-00';
a
1001-00-00
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a > '1001-00-00';
a
1001-01-01
1002-00-00
2001-01-01
SELECT * FROM t1 WHERE a = '1001-00-00';
a
1001-00-00
# Disabling warnings for the invalid date
SELECT * FROM t1 WHERE a < '1999-02-31';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a <= '1999-02-31';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a >= '1999-02-31';
a
2001-01-01
SELECT * FROM t1 WHERE a > '1999-02-31';
a
2001-01-01
SELECT * FROM t1 WHERE a = '1999-02-31';
a
SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
a
0000-00-00
0000-01-02
0001-01-01
1001-00-00
1001-01-01
SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
a
1001-00-00
1001-01-01
1002-00-00
SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
a
0001-01-01
1001-00-00
1001-01-01
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p1001-01-01 system NULL NULL NULL NULL 1
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1001-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
# Disabling warnings for the invalid date
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a < '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a <= '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a >= '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a > '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p2001-01-01,pNULL ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a = '1999-02-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1002-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0000-00-00' AND '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p0000-01-02,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-02' AND '1002-00-00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
EXPLAIN PARTITIONS SELECT * FROM t1 WHERE a BETWEEN '0001-01-01' AND '1001-01-01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0001-01-01,pNULL,p1001-01-01 ALL NULL NULL NULL NULL 7 Using where
DROP TABLE t1;
# Test with DATETIME column NOT NULL
CREATE TABLE t1 (
a int(10) unsigned NOT NULL,

View File

@ -1,6 +1,99 @@
drop table if exists t1, t2;
create table t1 (a int)
partition by range (a)
( partition p0 values less than (NULL),
partition p1 values less than (MAXVALUE));
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
create table t1 (a datetime not null)
partition by range (TO_SECONDS(a))
( partition p0 VALUES LESS THAN (TO_SECONDS('2007-03-08 00:00:00')),
partition p1 VALUES LESS THAN (TO_SECONDS('2007-04-01 00:00:00')));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
partition_method partition_expression partition_description
RANGE TO_SECONDS(a) 63340531200
RANGE TO_SECONDS(a) 63342604800
INSERT INTO t1 VALUES ('2007-03-01 12:00:00'), ('2007-03-07 12:00:00');
INSERT INTO t1 VALUES ('2007-03-08 12:00:00'), ('2007-03-15 12:00:00');
explain partitions select * from t1 where a < '2007-03-08 00:00:00';
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 < '2007-03-08 00:00:01';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a <= '2007-03-08 00:00:00';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0,p1 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a <= '2007-03-07 23:59:59';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
explain partitions select * from t1 where a < '2007-03-07 23:59:59';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 ALL NULL NULL NULL NULL 4 Using where
drop table t1;
create table t1 (a date)
partition by range(to_seconds(a))
(partition p0 values less than (to_seconds('2004-01-01')),
partition p1 values less than (to_seconds('2005-01-01')));
insert into t1 values ('2003-12-30'),('2004-12-31');
select * from t1;
a
2003-12-30
2004-12-31
explain partitions select * from t1 where a <= '2003-12-31';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
select * from t1 where a <= '2003-12-31';
a
2003-12-30
explain partitions select * from t1 where a <= '2005-01-01';
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
select * from t1 where a <= '2005-01-01';
a
2003-12-30
2004-12-31
drop table t1;
create table t1 (a datetime)
partition by range(to_seconds(a))
(partition p0 values less than (to_seconds('2004-01-01 12:00:00')),
partition p1 values less than (to_seconds('2005-01-01 12:00:00')));
insert into t1 values ('2004-01-01 11:59:29'),('2005-01-01 11:59:59');
select * from t1;
a
2004-01-01 11:59:29
2005-01-01 11:59:59
explain partitions select * from t1 where a <= '2004-01-01 11:59.59';
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 p0 system NULL NULL NULL NULL 1
select * from t1 where a <= '2004-01-01 11:59:59';
a
2004-01-01 11:59:29
explain partitions select * from t1 where a <= '2005-01-01';
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
select * from t1 where a <= '2005-01-01';
a
2004-01-01 11:59:29
drop table t1;
create table t1 (a int, b char(20))
partition by range column_list(a,b)
(partition p0 values less than (1));
ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
create table t1 (a int, b char(20))
partition by range(a)
(partition p0 values less than (1,"b"));
ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
create table t1 (a int, b char(20))
partition by range(a)
(partition p0 values less than (1,"b"));
ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
create table t1 (a int, b char(20))
partition by range column_list(b)
(partition p0 values less than ("b"));
drop table t1;
create table t1 (a int)
partition by range (a)
( partition p0 values less than (maxvalue));
alter table t1 add partition (partition p1 values less than (100000));
ERROR HY000: MAXVALUE can only be used in last partition definition

View File

@ -1,4 +1,4 @@
--error ER_TOO_MANY_KEY_PARTS
--error ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
eval create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h3)) engine=$engine
partition by key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1,a2,b2,c2,d2,e2,f2,g2,h2,a3,b3,c3,d3,e3,f3,g3,h3) (
partition pa1 max_rows=20 min_rows=2,

View File

@ -312,7 +312,7 @@ PARTITION BY RANGE(f_int1)
--echo #------------------------------------------------------------------------
--echo # 3.5.1 NULL in RANGE partitioning clause
--echo # 3.5.1.1 VALUE LESS THAN (NULL) is not allowed
--error ER_PARSE_ERROR
--error ER_NULL_IN_VALUES_LESS_THAN
eval CREATE TABLE t1 (
$column_list
)
@ -320,7 +320,7 @@ PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
--echo # 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
--error ER_PARSE_ERROR
--error ER_NULL_IN_VALUES_LESS_THAN
eval CREATE TABLE t1 (
$column_list
)

View File

@ -133,7 +133,7 @@ partition pa1 max_rows=20 min_rows=2,
partition pa2 max_rows=30 min_rows=3,
partition pa3 max_rows=30 min_rows=4,
partition pa4 max_rows=40 min_rows=2);
ERROR 42000: Too many key parts specified; max 16 parts allowed
ERROR HY000: Too many fields in 'list of partition fields'
create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1)) engine='InnoDB'
partition by key(a,b,c,d,e,f,g,h) (
partition pa1 max_rows=20 min_rows=2,

View File

@ -133,7 +133,7 @@ partition pa1 max_rows=20 min_rows=2,
partition pa2 max_rows=30 min_rows=3,
partition pa3 max_rows=30 min_rows=4,
partition pa4 max_rows=40 min_rows=2);
ERROR 42000: Too many key parts specified; max 16 parts allowed
ERROR HY000: Too many fields in 'list of partition fields'
create table t1 (a date not null, b varchar(50) not null, c varchar(50) not null, d enum('m', 'w') not null, e int not null, f decimal (18,2) not null, g bigint not null, h tinyint not null, a1 date not null, b1 varchar(50) not null, c1 varchar(50) not null, d1 enum('m', 'w') not null, e1 int not null, f1 decimal (18,2) not null, g1 bigint not null, h1 tinyint not null, a2 date not null, b2 varchar(50) not null, c2 varchar(50) not null, d2 enum('m', 'w') not null, e2 int not null, f2 decimal (18,2) not null, g2 bigint not null, h2 tinyint not null, a3 date not null, b3 varchar(50) not null, c3 varchar(50) not null, d3 enum('m', 'w') not null, e3 int not null, f3 decimal (18,2) not null, g3 bigint not null, h3 tinyint not null, i char(255), primary key(a,b,c,d,e,f,g,h,a1,b1,c1,d1,e1,f1,g1,h1)) engine='MyISAM'
partition by key(a,b,c,d,e,f,g,h) (
partition pa1 max_rows=20 min_rows=2,

View File

@ -610,8 +610,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
PARTITION part2 VALUES LESS THAN (1000))' at line 9
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
CREATE TABLE t1 (
f_int1 INTEGER,
@ -623,8 +622,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
PARTITION part2 VALUES LESS THAN (1000))' at line 9
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.2 NULL in LIST partitioning clause
# 3.5.2.1 VALUE IN (NULL)
CREATE TABLE t1 (

View File

@ -610,8 +610,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
PARTITION part2 VALUES LESS THAN (1000))' at line 9
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.1.2 VALUE LESS THAN (NULL) is not allowed
CREATE TABLE t1 (
f_int1 INTEGER,
@ -623,8 +622,7 @@ f_charbig VARCHAR(1000)
PARTITION BY RANGE(f_int1)
( PARTITION part1 VALUES LESS THAN (NULL),
PARTITION part2 VALUES LESS THAN (1000));
ERROR 42000: Not allowed to use NULL value in VALUES LESS THAN near '),
PARTITION part2 VALUES LESS THAN (1000))' at line 9
ERROR HY000: Not allowed to use NULL value in VALUES LESS THAN
# 3.5.2 NULL in LIST partitioning clause
# 3.5.2.1 VALUE IN (NULL)
CREATE TABLE t1 (

View File

@ -352,12 +352,12 @@ drop table t1;
#
# BUG 16002: Handle unsigned integer functions properly
#
--error ER_PARSE_ERROR
--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
create table t1 (a bigint)
partition by range (a)
(partition p0 values less than (0xFFFFFFFFFFFFFFFF),
partition p1 values less than (10));
--error ER_PARSE_ERROR
--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
create table t1 (a bigint)
partition by list (a)
(partition p0 values in (0xFFFFFFFFFFFFFFFF),
@ -1390,7 +1390,7 @@ PARTITION BY LIST (a)
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error ER_PARSE_ERROR
--error ER_NULL_IN_VALUES_LESS_THAN
CREATE TABLE t1 (a int)
PARTITION BY RANGE(a)
(PARTITION p0 VALUES LESS THAN (NULL));

View File

@ -0,0 +1,391 @@
#
# Tests for the new column list partitioning introduced in second
# version for partitioning.
#
--source include/have_partition.inc
--disable_warnings
drop table if exists t1;
--enable_warnings
#
# BUG#48164, too long partition fields causes crash
#
--error ER_PARTITION_FIELDS_TOO_LONG
create table t1 (a varchar(1500), b varchar(1570))
partition by list column_list(a,b)
( partition p0 values in (('a','b')));
create table t1 (a varchar(1023) character set utf8 collate utf8_spanish2_ci)
partition by range column_list(a)
( partition p0 values less than ('CZ'),
partition p1 values less than ('CH'),
partition p2 values less than ('D'));
insert into t1 values ('czz'),('chi'),('ci'),('cg');
select * from t1 where a between 'cg' AND 'ci';
drop table t1;
#
# BUG#48165, sql_mode gives error
#
set @@sql_mode=allow_invalid_dates;
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
create table t1 (a char, b char, c date)
partition by range column_list (a,b,c)
( partition p0 values less than (0,0,to_days('3000-11-31')));
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
create table t1 (a char, b char, c date)
partition by range column_list (a,b,c)
( partition p0 values less than (0,0,'3000-11-31'));
set @@sql_mode='';
#
# BUG#48163, Dagger in UCS2 not working as partition value
#
create table t1 (a varchar(2) character set ucs2)
partition by list column_list (a)
(partition p0 values in (0x2020),
partition p1 values in (''));
show create table t1;
insert into t1 values ('');
insert into t1 values (_ucs2 0x2020);
drop table t1;
create table t1 (a int, b char(10), c varchar(25), d datetime)
partition by range column_list(a,b,c,d)
subpartition by hash (to_seconds(d))
subpartitions 4
( partition p0 values less than (1, 0, MAXVALUE, 0),
partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
drop table t1;
--error ER_NULL_IN_VALUES_LESS_THAN
create table t1 (a int, b int)
partition by range column_list (a,b)
(partition p0 values less than (NULL, maxvalue));
--error ER_MAXVALUE_IN_VALUES_IN, ER_PARSE_ERROR
create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in ((maxvalue, 0)));
create table t1 (a int, b int)
partition by list column_list (a,b)
( partition p0 values in ((0,0)));
--error ER_MAXVALUE_IN_VALUES_IN, ER_PARSE_ERROR
alter table t1 add partition
(partition p1 values in (maxvalue, maxvalue));
drop table t1;
#
# BUG#47837, Crash when two same fields in column list processing
#
--error ER_SAME_NAME_PARTITION_FIELD
create table t1 (a int, b int)
partition by key (a,a);
--error ER_SAME_NAME_PARTITION_FIELD
create table t1 (a int, b int)
partition by list column_list(a,a)
( partition p values in ((1,1)));
#
# BUG#47838, List partitioning have problems with <= and >=
#
create table t1 (a int signed)
partition by list (a)
( partition p0 values in (1, 3, 5, 7, 9, NULL),
partition p1 values in (2, 4, 6, 8, 0));
insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
select * from t1 where NULL <= a;
select * from t1 where a is null;
explain partitions select * from t1 where a is null;
select * from t1 where a <= 1;
drop table t1;
create table t1 (a int signed)
partition by list column_list(a)
( partition p0 values in (1, 3, 5, 7, 9, NULL),
partition p1 values in (2, 4, 6, 8, 0));
insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
select * from t1 where a <= NULL;
select * from t1 where a is null;
explain partitions select * from t1 where a is null;
select * from t1 where a <= 1;
drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in ((1, NULL), (2, NULL), (NULL, NULL)),
partition p1 values in ((1,1), (2,2)),
partition p2 values in ((3, NULL), (NULL, 1)));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
#
# BUG#47754 Crash when selecting using NOT BETWEEN for column list partitioning
#
insert into t1 values (3, NULL);
insert into t1 values (NULL, 1);
insert into t1 values (NULL, NULL);
insert into t1 values (1, NULL);
insert into t1 values (2, NULL);
insert into t1 values (1,1);
insert into t1 values (2,2);
select * from t1 where a = 1;
select * from t1 where a = 2;
select * from t1 where a > 8;
select * from t1 where a not between 8 and 8;
show create table t1;
drop table t1;
--error ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR
create table t1 (a int)
partition by list (a)
( partition p0 values in (1),
partition p1 values in (1));
create table t1 (a int)
partition by list (a)
( partition p0 values in (2, 1),
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
insert into t1 values (4);
insert into t1 values (NULL);
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (5);
drop table t1;
--error ER_PARSE_ERROR
create table t1 (a int)
partition by list column_list(a)
( partition p0 values in (2, 1),
partition p1 values in ((4), (NULL), (3)));
create table t1 (a int)
partition by list column_list(a)
( partition p0 values in (2, 1),
partition p1 values in (4, NULL, 3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
insert into t1 values (1);
insert into t1 values (2);
insert into t1 values (3);
insert into t1 values (4);
insert into t1 values (NULL);
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (5);
show create table t1;
drop table t1;
create table t1 (a int, b char(10), c varchar(5), d int)
partition by range column_list(a,b,c)
subpartition by key (c,d)
subpartitions 3
( partition p0 values less than (1,'abc','abc'),
partition p1 values less than (2,'abc','abc'),
partition p2 values less than (3,'abc','abc'),
partition p3 values less than (4,'abc','abc'));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
insert into t1 values (1,'b','c',1),(2,'b','c',2),(3,'b','c',3);
insert into t1 values (1,'c','d',1),(2,'c','d',2),(3,'c','d',3);
insert into t1 values (1,'d','e',1),(2,'d','e',2),(3,'d','e',3);
select * from t1 where (a = 1 AND b < 'd' AND (c = 'b' OR (c = 'c' AND d = 1)) OR
(a = 1 AND b >= 'a' AND (c = 'c' OR (c = 'd' AND d = 2))));
drop table t1;
create table t1 (a int, b varchar(2), c int)
partition by range column_list (a, b, c)
(partition p0 values less than (1, 'A', 1),
partition p1 values less than (1, 'B', 1));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
show create table t1;
insert into t1 values (1, 'A', 1);
explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 1;
select * from t1 where a = 1 AND b <= 'A' and c = 1;
drop table t1;
create table t1 (a char, b char, c char)
partition by list column_list(a)
( partition p0 values in ('a'));
insert into t1 (a) values ('a');
select * from t1 where a = 'a';
drop table t1;
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
create table t1 (d time)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
create table t1 (d timestamp)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
--error ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
create table t1 (d bit(1))
partition by range column_list(d)
( partition p0 values less than (0),
partition p1 values less than (1));
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue, 10));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2009-01-01'));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('1999-01-01'),
partition p1 values less than ('2000-01-01'));
drop table t1;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('3000-01-01'));
drop table t1;
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p2 values less than (99,99),
partition p1 values less than (99,999));
insert into t1 values (99,998);
select * from t1 where b = 998;
drop table t1;
create table t1 as select to_seconds(null) as to_seconds;
select data_type from information_schema.columns
where column_name='to_seconds';
drop table t1;
--error ER_PARSE_ERROR
create table t1 (a int, b int)
partition by list column_list(a,b)
(partition p0 values in ((maxvalue,maxvalue)));
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (maxvalue,maxvalue));
drop table t1;
create table t1 (a int)
partition by list column_list(a)
(partition p0 values in (0));
select partition_method from information_schema.partitions where table_name='t1';
drop table t1;
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than ('H23456'),
partition p1 values less than ('M23456'));
insert into t1 values ('F23456');
select * from t1;
drop table t1;
-- error 1054
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than (H23456),
partition p1 values less than (M23456));
-- error ER_RANGE_NOT_INCREASING_ERROR
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than (23456),
partition p1 values less than (23456));
-- error 1064
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (10));
-- error ER_PARTITION_COLUMN_LIST_ERROR
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (1,1,1);
create table t1 (a int, b int)
partition by range column_list(a,b)
(partition p0 values less than (1, 0),
partition p1 values less than (2, maxvalue),
partition p2 values less than (3, 3),
partition p3 values less than (10, maxvalue));
-- error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (11,0);
insert into t1 values (0,1),(1,1),(2,1),(3,1),(3,4),(4,9),(9,1);
select * from t1;
alter table t1
partition by range column_list(b,a)
(partition p0 values less than (1,2),
partition p1 values less than (3,3),
partition p2 values less than (9,5));
explain partitions select * from t1 where b < 2;
select * from t1 where b < 2;
explain partitions select * from t1 where b < 4;
select * from t1 where b < 4;
alter table t1 reorganize partition p1 into
(partition p11 values less than (2,2),
partition p12 values less than (3,3));
-- error ER_REORG_OUTSIDE_RANGE
alter table t1 reorganize partition p0 into
(partition p01 values less than (0,3),
partition p02 values less than (1,1));
-- error ER_PARTITION_COLUMN_LIST_ERROR
alter table t1 reorganize partition p2 into
(partition p2 values less than(9,6,1));
-- error ER_PARTITION_COLUMN_LIST_ERROR
alter table t1 reorganize partition p2 into
(partition p2 values less than (10));
alter table t1 reorganize partition p2 into
(partition p21 values less than (4,7),
partition p22 values less than (9,5));
explain partitions select * from t1 where b < 4;
select * from t1 where b < 4;
drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
subpartition by hash (b)
subpartitions 2
(partition p0 values in ((0,0), (1,1)),
partition p1 values in ((1000,1000)));
insert into t1 values (1000,1000);
#select * from t1 where a = 0 and b = 0;
drop table t1;
create table t1 (a char, b char, c char)
partition by range column_list(a,b,c)
( partition p0 values less than ('a','b','c'));
alter table t1 add partition
(partition p1 values less than ('b','c','d'));
drop table t1;

View File

@ -0,0 +1,71 @@
#
# Partition pruning tests for new COLUMN LIST feature
#
-- source include/have_partition.inc
--disable_warnings
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
--enable_warnings
create table t1 (a char, b char, c char)
partition by range column_list(a,b,c)
( partition p0 values less than ('a','b','c'));
insert into t1 values ('a', NULL, 'd');
explain partitions select * from t1 where a = 'a' AND c = 'd';
select * from t1 where a = 'a' AND c = 'd';
drop table t1;
## COLUMN_LIST partition pruning tests
create table t1 (a int not null) partition by range column_list(a) (
partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (40),
partition p4 values less than (50),
partition p5 values less than (60),
partition p6 values less than (70)
);
insert into t1 values (5),(15),(25),(35),(45),(55),(65);
insert into t1 values (5),(15),(25),(35),(45),(55),(65);
create table t2 (a int not null) partition by range(a) (
partition p0 values less than (10),
partition p1 values less than (20),
partition p2 values less than (30),
partition p3 values less than (40),
partition p4 values less than (50),
partition p5 values less than (60),
partition p6 values less than (70)
);
insert into t2 values (5),(15),(25),(35),(45),(55),(65);
insert into t2 values (5),(15),(25),(35),(45),(55),(65);
explain partitions select * from t1 where a > 35 and a < 45;
explain partitions select * from t2 where a > 35 and a < 45;
drop table t1, t2;
create table t1 (a int not null, b int not null )
partition by range column_list(a,b) (
partition p01 values less than (2,10),
partition p02 values less than (2,20),
partition p03 values less than (2,30),
partition p11 values less than (4,10),
partition p12 values less than (4,20),
partition p13 values less than (4,30),
partition p21 values less than (6,10),
partition p22 values less than (6,20),
partition p23 values less than (6,30)
);
insert into t1 values (2,5), (2,15), (2,25),
(4,5), (4,15), (4,25), (6,5), (6,15), (6,25);
insert into t1 select * from t1;
explain partitions select * from t1 where a=2;
explain partitions select * from t1 where a=4;
explain partitions select * from t1 where a=2 and b < 22;
drop table t1;

View File

@ -4,6 +4,7 @@
# as partition by key
# Created to verify the fix for Bug#31705
# Partitions: crash if varchar length > 65530
# BUG#48164 limited size to 3072 bytes
#
-- source include/have_partition.inc
@ -192,27 +193,29 @@ create table t1 (a set('y','n')) partition by key (a);
insert into t1 values ('y');
select * from t1 where a = 'y';
drop table t1;
create table t1 (a varchar(65531)) partition by key (a);
create table t1 (a varchar(3068)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
create table t1 (a varchar(65532)) partition by key (a);
create table t1 (a varchar(3069)) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
create table t1 (a varchar(65533) not null) partition by key (a);
create table t1 (a varchar(3070) not null) partition by key (a);
insert into t1 values ('bbbb');
insert into t1 values ('aaaa');
select * from t1 where a = 'aaaa';
select * from t1 where a like 'aaa%';
select * from t1 where a = 'bbbb';
drop table t1;
-- error ER_PARTITION_FIELDS_TOO_LONG
create table t1 (a varchar(3070)) partition by key (a);
-- error ER_TOO_BIG_ROWSIZE
create table t1 (a varchar(65533)) partition by key (a);
-- error ER_TOO_BIG_ROWSIZE

View File

@ -180,7 +180,7 @@ partitions 3
(partition x1, partition x2);
#
# Partition by key specified 3 partitions but only defined 2 => error
# Partition by hash, random function
#
--error 1064
CREATE TABLE t1 (
@ -193,7 +193,7 @@ partitions 2
(partition x1, partition x2);
#
# Partition by key specified 3 partitions but only defined 2 => error
# Partition by range, random function
#
--error 1064
CREATE TABLE t1 (
@ -206,7 +206,7 @@ partitions 2
(partition x1 values less than (0), partition x2 values less than (2));
#
# Partition by key specified 3 partitions but only defined 2 => error
# Partition by list, random function
#
--error 1064
CREATE TABLE t1 (
@ -452,7 +452,7 @@ partitions 2
#
# Partition by range, inconsistent partition function and constants
#
--error 1064
--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@ -522,7 +522,7 @@ partitions 2
#
# Partition by range, missing parenthesis
#
--error 1064
--error ER_PARTITION_WRONG_VALUES_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@ -536,7 +536,7 @@ partitions 2
#
# Partition by range, maxvalue in wrong place
#
--error 1064
--error ER_PARTITION_MAXVALUE_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@ -550,7 +550,7 @@ partitions 2
#
# Partition by range, maxvalue in several places
#
--error 1064
--error ER_PARTITION_MAXVALUE_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,
@ -765,7 +765,7 @@ partitions 2
#
# Partition by list, wrong constant result type (not INT)
#
--error 1064
--error ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR
CREATE TABLE t1 (
a int not null,
b int not null,

View File

@ -5,6 +5,36 @@
drop table if exists t1;
--enable_warnings
#
# BUG#47776, Failed to update for MEMORY engine, crash for InnoDB and success for MyISAM
#
create table t1 (a varchar(5))
engine=memory
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
create table t1 (a varchar(5))
engine=myisam
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
create table t1 (a varchar(5))
engine=innodb
partition by range column_list(a)
( partition p0 values less than ('m'),
partition p1 values less than ('za'));
insert into t1 values ('j');
update t1 set a = 'z' where (a >= 'j');
drop table t1;
#
# Bug#47029: Crash when reorganize partition with subpartition
#

View File

@ -40,6 +40,8 @@ subpartitions 2
partition p1 values in (1),
partition pnull values in (null, 2),
partition p3 values in (3));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
insert into t1 values (0,0),(0,1),(1,0),(1,1),(null,0),(null,1);
insert into t1 values (2,0),(2,1),(3,0),(3,1);

View File

@ -61,7 +61,7 @@ ALTER TABLE t1 REORGANIZE PARTITION x0, x1, x1 INTO
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (5));
--error ER_REORG_OUTSIDE_RANGE
--error ER_RANGE_NOT_INCREASING_ERROR
ALTER TABLE t1 REORGANIZE PARTITION x0,x1 INTO
(PARTITION x01 VALUES LESS THAN (4),
PARTITION x11 VALUES LESS THAN (2));

View File

@ -51,6 +51,26 @@ INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
ALTER TABLE t1 DROP KEY a;
--source include/partition_date_range.inc
DROP TABLE t1;
--echo # TO_SECONDS, test of LIST and index
CREATE TABLE t1 (a DATE, KEY(a))
PARTITION BY LIST (TO_SECONDS(a))
(PARTITION `p0001-01-01` VALUES IN (TO_SECONDS('0001-01-01')),
PARTITION `p2001-01-01` VALUES IN (TO_SECONDS('2001-01-01')),
PARTITION `pNULL` VALUES IN (NULL),
PARTITION `p0000-01-02` VALUES IN (TO_SECONDS('0000-01-02')),
PARTITION `p1001-01-01` VALUES IN (TO_SECONDS('1001-01-01')));
if ($verify_without_partitions)
{
ALTER TABLE t1 REMOVE PARTITIONING;
}
INSERT INTO t1 VALUES ('0000-00-00'), ('0000-01-02'), ('0001-01-01'),
('1001-00-00'), ('1001-01-01'), ('1002-00-00'), ('2001-01-01');
--source include/partition_date_range.inc
--echo # test without index
ALTER TABLE t1 DROP KEY a;
--source include/partition_date_range.inc
DROP TABLE t1;
#
# Bug#46362: Endpoint should be set to false for TO_DAYS(DATE)

View File

@ -9,6 +9,78 @@
drop table if exists t1, t2;
--enable_warnings
--error ER_NULL_IN_VALUES_LESS_THAN
create table t1 (a int)
partition by range (a)
( partition p0 values less than (NULL),
partition p1 values less than (MAXVALUE));
#
# Merge fix of bug#27927 for TO_SECONDS function
#
create table t1 (a datetime not null)
partition by range (TO_SECONDS(a))
( partition p0 VALUES LESS THAN (TO_SECONDS('2007-03-08 00:00:00')),
partition p1 VALUES LESS THAN (TO_SECONDS('2007-04-01 00:00:00')));
select partition_method, partition_expression, partition_description
from information_schema.partitions where table_name = "t1";
INSERT INTO t1 VALUES ('2007-03-01 12:00:00'), ('2007-03-07 12:00:00');
INSERT INTO t1 VALUES ('2007-03-08 12:00:00'), ('2007-03-15 12:00:00');
explain partitions select * from t1 where a < '2007-03-08 00:00:00';
explain partitions select * from t1 where a < '2007-03-08 00:00:01';
explain partitions select * from t1 where a <= '2007-03-08 00:00:00';
explain partitions select * from t1 where a <= '2007-03-07 23:59:59';
explain partitions select * from t1 where a < '2007-03-07 23:59:59';
drop table t1;
#
# New test cases for new function to_seconds
#
create table t1 (a date)
partition by range(to_seconds(a))
(partition p0 values less than (to_seconds('2004-01-01')),
partition p1 values less than (to_seconds('2005-01-01')));
insert into t1 values ('2003-12-30'),('2004-12-31');
select * from t1;
explain partitions select * from t1 where a <= '2003-12-31';
select * from t1 where a <= '2003-12-31';
explain partitions select * from t1 where a <= '2005-01-01';
select * from t1 where a <= '2005-01-01';
drop table t1;
create table t1 (a datetime)
partition by range(to_seconds(a))
(partition p0 values less than (to_seconds('2004-01-01 12:00:00')),
partition p1 values less than (to_seconds('2005-01-01 12:00:00')));
insert into t1 values ('2004-01-01 11:59:29'),('2005-01-01 11:59:59');
select * from t1;
explain partitions select * from t1 where a <= '2004-01-01 11:59.59';
select * from t1 where a <= '2004-01-01 11:59:59';
explain partitions select * from t1 where a <= '2005-01-01';
select * from t1 where a <= '2005-01-01';
drop table t1;
#
# Adding new test cases for column list variant for partitioning
#
--error 1064
create table t1 (a int, b char(20))
partition by range column_list(a,b)
(partition p0 values less than (1));
--error ER_TOO_MANY_VALUES_ERROR
create table t1 (a int, b char(20))
partition by range(a)
(partition p0 values less than (1,"b"));
--error ER_TOO_MANY_VALUES_ERROR
create table t1 (a int, b char(20))
partition by range(a)
(partition p0 values less than (1,"b"));
create table t1 (a int, b char(20))
partition by range column_list(b)
(partition p0 values less than ("b"));
drop table t1;
#
# BUG 33429: Succeeds in adding partition when maxvalue on last partition
#

View File

@ -8,13 +8,13 @@ SET SQL_WARNINGS=1;
CREATE TABLE t1 (
id int(11) NOT NULL auto_increment,
datatype_id int(11) DEFAULT '0' NOT NULL,
minvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
maxvalue decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
min_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
max_value decimal(20,10) DEFAULT '0.0000000000' NOT NULL,
valuename varchar(20),
forecolor int(11),
backcolor int(11),
PRIMARY KEY (id),
UNIQUE datatype_id (datatype_id, minvalue, maxvalue)
UNIQUE datatype_id (datatype_id, min_value, max_value)
);
INSERT INTO t1 VALUES ( '1', '4', '0.0000000000', '0.0000000000', 'Ei saja', '0', '16776960');
INSERT INTO t1 VALUES ( '2', '4', '1.0000000000', '1.0000000000', 'Sajab', '16777215', '255');
@ -148,8 +148,8 @@ INSERT INTO t1 VALUES ( '139', '21', '326.0000000000', '326.0000000000', 'Lumine
INSERT INTO t1 VALUES ( '143', '16', '-4.9000000000', '-0.1000000000', '', NULL, '15774720');
INSERT INTO t1 VALUES ( '145', '15', '0.0000000000', '1.9000000000', '', '0', '16769024');
INSERT INTO t1 VALUES ( '146', '16', '0.0000000000', '1.9000000000', '', '0', '16769024');
select * from t1 where minvalue<=1 and maxvalue>=-1 and datatype_id=16;
select * from t1 where minvalue<=-1 and maxvalue>=-1 and datatype_id=16;
select * from t1 where min_value<=1 and max_value>=-1 and datatype_id=16;
select * from t1 where min_value<=-1 and max_value>=-1 and datatype_id=16;
drop table t1;
#

View File

@ -9783,7 +9783,7 @@ void ha_ndbcluster::set_auto_partitions(partition_info *part_info)
int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
{
NDBTAB *tab= (NDBTAB*)tab_ref;
int32 *range_data= (int32*)my_malloc(part_info->no_parts*sizeof(int32),
int32 *range_data= (int32*)my_malloc(part_info->num_parts*sizeof(int32),
MYF(0));
uint i;
int error= 0;
@ -9792,17 +9792,17 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
if (!range_data)
{
mem_alloc_error(part_info->no_parts*sizeof(int32));
mem_alloc_error(part_info->num_parts*sizeof(int32));
DBUG_RETURN(1);
}
for (i= 0; i < part_info->no_parts; i++)
for (i= 0; i < part_info->num_parts; i++)
{
longlong range_val= part_info->range_int_array[i];
if (unsigned_flag)
range_val-= 0x8000000000000000ULL;
if (range_val < INT_MIN32 || range_val >= INT_MAX32)
{
if ((i != part_info->no_parts - 1) ||
if ((i != part_info->num_parts - 1) ||
(range_val != LONGLONG_MAX))
{
my_error(ER_LIMITED_PART_RANGE, MYF(0), "NDB");
@ -9813,7 +9813,7 @@ int ha_ndbcluster::set_range_data(void *tab_ref, partition_info *part_info)
}
range_data[i]= (int32)range_val;
}
tab->setRangeListData(range_data, sizeof(int32)*part_info->no_parts);
tab->setRangeListData(range_data, sizeof(int32)*part_info->num_parts);
error:
my_free((char*)range_data, MYF(0));
DBUG_RETURN(error);
@ -9822,7 +9822,7 @@ error:
int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
{
NDBTAB *tab= (NDBTAB*)tab_ref;
int32 *list_data= (int32*)my_malloc(part_info->no_list_values * 2
int32 *list_data= (int32*)my_malloc(part_info->num_list_values * 2
* sizeof(int32), MYF(0));
uint32 *part_id, i;
int error= 0;
@ -9831,10 +9831,10 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
if (!list_data)
{
mem_alloc_error(part_info->no_list_values*2*sizeof(int32));
mem_alloc_error(part_info->num_list_values*2*sizeof(int32));
DBUG_RETURN(1);
}
for (i= 0; i < part_info->no_list_values; i++)
for (i= 0; i < part_info->num_list_values; i++)
{
LIST_PART_ENTRY *list_entry= &part_info->list_array[i];
longlong list_val= list_entry->list_value;
@ -9850,7 +9850,7 @@ int ha_ndbcluster::set_list_data(void *tab_ref, partition_info *part_info)
part_id= (uint32*)&list_data[2*i+1];
*part_id= list_entry->partition_id;
}
tab->setRangeListData(list_data, 2*sizeof(int32)*part_info->no_list_values);
tab->setRangeListData(list_data, 2*sizeof(int32)*part_info->num_list_values);
error:
my_free((char*)list_data, MYF(0));
DBUG_RETURN(error);
@ -9972,11 +9972,11 @@ uint ha_ndbcluster::set_up_partition_info(partition_info *part_info,
ng= 0;
ts_names[fd_index]= part_elem->tablespace_name;
frag_data[fd_index++]= ng;
} while (++j < part_info->no_subparts);
} while (++j < part_info->num_subparts);
}
first= FALSE;
} while (++i < part_info->no_parts);
tab->setDefaultNoPartitionsFlag(part_info->use_default_no_partitions);
} while (++i < part_info->num_parts);
tab->setDefaultNoPartitionsFlag(part_info->use_default_num_partitions);
tab->setLinearFlag(part_info->linear_hash_ind);
{
ha_rows max_rows= table_share->max_rows;
@ -10370,7 +10370,7 @@ ndberror2:
}
bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
bool ha_ndbcluster::get_no_parts(const char *name, uint *num_parts)
{
Ndb *ndb;
NDBDICT *dict;
@ -10392,7 +10392,7 @@ bool ha_ndbcluster::get_no_parts(const char *name, uint *no_parts)
Ndb_table_guard ndbtab_g(dict= ndb->getDictionary(), m_tabname);
if (!ndbtab_g.get_table())
ERR_BREAK(dict->getNdbError(), err);
*no_parts= ndbtab_g.get_table()->getFragmentCount();
*num_parts= ndbtab_g.get_table()->getFragmentCount();
DBUG_RETURN(FALSE);
}

View File

@ -1,4 +1,4 @@
/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -245,7 +245,7 @@ void ha_partition::init_handler_variables()
/*
this allows blackhole to work properly
*/
m_no_locks= 0;
m_num_locks= 0;
#ifdef DONT_HAVE_TO_BE_INITALIZED
m_start_key.flag= 0;
@ -580,8 +580,8 @@ int ha_partition::drop_partitions(const char *path)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
char part_name_buff[FN_REFLEN];
uint no_parts= m_part_info->partitions.elements;
uint no_subparts= m_part_info->no_subparts;
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint name_variant;
int ret_error;
@ -611,7 +611,7 @@ int ha_partition::drop_partitions(const char *path)
do
{
partition_element *sub_elem= sub_it++;
part= i * no_subparts + j;
part= i * num_subparts + j;
create_subpartition_name(part_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name, name_variant);
@ -621,7 +621,7 @@ int ha_partition::drop_partitions(const char *path)
error= ret_error;
if (deactivate_ddl_log_entry(sub_elem->log_entry->entry_pos))
error= 1;
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -640,7 +640,7 @@ int ha_partition::drop_partitions(const char *path)
else
part_elem->part_state= PART_IS_DROPPED;
}
} while (++i < no_parts);
} while (++i < num_parts);
VOID(sync_ddl_log());
DBUG_RETURN(error);
}
@ -671,9 +671,9 @@ int ha_partition::rename_partitions(const char *path)
List_iterator<partition_element> temp_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
char norm_name_buff[FN_REFLEN];
uint no_parts= m_part_info->partitions.elements;
uint num_parts= m_part_info->partitions.elements;
uint part_count= 0;
uint no_subparts= m_part_info->no_subparts;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint j= 0;
int error= 0;
@ -722,7 +722,7 @@ int ha_partition::rename_partitions(const char *path)
error= 1;
else
sub_elem->log_entry= NULL; /* Indicate success */
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -778,7 +778,7 @@ int ha_partition::rename_partitions(const char *path)
do
{
sub_elem= sub_it++;
part= i * no_subparts + j;
part= i * num_subparts + j;
create_subpartition_name(norm_name_buff, path,
part_elem->partition_name,
sub_elem->partition_name,
@ -807,7 +807,7 @@ int ha_partition::rename_partitions(const char *path)
error= 1;
else
sub_elem->log_entry= NULL;
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -839,7 +839,7 @@ int ha_partition::rename_partitions(const char *path)
part_elem->log_entry= NULL;
}
}
} while (++i < no_parts);
} while (++i < num_parts);
VOID(sync_ddl_log());
DBUG_RETURN(error);
}
@ -1093,8 +1093,8 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
uint flag)
{
List_iterator<partition_element> part_it(m_part_info->partitions);
uint no_parts= m_part_info->no_parts;
uint no_subparts= m_part_info->no_subparts;
uint num_parts= m_part_info->num_parts;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
int error;
DBUG_ENTER("ha_partition::handle_opt_partitions");
@ -1118,7 +1118,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
do
{
sub_elem= subpart_it++;
part= i * no_subparts + j;
part= i * num_subparts + j;
DBUG_PRINT("info", ("Optimize subpartition %u (%s)",
part, sub_elem->partition_name));
#ifdef NOT_USED
@ -1148,7 +1148,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
} while (part_elem= part_it++);
DBUG_RETURN(error);
}
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -1183,7 +1183,7 @@ int ha_partition::handle_opt_partitions(THD *thd, HA_CHECK_OPT *check_opt,
}
part_elem->part_state= PART_NORMAL;
}
} while (++i < no_parts);
} while (++i < num_parts);
DBUG_RETURN(FALSE);
}
@ -1387,10 +1387,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
List_iterator<partition_element> part_it(m_part_info->partitions);
List_iterator <partition_element> t_it(m_part_info->temp_partitions);
char part_name_buff[FN_REFLEN];
uint no_parts= m_part_info->partitions.elements;
uint no_subparts= m_part_info->no_subparts;
uint num_parts= m_part_info->partitions.elements;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint no_remain_partitions, part_count, orig_count;
uint num_remain_partitions, part_count, orig_count;
handler **new_file_array;
int error= 1;
bool first;
@ -1406,7 +1406,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_name_buff)));
m_reorged_parts= 0;
if (!m_part_info->is_sub_partitioned())
no_subparts= 1;
num_subparts= 1;
/*
Step 1:
@ -1415,7 +1415,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
*/
if (temp_partitions)
{
m_reorged_parts= temp_partitions * no_subparts;
m_reorged_parts= temp_partitions * num_subparts;
}
else
{
@ -1425,9 +1425,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
if (part_elem->part_state == PART_CHANGED ||
part_elem->part_state == PART_REORGED_DROPPED)
{
m_reorged_parts+= no_subparts;
m_reorged_parts+= num_subparts;
}
} while (++i < no_parts);
} while (++i < num_parts);
}
if (m_reorged_parts &&
!(m_reorged_file= (handler**)sql_calloc(sizeof(handler*)*
@ -1442,10 +1442,10 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
Calculate number of partitions after change and allocate space for
their handler references.
*/
no_remain_partitions= 0;
num_remain_partitions= 0;
if (temp_partitions)
{
no_remain_partitions= no_parts * no_subparts;
num_remain_partitions= num_parts * num_subparts;
}
else
{
@ -1458,17 +1458,17 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state == PART_TO_BE_ADDED ||
part_elem->part_state == PART_CHANGED)
{
no_remain_partitions+= no_subparts;
num_remain_partitions+= num_subparts;
}
} while (++i < no_parts);
} while (++i < num_parts);
}
if (!(new_file_array= (handler**)sql_calloc(sizeof(handler*)*
(2*(no_remain_partitions + 1)))))
(2*(num_remain_partitions + 1)))))
{
mem_alloc_error(sizeof(handler*)*2*(no_remain_partitions+1));
mem_alloc_error(sizeof(handler*)*2*(num_remain_partitions+1));
DBUG_RETURN(ER_OUTOFMEMORY);
}
m_added_file= &new_file_array[no_remain_partitions + 1];
m_added_file= &new_file_array[num_remain_partitions + 1];
/*
Step 3:
@ -1487,9 +1487,9 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state == PART_REORGED_DROPPED)
{
memcpy((void*)&m_reorged_file[part_count],
(void*)&m_file[i*no_subparts],
sizeof(handler*)*no_subparts);
part_count+= no_subparts;
(void*)&m_file[i*num_subparts],
sizeof(handler*)*num_subparts);
part_count+= num_subparts;
}
else if (first && temp_partitions &&
part_elem->part_state == PART_TO_BE_ADDED)
@ -1504,11 +1504,11 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
ones used to be.
*/
first= FALSE;
DBUG_ASSERT(((i*no_subparts) + m_reorged_parts) <= m_file_tot_parts);
memcpy((void*)m_reorged_file, &m_file[i*no_subparts],
DBUG_ASSERT(((i*num_subparts) + m_reorged_parts) <= m_file_tot_parts);
memcpy((void*)m_reorged_file, &m_file[i*num_subparts],
sizeof(handler*)*m_reorged_parts);
}
} while (++i < no_parts);
} while (++i < num_parts);
}
/*
@ -1526,11 +1526,11 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
partition_element *part_elem= part_it++;
if (part_elem->part_state == PART_NORMAL)
{
DBUG_ASSERT(orig_count + no_subparts <= m_file_tot_parts);
DBUG_ASSERT(orig_count + num_subparts <= m_file_tot_parts);
memcpy((void*)&new_file_array[part_count], (void*)&m_file[orig_count],
sizeof(handler*)*no_subparts);
part_count+= no_subparts;
orig_count+= no_subparts;
sizeof(handler*)*num_subparts);
part_count+= num_subparts;
orig_count+= num_subparts;
}
else if (part_elem->part_state == PART_CHANGED ||
part_elem->part_state == PART_TO_BE_ADDED)
@ -1546,16 +1546,16 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
mem_alloc_error(sizeof(handler));
DBUG_RETURN(ER_OUTOFMEMORY);
}
} while (++j < no_subparts);
} while (++j < num_subparts);
if (part_elem->part_state == PART_CHANGED)
orig_count+= no_subparts;
orig_count+= num_subparts;
else if (temp_partitions && first)
{
orig_count+= (no_subparts * temp_partitions);
orig_count+= (num_subparts * temp_partitions);
first= FALSE;
}
}
} while (++i < no_parts);
} while (++i < num_parts);
first= FALSE;
/*
Step 5:
@ -1592,7 +1592,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->partition_name,
sub_elem->partition_name,
name_variant);
part= i * no_subparts + j;
part= i * num_subparts + j;
DBUG_PRINT("info", ("Add subpartition %s", part_name_buff));
if ((error= prepare_new_partition(table, create_info,
new_file_array[part],
@ -1603,7 +1603,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
DBUG_RETURN(error);
}
m_added_file[part_count++]= new_file_array[part];
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -1622,7 +1622,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
m_added_file[part_count++]= new_file_array[i];
}
}
} while (++i < no_parts);
} while (++i < num_parts);
/*
Step 6:
@ -1639,7 +1639,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
part_elem->part_state= PART_IS_CHANGED;
else if (part_elem->part_state == PART_REORGED_DROPPED)
part_elem->part_state= PART_TO_BE_DROPPED;
} while (++i < no_parts);
} while (++i < num_parts);
for (i= 0; i < temp_partitions; i++)
{
partition_element *part_elem= t_it++;
@ -1680,9 +1680,9 @@ int ha_partition::copy_partitions(ulonglong * const copied,
if (m_part_info->linear_hash_ind)
{
if (m_part_info->part_type == HASH_PARTITION)
set_linear_hash_mask(m_part_info, m_part_info->no_parts);
set_linear_hash_mask(m_part_info, m_part_info->num_parts);
else
set_linear_hash_mask(m_part_info, m_part_info->no_subparts);
set_linear_hash_mask(m_part_info, m_part_info->num_subparts);
}
while (reorg_part < m_reorged_parts)
@ -1961,7 +1961,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
uint curr_part_id= 0;
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
for (i= 0; i < m_part_info->no_parts; i++)
for (i= 0; i < m_part_info->num_parts; i++)
{
partition_element *part_elem;
part_elem= part_it++;
@ -1969,7 +1969,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
{
uint j;
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
for (j= 0; j < m_part_info->no_subparts; j++)
for (j= 0; j < m_part_info->num_subparts; j++)
{
part_elem= sub_it++;
if (part_id == curr_part_id++)
@ -2090,7 +2090,7 @@ bool ha_partition::create_handler_file(const char *name)
{
partition_element *part_elem, *subpart_elem;
uint i, j, part_name_len, subpart_name_len;
uint tot_partition_words, tot_name_len, no_parts;
uint tot_partition_words, tot_name_len, num_parts;
uint tot_parts= 0;
uint tot_len_words, tot_len_byte, chksum, tot_name_words;
char *name_buffer_ptr;
@ -2103,11 +2103,11 @@ bool ha_partition::create_handler_file(const char *name)
List_iterator_fast <partition_element> part_it(m_part_info->partitions);
DBUG_ENTER("create_handler_file");
no_parts= m_part_info->partitions.elements;
DBUG_PRINT("info", ("table name = %s, no_parts = %u", name,
no_parts));
num_parts= m_part_info->partitions.elements;
DBUG_PRINT("info", ("table name = %s, num_parts = %u", name,
num_parts));
tot_name_len= 0;
for (i= 0; i < no_parts; i++)
for (i= 0; i < num_parts; i++)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
@ -2125,7 +2125,7 @@ bool ha_partition::create_handler_file(const char *name)
else
{
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
for (j= 0; j < m_part_info->no_subparts; j++)
for (j= 0; j < m_part_info->num_subparts; j++)
{
subpart_elem= sub_it++;
tablename_to_filename(subpart_elem->partition_name,
@ -2159,7 +2159,7 @@ bool ha_partition::create_handler_file(const char *name)
engine_array= (file_buffer + 12);
name_buffer_ptr= (char*) (file_buffer + ((4 + tot_partition_words) * 4));
part_it.rewind();
for (i= 0; i < no_parts; i++)
for (i= 0; i < num_parts; i++)
{
part_elem= part_it++;
if (part_elem->part_state != PART_NORMAL &&
@ -2177,7 +2177,7 @@ bool ha_partition::create_handler_file(const char *name)
else
{
List_iterator_fast <partition_element> sub_it(part_elem->subpartitions);
for (j= 0; j < m_part_info->no_subparts; j++)
for (j= 0; j < m_part_info->num_subparts; j++)
{
subpart_elem= sub_it++;
tablename_to_filename(part_elem->partition_name, part_name,
@ -2313,7 +2313,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
}
m_file_tot_parts= m_tot_parts;
bzero((char*) m_file, alloc_len);
DBUG_ASSERT(m_part_info->no_parts > 0);
DBUG_ASSERT(m_part_info->num_parts > 0);
i= 0;
part_count= 0;
@ -2326,7 +2326,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
part_elem= part_it++;
if (m_is_sub_partitioned)
{
for (j= 0; j < m_part_info->no_subparts; j++)
for (j= 0; j < m_part_info->num_subparts; j++)
{
if (!(m_file[part_count++]= get_new_handler(table_share, mem_root,
part_elem->engine_type)))
@ -2343,7 +2343,7 @@ bool ha_partition::new_handlers_from_part_info(MEM_ROOT *mem_root)
DBUG_PRINT("info", ("engine_type: %u",
(uint) ha_legacy_type(part_elem->engine_type)));
}
} while (++i < m_part_info->no_parts);
} while (++i < m_part_info->num_parts);
if (part_elem->engine_type == myisam_hton)
{
DBUG_PRINT("info", ("MyISAM"));
@ -2546,7 +2546,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if ((error= (*file)->ha_open(table, (const char*) name_buff, mode,
test_if_locked)))
goto err_handler;
m_no_locks+= (*file)->lock_count();
m_num_locks+= (*file)->lock_count();
name_buffer_ptr+= strlen(name_buffer_ptr) + 1;
set_if_bigger(ref_length, ((*file)->ref_length));
/*
@ -2893,8 +2893,8 @@ int ha_partition::start_stmt(THD *thd, thr_lock_type lock_type)
uint ha_partition::lock_count() const
{
DBUG_ENTER("ha_partition::lock_count");
DBUG_PRINT("info", ("m_no_locks %d", m_no_locks));
DBUG_RETURN(m_no_locks);
DBUG_PRINT("info", ("m_num_locks %d", m_num_locks));
DBUG_RETURN(m_num_locks);
}
@ -3305,13 +3305,13 @@ int ha_partition::delete_all_rows()
/* ALTER TABLE t TRUNCATE PARTITION ... */
List_iterator<partition_element> part_it(m_part_info->partitions);
int saved_error= 0;
uint no_parts= m_part_info->no_parts;
uint no_subparts= m_part_info->no_subparts;
uint num_parts= m_part_info->num_parts;
uint num_subparts= m_part_info->num_subparts;
uint i= 0;
uint no_parts_set= alter_info->partition_names.elements;
uint no_parts_found= set_part_state(alter_info, m_part_info,
PART_ADMIN);
if (no_parts_set != no_parts_found &&
uint num_parts_set= alter_info->partition_names.elements;
uint num_parts_found= set_part_state(alter_info, m_part_info,
PART_ADMIN);
if (num_parts_set != num_parts_found &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
@ -3334,7 +3334,7 @@ int ha_partition::delete_all_rows()
do
{
sub_elem= subpart_it++;
part= i * no_subparts + j;
part= i * num_subparts + j;
bitmap_set_bit(&m_part_info->used_partitions, part);
if (!saved_error)
{
@ -3348,7 +3348,7 @@ int ha_partition::delete_all_rows()
error != HA_ERR_WRONG_COMMAND)
saved_error= error;
}
} while (++j < no_subparts);
} while (++j < num_subparts);
}
else
{
@ -3368,7 +3368,7 @@ int ha_partition::delete_all_rows()
}
part_elem->part_state= PART_NORMAL;
}
} while (++i < no_parts);
} while (++i < num_parts);
DBUG_RETURN(saved_error);
}
truncate= TRUE;

View File

@ -1,7 +1,7 @@
#ifndef HA_PARTITION_INCLUDED
#define HA_PARTITION_INCLUDED
/* Copyright 2005-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2005-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -22,7 +22,8 @@
enum partition_keywords
{
PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR
PKW_HASH= 0, PKW_RANGE, PKW_LIST, PKW_KEY, PKW_MAXVALUE, PKW_LINEAR,
PKW_COLUMNS
};
/*
@ -114,7 +115,7 @@ private:
uint m_reorged_parts; // Number of reorganised parts
uint m_tot_parts; // Total number of partitions;
uint m_no_locks; // For engines like ha_blackhole, which needs no locks
uint m_num_locks; // For engines like ha_blackhole, which needs no locks
uint m_last_part; // Last file that we update,write,read
int m_lock_type; // Remembers type of last
// external_lock
@ -246,10 +247,10 @@ public:
size_t pack_frm_len);
virtual int drop_partitions(const char *path);
virtual int rename_partitions(const char *path);
bool get_no_parts(const char *name, uint *no_parts)
bool get_no_parts(const char *name, uint *num_parts)
{
DBUG_ENTER("ha_partition::get_no_parts");
*no_parts= m_tot_parts;
*num_parts= m_tot_parts;
DBUG_RETURN(0);
}
virtual void change_table_ptr(TABLE *table_arg, TABLE_SHARE *share);

View File

@ -2052,6 +2052,18 @@ protected:
virtual ~Create_func_to_days() {}
};
class Create_func_to_seconds : public Create_func_arg1
{
public:
virtual Item* create(THD *thd, Item *arg1);
static Create_func_to_seconds s_singleton;
protected:
Create_func_to_seconds() {}
virtual ~Create_func_to_seconds() {}
};
#ifdef HAVE_SPATIAL
class Create_func_touches : public Create_func_arg2
@ -4505,6 +4517,15 @@ Create_func_to_days::create(THD *thd, Item *arg1)
}
Create_func_to_seconds Create_func_to_seconds::s_singleton;
Item*
Create_func_to_seconds::create(THD *thd, Item *arg1)
{
return new (thd->mem_root) Item_func_to_seconds(arg1);
}
#ifdef HAVE_SPATIAL
Create_func_touches Create_func_touches::s_singleton;
@ -4942,6 +4963,7 @@ static Native_func_registry func_array[] =
{ { C_STRING_WITH_LEN("TIME_TO_SEC") }, BUILDER(Create_func_time_to_sec)},
{ { C_STRING_WITH_LEN("TOUCHES") }, GEOM_BUILDER(Create_func_touches)},
{ { C_STRING_WITH_LEN("TO_DAYS") }, BUILDER(Create_func_to_days)},
{ { C_STRING_WITH_LEN("TO_SECONDS") }, BUILDER(Create_func_to_seconds)},
{ { C_STRING_WITH_LEN("UCASE") }, BUILDER(Create_func_ucase)},
{ { C_STRING_WITH_LEN("UNCOMPRESS") }, BUILDER(Create_func_uncompress)},
{ { C_STRING_WITH_LEN("UNCOMPRESSED_LENGTH") }, BUILDER(Create_func_uncompressed_length)},

View File

@ -936,6 +936,48 @@ longlong Item_func_to_days::val_int()
}
longlong Item_func_to_seconds::val_int_endpoint(bool left_endp,
bool *incl_endp)
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
longlong seconds;
longlong days;
int dummy; /* unused */
if (get_arg0_date(&ltime, TIME_FUZZY_DATE))
{
/* got NULL, leave the incl_endp intact */
return LONGLONG_MIN;
}
seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
seconds= ltime.neg ? -seconds : seconds;
days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
seconds+= days * 24L * 3600L;
/* Set to NULL if invalid date, but keep the value */
null_value= check_date(&ltime,
(ltime.year || ltime.month || ltime.day),
(TIME_NO_ZERO_IN_DATE | TIME_NO_ZERO_DATE),
&dummy);
/*
Even if the evaluation return NULL, seconds is useful for pruning
*/
return seconds;
}
longlong Item_func_to_seconds::val_int()
{
DBUG_ASSERT(fixed == 1);
MYSQL_TIME ltime;
longlong seconds;
longlong days;
if (get_arg0_date(&ltime, TIME_NO_ZERO_DATE))
return 0;
seconds= ltime.hour * 3600L + ltime.minute * 60 + ltime.second;
seconds=ltime.neg ? -seconds : seconds;
days= (longlong) calc_daynr(ltime.year, ltime.month, ltime.day);
return seconds + days * 24L * 3600L;
}
/*
Get information about this Item tree monotonicity
@ -962,6 +1004,17 @@ enum_monotonicity_info Item_func_to_days::get_monotonicity_info() const
return NON_MONOTONIC;
}
enum_monotonicity_info Item_func_to_seconds::get_monotonicity_info() const
{
if (args[0]->type() == Item::FIELD_ITEM)
{
if (args[0]->field_type() == MYSQL_TYPE_DATE ||
args[0]->field_type() == MYSQL_TYPE_DATETIME)
return MONOTONIC_STRICT_INCREASING_NOT_NULL;
}
return NON_MONOTONIC;
}
longlong Item_func_to_days::val_int_endpoint(bool left_endp, bool *incl_endp)
{

View File

@ -76,6 +76,24 @@ public:
};
class Item_func_to_seconds :public Item_int_func
{
public:
Item_func_to_seconds(Item *a) :Item_int_func(a) {}
longlong val_int();
const char *func_name() const { return "to_seconds"; }
void fix_length_and_dec()
{
decimals=0;
max_length=6*MY_CHARSET_BIN_MB_MAXLEN;
maybe_null=1;
}
enum_monotonicity_info get_monotonicity_info() const;
longlong val_int_endpoint(bool left_endp, bool *incl_endp);
bool check_partition_func_processor(uchar *bool_arg) { return FALSE;}
};
class Item_func_dayofmonth :public Item_int_func
{
public:

View File

@ -119,6 +119,7 @@ static SYMBOL symbols[] = {
{ "COLUMN", SYM(COLUMN_SYM)},
{ "COLUMN_NAME", SYM(COLUMN_NAME_SYM)},
{ "COLUMNS", SYM(COLUMNS)},
{ "COLUMN_LIST", SYM(COLUMN_LIST_SYM)},
{ "COMMENT", SYM(COMMENT_SYM)},
{ "COMMIT", SYM(COMMIT_SYM)},
{ "COMMITTED", SYM(COMMITTED_SYM)},

View File

@ -1153,6 +1153,8 @@ int prepare_create_field(Create_field *sql_field,
uint *blob_columns,
int *timestamps, int *timestamps_with_niladic,
longlong table_flags);
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
HA_CREATE_INFO *create_info);
bool mysql_create_table(THD *thd,const char *db, const char *table_name,
HA_CREATE_INFO *create_info,
Alter_info *alter_info,
@ -1542,6 +1544,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
handlerton *old_db_type,
bool *partition_changed,
uint *fast_alter_partition);
char *generate_partition_syntax(partition_info *part_info,
uint *buf_length, bool use_sql_alloc,
bool show_partition_options,
HA_CREATE_INFO *create_info,
Alter_info *alter_info);
#endif
/* bits for last argument to remove_table_from_cache() */

View File

@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -438,35 +438,55 @@ public:
return 0;
}
/* returns a number of keypart values appended to the key buffer */
int store_min_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
/*
Returns a number of keypart values appended to the key buffer
for min key and max key. This function is used by both Range
Analysis and Partition pruning. For partition pruning we have
to ensure that we don't store also subpartition fields. Thus
we have to stop at the last partition part and not step into
the subpartition fields. For Range Analysis we set last_part
to MAX_KEY which we should never reach.
*/
int store_min_key(KEY_PART *key,
uchar **range_key,
uint *range_key_flag,
uint last_part)
{
SEL_ARG *key_tree= first();
uint res= key_tree->store_min(key[key_tree->part].store_length,
range_key, *range_key_flag);
*range_key_flag|= key_tree->min_flag;
if (key_tree->next_key_part &&
key_tree->part != last_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MIN_RANGE | NEAR_MIN)) &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
res+= key_tree->next_key_part->store_min_key(key, range_key,
range_key_flag);
res+= key_tree->next_key_part->store_min_key(key,
range_key,
range_key_flag,
last_part);
return res;
}
/* returns a number of keypart values appended to the key buffer */
int store_max_key(KEY_PART *key, uchar **range_key, uint *range_key_flag)
int store_max_key(KEY_PART *key,
uchar **range_key,
uint *range_key_flag,
uint last_part)
{
SEL_ARG *key_tree= last();
uint res=key_tree->store_max(key[key_tree->part].store_length,
range_key, *range_key_flag);
(*range_key_flag)|= key_tree->max_flag;
if (key_tree->next_key_part &&
key_tree->part != last_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
!(*range_key_flag & (NO_MAX_RANGE | NEAR_MAX)) &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
res+= key_tree->next_key_part->store_max_key(key, range_key,
range_key_flag);
res+= key_tree->next_key_part->store_max_key(key,
range_key,
range_key_flag,
last_part);
return res;
}
@ -634,6 +654,14 @@ public:
using_real_indexes==TRUE
*/
uint real_keynr[MAX_KEY];
/*
Used to store 'current key tuples', in both range analysis and
partitioning (list) analysis
*/
uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
/* Number of SEL_ARG objects allocated by SEL_ARG::clone_tree operations */
uint alloced_sel_args;
};
@ -645,8 +673,6 @@ public:
longlong baseflag;
uint max_key_part, range_count;
uchar min_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH],
max_key[MAX_KEY_LENGTH+MAX_FIELD_WIDTH];
bool quick; // Don't calulate possible keys
uint fields_bitmap_size;
@ -2604,6 +2630,8 @@ typedef struct st_part_prune_param
/* Same as above for subpartitioning */
my_bool *is_subpart_keypart;
my_bool ignore_part_fields; /* Ignore rest of partioning fields */
/***************************************************************
Following fields form find_used_partitions() recursion context:
**************************************************************/
@ -2617,8 +2645,13 @@ typedef struct st_part_prune_param
/* Iterator to be used to obtain the "current" set of used partitions */
PARTITION_ITERATOR part_iter;
/* Initialized bitmap of no_subparts size */
/* Initialized bitmap of num_subparts size */
MY_BITMAP subparts_bitmap;
uchar *cur_min_key;
uchar *cur_max_key;
uint cur_min_flag, cur_max_flag;
} PART_PRUNE_PARAM;
static bool create_partition_index_description(PART_PRUNE_PARAM *prune_par);
@ -2736,6 +2769,11 @@ bool prune_partitions(THD *thd, TABLE *table, Item *pprune_cond)
prune_param.arg_stack_end= prune_param.arg_stack;
prune_param.cur_part_fields= 0;
prune_param.cur_subpart_fields= 0;
prune_param.cur_min_key= prune_param.range_param.min_key;
prune_param.cur_max_key= prune_param.range_param.max_key;
prune_param.cur_min_flag= prune_param.cur_max_flag= 0;
init_all_partitions_iterator(part_info, &prune_param.part_iter);
if (!tree->keys[0] || (-1 == (res= find_used_partitions(&prune_param,
tree->keys[0]))))
@ -2873,8 +2911,8 @@ static void mark_full_partition_used_no_parts(partition_info* part_info,
static void mark_full_partition_used_with_parts(partition_info *part_info,
uint32 part_id)
{
uint32 start= part_id * part_info->no_subparts;
uint32 end= start + part_info->no_subparts;
uint32 start= part_id * part_info->num_subparts;
uint32 end= start + part_info->num_subparts;
DBUG_ENTER("mark_full_partition_used_with_parts");
for (; start != end; start++)
@ -2972,6 +3010,11 @@ int find_used_partitions_imerge(PART_PRUNE_PARAM *ppar, SEL_IMERGE *imerge)
ppar->arg_stack_end= ppar->arg_stack;
ppar->cur_part_fields= 0;
ppar->cur_subpart_fields= 0;
ppar->cur_min_key= ppar->range_param.min_key;
ppar->cur_max_key= ppar->range_param.max_key;
ppar->cur_min_flag= ppar->cur_max_flag= 0;
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
SEL_ARG *key_tree= (*ptree)->keys[0];
if (!key_tree || (-1 == (res |= find_used_partitions(ppar, key_tree))))
@ -3095,9 +3138,13 @@ static
int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
{
int res, left_res=0, right_res=0;
int partno= (int)key_tree->part;
bool pushed= FALSE;
int key_tree_part= (int)key_tree->part;
bool set_full_part_if_bad_ret= FALSE;
bool ignore_part_fields= ppar->ignore_part_fields;
bool did_set_ignore_part_fields= FALSE;
if (check_stack_overrun(ppar->range_param.thd, 3*STACK_MIN_SIZE, NULL))
return -1;
if (key_tree->left != &null_element)
{
@ -3105,40 +3152,159 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
return -1;
}
/* Push SEL_ARG's to stack to enable looking backwards as well */
ppar->cur_part_fields+= ppar->is_part_keypart[key_tree_part];
ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part];
*(ppar->arg_stack_end++)= key_tree;
if (key_tree->type == SEL_ARG::KEY_RANGE)
{
if (partno == 0 && (NULL != ppar->part_info->get_part_iter_for_interval))
if (ppar->part_info->get_part_iter_for_interval &&
key_tree->part <= ppar->last_part_partno)
{
/*
Partitioning is done by RANGE|INTERVAL(monotonic_expr(fieldX)), and
we got "const1 CMP fieldX CMP const2" interval <-- psergey-todo: change
if (ignore_part_fields)
{
/*
We come here when a condition on the first partitioning
fields led to evaluating the partitioning condition
(due to finding a condition of the type a < const or
b > const). Thus we must ignore the rest of the
partitioning fields but we still want to analyse the
subpartitioning fields.
*/
if (key_tree->next_key_part)
res= find_used_partitions(ppar, key_tree->next_key_part);
else
res= -1;
goto pop_and_go_right;
}
/* Collect left and right bound, their lengths and flags */
uchar *min_key= ppar->cur_min_key;
uchar *max_key= ppar->cur_max_key;
uchar *tmp_min_key= min_key;
uchar *tmp_max_key= max_key;
key_tree->store_min(ppar->key[key_tree->part].store_length,
&tmp_min_key, ppar->cur_min_flag);
key_tree->store_max(ppar->key[key_tree->part].store_length,
&tmp_max_key, ppar->cur_max_flag);
uint flag;
if (key_tree->next_key_part &&
key_tree->next_key_part->part == key_tree->part+1 &&
key_tree->next_key_part->part <= ppar->last_part_partno &&
key_tree->next_key_part->type == SEL_ARG::KEY_RANGE)
{
/*
There are more key parts for partition pruning to handle
This mainly happens when the condition is an equality
condition.
*/
if ((tmp_min_key - min_key) == (tmp_max_key - max_key) &&
(memcmp(min_key, max_key, (uint)(tmp_max_key - max_key)) == 0) &&
!key_tree->min_flag && !key_tree->max_flag)
{
/* Set 'parameters' */
ppar->cur_min_key= tmp_min_key;
ppar->cur_max_key= tmp_max_key;
uint save_min_flag= ppar->cur_min_flag;
uint save_max_flag= ppar->cur_max_flag;
ppar->cur_min_flag|= key_tree->min_flag;
ppar->cur_max_flag|= key_tree->max_flag;
res= find_used_partitions(ppar, key_tree->next_key_part);
/* Restore 'parameters' back */
ppar->cur_min_key= min_key;
ppar->cur_max_key= max_key;
ppar->cur_min_flag= save_min_flag;
ppar->cur_max_flag= save_max_flag;
goto pop_and_go_right;
}
/* We have arrived at the last field in the partition pruning */
uint tmp_min_flag= key_tree->min_flag,
tmp_max_flag= key_tree->max_flag;
if (!tmp_min_flag)
key_tree->next_key_part->store_min_key(ppar->key,
&tmp_min_key,
&tmp_min_flag,
ppar->last_part_partno);
if (!tmp_max_flag)
key_tree->next_key_part->store_max_key(ppar->key,
&tmp_max_key,
&tmp_max_flag,
ppar->last_part_partno);
flag= tmp_min_flag | tmp_max_flag;
}
else
flag= key_tree->min_flag | key_tree->max_flag;
if (tmp_min_key != ppar->range_param.min_key)
flag&= ~NO_MIN_RANGE;
else
flag|= NO_MIN_RANGE;
if (tmp_max_key != ppar->range_param.max_key)
flag&= ~NO_MAX_RANGE;
else
flag|= NO_MAX_RANGE;
/*
We need to call the interval mapper if we have a condition which
makes sense to prune on. In the example of a COLUMN_LIST on a and
b it makes sense if we have a condition on a, or conditions on
both a and b. If we only have conditions on b it might make sense
but this is a harder case we will solve later. For the harder case
this clause then turns into use of all partitions and thus we
simply set res= -1 as if the mapper had returned that.
TODO: What to do here is defined in WL#4065.
*/
DBUG_EXECUTE("info", dbug_print_segment_range(key_tree,
ppar->range_param.
key_parts););
res= ppar->part_info->
get_part_iter_for_interval(ppar->part_info,
FALSE,
key_tree->min_value,
key_tree->max_value,
key_tree->min_flag | key_tree->max_flag,
&ppar->part_iter);
if (!res)
goto go_right; /* res==0 --> no satisfying partitions */
if (ppar->arg_stack[0]->part == 0)
{
uint32 i;
uint32 store_length_array[MAX_KEY];
uint32 num_keys= ppar->part_fields;
for (i= 0; i < num_keys; i++)
store_length_array[i]= ppar->key[i].store_length;
res= ppar->part_info->
get_part_iter_for_interval(ppar->part_info,
FALSE,
store_length_array,
ppar->range_param.min_key,
ppar->range_param.max_key,
tmp_min_key - ppar->range_param.min_key,
tmp_max_key - ppar->range_param.max_key,
flag,
&ppar->part_iter);
if (!res)
goto pop_and_go_right; /* res==0 --> no satisfying partitions */
}
else
res= -1;
if (res == -1)
{
//get a full range iterator
/* get a full range iterator */
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
}
/*
Save our intent to mark full partition as used if we will not be able
to obtain further limits on subpartitions
*/
if (key_tree_part < ppar->last_part_partno)
{
/*
We need to ignore the rest of the partitioning fields in all
evaluations after this
*/
did_set_ignore_part_fields= TRUE;
ppar->ignore_part_fields= TRUE;
}
set_full_part_if_bad_ret= TRUE;
goto process_next_key_part;
}
if (partno == ppar->last_subpart_partno &&
if (key_tree_part == ppar->last_subpart_partno &&
(NULL != ppar->part_info->get_subpart_iter_for_interval))
{
PARTITION_ITERATOR subpart_iter;
@ -3148,13 +3314,16 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
res= ppar->part_info->
get_subpart_iter_for_interval(ppar->part_info,
TRUE,
NULL, /* Currently not used here */
key_tree->min_value,
key_tree->max_value,
key_tree->min_flag | key_tree->max_flag,
0, 0, /* Those are ignored here */
key_tree->min_flag |
key_tree->max_flag,
&subpart_iter);
DBUG_ASSERT(res); /* We can't get "no satisfying subpartitions" */
if (res == -1)
return -1; /* all subpartitions satisfy */
goto pop_and_go_right; /* all subpartitions satisfy */
uint32 subpart_id;
bitmap_clear_all(&ppar->subparts_bitmap);
@ -3167,23 +3336,19 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
while ((part_id= ppar->part_iter.get_next(&ppar->part_iter)) !=
NOT_A_PARTITION_ID)
{
for (uint i= 0; i < ppar->part_info->no_subparts; i++)
for (uint i= 0; i < ppar->part_info->num_subparts; i++)
if (bitmap_is_set(&ppar->subparts_bitmap, i))
bitmap_set_bit(&ppar->part_info->used_partitions,
part_id * ppar->part_info->no_subparts + i);
part_id * ppar->part_info->num_subparts + i);
}
goto go_right;
goto pop_and_go_right;
}
if (key_tree->is_singlepoint())
{
pushed= TRUE;
ppar->cur_part_fields+= ppar->is_part_keypart[partno];
ppar->cur_subpart_fields+= ppar->is_subpart_keypart[partno];
*(ppar->arg_stack_end++) = key_tree;
if (partno == ppar->last_part_partno &&
ppar->cur_part_fields == ppar->part_fields)
if (key_tree_part == ppar->last_part_partno &&
ppar->cur_part_fields == ppar->part_fields &&
ppar->part_info->get_part_iter_for_interval == NULL)
{
/*
Ok, we've got "fieldN<=>constN"-type SEL_ARGs for all partitioning
@ -3212,7 +3377,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
goto process_next_key_part;
}
if (partno == ppar->last_subpart_partno &&
if (key_tree_part == ppar->last_subpart_partno &&
ppar->cur_subpart_fields == ppar->subpart_fields)
{
/*
@ -3236,7 +3401,7 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
NOT_A_PARTITION_ID)
{
bitmap_set_bit(&part_info->used_partitions,
part_id * part_info->no_subparts + subpart_id);
part_id * part_info->num_subparts + subpart_id);
}
res= 1; /* Some partitions were marked as used */
goto pop_and_go_right;
@ -3249,8 +3414,11 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
we're processing subpartititoning's key parts, this means we'll not be
able to infer any suitable condition, so bail out.
*/
if (partno >= ppar->last_part_partno)
return -1;
if (key_tree_part >= ppar->last_part_partno)
{
res= -1;
goto pop_and_go_right;
}
}
}
@ -3259,7 +3427,17 @@ process_next_key_part:
res= find_used_partitions(ppar, key_tree->next_key_part);
else
res= -1;
if (did_set_ignore_part_fields)
{
/*
We have returned from processing all key trees linked to our next
key part. We are ready to be moving down (using right pointers) and
this tree is a new evaluation requiring its own decision on whether
to ignore partitioning fields.
*/
ppar->ignore_part_fields= FALSE;
}
if (set_full_part_if_bad_ret)
{
if (res == -1)
@ -3282,18 +3460,14 @@ process_next_key_part:
init_all_partitions_iterator(ppar->part_info, &ppar->part_iter);
}
if (pushed)
{
pop_and_go_right:
/* Pop this key part info off the "stack" */
ppar->arg_stack_end--;
ppar->cur_part_fields-= ppar->is_part_keypart[partno];
ppar->cur_subpart_fields-= ppar->is_subpart_keypart[partno];
}
/* Pop this key part info off the "stack" */
ppar->arg_stack_end--;
ppar->cur_part_fields-= ppar->is_part_keypart[key_tree_part];
ppar->cur_subpart_fields-= ppar->is_subpart_keypart[key_tree_part];
if (res == -1)
return -1;
go_right:
if (key_tree->right != &null_element)
{
if (-1 == (right_res= find_used_partitions(ppar,key_tree->right)))
@ -3375,13 +3549,14 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
uint used_part_fields, used_subpart_fields;
used_part_fields= fields_ok_for_partition_index(part_info->part_field_array) ?
part_info->no_part_fields : 0;
part_info->num_part_fields : 0;
used_subpart_fields=
fields_ok_for_partition_index(part_info->subpart_field_array)?
part_info->no_subpart_fields : 0;
part_info->num_subpart_fields : 0;
uint total_parts= used_part_fields + used_subpart_fields;
ppar->ignore_part_fields= FALSE;
ppar->part_fields= used_part_fields;
ppar->last_part_partno= (int)used_part_fields - 1;
@ -3416,10 +3591,10 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
if (ppar->subpart_fields)
{
my_bitmap_map *buf;
uint32 bufsize= bitmap_buffer_size(ppar->part_info->no_subparts);
uint32 bufsize= bitmap_buffer_size(ppar->part_info->num_subparts);
if (!(buf= (my_bitmap_map*) alloc_root(alloc, bufsize)))
return TRUE;
bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->no_subparts,
bitmap_init(&ppar->subparts_bitmap, buf, ppar->part_info->num_subparts,
FALSE);
}
range_par->key_parts= key_part;
@ -3430,12 +3605,8 @@ static bool create_partition_index_description(PART_PRUNE_PARAM *ppar)
{
key_part->key= 0;
key_part->part= part;
key_part->store_length= key_part->length= (uint16) (*field)->key_length();
if ((*field)->real_maybe_null())
key_part->store_length+= HA_KEY_NULL_LENGTH;
if ((*field)->type() == MYSQL_TYPE_BLOB ||
(*field)->real_type() == MYSQL_TYPE_VARCHAR)
key_part->store_length+= HA_KEY_BLOB_LENGTH;
key_part->length= (uint16)get_partition_field_store_length(*field);
key_part->store_length= key_part->length;
DBUG_PRINT("info", ("part %u length %u store_length %u", part,
key_part->length, key_part->store_length));
@ -7553,12 +7724,16 @@ check_quick_keys(PARAM *param, uint idx, SEL_ARG *key_tree,
tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
tmp_min_keypart+=
key_tree->next_key_part->store_min_key(param->key[idx], &tmp_min_key,
&tmp_min_flag);
key_tree->next_key_part->store_min_key(param->key[idx],
&tmp_min_key,
&tmp_min_flag,
MAX_KEY);
if (!tmp_max_flag)
tmp_max_keypart+=
key_tree->next_key_part->store_max_key(param->key[idx], &tmp_max_key,
&tmp_max_flag);
key_tree->next_key_part->store_max_key(param->key[idx],
&tmp_max_key,
&tmp_max_flag,
MAX_KEY);
min_key_length= (uint) (tmp_min_key - param->min_key);
max_key_length= (uint) (tmp_max_key - param->max_key);
}
@ -7828,11 +8003,15 @@ get_quick_keys(PARAM *param,QUICK_RANGE_SELECT *quick,KEY_PART *key,
{
uint tmp_min_flag=key_tree->min_flag,tmp_max_flag=key_tree->max_flag;
if (!tmp_min_flag)
min_part+= key_tree->next_key_part->store_min_key(key, &tmp_min_key,
&tmp_min_flag);
min_part+= key_tree->next_key_part->store_min_key(key,
&tmp_min_key,
&tmp_min_flag,
MAX_KEY);
if (!tmp_max_flag)
max_part+= key_tree->next_key_part->store_max_key(key, &tmp_max_key,
&tmp_max_flag);
max_part+= key_tree->next_key_part->store_max_key(key,
&tmp_max_key,
&tmp_max_flag,
MAX_KEY);
flag=tmp_min_flag | tmp_max_flag;
}
}

View File

@ -1,7 +1,7 @@
#ifndef PARTITION_ELEMENT_INCLUDED
#define PARTITION_ELEMENT_INCLUDED
/* Copyright (C) 2006 MySQL AB
/* Copyright (C) 2006-2008 MySQL AB, Sun Microsystems Inc. 2008-2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -39,6 +39,35 @@ enum partition_state {
PART_ADMIN= 9
};
/*
This struct is used to keep track of column expressions as part
of the COLUMNS concept in conjunction with RANGE and LIST partitioning.
The value can be either of MINVALUE, MAXVALUE and an expression that
must be constant and evaluate to the same type as the column it
represents.
The data in this fixed in two steps. The parser will only fill in whether
it is a max_value or provide an expression. Filling in
column_value, part_info, partition_id, null_value is done by the
function fix_column_value_function. However the item tree needs
fixed also before writing it into the frm file (in add_column_list_values).
To distinguish between those two variants, fixed= 1 after the
fixing in add_column_list_values and fixed= 2 otherwise. This is
since the fixing in add_column_list_values isn't a complete fixing.
*/
typedef struct p_column_list_val
{
void* column_value;
Item* item_expression;
partition_info *part_info;
uint partition_id;
bool max_value;
bool null_value;
char fixed;
} part_column_list_val;
/*
This struct is used to contain the value of an element
in the VALUES IN struct. It needs to keep knowledge of
@ -49,8 +78,10 @@ enum partition_state {
typedef struct p_elem_val
{
longlong value;
uint added_items;
bool null_value;
bool unsigned_flag;
part_column_list_val *col_val_array;
} part_elem_value;
struct st_ddl_log_memory_entry;
@ -72,8 +103,9 @@ public:
enum partition_state part_state;
uint16 nodegroup_id;
bool has_null_value;
bool signed_flag;/* Indicate whether this partition uses signed constants */
bool max_value; /* Indicate whether this partition uses MAXVALUE */
/* signed_flag and max_value only relevant for subpartitions */
bool signed_flag;
bool max_value;
partition_element()
: part_max_rows(0), part_min_rows(0), range_value(0),

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef PARTITION_INFO_INCLUDED
#define PARTITION_INFO_INCLUDED
/* Copyright 2006-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2006-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -67,10 +67,9 @@ public:
/*
When we have various string fields we might need some preparation
before and clean-up after calling the get_part_id_func's. We need
one such method for get_partition_id and one for
get_part_partition_id and one for get_subpartition_id.
one such method for get_part_partition_id and one for
get_subpartition_id.
*/
get_part_id_func get_partition_id_charset;
get_part_id_func get_part_partition_id_charset;
get_subpart_id_func get_subpartition_id_charset;
@ -84,7 +83,6 @@ public:
without duplicates, NULL-terminated.
*/
Field **full_part_field_array;
Field **full_part_charset_field_array;
/*
Set of all fields used in partition and subpartition expression.
Required for testing of partition fields in write_set when
@ -100,10 +98,8 @@ public:
*/
uchar **part_field_buffers;
uchar **subpart_field_buffers;
uchar **full_part_field_buffers;
uchar **restore_part_field_ptrs;
uchar **restore_subpart_field_ptrs;
uchar **restore_full_part_field_ptrs;
Item *part_expr;
Item *subpart_expr;
@ -127,6 +123,8 @@ public:
union {
longlong *range_int_array;
LIST_PART_ENTRY *list_array;
part_column_list_val *range_col_array;
part_column_list_val *list_col_array;
};
/********************************************
@ -157,6 +155,10 @@ public:
partition_element *curr_part_elem;
partition_element *current_partition;
part_elem_value *curr_list_val;
uint curr_list_object;
uint num_columns;
/*
These key_map's are used for Partitioning to enable quick decisions
on whether we can derive more information about which partition to
@ -175,17 +177,17 @@ public:
uint part_func_len;
uint subpart_func_len;
uint no_parts;
uint no_subparts;
uint num_parts;
uint num_subparts;
uint count_curr_subparts;
uint part_error_code;
uint no_list_values;
uint num_list_values;
uint no_part_fields;
uint no_subpart_fields;
uint no_full_part_fields;
uint num_part_fields;
uint num_subpart_fields;
uint num_full_part_fields;
uint has_null_part_id;
/*
@ -196,9 +198,9 @@ public:
uint16 linear_hash_mask;
bool use_default_partitions;
bool use_default_no_partitions;
bool use_default_num_partitions;
bool use_default_subpartitions;
bool use_default_no_subpartitions;
bool use_default_num_subpartitions;
bool default_partitions_setup;
bool defined_max_value;
bool list_of_part_fields;
@ -208,7 +210,7 @@ public:
bool is_auto_partitioned;
bool from_openfrm;
bool has_null_value;
bool column_list;
partition_info()
: get_partition_id(NULL), get_part_partition_id(NULL),
@ -217,11 +219,8 @@ public:
part_charset_field_array(NULL),
subpart_charset_field_array(NULL),
full_part_field_array(NULL),
full_part_charset_field_array(NULL),
part_field_buffers(NULL), subpart_field_buffers(NULL),
full_part_field_buffers(NULL),
restore_part_field_ptrs(NULL), restore_subpart_field_ptrs(NULL),
restore_full_part_field_ptrs(NULL),
part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
first_log_entry(NULL), exec_log_entry(NULL), frm_log_entry(NULL),
list_array(NULL), err_value(0),
@ -229,22 +228,23 @@ public:
part_func_string(NULL), subpart_func_string(NULL),
part_state(NULL),
curr_part_elem(NULL), current_partition(NULL),
curr_list_object(0), num_columns(0),
default_engine_type(NULL),
part_result_type(INT_RESULT),
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
part_info_len(0), part_state_len(0),
part_func_len(0), subpart_func_len(0),
no_parts(0), no_subparts(0),
num_parts(0), num_subparts(0),
count_curr_subparts(0), part_error_code(0),
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
no_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
use_default_partitions(TRUE), use_default_no_partitions(TRUE),
use_default_subpartitions(TRUE), use_default_no_subpartitions(TRUE),
num_list_values(0), num_part_fields(0), num_subpart_fields(0),
num_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
use_default_partitions(TRUE), use_default_num_partitions(TRUE),
use_default_subpartitions(TRUE), use_default_num_subpartitions(TRUE),
default_partitions_setup(FALSE), defined_max_value(FALSE),
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
linear_hash_ind(FALSE), fixed(FALSE),
is_auto_partitioned(FALSE), from_openfrm(FALSE),
has_null_value(FALSE)
has_null_value(FALSE), column_list(FALSE)
{
all_fields_in_PF.clear_all();
all_fields_in_PPF.clear_all();
@ -267,27 +267,47 @@ public:
/* Returns the total number of partitions on the leaf level */
uint get_tot_partitions()
{
return no_parts * (is_sub_partitioned() ? no_subparts : 1);
return num_parts * (is_sub_partitioned() ? num_subparts : 1);
}
bool set_up_defaults_for_partitioning(handler *file, HA_CREATE_INFO *info,
uint start_no);
char *has_unique_fields();
char *has_unique_names();
bool check_engine_mix(handlerton *engine_type, bool default_engine);
bool check_range_constants();
bool check_list_constants();
bool check_range_constants(THD *thd);
bool check_list_constants(THD *thd);
bool check_partition_info(THD *thd, handlerton **eng_type,
handler *file, HA_CREATE_INFO *info,
bool check_partition_function);
void print_no_partition_found(TABLE *table);
void print_debug(const char *str, uint*);
Item* get_column_item(Item *item, Field *field);
int fix_func_partition(THD *thd,
part_elem_value *val,
partition_element *part_elem,
uint part_id);
bool fix_column_value_functions(THD *thd,
part_elem_value *val,
uint part_id);
int fix_parser_data(THD *thd);
int add_max_value();
void init_col_val(part_column_list_val *col_val, Item *item);
int reorganize_into_single_field_col_val();
part_column_list_val *add_column_value();
bool set_part_expr(char *start_token, Item *item_ptr,
char *end_token, bool is_subpart);
static int compare_column_values(const void *a, const void *b);
bool set_up_charset_field_preps();
bool check_partition_field_length();
bool init_column_part();
bool add_column_list_value(THD *thd, Item *item);
private:
static int list_part_cmp(const void* a, const void* b);
static int list_part_cmp_unsigned(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
uint start_no);
bool set_up_default_subpartitions(handler *file, HA_CREATE_INFO *info);
char *create_default_partition_names(uint part_no, uint no_parts,
char *create_default_partition_names(uint part_no, uint num_parts,
uint start_no);
char *create_subpartition_name(uint subpart_no, const char *part_name);
bool has_unique_name(partition_element *element);
@ -313,7 +333,7 @@ void init_all_partitions_iterator(partition_info *part_info,
PARTITION_ITERATOR *part_iter)
{
part_iter->part_nums.start= part_iter->part_nums.cur= 0;
part_iter->part_nums.end= part_info->no_parts;
part_iter->part_nums.end= part_info->num_parts;
part_iter->ret_null_part= part_iter->ret_null_part_orig= FALSE;
part_iter->get_next= get_next_partition_id_range;
}

View File

@ -6240,4 +6240,21 @@ ER_UNKNOWN_LOCALE
ER_SLAVE_IGNORE_SERVER_IDS
eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id"
ER_SAME_NAME_PARTITION_FIELD
eng "Duplicate partition field name '%-.192s'"
ER_PARTITION_COLUMN_LIST_ERROR
eng "Inconsistency in usage of column lists for partitioning"
ER_WRONG_TYPE_COLUMN_VALUE_ERROR
eng "Partition column values of incorrect type"
ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
eng "Too many fields in '%-.192s'"
ER_MAXVALUE_IN_VALUES_IN
eng "Cannot use MAXVALUE as value in VALUES IN"
ER_TOO_MANY_VALUES_ERROR
eng "Cannot have more than one value for this type of %-.64s partitioning"
ER_ROW_SINGLE_PARTITION_FIELD_ERROR
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
ER_PARTITION_FIELDS_TOO_LONG
eng "The total length of the partitioning fields is too large"

View File

@ -6241,3 +6241,21 @@ ER_UNKNOWN_LOCALE
ER_SLAVE_IGNORE_SERVER_IDS
eng "The requested server id %d clashes with the slave startup option --replicate-same-server-id"
ER_SAME_NAME_PARTITION_FIELD
eng "Duplicate partition field name '%-.192s'"
ER_PARTITION_COLUMN_LIST_ERROR
eng "Inconsistency in usage of column lists for partitioning"
ER_WRONG_TYPE_COLUMN_VALUE_ERROR
eng "Partition column values of incorrect type"
ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
eng "Too many fields in '%-.192s'"
ER_MAXVALUE_IN_VALUES_IN
eng "Cannot use MAXVALUE as value in VALUES IN"
ER_TOO_MANY_VALUES_ERROR
eng "Cannot have more than one value for this type of %-.64s partitioning"
ER_ROW_SINGLE_PARTITION_FIELD_ERROR
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
ER_FIELD_TYPE_NOT_ALLOWED_AS_PARTITION_FIELD
eng "Field '%-.192s' is of a not allowed type for this type of partitioning"
ER_PARTITION_FIELDS_TOO_LONG
eng "The total length of the partitioning fields is too large"

View File

@ -1497,7 +1497,7 @@ Alter_info::Alter_info(const Alter_info &rhs, MEM_ROOT *mem_root)
keys_onoff(rhs.keys_onoff),
tablespace_op(rhs.tablespace_op),
partition_names(rhs.partition_names, mem_root),
no_parts(rhs.no_parts),
num_parts(rhs.num_parts),
change_level(rhs.change_level),
datetime_field(rhs.datetime_field),
error_if_not_empty(rhs.error_if_not_empty)

View File

@ -899,7 +899,7 @@ public:
enum enum_enable_or_disable keys_onoff;
enum tablespace_op_type tablespace_op;
List<char> partition_names;
uint no_parts;
uint num_parts;
enum_alter_table_change_level change_level;
Create_field *datetime_field;
bool error_if_not_empty;
@ -909,7 +909,7 @@ public:
flags(0),
keys_onoff(LEAVE_AS_IS),
tablespace_op(NO_TABLESPACE_OP),
no_parts(0),
num_parts(0),
change_level(ALTER_TABLE_METADATA_ONLY),
datetime_field(NULL),
error_if_not_empty(FALSE)
@ -924,7 +924,7 @@ public:
flags= 0;
keys_onoff= LEAVE_AS_IS;
tablespace_op= NO_TABLESPACE_OP;
no_parts= 0;
num_parts= 0;
partition_names.empty();
change_level= ALTER_TABLE_METADATA_ONLY;
datetime_field= 0;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
#ifndef SQL_PARTITION_INCLUDED
#define SQL_PARTITION_INCLUDED
/* Copyright (C) 2006 MySQL AB
/* Copyright (C) 2006-2008 MySQL AB, Sun Microsystems Inc. 2008-2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -68,15 +68,13 @@ int get_part_for_delete(const uchar *buf, const uchar *rec0,
void prune_partition_set(const TABLE *table, part_id_range *part_spec);
bool check_partition_info(partition_info *part_info,handlerton **eng_type,
TABLE *table, handler *file, HA_CREATE_INFO *info);
void set_linear_hash_mask(partition_info *part_info, uint no_parts);
void set_linear_hash_mask(partition_info *part_info, uint num_parts);
bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
char *generate_partition_syntax(partition_info *part_info,
uint *buf_length, bool use_sql_alloc,
bool show_partition_options);
bool partition_key_modified(TABLE *table, const MY_BITMAP *fields);
void get_partition_set(const TABLE *table, uchar *buf, const uint index,
const key_range *key_spec,
part_id_range *part_spec);
uint get_partition_field_store_length(Field *field);
void get_full_part_id_from_key(const TABLE *table, uchar *buf,
KEY *key_info,
const key_range *key_spec,
@ -99,6 +97,7 @@ bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
bool check_part_func_fields(Field **ptr, bool ok_with_charsets);
bool field_is_partition_charset(Field *field);
Item* convert_charset_partition_constant(Item *item, CHARSET_INFO *cs);
/*
A "Get next" function for partition iterator.
@ -176,11 +175,14 @@ typedef struct st_partition_iter
SYNOPSIS
get_partitions_in_range_iter()
part_info Partitioning info
is_subpart
min_val Left edge, field value in opt_range_key format.
max_val Right edge, field value in opt_range_key format.
is_subpart
store_length_array Length of fields packed in opt_range_key format
min_val Left edge, field value in opt_range_key format
max_val Right edge, field value in opt_range_key format
min_len Length of minimum value
max_len Length of maximum value
flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
NO_MAX_RANGE.
NO_MAX_RANGE
part_iter Iterator structure to be initialized
DESCRIPTION
@ -194,8 +196,9 @@ typedef struct st_partition_iter
The set of partitions is returned by initializing an iterator in *part_iter
NOTES
There are currently two functions of this type:
There are currently three functions of this type:
- get_part_iter_for_interval_via_walking
- get_part_iter_for_interval_cols_via_map
- get_part_iter_for_interval_via_mapping
RETURN
@ -206,7 +209,9 @@ typedef struct st_partition_iter
typedef int (*get_partitions_in_range_iter)(partition_info *part_info,
bool is_subpart,
uint32 *store_length_array,
uchar *min_val, uchar *max_val,
uint min_len, uint max_len,
uint flags,
PARTITION_ITERATOR *part_iter);

View File

@ -1574,7 +1574,8 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
((part_syntax= generate_partition_syntax(table->part_info,
&part_syntax_len,
FALSE,
show_table_options))))
show_table_options,
NULL, NULL))))
{
packet->append(STRING_WITH_LEN("\n/*!50100"));
packet->append(part_syntax, part_syntax_len);
@ -4949,6 +4950,50 @@ static void store_schema_partitions_record(THD *thd, TABLE *schema_table,
return;
}
static int
get_partition_column_description(partition_info *part_info,
part_elem_value *list_value,
String &tmp_str)
{
uint num_elements= part_info->part_field_list.elements;
uint i;
DBUG_ENTER("get_partition_column_description");
for (i= 0; i < num_elements; i++)
{
part_column_list_val *col_val= &list_value->col_val_array[i];
if (col_val->max_value)
tmp_str.append(partition_keywords[PKW_MAXVALUE].str);
else if (col_val->null_value)
tmp_str.append("NULL");
else
{
char buffer[MAX_KEY_LENGTH];
String str(buffer, sizeof(buffer), &my_charset_bin);
Item *item= col_val->item_expression;
if (!(item= part_info->get_column_item(item,
part_info->part_field_array[i])))
{
DBUG_RETURN(1);
}
String *res= item->val_str(&str);
if (!res)
{
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
DBUG_RETURN(1);
}
if (item->result_type() == STRING_RESULT)
tmp_str.append("'");
tmp_str.append(*res);
if (item->result_type() == STRING_RESULT)
tmp_str.append("'");
}
if (i != num_elements - 1)
tmp_str.append(",");
}
DBUG_RETURN(0);
}
static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
TABLE *table, bool res,
@ -4959,6 +5004,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
char buff[61];
String tmp_res(buff, sizeof(buff), cs);
String tmp_str;
uint num_elements;
TABLE *show_table= tables->table;
handler *file;
#ifdef WITH_PARTITION_STORAGE_ENGINE
@ -4991,12 +5037,18 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
/* Partition method*/
switch (part_info->part_type) {
case RANGE_PARTITION:
table->field[7]->store(partition_keywords[PKW_RANGE].str,
partition_keywords[PKW_RANGE].length, cs);
break;
case LIST_PARTITION:
table->field[7]->store(partition_keywords[PKW_LIST].str,
partition_keywords[PKW_LIST].length, cs);
tmp_res.length(0);
if (part_info->part_type == RANGE_PARTITION)
tmp_res.append(partition_keywords[PKW_RANGE].str,
partition_keywords[PKW_RANGE].length);
else
tmp_res.append(partition_keywords[PKW_LIST].str,
partition_keywords[PKW_LIST].length);
if (part_info->column_list)
tmp_res.append(partition_keywords[PKW_COLUMNS].str,
partition_keywords[PKW_COLUMNS].length);
table->field[7]->store(tmp_res.ptr(), tmp_res.length(), cs);
break;
case HASH_PARTITION:
tmp_res.length(0);
@ -5074,36 +5126,68 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
/* Partition description */
if (part_info->part_type == RANGE_PARTITION)
{
if (part_elem->range_value != LONGLONG_MAX)
table->field[11]->store((longlong) part_elem->range_value, FALSE);
if (part_info->column_list)
{
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
part_elem_value *list_value= list_val_it++;
tmp_str.length(0);
if (get_partition_column_description(part_info,
list_value,
tmp_str))
{
DBUG_RETURN(1);
}
table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
}
else
table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
{
if (part_elem->range_value != LONGLONG_MAX)
table->field[11]->store((longlong) part_elem->range_value, FALSE);
else
table->field[11]->store(partition_keywords[PKW_MAXVALUE].str,
partition_keywords[PKW_MAXVALUE].length, cs);
}
table->field[11]->set_notnull();
}
else if (part_info->part_type == LIST_PARTITION)
{
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
part_elem_value *list_value;
uint no_items= part_elem->list_val_list.elements;
uint num_items= part_elem->list_val_list.elements;
tmp_str.length(0);
tmp_res.length(0);
if (part_elem->has_null_value)
{
tmp_str.append("NULL");
if (no_items > 0)
if (num_items > 0)
tmp_str.append(",");
}
while ((list_value= list_val_it++))
{
if (!list_value->unsigned_flag)
tmp_res.set(list_value->value, cs);
if (part_info->column_list)
{
if (part_info->part_field_list.elements > 1U)
tmp_str.append("(");
if (get_partition_column_description(part_info,
list_value,
tmp_str))
{
DBUG_RETURN(1);
}
if (part_info->part_field_list.elements > 1U)
tmp_str.append(")");
}
else
tmp_res.set((ulonglong)list_value->value, cs);
tmp_str.append(tmp_res);
if (--no_items != 0)
{
if (!list_value->unsigned_flag)
tmp_res.set(list_value->value, cs);
else
tmp_res.set((ulonglong)list_value->value, cs);
tmp_str.append(tmp_res);
}
if (--num_items != 0)
tmp_str.append(",");
};
}
table->field[11]->store(tmp_str.ptr(), tmp_str.length(), cs);
table->field[11]->set_notnull();
}
@ -6606,7 +6690,7 @@ ST_FIELD_INFO partitions_fields_info[]=
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
{"SUBPARTITION_ORDINAL_POSITION", 21 , MYSQL_TYPE_LONGLONG, 0,
(MY_I_S_MAYBE_NULL | MY_I_S_UNSIGNED), 0, OPEN_FULL_TABLE},
{"PARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"PARTITION_METHOD", 18, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"SUBPARTITION_METHOD", 12, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"PARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0, OPEN_FULL_TABLE},
{"SUBPARTITION_EXPRESSION", 65535, MYSQL_TYPE_STRING, 0, 1, 0,

View File

@ -1585,7 +1585,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
{
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
TRUE, TRUE)))
TRUE, TRUE,
lpt->create_info,
lpt->alter_info)))
{
DBUG_RETURN(TRUE);
}
@ -1677,7 +1679,9 @@ bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
char *tmp_part_syntax_str;
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
TRUE, TRUE)))
TRUE, TRUE,
lpt->create_info,
lpt->alter_info)))
{
error= 1;
goto err;
@ -2498,6 +2502,39 @@ int prepare_create_field(Create_field *sql_field,
DBUG_RETURN(0);
}
/*
Get character set from field object generated by parser using
default values when not set.
SYNOPSIS
get_sql_field_charset()
sql_field The sql_field object
create_info Info generated by parser
RETURN VALUES
cs Character set
*/
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
HA_CREATE_INFO *create_info)
{
CHARSET_INFO *cs= sql_field->charset;
if (!cs)
cs= create_info->default_table_charset;
/*
table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
if we want change character set for all varchar/char columns.
But the table charset must not affect the BLOB fields, so don't
allow to change my_charset_bin to somethig else.
*/
if (create_info->table_charset && cs != &my_charset_bin)
cs= create_info->table_charset;
return cs;
}
/*
Preparation for table creation
@ -2561,18 +2598,8 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
executing a prepared statement for the second time.
*/
sql_field->length= sql_field->char_length;
if (!sql_field->charset)
sql_field->charset= create_info->default_table_charset;
/*
table_charset is set in ALTER TABLE if we want change character set
for all varchar/char columns.
But the table charset must not affect the BLOB fields, so don't
allow to change my_charset_bin to somethig else.
*/
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
sql_field->charset= create_info->table_charset;
save_cs= sql_field->charset;
save_cs= sql_field->charset= get_sql_field_charset(sql_field,
create_info);
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
@ -3622,6 +3649,9 @@ bool mysql_create_table_no_lock(THD *thd,
}
if (check_engine(thd, table_name, create_info))
DBUG_RETURN(TRUE);
set_table_default_charset(thd, create_info, (char*) db);
db_options= create_info->table_options;
if (create_info->row_type == ROW_TYPE_DYNAMIC)
db_options|=HA_OPTION_PACK_RECORD;
@ -3715,7 +3745,7 @@ bool mysql_create_table_no_lock(THD *thd,
ha_resolve_storage_engine_name(part_info->default_engine_type),
ha_resolve_storage_engine_name(create_info->db_type)));
if (part_info->check_partition_info(thd, &engine_type, file,
create_info, TRUE))
create_info, FALSE))
goto err;
part_info->default_engine_type= engine_type;
@ -3725,7 +3755,9 @@ bool mysql_create_table_no_lock(THD *thd,
*/
if (!(part_syntax_buf= generate_partition_syntax(part_info,
&syntax_len,
TRUE, TRUE)))
TRUE, TRUE,
create_info,
alter_info)))
goto err;
part_info->part_info_string= part_syntax_buf;
part_info->part_info_len= syntax_len;
@ -3751,9 +3783,9 @@ bool mysql_create_table_no_lock(THD *thd,
creates a proper .par file. The current part_info object is
only used to create the frm-file and .par-file.
*/
if (part_info->use_default_no_partitions &&
part_info->no_parts &&
(int)part_info->no_parts !=
if (part_info->use_default_num_partitions &&
part_info->num_parts &&
(int)part_info->num_parts !=
file->get_default_no_partitions(create_info))
{
uint i;
@ -3764,13 +3796,13 @@ bool mysql_create_table_no_lock(THD *thd,
(part_it++)->part_state= PART_TO_BE_DROPPED;
}
else if (part_info->is_sub_partitioned() &&
part_info->use_default_no_subpartitions &&
part_info->no_subparts &&
(int)part_info->no_subparts !=
part_info->use_default_num_subpartitions &&
part_info->num_subparts &&
(int)part_info->num_subparts !=
file->get_default_no_partitions(create_info))
{
DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
part_info->no_subparts= file->get_default_no_partitions(create_info);
part_info->num_subparts= file->get_default_no_partitions(create_info);
}
}
else if (create_info->db_type != engine_type)
@ -3792,8 +3824,6 @@ bool mysql_create_table_no_lock(THD *thd,
}
#endif
set_table_default_charset(thd, create_info, (char*) db);
if (mysql_prepare_create_table(thd, create_info, alter_info,
internal_tmp_table,
&db_options, file,
@ -4583,11 +4613,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
DBUG_RETURN(TRUE);
}
uint no_parts_found;
uint no_parts_opt= alter_info->partition_names.elements;
no_parts_found= set_part_state(alter_info, table->table->part_info,
PART_ADMIN);
if (no_parts_found != no_parts_opt &&
uint num_parts_found;
uint num_parts_opt= alter_info->partition_names.elements;
num_parts_found= set_part_state(alter_info, table->table->part_info,
PART_ADMIN);
if (num_parts_found != num_parts_opt &&
(!(alter_info->flags & ALTER_ALL_PARTITION)))
{
char buff[FN_REFLEN + MYSQL_ERRMSG_SIZE];

View File

@ -1,4 +1,4 @@
/* Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.
/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -611,6 +611,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token COLLATE_SYM /* SQL-2003-R */
%token COLLATION_SYM /* SQL-2003-N */
%token COLUMNS
%token COLUMN_LIST_SYM
%token COLUMN_SYM /* SQL-2003-R */
%token COLUMN_NAME_SYM /* SQL-2003-N */
%token COMMENT_SYM
@ -1187,9 +1188,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <ulonglong_number>
ulonglong_num real_ulonglong_num size_number
%type <p_elem_value>
part_bit_expr
%type <lock_type>
replace_lock_option opt_low_priority insert_lock_option load_data_lock
@ -1325,6 +1323,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail
install uninstall partition_entry binlog_base64_event
init_key_options key_options key_opts key_opt key_using_alg
part_column_list
server_def server_options_list server_option
definer_opt no_definer definer
END_OF_INPUT
@ -4062,25 +4061,28 @@ partition_entry:
;
partition:
BY part_type_def opt_no_parts opt_sub_part part_defs
BY part_type_def opt_num_parts opt_sub_part part_defs
;
part_type_def:
opt_linear KEY_SYM '(' part_field_list ')'
{
LEX *lex= Lex;
lex->part_info->list_of_part_fields= TRUE;
lex->part_info->part_type= HASH_PARTITION;
partition_info *part_info= Lex->part_info;
part_info->list_of_part_fields= TRUE;
part_info->column_list= FALSE;
part_info->part_type= HASH_PARTITION;
}
| opt_linear HASH_SYM
{ Lex->part_info->part_type= HASH_PARTITION; }
part_func {}
| RANGE_SYM
| RANGE_SYM part_func
{ Lex->part_info->part_type= RANGE_PARTITION; }
part_func {}
| LIST_SYM
| RANGE_SYM part_column_list
{ Lex->part_info->part_type= RANGE_PARTITION; }
| LIST_SYM part_func
{ Lex->part_info->part_type= LIST_PARTITION; }
| LIST_SYM part_column_list
{ Lex->part_info->part_type= LIST_PARTITION; }
part_func {}
;
opt_linear:
@ -4102,59 +4104,66 @@ part_field_item_list:
part_field_item:
ident
{
if (Lex->part_info->part_field_list.push_back($1.str))
partition_info *part_info= Lex->part_info;
part_info->num_columns++;
if (part_info->part_field_list.push_back($1.str))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
if (part_info->num_columns > MAX_REF_PARTS)
{
my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
"list of partition fields");
MYSQL_YYABORT;
}
}
;
part_column_list:
COLUMN_LIST_SYM '(' part_field_list ')'
{
partition_info *part_info= Lex->part_info;
part_info->column_list= TRUE;
part_info->list_of_part_fields= TRUE;
}
;
part_func:
'(' remember_name part_func_expr remember_end ')'
{
LEX *lex= Lex;
uint expr_len= (uint)($4 - $2) - 1;
lex->part_info->list_of_part_fields= FALSE;
lex->part_info->part_expr= $3;
char *func_string= (char*) sql_memdup($2+1, expr_len);
if (func_string == NULL)
MYSQL_YYABORT;
lex->part_info->part_func_string= func_string;
lex->part_info->part_func_len= expr_len;
partition_info *part_info= Lex->part_info;
if (part_info->set_part_expr($2+1, $3, $4, FALSE))
{ MYSQL_YYABORT; }
part_info->num_columns= 1;
part_info->column_list= FALSE;
}
;
sub_part_func:
'(' remember_name part_func_expr remember_end ')'
{
LEX *lex= Lex;
uint expr_len= (uint)($4 - $2) - 1;
lex->part_info->list_of_subpart_fields= FALSE;
lex->part_info->subpart_expr= $3;
char *func_string= (char*) sql_memdup($2+1, expr_len);
if (func_string == NULL)
MYSQL_YYABORT;
lex->part_info->subpart_func_string= func_string;
lex->part_info->subpart_func_len= expr_len;
if (Lex->part_info->set_part_expr($2+1, $3, $4, TRUE))
{ MYSQL_YYABORT; }
}
;
opt_no_parts:
opt_num_parts:
/* empty */ {}
| PARTITIONS_SYM real_ulong_num
{
uint no_parts= $2;
LEX *lex= Lex;
if (no_parts == 0)
uint num_parts= $2;
partition_info *part_info= Lex->part_info;
if (num_parts == 0)
{
my_error(ER_NO_PARTS_ERROR, MYF(0), "partitions");
MYSQL_YYABORT;
}
lex->part_info->no_parts= no_parts;
lex->part_info->use_default_no_partitions= FALSE;
part_info->num_parts= num_parts;
part_info->use_default_num_partitions= FALSE;
}
;
@ -4162,15 +4171,15 @@ opt_sub_part:
/* empty */ {}
| SUBPARTITION_SYM BY opt_linear HASH_SYM sub_part_func
{ Lex->part_info->subpart_type= HASH_PARTITION; }
opt_no_subparts {}
opt_num_subparts {}
| SUBPARTITION_SYM BY opt_linear KEY_SYM
'(' sub_part_field_list ')'
{
LEX *lex= Lex;
lex->part_info->subpart_type= HASH_PARTITION;
lex->part_info->list_of_subpart_fields= TRUE;
partition_info *part_info= Lex->part_info;
part_info->subpart_type= HASH_PARTITION;
part_info->list_of_subpart_fields= TRUE;
}
opt_no_subparts {}
opt_num_subparts {}
;
sub_part_field_list:
@ -4181,11 +4190,18 @@ sub_part_field_list:
sub_part_field_item:
ident
{
if (Lex->part_info->subpart_field_list.push_back($1.str))
partition_info *part_info= Lex->part_info;
if (part_info->subpart_field_list.push_back($1.str))
{
mem_alloc_error(1);
MYSQL_YYABORT;
}
if (part_info->subpart_field_list.elements > MAX_REF_PARTS)
{
my_error(ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR, MYF(0),
"list of subpartition fields");
MYSQL_YYABORT;
}
}
;
@ -4205,33 +4221,46 @@ part_func_expr:
}
;
opt_no_subparts:
opt_num_subparts:
/* empty */ {}
| SUBPARTITIONS_SYM real_ulong_num
{
uint no_parts= $2;
uint num_parts= $2;
LEX *lex= Lex;
if (no_parts == 0)
if (num_parts == 0)
{
my_error(ER_NO_PARTS_ERROR, MYF(0), "subpartitions");
MYSQL_YYABORT;
}
lex->part_info->no_subparts= no_parts;
lex->part_info->use_default_no_subpartitions= FALSE;
lex->part_info->num_subparts= num_parts;
lex->part_info->use_default_num_subpartitions= FALSE;
}
;
part_defs:
/* empty */
{}
{
partition_info *part_info= Lex->part_info;
if (part_info->part_type == RANGE_PARTITION)
{
my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
"RANGE");
MYSQL_YYABORT;
}
else if (part_info->part_type == LIST_PARTITION)
{
my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0),
"LIST");
MYSQL_YYABORT;
}
}
| '(' part_def_list ')'
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
partition_info *part_info= Lex->part_info;
uint count_curr_parts= part_info->partitions.elements;
if (part_info->no_parts != 0)
if (part_info->num_parts != 0)
{
if (part_info->no_parts !=
if (part_info->num_parts !=
count_curr_parts)
{
my_parse_error(ER(ER_PARTITION_WRONG_NO_PART_ERROR));
@ -4240,7 +4269,7 @@ part_defs:
}
else if (count_curr_parts > 0)
{
part_info->no_parts= count_curr_parts;
part_info->num_parts= count_curr_parts;
}
part_info->count_curr_subparts= 0;
}
@ -4254,8 +4283,7 @@ part_def_list:
part_definition:
PARTITION_SYM
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
partition_info *part_info= Lex->part_info;
partition_element *p_elem= new partition_element();
if (!p_elem || part_info->partitions.push_back(p_elem))
@ -4267,7 +4295,7 @@ part_definition:
part_info->curr_part_elem= p_elem;
part_info->current_partition= p_elem;
part_info->use_default_partitions= FALSE;
part_info->use_default_no_partitions= FALSE;
part_info->use_default_num_partitions= FALSE;
}
part_name
opt_part_values
@ -4279,8 +4307,7 @@ part_definition:
part_name:
ident
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
partition_info *part_info= Lex->part_info;
partition_element *p_elem= part_info->curr_part_elem;
p_elem->partition_name= $1.str;
}
@ -4290,15 +4317,16 @@ opt_part_values:
/* empty */
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
if (lex->part_info->part_type == RANGE_PARTITION)
if (part_info->part_type == RANGE_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
MYSQL_YYABORT;
}
if (lex->part_info->part_type == LIST_PARTITION)
if (part_info->part_type == LIST_PARTITION)
{
my_error(ER_PARTITION_REQUIRES_VALUES_ERROR, MYF(0),
"LIST", "IN");
@ -4306,14 +4334,15 @@ opt_part_values:
}
}
else
lex->part_info->part_type= HASH_PARTITION;
part_info->part_type= HASH_PARTITION;
}
| VALUES LESS_SYM THAN_SYM part_func_max
| VALUES LESS_SYM THAN_SYM
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
if (Lex->part_info->part_type != RANGE_PARTITION)
if (part_info->part_type != RANGE_PARTITION)
{
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"RANGE", "LESS THAN");
@ -4321,153 +4350,183 @@ opt_part_values:
}
}
else
lex->part_info->part_type= RANGE_PARTITION;
part_info->part_type= RANGE_PARTITION;
}
| VALUES IN_SYM '(' part_list_func ')'
part_func_max {}
| VALUES IN_SYM
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
if (! lex->is_partition_management())
{
if (Lex->part_info->part_type != LIST_PARTITION)
if (part_info->part_type != LIST_PARTITION)
{
my_error(ER_PARTITION_WRONG_VALUES_ERROR, MYF(0),
"LIST", "IN");
"LIST", "IN");
MYSQL_YYABORT;
}
}
else
lex->part_info->part_type= LIST_PARTITION;
part_info->part_type= LIST_PARTITION;
}
part_values_in {}
;
part_func_max:
max_value_sym
MAX_VALUE_SYM
{
partition_info *part_info= Lex->part_info;
if (part_info->num_columns &&
part_info->num_columns != 1U)
{
part_info->print_debug("Kilroy II", NULL);
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
else
part_info->num_columns= 1U;
if (part_info->init_column_part())
{
MYSQL_YYABORT;
}
if (part_info->add_max_value())
{
MYSQL_YYABORT;
}
}
| part_value_item {}
;
part_values_in:
part_value_item
{
LEX *lex= Lex;
if (lex->part_info->defined_max_value)
partition_info *part_info= lex->part_info;
part_info->print_debug("part_values_in: part_value_item", NULL);
if (part_info->num_columns != 1U)
{
my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
MYSQL_YYABORT;
if (!lex->is_partition_management() ||
part_info->num_columns == 0 ||
part_info->num_columns > MAX_REF_PARTS)
{
part_info->print_debug("Kilroy III", NULL);
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
/*
Reorganize the current large array into a list of small
arrays with one entry in each array. This can happen
in the first partition of an ALTER TABLE statement where
we ADD or REORGANIZE partitions. Also can only happen
for LIST partitions.
*/
if (part_info->reorganize_into_single_field_col_val())
{
MYSQL_YYABORT;
}
}
lex->part_info->defined_max_value= TRUE;
lex->part_info->curr_part_elem->max_value= TRUE;
lex->part_info->curr_part_elem->range_value= LONGLONG_MAX;
}
| part_range_func
| '(' part_value_list ')'
{
if (Lex->part_info->defined_max_value)
partition_info *part_info= Lex->part_info;
if (part_info->num_columns < 2U)
{
my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
MYSQL_YYABORT;
}
if (Lex->part_info->curr_part_elem->has_null_value)
{
my_parse_error(ER(ER_NULL_IN_VALUES_LESS_THAN));
my_parse_error(ER(ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
MYSQL_YYABORT;
}
}
;
max_value_sym:
part_value_list:
part_value_item {}
| part_value_list ',' part_value_item {}
;
part_value_item:
'('
{
partition_info *part_info= Lex->part_info;
part_info->print_debug("( part_value_item", NULL);
/* Initialisation code needed for each list of value expressions */
if (!(part_info->part_type == LIST_PARTITION &&
part_info->num_columns == 1U) &&
part_info->init_column_part())
{
MYSQL_YYABORT;
}
}
part_value_item_list {}
')'
{
LEX *lex= Lex;
partition_info *part_info= Lex->part_info;
part_info->print_debug(") part_value_item", NULL);
if (part_info->num_columns == 0)
part_info->num_columns= part_info->curr_list_object;
if (part_info->num_columns != part_info->curr_list_object)
{
/*
All value items lists must be of equal length, in some cases
which is covered by the above if-statement we don't know yet
how many columns is in the partition so the assignment above
ensures that we only report errors when we know we have an
error.
*/
part_info->print_debug("Kilroy I", NULL);
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
part_info->curr_list_object= 0;
}
;
part_value_item_list:
part_value_expr_item {}
| part_value_item_list ',' part_value_expr_item {}
;
part_value_expr_item:
MAX_VALUE_SYM
| '(' MAX_VALUE_SYM ')'
;
part_range_func:
'(' part_bit_expr ')'
{
partition_info *part_info= Lex->part_info;
if (!($2->unsigned_flag))
part_info->curr_part_elem->signed_flag= TRUE;
part_info->curr_part_elem->range_value= $2->value;
}
;
part_list_func:
part_list_item {}
| part_list_func ',' part_list_item {}
;
part_list_item:
part_bit_expr
{
part_elem_value *value_ptr= $1;
partition_info *part_info= Lex->part_info;
if (!value_ptr->unsigned_flag)
part_info->curr_part_elem->signed_flag= TRUE;
if (!value_ptr->null_value &&
part_info->curr_part_elem->
list_val_list.push_back(value_ptr))
part_column_list_val *col_val;
if (part_info->part_type == LIST_PARTITION)
{
my_parse_error(ER(ER_MAXVALUE_IN_VALUES_IN));
MYSQL_YYABORT;
}
if (part_info->add_max_value())
{
mem_alloc_error(sizeof(part_elem_value));
MYSQL_YYABORT;
}
}
;
part_bit_expr:
bit_expr
| bit_expr
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
Item *part_expr= $1;
THD *thd= YYTHD;
LEX *lex= thd->lex;
Name_resolution_context *context= &lex->current_select->context;
TABLE_LIST *save_list= context->table_list;
const char *save_where= thd->where;
context->table_list= 0;
thd->where= "partition function";
part_elem_value *value_ptr=
(part_elem_value*)sql_alloc(sizeof(part_elem_value));
if (!value_ptr)
{
mem_alloc_error(sizeof(part_elem_value));
MYSQL_YYABORT;
}
if (part_expr->walk(&Item::check_partition_func_processor, 0,
NULL))
if (!lex->safe_to_cache_query)
{
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
MYSQL_YYABORT;
}
if (part_expr->fix_fields(YYTHD, (Item**)0) ||
((context->table_list= save_list), FALSE) ||
(!part_expr->const_item()) ||
(!lex->safe_to_cache_query))
if (part_info->add_column_list_value(YYTHD, part_expr))
{
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
MYSQL_YYABORT;
}
thd->where= save_where;
value_ptr->value= part_expr->val_int();
value_ptr->unsigned_flag= TRUE;
if (!part_expr->unsigned_flag &&
value_ptr->value < 0)
value_ptr->unsigned_flag= FALSE;
if ((value_ptr->null_value= part_expr->null_value))
{
if (Lex->part_info->curr_part_elem->has_null_value)
{
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
MYSQL_YYABORT;
}
Lex->part_info->curr_part_elem->has_null_value= TRUE;
}
else if (part_expr->result_type() != INT_RESULT)
{
my_parse_error(ER(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR));
MYSQL_YYABORT;
}
$$= value_ptr;
}
;
opt_sub_partition:
/* empty */
{
if (Lex->part_info->no_subparts != 0 &&
!Lex->part_info->use_default_subpartitions)
partition_info *part_info= Lex->part_info;
if (part_info->num_subparts != 0 &&
!part_info->use_default_subpartitions)
{
/*
We come here when we have defined subpartitions on the first
@ -4479,11 +4538,10 @@ opt_sub_partition:
}
| '(' sub_part_list ')'
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
if (part_info->no_subparts != 0)
partition_info *part_info= Lex->part_info;
if (part_info->num_subparts != 0)
{
if (part_info->no_subparts !=
if (part_info->num_subparts !=
part_info->count_curr_subparts)
{
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
@ -4497,7 +4555,7 @@ opt_sub_partition:
my_parse_error(ER(ER_PARTITION_WRONG_NO_SUBPART_ERROR));
MYSQL_YYABORT;
}
part_info->no_subparts= part_info->count_curr_subparts;
part_info->num_subparts= part_info->count_curr_subparts;
}
part_info->count_curr_subparts= 0;
}
@ -4511,8 +4569,7 @@ sub_part_list:
sub_part_definition:
SUBPARTITION_SYM
{
LEX *lex= Lex;
partition_info *part_info= lex->part_info;
partition_info *part_info= Lex->part_info;
partition_element *curr_part= part_info->current_partition;
partition_element *sub_p_elem= new partition_element(curr_part);
if (part_info->use_default_subpartitions &&
@ -4540,7 +4597,7 @@ sub_part_definition:
}
part_info->curr_part_elem= sub_p_elem;
part_info->use_default_subpartitions= FALSE;
part_info->use_default_no_subpartitions= FALSE;
part_info->use_default_num_subpartitions= FALSE;
part_info->count_curr_subparts++;
}
sub_name opt_part_options {}
@ -4566,9 +4623,9 @@ opt_part_option:
{ Lex->part_info->curr_part_elem->tablespace_name= $3.str; }
| opt_storage ENGINE_SYM opt_equal storage_engines
{
LEX *lex= Lex;
lex->part_info->curr_part_elem->engine_type= $4;
lex->part_info->default_engine_type= $4;
partition_info *part_info= Lex->part_info;
part_info->curr_part_elem->engine_type= $4;
part_info->default_engine_type= $4;
}
| NODEGROUP_SYM opt_equal real_ulong_num
{ Lex->part_info->curr_part_elem->nodegroup_id= (uint16) $3; }
@ -5975,7 +6032,7 @@ alter_commands:
LEX *lex= Lex;
lex->alter_info.flags|= ALTER_COALESCE_PARTITION;
lex->no_write_to_binlog= $3;
lex->alter_info.no_parts= $4;
lex->alter_info.num_parts= $4;
}
| TRUNCATE_SYM PARTITION_SYM all_or_alt_part_name_list
{
@ -6024,12 +6081,11 @@ add_part_extra:
| '(' part_def_list ')'
{
LEX *lex= Lex;
lex->part_info->no_parts= lex->part_info->partitions.elements;
lex->part_info->num_parts= lex->part_info->partitions.elements;
}
| PARTITIONS_SYM real_ulong_num
{
LEX *lex= Lex;
lex->part_info->no_parts= $2;
Lex->part_info->num_parts= $2;
}
;
@ -6059,8 +6115,8 @@ reorg_parts_rule:
}
INTO '(' part_def_list ')'
{
LEX *lex= Lex;
lex->part_info->no_parts= lex->part_info->partitions.elements;
partition_info *part_info= Lex->part_info;
part_info->num_parts= part_info->partitions.elements;
}
;
@ -11880,7 +11936,6 @@ keyword_sp:
| MAX_SIZE_SYM {}
| MAX_UPDATES_PER_HOUR {}
| MAX_USER_CONNECTIONS_SYM {}
| MAX_VALUE_SYM {}
| MEDIUM_SYM {}
| MEMORY_SYM {}
| MERGE_SYM {}