mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Fixed removal of column_list keyword for VALUES part, retained for PARTITION BY RANGE/LIST COLUMN_LIST, not entirely working yet
This commit is contained in:
parent
576dd76aa8
commit
c90669c4d4
11 changed files with 765 additions and 427 deletions
|
@ -2,24 +2,24 @@ drop table if exists t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=memory
|
engine=memory
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=myisam
|
engine=myisam
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=innodb
|
engine=innodb
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
|
@ -78,12 +78,12 @@ partition by range column_list(a,b)
|
||||||
ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
|
ERROR 42000: Inconsistency in usage of column lists for partitioning near '))' at line 3
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range(a)
|
partition by range(a)
|
||||||
(partition p0 values less than (column_list(1,"b")));
|
(partition p0 values less than (1,"b"));
|
||||||
ERROR HY000: Inconsistency in usage of column lists for partitioning
|
ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range(a)
|
partition by range(a)
|
||||||
(partition p0 values less than (column_list(1,"b")));
|
(partition p0 values less than (1,"b"));
|
||||||
ERROR HY000: Inconsistency in usage of column lists for partitioning
|
ERROR HY000: Cannot have more than one value for this type of RANGE partitioning
|
||||||
create table t1 (a int, b char(20));
|
create table t1 (a int, b char(20));
|
||||||
create global index inx on t1 (a,b)
|
create global index inx on t1 (a,b)
|
||||||
partition by range (a)
|
partition by range (a)
|
||||||
|
@ -91,7 +91,7 @@ partition by range (a)
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range column_list(b)
|
partition by range column_list(b)
|
||||||
(partition p0 values less than (column_list("b")));
|
(partition p0 values less than ("b"));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
create table t1 (a int)
|
create table t1 (a int)
|
||||||
partition by range (a)
|
partition by range (a)
|
||||||
|
|
|
@ -17,7 +17,7 @@ partition by key (a,a);
|
||||||
--error ER_SAME_NAME_PARTITION_FIELD
|
--error ER_SAME_NAME_PARTITION_FIELD
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by list column_list(a,a)
|
partition by list column_list(a,a)
|
||||||
( partition p values in (column_list(1,1)));
|
( partition p values in ((1,1)));
|
||||||
|
|
||||||
#
|
#
|
||||||
# BUG#47838, List partitioning have problems with <= and >=
|
# BUG#47838, List partitioning have problems with <= and >=
|
||||||
|
@ -35,10 +35,8 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (a int signed)
|
create table t1 (a int signed)
|
||||||
partition by list column_list(a)
|
partition by list column_list(a)
|
||||||
( partition p0 values in (column_list(1), column_list(3), column_list(5),
|
( partition p0 values in (1, 3, 5, 7, 9, NULL),
|
||||||
column_list(7), column_list(9), column_list(NULL)),
|
partition p1 values in (2, 4, 6, 8, 0));
|
||||||
partition p1 values in (column_list(2), column_list(4), column_list(6),
|
|
||||||
column_list(8), column_list(0)));
|
|
||||||
insert into t1 values (NULL),(0),(1),(2),(2),(4),(4),(4),(8),(8);
|
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 <= NULL;
|
||||||
select * from t1 where a is null;
|
select * from t1 where a is null;
|
||||||
|
@ -48,10 +46,9 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by list column_list(a,b)
|
partition by list column_list(a,b)
|
||||||
( partition p0 values in (column_list(1, NULL), column_list(2, NULL),
|
( partition p0 values in ((1, NULL), (2, NULL), (NULL, NULL)),
|
||||||
column_list(NULL, NULL)),
|
partition p1 values in ((1,1), (2,2)),
|
||||||
partition p1 values in (column_list(1,1), column_list(2,2)),
|
partition p2 values in ((3, NULL), (NULL, 1)));
|
||||||
partition p2 values in (column_list(3, NULL), column_list(NULL, 1)));
|
|
||||||
#
|
#
|
||||||
# BUG#47754 Crash when selecting using NOT BETWEEN for column list partitioning
|
# BUG#47754 Crash when selecting using NOT BETWEEN for column list partitioning
|
||||||
#
|
#
|
||||||
|
@ -88,10 +85,16 @@ insert into t1 values (NULL);
|
||||||
insert into t1 values (5);
|
insert into t1 values (5);
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
--error ER_PARSE_ERROR
|
||||||
create table t1 (a int)
|
create table t1 (a int)
|
||||||
partition by list column_list(a)
|
partition by list column_list(a)
|
||||||
( partition p0 values in (column_list(2), column_list(1)),
|
( partition p0 values in (2, 1),
|
||||||
partition p1 values in (column_list(4), column_list(NULL), column_list(3)));
|
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));
|
||||||
insert into t1 values (1);
|
insert into t1 values (1);
|
||||||
insert into t1 values (2);
|
insert into t1 values (2);
|
||||||
insert into t1 values (3);
|
insert into t1 values (3);
|
||||||
|
@ -106,20 +109,20 @@ create table t1 (a int, b char(10), c varchar(25), d datetime)
|
||||||
partition by range column_list(a,b,c,d)
|
partition by range column_list(a,b,c,d)
|
||||||
subpartition by hash (to_seconds(d))
|
subpartition by hash (to_seconds(d))
|
||||||
subpartitions 4
|
subpartitions 4
|
||||||
( partition p0 values less than (column_list(1, NULL, MAXVALUE, NULL)),
|
( partition p0 values less than (1, NULL, MAXVALUE, NULL),
|
||||||
partition p1 values less than (column_list(1, 'a', MAXVALUE, TO_DAYS('1999-01-01'))),
|
partition p1 values less than (1, 'a', MAXVALUE, TO_DAYS('1999-01-01')),
|
||||||
partition p2 values less than (column_list(1, 'a', MAXVALUE, MAXVALUE)),
|
partition p2 values less than (1, 'a', MAXVALUE, MAXVALUE),
|
||||||
partition p3 values less than (column_list(1, MAXVALUE, MAXVALUE, MAXVALUE)));
|
partition p3 values less than (1, MAXVALUE, MAXVALUE, MAXVALUE));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b char(10), c varchar(5), d int)
|
create table t1 (a int, b char(10), c varchar(5), d int)
|
||||||
partition by range column_list(a,b,c)
|
partition by range column_list(a,b,c)
|
||||||
subpartition by key (c,d)
|
subpartition by key (c,d)
|
||||||
subpartitions 3
|
subpartitions 3
|
||||||
( partition p0 values less than (column_list(1,'abc','abc')),
|
( partition p0 values less than (1,'abc','abc'),
|
||||||
partition p1 values less than (column_list(2,'abc','abc')),
|
partition p1 values less than (2,'abc','abc'),
|
||||||
partition p2 values less than (column_list(3,'abc','abc')),
|
partition p2 values less than (3,'abc','abc'),
|
||||||
partition p3 values less than (column_list(4,'abc','abc')));
|
partition p3 values less than (4,'abc','abc'));
|
||||||
|
|
||||||
insert into t1 values (1,'a','b',1),(2,'a','b',2),(3,'a','b',3);
|
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,'b','c',1),(2,'b','c',2),(3,'b','c',3);
|
||||||
|
@ -131,8 +134,8 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b varchar(2), c int)
|
create table t1 (a int, b varchar(2), c int)
|
||||||
partition by range column_list (a, b, c)
|
partition by range column_list (a, b, c)
|
||||||
(partition p0 values less than (column_list(1, 'A', 1)),
|
(partition p0 values less than (1, 'A', 1),
|
||||||
partition p1 values less than (column_list(1, 'B', 1)));
|
partition p1 values less than (1, 'B', 1));
|
||||||
insert into t1 values (1, 'A', 1);
|
insert into t1 values (1, 'A', 1);
|
||||||
explain partitions select * from t1 where a = 1 AND b <= 'A' and c = 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;
|
select * from t1 where a = 1 AND b <= 'A' and c = 1;
|
||||||
|
@ -140,7 +143,7 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (a char, b char, c char)
|
create table t1 (a char, b char, c char)
|
||||||
partition by list column_list(a)
|
partition by list column_list(a)
|
||||||
( partition p0 values in (column_list('a')));
|
( partition p0 values in ('a'));
|
||||||
insert into t1 (a) values ('a');
|
insert into t1 (a) values ('a');
|
||||||
select * from t1 where a = 'a';
|
select * from t1 where a = 'a';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -148,36 +151,36 @@ drop table t1;
|
||||||
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
|
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
|
||||||
create table t1 (d timestamp)
|
create table t1 (d timestamp)
|
||||||
partition by range column_list(d)
|
partition by range column_list(d)
|
||||||
( partition p0 values less than (column_list('2000-01-01')),
|
( partition p0 values less than ('2000-01-01'),
|
||||||
partition p1 values less than (column_list('2040-01-01')));
|
partition p1 values less than ('2040-01-01'));
|
||||||
|
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p0 values less than (column_list(null, 10)));
|
(partition p0 values less than (null, 10));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (d date)
|
create table t1 (d date)
|
||||||
partition by range column_list(d)
|
partition by range column_list(d)
|
||||||
( partition p0 values less than (column_list('2000-01-01')),
|
( partition p0 values less than ('2000-01-01'),
|
||||||
partition p1 values less than (column_list('2009-01-01')));
|
partition p1 values less than ('2009-01-01'));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (d date)
|
create table t1 (d date)
|
||||||
partition by range column_list(d)
|
partition by range column_list(d)
|
||||||
( partition p0 values less than (column_list('1999-01-01')),
|
( partition p0 values less than ('1999-01-01'),
|
||||||
partition p1 values less than (column_list('2000-01-01')));
|
partition p1 values less than ('2000-01-01'));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (d date)
|
create table t1 (d date)
|
||||||
partition by range column_list(d)
|
partition by range column_list(d)
|
||||||
( partition p0 values less than (column_list('2000-01-01')),
|
( partition p0 values less than ('2000-01-01'),
|
||||||
partition p1 values less than (column_list('3000-01-01')));
|
partition p1 values less than ('3000-01-01'));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p2 values less than (column_list(99,99)),
|
(partition p2 values less than (99,99),
|
||||||
partition p1 values less than (column_list(99,999)));
|
partition p1 values less than (99,999));
|
||||||
|
|
||||||
insert into t1 values (99,998);
|
insert into t1 values (99,998);
|
||||||
select * from t1 where b = 998;
|
select * from t1 where b = 998;
|
||||||
|
@ -191,22 +194,22 @@ drop table t1;
|
||||||
--error ER_PARSE_ERROR
|
--error ER_PARSE_ERROR
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by list column_list(a,b)
|
partition by list column_list(a,b)
|
||||||
(partition p0 values in (column_list(maxvalue,maxvalue)));
|
(partition p0 values in ((maxvalue,maxvalue)));
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p0 values less than (column_list(maxvalue,maxvalue)));
|
(partition p0 values less than (maxvalue,maxvalue));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a int)
|
create table t1 (a int)
|
||||||
partition by list column_list(a)
|
partition by list column_list(a)
|
||||||
(partition p0 values in (column_list(0)));
|
(partition p0 values in (0));
|
||||||
select partition_method from information_schema.partitions where table_name='t1';
|
select partition_method from information_schema.partitions where table_name='t1';
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a char(6))
|
create table t1 (a char(6))
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
(partition p0 values less than (column_list('H23456')),
|
(partition p0 values less than ('H23456'),
|
||||||
partition p1 values less than (column_list('M23456')));
|
partition p1 values less than ('M23456'));
|
||||||
insert into t1 values ('F23456');
|
insert into t1 values ('F23456');
|
||||||
select * from t1;
|
select * from t1;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -214,14 +217,14 @@ drop table t1;
|
||||||
-- error 1054
|
-- error 1054
|
||||||
create table t1 (a char(6))
|
create table t1 (a char(6))
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
(partition p0 values less than (column_list(H23456)),
|
(partition p0 values less than (H23456),
|
||||||
partition p1 values less than (column_list(M23456)));
|
partition p1 values less than (M23456));
|
||||||
|
|
||||||
-- error ER_RANGE_NOT_INCREASING_ERROR
|
-- error ER_RANGE_NOT_INCREASING_ERROR
|
||||||
create table t1 (a char(6))
|
create table t1 (a char(6))
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
(partition p0 values less than (column_list(23456)),
|
(partition p0 values less than (23456),
|
||||||
partition p1 values less than (column_list(23456)));
|
partition p1 values less than (23456));
|
||||||
|
|
||||||
-- error 1064
|
-- error 1064
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
|
@ -231,14 +234,14 @@ partition by range column_list(a,b)
|
||||||
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p0 values less than (column_list(1,1,1));
|
(partition p0 values less than (1,1,1);
|
||||||
|
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p0 values less than (column_list(1, NULL)),
|
(partition p0 values less than (1, NULL),
|
||||||
partition p1 values less than (column_list(2, maxvalue)),
|
partition p1 values less than (2, maxvalue),
|
||||||
partition p2 values less than (column_list(3, 3)),
|
partition p2 values less than (3, 3),
|
||||||
partition p3 values less than (column_list(10, NULL)));
|
partition p3 values less than (10, NULL));
|
||||||
|
|
||||||
-- error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
-- error ER_NO_PARTITION_FOR_GIVEN_VALUE
|
||||||
insert into t1 values (10,0);
|
insert into t1 values (10,0);
|
||||||
|
@ -247,57 +250,51 @@ select * from t1;
|
||||||
|
|
||||||
alter table t1
|
alter table t1
|
||||||
partition by range column_list(b,a)
|
partition by range column_list(b,a)
|
||||||
(partition p0 values less than (column_list(1,2)),
|
(partition p0 values less than (1,2),
|
||||||
partition p1 values less than (column_list(3,3)),
|
partition p1 values less than (3,3),
|
||||||
partition p2 values less than (column_list(9,5)));
|
partition p2 values less than (9,5));
|
||||||
explain partitions select * from t1 where b < 2;
|
explain partitions select * from t1 where b < 2;
|
||||||
select * from t1 where b < 2;
|
select * from t1 where b < 2;
|
||||||
explain partitions select * from t1 where b < 4;
|
explain partitions select * from t1 where b < 4;
|
||||||
select * from t1 where b < 4;
|
select * from t1 where b < 4;
|
||||||
|
|
||||||
alter table t1 reorganize partition p1 into
|
alter table t1 reorganize partition p1 into
|
||||||
(partition p11 values less than (column_list(2,2)),
|
(partition p11 values less than (2,2),
|
||||||
partition p12 values less than (column_list(3,3)));
|
partition p12 values less than (3,3));
|
||||||
|
|
||||||
-- error ER_REORG_OUTSIDE_RANGE
|
-- error ER_REORG_OUTSIDE_RANGE
|
||||||
alter table t1 reorganize partition p0 into
|
alter table t1 reorganize partition p0 into
|
||||||
(partition p01 values less than (column_list(0,3)),
|
(partition p01 values less than (0,3),
|
||||||
partition p02 values less than (column_list(1,1)));
|
partition p02 values less than (1,1));
|
||||||
|
|
||||||
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
||||||
alter table t1 reorganize partition p2 into
|
alter table t1 reorganize partition p2 into
|
||||||
(partition p2 values less than(column_list(9,6,1)));
|
(partition p2 values less than(9,6,1));
|
||||||
|
|
||||||
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
-- error ER_PARTITION_COLUMN_LIST_ERROR
|
||||||
alter table t1 reorganize partition p2 into
|
alter table t1 reorganize partition p2 into
|
||||||
(partition p2 values less than (10));
|
(partition p2 values less than (10));
|
||||||
|
|
||||||
alter table t1 reorganize partition p2 into
|
alter table t1 reorganize partition p2 into
|
||||||
(partition p21 values less than (column_list(4,7)),
|
(partition p21 values less than (4,7),
|
||||||
partition p22 values less than (column_list(9,5)));
|
partition p22 values less than (9,5));
|
||||||
explain partitions select * from t1 where b < 4;
|
explain partitions select * from t1 where b < 4;
|
||||||
select * from t1 where b < 4;
|
select * from t1 where b < 4;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
#create table t1 (a int, b int)
|
|
||||||
#partition by range column_list(a,b)
|
|
||||||
#(partition p0 values less than (column_list(99,99)),
|
|
||||||
# partition p1 values less than (column_list(99,maxvalue)));
|
|
||||||
#drop table t1;
|
|
||||||
|
|
||||||
create table t1 (a int, b int)
|
create table t1 (a int, b int)
|
||||||
partition by list column_list(a,b)
|
partition by list column_list(a,b)
|
||||||
subpartition by hash (b)
|
subpartition by hash (b)
|
||||||
subpartitions 2
|
subpartitions 2
|
||||||
(partition p0 values in (column_list(0,0), column_list(1,1)),
|
(partition p0 values in ((0,0), (1,1)),
|
||||||
partition p1 values in (column_list(1000,1000)));
|
partition p1 values in ((1000,1000)));
|
||||||
insert into t1 values (1000,1000);
|
insert into t1 values (1000,1000);
|
||||||
#select * from t1 where a = 0 and b = 0;
|
#select * from t1 where a = 0 and b = 0;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
create table t1 (a char, b char, c char)
|
create table t1 (a char, b char, c char)
|
||||||
partition by range column_list(a,b,c)
|
partition by range column_list(a,b,c)
|
||||||
( partition p0 values less than (column_list('a','b','c')));
|
( partition p0 values less than ('a','b','c'));
|
||||||
alter table t1 add partition
|
alter table t1 add partition
|
||||||
(partition p1 values less than (column_list('b','c','d')));
|
(partition p1 values less than ('b','c','d'));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
|
@ -11,8 +11,8 @@ drop table if exists t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=memory
|
engine=memory
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -20,8 +20,8 @@ drop table t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=myisam
|
engine=myisam
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
@ -29,8 +29,8 @@ drop table t1;
|
||||||
create table t1 (a varchar(5))
|
create table t1 (a varchar(5))
|
||||||
engine=innodb
|
engine=innodb
|
||||||
partition by range column_list(a)
|
partition by range column_list(a)
|
||||||
( partition p0 values less than (column_list('m')),
|
( partition p0 values less than ('m'),
|
||||||
partition p1 values less than (column_list('za')));
|
partition p1 values less than ('za'));
|
||||||
insert into t1 values ('j');
|
insert into t1 values ('j');
|
||||||
update t1 set a = 'z' where (a >= 'j');
|
update t1 set a = 'z' where (a >= 'j');
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
|
@ -64,15 +64,15 @@ create table t1 (a int, b char(20))
|
||||||
partition by range column_list(a,b)
|
partition by range column_list(a,b)
|
||||||
(partition p0 values less than (1));
|
(partition p0 values less than (1));
|
||||||
|
|
||||||
--error ER_PARTITION_COLUMN_LIST_ERROR
|
--error ER_TOO_MANY_VALUES_ERROR
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range(a)
|
partition by range(a)
|
||||||
(partition p0 values less than (column_list(1,"b")));
|
(partition p0 values less than (1,"b"));
|
||||||
|
|
||||||
--error ER_PARTITION_COLUMN_LIST_ERROR
|
--error ER_TOO_MANY_VALUES_ERROR
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range(a)
|
partition by range(a)
|
||||||
(partition p0 values less than (column_list(1,"b")));
|
(partition p0 values less than (1,"b"));
|
||||||
|
|
||||||
create table t1 (a int, b char(20));
|
create table t1 (a int, b char(20));
|
||||||
create global index inx on t1 (a,b)
|
create global index inx on t1 (a,b)
|
||||||
|
@ -82,7 +82,7 @@ drop table t1;
|
||||||
|
|
||||||
create table t1 (a int, b char(20))
|
create table t1 (a int, b char(20))
|
||||||
partition by range column_list(b)
|
partition by range column_list(b)
|
||||||
(partition p0 values less than (column_list("b")));
|
(partition p0 values less than ("b"));
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -74,6 +74,7 @@ typedef struct p_column_list_val
|
||||||
typedef struct p_elem_val
|
typedef struct p_elem_val
|
||||||
{
|
{
|
||||||
longlong value;
|
longlong value;
|
||||||
|
uint added_items;
|
||||||
bool null_value;
|
bool null_value;
|
||||||
bool unsigned_flag;
|
bool unsigned_flag;
|
||||||
part_column_list_val *col_val_array;
|
part_column_list_val *col_val_array;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/* Copyright (C) 2006 MySQL AB
|
/* Copyrght (C) 2006 MySQL AB
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
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
|
it under the terms of the GNU General Public License as published by
|
||||||
|
@ -682,7 +682,7 @@ bool partition_info::check_range_constants(THD *thd)
|
||||||
part_elem_value *range_val= list_val_it++;
|
part_elem_value *range_val= list_val_it++;
|
||||||
part_column_list_val *col_val= range_val->col_val_array;
|
part_column_list_val *col_val= range_val->col_val_array;
|
||||||
|
|
||||||
if (fix_column_value_functions(thd, col_val, i))
|
if (fix_column_value_functions(thd, range_val, i))
|
||||||
goto end;
|
goto end;
|
||||||
memcpy(loc_range_col_array, (const void*)col_val, size_entries);
|
memcpy(loc_range_col_array, (const void*)col_val, size_entries);
|
||||||
loc_range_col_array+= num_column_values;
|
loc_range_col_array+= num_column_values;
|
||||||
|
@ -826,85 +826,6 @@ int partition_info::compare_column_values(const void *first_arg,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
Evaluate VALUES functions for column list values
|
|
||||||
SYNOPSIS
|
|
||||||
fix_column_value_functions()
|
|
||||||
thd Thread object
|
|
||||||
col_val List of column values
|
|
||||||
part_id Partition id we are fixing
|
|
||||||
RETURN VALUES
|
|
||||||
TRUE Error
|
|
||||||
FALSE Success
|
|
||||||
DESCRIPTION
|
|
||||||
Fix column VALUES and store in memory array adapted to the data type
|
|
||||||
*/
|
|
||||||
|
|
||||||
bool partition_info::fix_column_value_functions(THD *thd,
|
|
||||||
part_column_list_val *col_val,
|
|
||||||
uint part_id)
|
|
||||||
{
|
|
||||||
uint num_columns= part_field_list.elements;
|
|
||||||
Name_resolution_context *context= &thd->lex->current_select->context;
|
|
||||||
TABLE_LIST *save_list= context->table_list;
|
|
||||||
bool result= FALSE;
|
|
||||||
uint i;
|
|
||||||
const char *save_where= thd->where;
|
|
||||||
DBUG_ENTER("partition_info::fix_column_value_functions");
|
|
||||||
if (col_val->fixed > 1)
|
|
||||||
{
|
|
||||||
DBUG_RETURN(FALSE);
|
|
||||||
}
|
|
||||||
context->table_list= 0;
|
|
||||||
thd->where= "partition function";
|
|
||||||
for (i= 0; i < num_columns; col_val++, i++)
|
|
||||||
{
|
|
||||||
Item *column_item= col_val->item_expression;
|
|
||||||
Field *field= part_field_array[i];
|
|
||||||
col_val->part_info= this;
|
|
||||||
col_val->partition_id= part_id;
|
|
||||||
if (col_val->max_value)
|
|
||||||
col_val->column_value= NULL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!col_val->fixed &&
|
|
||||||
(column_item->fix_fields(thd, (Item**)0) ||
|
|
||||||
(!column_item->const_item())))
|
|
||||||
{
|
|
||||||
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
|
|
||||||
result= TRUE;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
col_val->null_value= column_item->null_value;
|
|
||||||
col_val->column_value= NULL;
|
|
||||||
if (!col_val->null_value)
|
|
||||||
{
|
|
||||||
uchar *val_ptr;
|
|
||||||
uint len= field->pack_length();
|
|
||||||
if (column_item->save_in_field(field, TRUE))
|
|
||||||
{
|
|
||||||
my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
|
|
||||||
result= TRUE;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
if (!(val_ptr= (uchar*) sql_calloc(len)))
|
|
||||||
{
|
|
||||||
mem_alloc_error(len);
|
|
||||||
result= TRUE;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
col_val->column_value= val_ptr;
|
|
||||||
memcpy(val_ptr, field->ptr, len);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
col_val->fixed= 2;
|
|
||||||
}
|
|
||||||
end:
|
|
||||||
thd->where= save_where;
|
|
||||||
context->table_list= save_list;
|
|
||||||
DBUG_RETURN(result);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This routine allocates an array for all list constants to achieve a fast
|
This routine allocates an array for all list constants to achieve a fast
|
||||||
check what partition a certain value belongs to. At the same time it does
|
check what partition a certain value belongs to. At the same time it does
|
||||||
|
@ -1002,7 +923,7 @@ bool partition_info::check_list_constants(THD *thd)
|
||||||
while ((list_value= list_val_it2++))
|
while ((list_value= list_val_it2++))
|
||||||
{
|
{
|
||||||
part_column_list_val *col_val= list_value->col_val_array;
|
part_column_list_val *col_val= list_value->col_val_array;
|
||||||
if (unlikely(fix_column_value_functions(thd, col_val, i)))
|
if (unlikely(fix_column_value_functions(thd, list_value, i)))
|
||||||
{
|
{
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
@ -1126,6 +1047,8 @@ bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
|
||||||
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
|
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
if (fix_parser_data(thd))
|
||||||
|
goto end;
|
||||||
}
|
}
|
||||||
if (unlikely(!is_sub_partitioned() &&
|
if (unlikely(!is_sub_partitioned() &&
|
||||||
!(use_default_subpartitions && use_default_num_subpartitions)))
|
!(use_default_subpartitions && use_default_num_subpartitions)))
|
||||||
|
@ -1377,31 +1300,6 @@ void partition_info::print_no_partition_found(TABLE *table)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a new column value in current list
|
|
||||||
SYNOPSIS
|
|
||||||
add_column_value()
|
|
||||||
RETURN
|
|
||||||
>0 A part_column_list_val object which have been
|
|
||||||
inserted into its list
|
|
||||||
0 Memory allocation failure
|
|
||||||
*/
|
|
||||||
|
|
||||||
part_column_list_val *partition_info::add_column_value()
|
|
||||||
{
|
|
||||||
uint max_val= num_columns ? num_columns : MAX_REF_PARTS;
|
|
||||||
DBUG_ENTER("add_column_value");
|
|
||||||
DBUG_PRINT("enter", ("num_columns = %u, curr_list_object %u, max_val = %u",
|
|
||||||
num_columns, curr_list_object, max_val));
|
|
||||||
if (curr_list_object < max_val)
|
|
||||||
{
|
|
||||||
DBUG_RETURN(&curr_list_val->col_val_array[curr_list_object++]);
|
|
||||||
}
|
|
||||||
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
|
||||||
DBUG_RETURN(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set fields related to partition expression
|
Set fields related to partition expression
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
|
@ -1616,4 +1514,507 @@ id_err:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a new column value in current list with maxvalue
|
||||||
|
Called from parser
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
add_max_value()
|
||||||
|
RETURN
|
||||||
|
TRUE Error
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
int partition_info::add_max_value()
|
||||||
|
{
|
||||||
|
DBUG_ENTER("partition_info::add_max_value");
|
||||||
|
|
||||||
|
part_column_list_val *col_val;
|
||||||
|
if (!(col_val= add_column_value()))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
col_val->max_value= TRUE;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Create a new column value in current list
|
||||||
|
Called from parser
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
add_column_value()
|
||||||
|
RETURN
|
||||||
|
>0 A part_column_list_val object which have been
|
||||||
|
inserted into its list
|
||||||
|
0 Memory allocation failure
|
||||||
|
*/
|
||||||
|
|
||||||
|
part_column_list_val *partition_info::add_column_value()
|
||||||
|
{
|
||||||
|
uint max_val= num_columns ? num_columns : MAX_REF_PARTS;
|
||||||
|
DBUG_ENTER("add_column_value");
|
||||||
|
DBUG_PRINT("enter", ("num_columns = %u, curr_list_object %u, max_val = %u",
|
||||||
|
num_columns, curr_list_object, max_val));
|
||||||
|
if (curr_list_object < max_val)
|
||||||
|
{
|
||||||
|
curr_list_val->added_items++;
|
||||||
|
DBUG_RETURN(&curr_list_val->col_val_array[curr_list_object++]);
|
||||||
|
}
|
||||||
|
if (!num_columns && part_type == LIST_PARTITION)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
We're trying to add more than MAX_REF_PARTS, this can happen
|
||||||
|
in ALTER TABLE using List partitions where the first partition
|
||||||
|
uses VALUES IN (1,2,3...,17) where the number of fields in
|
||||||
|
the list is more than MAX_REF_PARTS, in this case we know
|
||||||
|
that the number of columns must be 1 and we thus reorganize
|
||||||
|
into the structure used for 1 column. After this we call
|
||||||
|
ourselves recursively which should always succeed.
|
||||||
|
*/
|
||||||
|
if (!reorganize_into_single_field_col_val())
|
||||||
|
{
|
||||||
|
DBUG_RETURN(add_column_value());
|
||||||
|
}
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
}
|
||||||
|
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add a column value in VALUES LESS THAN or VALUES IN
|
||||||
|
(Called from parser)
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
add_column_list_value()
|
||||||
|
lex Parser's lex object
|
||||||
|
item Item object representing column value
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
bool partition_info::add_column_list_value(Item *item)
|
||||||
|
{
|
||||||
|
part_column_list_val *col_val;
|
||||||
|
DBUG_ENTER("partition_info::add_column_list_value");
|
||||||
|
|
||||||
|
if (part_type == LIST_PARTITION &&
|
||||||
|
num_columns == 1U)
|
||||||
|
{
|
||||||
|
if (init_column_part())
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!(col_val= add_column_value()))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
col_val->item_expression= item;
|
||||||
|
col_val->part_info= NULL;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Initialise part_info object for receiving a set of column values
|
||||||
|
for a partition, called when parser reaches VALUES LESS THAN or
|
||||||
|
VALUES IN.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
init_column_part()
|
||||||
|
lex Parser's lex object
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
bool partition_info::init_column_part()
|
||||||
|
{
|
||||||
|
partition_element *p_elem= curr_part_elem;
|
||||||
|
part_column_list_val *col_val_array;
|
||||||
|
part_elem_value *list_val;
|
||||||
|
uint loc_num_columns;
|
||||||
|
DBUG_ENTER("partition_info::init_column_part");
|
||||||
|
|
||||||
|
if (!(list_val=
|
||||||
|
(part_elem_value*)sql_calloc(sizeof(part_elem_value))) ||
|
||||||
|
p_elem->list_val_list.push_back(list_val))
|
||||||
|
{
|
||||||
|
mem_alloc_error(sizeof(part_elem_value));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (num_columns)
|
||||||
|
loc_num_columns= num_columns;
|
||||||
|
else
|
||||||
|
loc_num_columns= MAX_REF_PARTS;
|
||||||
|
if (!(col_val_array=
|
||||||
|
(part_column_list_val*)sql_calloc(loc_num_columns *
|
||||||
|
sizeof(part_column_list_val))))
|
||||||
|
{
|
||||||
|
mem_alloc_error(loc_num_columns * sizeof(part_elem_value));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
list_val->col_val_array= col_val_array;
|
||||||
|
list_val->added_items= 0;
|
||||||
|
curr_list_val= list_val;
|
||||||
|
curr_list_object= 0;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
In the case of ALTER TABLE ADD/REORGANIZE PARTITION for LIST
|
||||||
|
partitions we can specify list values as:
|
||||||
|
VALUES IN (v1, v2,,,, v17) if we're using the first partitioning
|
||||||
|
variant with a function or a column list partitioned table with
|
||||||
|
one partition field. In this case the parser knows not the
|
||||||
|
number of columns start with and allocates MAX_REF_PARTS in the
|
||||||
|
array. If we try to allocate something beyond MAX_REF_PARTS we
|
||||||
|
will call this function to reorganize into a structure with
|
||||||
|
num_columns = 1. Also when the parser knows that we used LIST
|
||||||
|
partitioning and we used a VALUES IN like above where number of
|
||||||
|
values was smaller than MAX_REF_PARTS or equal, then we will
|
||||||
|
reorganize after discovering this in the parser.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
reorganize_into_single_field_col_val()
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
int partition_info::reorganize_into_single_field_col_val()
|
||||||
|
{
|
||||||
|
part_column_list_val *col_val;
|
||||||
|
Item *part_expr;
|
||||||
|
uint loc_num_columns= num_columns;
|
||||||
|
uint i;
|
||||||
|
DBUG_ENTER("partition_info::reorganize_into_single_field_col_val");
|
||||||
|
|
||||||
|
num_columns= 1;
|
||||||
|
curr_list_val->added_items= 1U;
|
||||||
|
for (i= 1; i < loc_num_columns; i++)
|
||||||
|
{
|
||||||
|
col_val= &curr_list_val->col_val_array[i];
|
||||||
|
part_expr= col_val->item_expression;
|
||||||
|
if ((part_type != LIST_PARTITION &&
|
||||||
|
init_column_part()) ||
|
||||||
|
add_column_list_value(part_expr))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
This function handles the case of function-based partitioning.
|
||||||
|
It fixes some data structures created in the parser and puts
|
||||||
|
them in the format required by the rest of the partitioning
|
||||||
|
code.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
fix_func_partition()
|
||||||
|
thd Thread object
|
||||||
|
col_val Array of one value
|
||||||
|
part_elem The partition instance
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
int partition_info::fix_func_partition(THD *thd,
|
||||||
|
part_elem_value *val,
|
||||||
|
partition_element *part_elem)
|
||||||
|
{
|
||||||
|
uint i;
|
||||||
|
part_column_list_val *col_val= val->col_val_array;
|
||||||
|
DBUG_ENTER("partition_info::fix_func_partition");
|
||||||
|
|
||||||
|
if (col_val->fixed)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
if (val->added_items != 1)
|
||||||
|
{
|
||||||
|
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (col_val->max_value)
|
||||||
|
{
|
||||||
|
/* The parser ensures we're not LIST partitioned here */
|
||||||
|
DBUG_ASSERT(part_type == RANGE_PARTITION);
|
||||||
|
if (defined_max_value)
|
||||||
|
{
|
||||||
|
my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (i == (num_parts - 1))
|
||||||
|
{
|
||||||
|
defined_max_value= TRUE;
|
||||||
|
part_elem->max_value= TRUE;
|
||||||
|
part_elem->range_value= LONGLONG_MAX;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_error(ER_PARTITION_MAXVALUE_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
part_elem_value *value_ptr;
|
||||||
|
Name_resolution_context *context= &thd->lex->current_select->context;
|
||||||
|
TABLE_LIST *save_list= context->table_list;
|
||||||
|
const char *save_where= thd->where;
|
||||||
|
Item *item_expr= col_val->item_expression;
|
||||||
|
|
||||||
|
context->table_list= 0;
|
||||||
|
thd->where= "partition function";
|
||||||
|
|
||||||
|
value_ptr= (part_elem_value*)sql_alloc(sizeof(part_elem_value));
|
||||||
|
if (!value_ptr)
|
||||||
|
{
|
||||||
|
mem_alloc_error(sizeof(part_elem_value));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (item_expr->walk(&Item::check_partition_func_processor, 0,
|
||||||
|
NULL))
|
||||||
|
{
|
||||||
|
my_error(ER_PARTITION_FUNCTION_IS_NOT_ALLOWED, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (item_expr->fix_fields(thd, (Item**)0) ||
|
||||||
|
((context->table_list= save_list), FALSE) ||
|
||||||
|
(!item_expr->const_item()))
|
||||||
|
{
|
||||||
|
context->table_list= save_list;
|
||||||
|
thd->where= save_where;
|
||||||
|
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
thd->where= save_where;
|
||||||
|
value_ptr->value= part_expr->val_int();
|
||||||
|
value_ptr->unsigned_flag= TRUE;
|
||||||
|
if (!item_expr->unsigned_flag &&
|
||||||
|
value_ptr->value < 0)
|
||||||
|
value_ptr->unsigned_flag= FALSE;
|
||||||
|
if ((value_ptr->null_value= item_expr->null_value))
|
||||||
|
{
|
||||||
|
if (part_elem->has_null_value)
|
||||||
|
{
|
||||||
|
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
part_elem->has_null_value= TRUE;
|
||||||
|
}
|
||||||
|
else if (item_expr->result_type() != INT_RESULT)
|
||||||
|
{
|
||||||
|
my_error(ER_INCONSISTENT_TYPE_OF_FUNCTIONS_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
if (!value_ptr->unsigned_flag)
|
||||||
|
part_elem->signed_flag= TRUE;
|
||||||
|
if (part_type == RANGE_PARTITION)
|
||||||
|
{
|
||||||
|
if (part_elem->has_null_value)
|
||||||
|
{
|
||||||
|
my_error(ER_NULL_IN_VALUES_LESS_THAN, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
part_elem->range_value= value_ptr->value;
|
||||||
|
}
|
||||||
|
else if (part_type == LIST_PARTITION)
|
||||||
|
{
|
||||||
|
if (!value_ptr->null_value &&
|
||||||
|
part_elem->list_val_list.push_back(value_ptr))
|
||||||
|
{
|
||||||
|
mem_alloc_error(sizeof(part_elem_value));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
col_val->fixed= 2;
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Evaluate VALUES functions for column list values
|
||||||
|
SYNOPSIS
|
||||||
|
fix_column_value_functions()
|
||||||
|
thd Thread object
|
||||||
|
col_val List of column values
|
||||||
|
part_id Partition id we are fixing
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Error
|
||||||
|
FALSE Success
|
||||||
|
DESCRIPTION
|
||||||
|
Fix column VALUES and store in memory array adapted to the data type
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool partition_info::fix_column_value_functions(THD *thd,
|
||||||
|
part_elem_value *val,
|
||||||
|
uint part_id)
|
||||||
|
{
|
||||||
|
uint num_columns= part_field_list.elements;
|
||||||
|
Name_resolution_context *context= &thd->lex->current_select->context;
|
||||||
|
TABLE_LIST *save_list= context->table_list;
|
||||||
|
bool result= FALSE;
|
||||||
|
uint i;
|
||||||
|
const char *save_where= thd->where;
|
||||||
|
part_column_list_val *col_val= val->col_val_array;
|
||||||
|
DBUG_ENTER("partition_info::fix_column_value_functions");
|
||||||
|
|
||||||
|
if (col_val->fixed > 1)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
if (val->added_items != num_columns)
|
||||||
|
{
|
||||||
|
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
context->table_list= 0;
|
||||||
|
thd->where= "partition function";
|
||||||
|
for (i= 0; i < num_columns; col_val++, i++)
|
||||||
|
{
|
||||||
|
Item *column_item= col_val->item_expression;
|
||||||
|
Field *field= part_field_array[i];
|
||||||
|
col_val->part_info= this;
|
||||||
|
col_val->partition_id= part_id;
|
||||||
|
if (col_val->max_value)
|
||||||
|
col_val->column_value= NULL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!col_val->fixed &&
|
||||||
|
(column_item->fix_fields(thd, (Item**)0) ||
|
||||||
|
(!column_item->const_item())))
|
||||||
|
{
|
||||||
|
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
|
||||||
|
result= TRUE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
col_val->null_value= column_item->null_value;
|
||||||
|
col_val->column_value= NULL;
|
||||||
|
if (!col_val->null_value)
|
||||||
|
{
|
||||||
|
uchar *val_ptr;
|
||||||
|
uint len= field->pack_length();
|
||||||
|
if (column_item->save_in_field(field, TRUE))
|
||||||
|
{
|
||||||
|
my_error(ER_WRONG_TYPE_COLUMN_VALUE_ERROR, MYF(0));
|
||||||
|
result= TRUE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (!(val_ptr= (uchar*) sql_calloc(len)))
|
||||||
|
{
|
||||||
|
mem_alloc_error(len);
|
||||||
|
result= TRUE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
col_val->column_value= val_ptr;
|
||||||
|
memcpy(val_ptr, field->ptr, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
col_val->fixed= 2;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
thd->where= save_where;
|
||||||
|
context->table_list= save_list;
|
||||||
|
DBUG_RETURN(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
The parser generates generic data structures, we need to set them up
|
||||||
|
as the rest of the code expects to find them. This is in reality part
|
||||||
|
of the syntax check of the parser code.
|
||||||
|
|
||||||
|
It is necessary to call this function in the case of a CREATE TABLE
|
||||||
|
statement, in this case we do it early in the check_partition_info
|
||||||
|
function.
|
||||||
|
|
||||||
|
It is necessary to call this function for ALTER TABLE where we
|
||||||
|
assign a completely new partition structure, in this case we do it
|
||||||
|
in prep_alter_part_table after discovering that the partition
|
||||||
|
structure is entirely redefined.
|
||||||
|
|
||||||
|
It's necessary to call this method also for ALTER TABLE ADD/REORGANIZE
|
||||||
|
of partitions, in this we call it in prep_alter_part_table after
|
||||||
|
making some initial checks but before going deep to check the partition
|
||||||
|
info, we also assign the column_list variable before calling this function
|
||||||
|
here.
|
||||||
|
|
||||||
|
Finally we also call it immediately after returning from parsing the
|
||||||
|
partitioning text found in the frm file.
|
||||||
|
|
||||||
|
This function mainly fixes the VALUES parts, these are handled differently
|
||||||
|
whether or not we use column list partitioning. Since the parser doesn't
|
||||||
|
know which we are using we need to set-up the old data structures after
|
||||||
|
the parser is complete when we know if what type of partitioning the
|
||||||
|
base table is using.
|
||||||
|
|
||||||
|
For column lists we will handle this in the fix_column_value_function.
|
||||||
|
For column lists it is sufficient to verify that the number of columns
|
||||||
|
and number of elements are in synch with each other. So only partitioning
|
||||||
|
using functions need to be set-up to their data structures.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
fix_parser_data()
|
||||||
|
thd Thread object
|
||||||
|
|
||||||
|
RETURN VALUES
|
||||||
|
TRUE Failure
|
||||||
|
FALSE Success
|
||||||
|
*/
|
||||||
|
|
||||||
|
int partition_info::fix_parser_data(THD *thd)
|
||||||
|
{
|
||||||
|
List_iterator<partition_element> it(partitions);
|
||||||
|
partition_element *part_elem;
|
||||||
|
part_elem_value *val;
|
||||||
|
uint num_elements;
|
||||||
|
uint i= 0, j;
|
||||||
|
int result;
|
||||||
|
DBUG_ENTER("partition_info::fix_parser_data");
|
||||||
|
|
||||||
|
if (!(part_type == RANGE_PARTITION ||
|
||||||
|
part_type == LIST_PARTITION))
|
||||||
|
{
|
||||||
|
/* Nothing to do for HASH/KEY partitioning */
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
|
}
|
||||||
|
do
|
||||||
|
{
|
||||||
|
part_elem= it++;
|
||||||
|
j= 0;
|
||||||
|
num_elements= part_elem->list_val_list.elements;
|
||||||
|
DBUG_ASSERT(part_type == RANGE_PARTITION ?
|
||||||
|
num_elements == 1U : TRUE);
|
||||||
|
{
|
||||||
|
List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
|
||||||
|
part_elem_value *val= list_val_it++;
|
||||||
|
result= column_list ?
|
||||||
|
fix_column_value_functions(thd, val, i) :
|
||||||
|
fix_func_partition(thd, val, part_elem);
|
||||||
|
if (result)
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
|
} while (++j < num_elements);
|
||||||
|
} while (++i < num_parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
void partition_info::print_debug(const char *str, uint *value)
|
||||||
|
{
|
||||||
|
DBUG_ENTER("print_debug");
|
||||||
|
if (value)
|
||||||
|
DBUG_PRINT("info", ("parser: %s, val = %u", str, *value));
|
||||||
|
else
|
||||||
|
DBUG_PRINT("info", ("parser: %s", str));
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
#endif /* WITH_PARTITION_STORAGE_ENGINE */
|
||||||
|
|
|
@ -280,11 +280,23 @@ public:
|
||||||
handler *file, HA_CREATE_INFO *info,
|
handler *file, HA_CREATE_INFO *info,
|
||||||
bool check_partition_function);
|
bool check_partition_function);
|
||||||
void print_no_partition_found(TABLE *table);
|
void print_no_partition_found(TABLE *table);
|
||||||
|
void print_debug(const char *str, uint*);
|
||||||
|
int fix_func_partition(THD *thd,
|
||||||
|
part_elem_value *val,
|
||||||
|
partition_element *part_elem);
|
||||||
|
bool fix_column_value_functions(THD *thd,
|
||||||
|
part_elem_value *val,
|
||||||
|
uint part_id);
|
||||||
|
int fix_parser_data(THD *thd);
|
||||||
|
int add_max_value();
|
||||||
|
int reorganize_into_single_field_col_val();
|
||||||
part_column_list_val *add_column_value();
|
part_column_list_val *add_column_value();
|
||||||
bool set_part_expr(char *start_token, Item *item_ptr,
|
bool set_part_expr(char *start_token, Item *item_ptr,
|
||||||
char *end_token, bool is_subpart);
|
char *end_token, bool is_subpart);
|
||||||
static int compare_column_values(const void *a, const void *b);
|
static int compare_column_values(const void *a, const void *b);
|
||||||
bool set_up_charset_field_preps();
|
bool set_up_charset_field_preps();
|
||||||
|
bool init_column_part();
|
||||||
|
bool add_column_list_value(Item *item);
|
||||||
private:
|
private:
|
||||||
static int list_part_cmp(const void* a, const void* b);
|
static int list_part_cmp(const void* a, const void* b);
|
||||||
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
|
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
|
||||||
|
@ -294,9 +306,6 @@ private:
|
||||||
uint start_no);
|
uint start_no);
|
||||||
char *create_subpartition_name(uint subpart_no, const char *part_name);
|
char *create_subpartition_name(uint subpart_no, const char *part_name);
|
||||||
bool has_unique_name(partition_element *element);
|
bool has_unique_name(partition_element *element);
|
||||||
bool fix_column_value_functions(THD *thd,
|
|
||||||
part_column_list_val *col_val,
|
|
||||||
uint part_id);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
|
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
|
||||||
|
|
|
@ -5822,8 +5822,6 @@ ER_SAME_NAME_PARTITION
|
||||||
eng "Duplicate partition name %-.192s"
|
eng "Duplicate partition name %-.192s"
|
||||||
ger "Doppelter Partitionsname: %-.192s"
|
ger "Doppelter Partitionsname: %-.192s"
|
||||||
swe "Duplicerat partitionsnamn %-.192s"
|
swe "Duplicerat partitionsnamn %-.192s"
|
||||||
ER_SAME_NAME_PARTITION_FIELD
|
|
||||||
eng "Duplicate partition field name %-.192s"
|
|
||||||
ER_NO_BINLOG_ERROR
|
ER_NO_BINLOG_ERROR
|
||||||
eng "It is not allowed to shut off binlog on this command"
|
eng "It is not allowed to shut off binlog on this command"
|
||||||
ger "Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten"
|
ger "Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten"
|
||||||
|
@ -6192,6 +6190,12 @@ ER_TOO_MANY_PARTITION_FUNC_FIELDS_ERROR
|
||||||
eng "Too many fields in '%s'"
|
eng "Too many fields in '%s'"
|
||||||
ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR
|
ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR
|
||||||
eng "Cannot use MAXVALUE as value in List partitioning"
|
eng "Cannot use MAXVALUE as value in List partitioning"
|
||||||
|
ER_TOO_MANY_VALUES_ERROR
|
||||||
|
eng "Cannot have more than one value for this type of %-.64s partitioning"
|
||||||
|
ER_SAME_NAME_PARTITION_FIELD
|
||||||
|
eng "Duplicate partition field name %-.192s"
|
||||||
|
ER_ROW_SINGLE_PARTITION_FIELD_ERROR
|
||||||
|
eng "Row expressions in VALUES IN only allowed for multi-field column partitioning"
|
||||||
|
|
||||||
# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in
|
# When updating these, please update EXPLAIN_FILENAME_MAX_EXTRA_LENGTH in
|
||||||
# mysql_priv.h with the new maximal additional length for explain_filename.
|
# mysql_priv.h with the new maximal additional length for explain_filename.
|
||||||
|
|
|
@ -1990,7 +1990,10 @@ static int add_column_list_values(File fptr, partition_info *part_info,
|
||||||
int err= 0;
|
int err= 0;
|
||||||
uint i;
|
uint i;
|
||||||
uint num_elements= part_info->part_field_list.elements;
|
uint num_elements= part_info->part_field_list.elements;
|
||||||
err+= add_string(fptr, partition_keywords[PKW_COLUMNS].str);
|
bool use_parenthesis= (part_info->part_type == LIST_PARTITION &&
|
||||||
|
part_info->num_columns > 1U);
|
||||||
|
|
||||||
|
if (use_parenthesis)
|
||||||
err+= add_begin_parenthesis(fptr);
|
err+= add_begin_parenthesis(fptr);
|
||||||
for (i= 0; i < num_elements; i++)
|
for (i= 0; i < num_elements; i++)
|
||||||
{
|
{
|
||||||
|
@ -2032,6 +2035,7 @@ static int add_column_list_values(File fptr, partition_info *part_info,
|
||||||
if (i != (num_elements - 1))
|
if (i != (num_elements - 1))
|
||||||
err+= add_string(fptr, comma_str);
|
err+= add_string(fptr, comma_str);
|
||||||
}
|
}
|
||||||
|
if (use_parenthesis)
|
||||||
err+= add_end_parenthesis(fptr);
|
err+= add_end_parenthesis(fptr);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
@ -3894,10 +3898,12 @@ bool mysql_unpack_partition(THD *thd,
|
||||||
mem_alloc_error(sizeof(partition_info));
|
mem_alloc_error(sizeof(partition_info));
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
lex.part_info->part_state= part_state;
|
part_info= lex.part_info;
|
||||||
lex.part_info->part_state_len= part_state_len;
|
part_info->part_state= part_state;
|
||||||
|
part_info->part_state_len= part_state_len;
|
||||||
DBUG_PRINT("info", ("Parse: %s", part_buf));
|
DBUG_PRINT("info", ("Parse: %s", part_buf));
|
||||||
if (parse_sql(thd, & parser_state, NULL))
|
if (parse_sql(thd, & parser_state, NULL) ||
|
||||||
|
part_info->fix_parser_data(thd))
|
||||||
{
|
{
|
||||||
thd->free_items();
|
thd->free_items();
|
||||||
goto end;
|
goto end;
|
||||||
|
@ -3918,7 +3924,6 @@ bool mysql_unpack_partition(THD *thd,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Successful parse"));
|
DBUG_PRINT("info", ("Successful parse"));
|
||||||
part_info= lex.part_info;
|
|
||||||
DBUG_PRINT("info", ("default engine = %s, default_db_type = %s",
|
DBUG_PRINT("info", ("default engine = %s, default_db_type = %s",
|
||||||
ha_resolve_storage_engine_name(part_info->default_engine_type),
|
ha_resolve_storage_engine_name(part_info->default_engine_type),
|
||||||
ha_resolve_storage_engine_name(default_db_type)));
|
ha_resolve_storage_engine_name(default_db_type)));
|
||||||
|
@ -4370,6 +4375,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
|
||||||
}
|
}
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
alt_part_info->column_list= tab_part_info->column_list;
|
||||||
|
if (alt_part_info->fix_parser_data(thd))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (alter_info->flags & ALTER_ADD_PARTITION)
|
if (alter_info->flags & ALTER_ADD_PARTITION)
|
||||||
{
|
{
|
||||||
|
@ -5126,6 +5136,10 @@ the generated partition syntax in a correct manner.
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("partition changed"));
|
DBUG_PRINT("info", ("partition changed"));
|
||||||
*partition_changed= TRUE;
|
*partition_changed= TRUE;
|
||||||
|
if (thd->work_part_info->fix_parser_data(thd))
|
||||||
|
{
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Set up partition default_engine_type either from the create_info
|
Set up partition default_engine_type either from the create_info
|
||||||
|
|
338
sql/sql_yacc.yy
338
sql/sql_yacc.yy
|
@ -515,10 +515,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
|
|
||||||
%pure_parser /* We have threads */
|
%pure_parser /* We have threads */
|
||||||
/*
|
/*
|
||||||
Currently there are 168 shift/reduce conflicts.
|
Currently there are 169 shift/reduce conflicts.
|
||||||
We should not introduce new conflicts any more.
|
We should not introduce new conflicts any more.
|
||||||
*/
|
*/
|
||||||
%expect 168
|
%expect 169
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Comments for TOKENS.
|
Comments for TOKENS.
|
||||||
|
@ -1165,9 +1165,6 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
%type <ulonglong_number>
|
%type <ulonglong_number>
|
||||||
ulonglong_num real_ulonglong_num size_number
|
ulonglong_num real_ulonglong_num size_number
|
||||||
|
|
||||||
%type <p_elem_value>
|
|
||||||
part_bit_expr
|
|
||||||
|
|
||||||
%type <lock_type>
|
%type <lock_type>
|
||||||
replace_lock_option opt_low_priority insert_lock_option load_data_lock
|
replace_lock_option opt_low_priority insert_lock_option load_data_lock
|
||||||
|
|
||||||
|
@ -1300,8 +1297,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||||
view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail
|
view_check_option trigger_tail sp_tail sf_tail udf_tail event_tail
|
||||||
install uninstall partition_entry binlog_base64_event
|
install uninstall partition_entry binlog_base64_event
|
||||||
init_key_options key_options key_opts key_opt key_using_alg
|
init_key_options key_options key_opts key_opt key_using_alg
|
||||||
part_column_list part_column_expr_list part_column_expr_item
|
part_column_list
|
||||||
part_column_list_value
|
|
||||||
server_def server_options_list server_option
|
server_def server_options_list server_option
|
||||||
definer_opt no_definer definer
|
definer_opt no_definer definer
|
||||||
END_OF_INPUT
|
END_OF_INPUT
|
||||||
|
@ -3818,6 +3814,7 @@ part_type_def:
|
||||||
{
|
{
|
||||||
partition_info *part_info= Lex->part_info;
|
partition_info *part_info= Lex->part_info;
|
||||||
part_info->list_of_part_fields= TRUE;
|
part_info->list_of_part_fields= TRUE;
|
||||||
|
part_info->column_list= FALSE;
|
||||||
part_info->part_type= HASH_PARTITION;
|
part_info->part_type= HASH_PARTITION;
|
||||||
}
|
}
|
||||||
| opt_linear HASH_SYM
|
| opt_linear HASH_SYM
|
||||||
|
@ -3881,8 +3878,10 @@ part_column_list:
|
||||||
part_func:
|
part_func:
|
||||||
'(' remember_name part_func_expr remember_end ')'
|
'(' remember_name part_func_expr remember_end ')'
|
||||||
{
|
{
|
||||||
if (Lex->part_info->set_part_expr($2+1, $3, $4, FALSE))
|
partition_info *part_info= Lex->part_info;
|
||||||
|
if (part_info->set_part_expr($2+1, $3, $4, FALSE))
|
||||||
{ MYSQL_YYABORT; }
|
{ MYSQL_YYABORT; }
|
||||||
|
part_info->column_list= FALSE;
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -4067,7 +4066,7 @@ opt_part_values:
|
||||||
else
|
else
|
||||||
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;
|
LEX *lex= Lex;
|
||||||
partition_info *part_info= lex->part_info;
|
partition_info *part_info= lex->part_info;
|
||||||
|
@ -4083,7 +4082,8 @@ opt_part_values:
|
||||||
else
|
else
|
||||||
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;
|
LEX *lex= Lex;
|
||||||
partition_info *part_info= lex->part_info;
|
partition_info *part_info= lex->part_info;
|
||||||
|
@ -4099,14 +4099,120 @@ opt_part_values:
|
||||||
else
|
else
|
||||||
part_info->part_type= LIST_PARTITION;
|
part_info->part_type= LIST_PARTITION;
|
||||||
}
|
}
|
||||||
|
part_values_in {}
|
||||||
;
|
;
|
||||||
|
|
||||||
part_column_expr_list:
|
part_func_max:
|
||||||
part_column_expr_item {}
|
MAX_VALUE_SYM
|
||||||
| part_column_expr_list ',' part_column_expr_item {}
|
{
|
||||||
|
partition_info *part_info= Lex->part_info;
|
||||||
|
|
||||||
|
if (part_info->num_columns &&
|
||||||
|
part_info->num_columns != 1U)
|
||||||
|
{
|
||||||
|
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_column_expr_item:
|
part_values_in:
|
||||||
|
part_value_item
|
||||||
|
{
|
||||||
|
LEX *lex= Lex;
|
||||||
|
partition_info *part_info= lex->part_info;
|
||||||
|
|
||||||
|
if (part_info->num_columns != 1U)
|
||||||
|
{
|
||||||
|
if (!lex->is_partition_management() ||
|
||||||
|
part_info->num_columns == 0 ||
|
||||||
|
part_info->num_columns > MAX_REF_PARTS)
|
||||||
|
{
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
if (part_info->reorganize_into_single_field_col_val())
|
||||||
|
{
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
| '(' part_value_list ')'
|
||||||
|
{
|
||||||
|
partition_info *part_info= Lex->part_info;
|
||||||
|
if (part_info->num_columns < 2U)
|
||||||
|
{
|
||||||
|
my_parse_error(ER(ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
part_value_list:
|
||||||
|
part_value_item {}
|
||||||
|
| part_value_list ',' part_value_item {}
|
||||||
|
;
|
||||||
|
|
||||||
|
part_value_item:
|
||||||
|
'('
|
||||||
|
{
|
||||||
|
partition_info *part_info= Lex->part_info;
|
||||||
|
/* Initialisation code needed for each list of value expressions */
|
||||||
|
if (!(part_info->column_list &&
|
||||||
|
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;
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
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
|
||||||
{
|
{
|
||||||
partition_info *part_info= Lex->part_info;
|
partition_info *part_info= Lex->part_info;
|
||||||
|
@ -4116,223 +4222,29 @@ part_column_expr_item:
|
||||||
my_parse_error(ER(ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR));
|
my_parse_error(ER(ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR));
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
if (!(col_val= part_info->add_column_value()))
|
if (part_info->add_max_value())
|
||||||
{
|
{
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
col_val->max_value= TRUE;
|
|
||||||
}
|
}
|
||||||
| bit_expr
|
| bit_expr
|
||||||
{
|
{
|
||||||
part_column_list_val *col_val;
|
|
||||||
LEX *lex= Lex;
|
LEX *lex= Lex;
|
||||||
|
partition_info *part_info= lex->part_info;
|
||||||
|
Item *part_expr= $1;
|
||||||
|
|
||||||
if (!lex->safe_to_cache_query)
|
if (!lex->safe_to_cache_query)
|
||||||
{
|
{
|
||||||
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
|
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
if (!(col_val= lex->part_info->add_column_value()))
|
if (part_info->add_column_list_value(part_expr))
|
||||||
{
|
{
|
||||||
MYSQL_YYABORT;
|
MYSQL_YYABORT;
|
||||||
}
|
}
|
||||||
col_val->item_expression= $1;
|
|
||||||
col_val->part_info= NULL;
|
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
part_column_list_value:
|
|
||||||
COLUMN_LIST_SYM
|
|
||||||
{
|
|
||||||
LEX *lex= Lex;
|
|
||||||
partition_info *part_info= lex->part_info;
|
|
||||||
uint num_columns;
|
|
||||||
partition_element *p_elem= part_info->curr_part_elem;
|
|
||||||
part_column_list_val *col_val_array;
|
|
||||||
part_elem_value *list_val;
|
|
||||||
|
|
||||||
if (!part_info->column_list &&
|
|
||||||
!lex->is_partition_management())
|
|
||||||
{
|
|
||||||
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (!(list_val=
|
|
||||||
(part_elem_value*)sql_calloc(sizeof(part_elem_value))) ||
|
|
||||||
p_elem->list_val_list.push_back(list_val))
|
|
||||||
{
|
|
||||||
mem_alloc_error(sizeof(part_elem_value));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (part_info->num_columns)
|
|
||||||
num_columns= part_info->num_columns;
|
|
||||||
else
|
|
||||||
num_columns= MAX_REF_PARTS;
|
|
||||||
if (!(col_val_array=
|
|
||||||
(part_column_list_val*)sql_calloc(num_columns *
|
|
||||||
sizeof(part_column_list_val))))
|
|
||||||
{
|
|
||||||
mem_alloc_error(num_columns * sizeof(part_elem_value));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
list_val->col_val_array= col_val_array;
|
|
||||||
part_info->curr_list_val= list_val;
|
|
||||||
part_info->curr_list_object= 0;
|
|
||||||
}
|
|
||||||
'(' part_column_expr_list ')'
|
|
||||||
{
|
|
||||||
partition_info *part_info= Lex->part_info;
|
|
||||||
uint num_columns= part_info->num_columns;
|
|
||||||
if (num_columns && num_columns != part_info->curr_list_object)
|
|
||||||
{
|
|
||||||
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
part_info->num_columns= part_info->curr_list_object;
|
|
||||||
}
|
|
||||||
;
|
|
||||||
|
|
||||||
part_func_max:
|
|
||||||
max_value_sym
|
|
||||||
{
|
|
||||||
partition_info *part_info= Lex->part_info;
|
|
||||||
if (part_info->defined_max_value)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (part_info->column_list)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
part_info->defined_max_value= TRUE;
|
|
||||||
part_info->curr_part_elem->max_value= TRUE;
|
|
||||||
part_info->curr_part_elem->range_value= LONGLONG_MAX;
|
|
||||||
}
|
|
||||||
| part_range_func
|
|
||||||
{
|
|
||||||
partition_info *part_info= Lex->part_info;
|
|
||||||
if (part_info->defined_max_value)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (part_info->curr_part_elem->has_null_value)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_NULL_IN_VALUES_LESS_THAN));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (part_info->column_list)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| '(' part_column_list_value ')'
|
|
||||||
{}
|
|
||||||
;
|
|
||||||
|
|
||||||
max_value_sym:
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
mem_alloc_error(sizeof(part_elem_value));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
if (part_info->column_list)
|
|
||||||
{
|
|
||||||
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
| part_column_list_value
|
|
||||||
;
|
|
||||||
|
|
||||||
part_bit_expr:
|
|
||||||
bit_expr
|
|
||||||
{
|
|
||||||
Item *part_expr= $1;
|
|
||||||
THD *thd= YYTHD;
|
|
||||||
LEX *lex= thd->lex;
|
|
||||||
partition_info *part_info= lex->part_info;
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
{
|
|
||||||
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 (part_info->curr_part_elem->has_null_value)
|
|
||||||
{
|
|
||||||
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
|
|
||||||
MYSQL_YYABORT;
|
|
||||||
}
|
|
||||||
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:
|
opt_sub_partition:
|
||||||
/* empty */
|
/* empty */
|
||||||
|
|
Loading…
Reference in a new issue