Commit c90669c4 authored by Mikael Ronstrom's avatar Mikael Ronstrom

Fixed removal of column_list keyword for VALUES part, retained for PARTITION...

Fixed removal of column_list keyword for VALUES part, retained for PARTITION BY RANGE/LIST COLUMN_LIST, not entirely working yet
parent 576dd76a
......@@ -2,24 +2,24 @@ drop table if exists t1;
create table t1 (a varchar(5))
engine=memory
partition by range column_list(a)
( partition p0 values less than (column_list('m')),
partition p1 values less than (column_list('za')));
( 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 (column_list('m')),
partition p1 values less than (column_list('za')));
( 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 (column_list('m')),
partition p1 values less than (column_list('za')));
( 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;
......
......@@ -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
create table t1 (a int, b char(20))
partition by range(a)
(partition p0 values less than (column_list(1,"b")));
ERROR HY000: Inconsistency in usage of column lists for partitioning
(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 (column_list(1,"b")));
ERROR HY000: Inconsistency in usage of column lists for partitioning
(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));
create global index inx on t1 (a,b)
partition by range (a)
......@@ -91,7 +91,7 @@ partition by range (a)
drop table t1;
create table t1 (a int, b char(20))
partition by range column_list(b)
(partition p0 values less than (column_list("b")));
(partition p0 values less than ("b"));
drop table t1;
create table t1 (a int)
partition by range (a)
......
......@@ -17,7 +17,7 @@ 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 (column_list(1,1)));
( partition p values in ((1,1)));
#
# BUG#47838, List partitioning have problems with <= and >=
......@@ -35,10 +35,8 @@ drop table t1;
create table t1 (a int signed)
partition by list column_list(a)
( partition p0 values in (column_list(1), column_list(3), column_list(5),
column_list(7), column_list(9), column_list(NULL)),
partition p1 values in (column_list(2), column_list(4), column_list(6),
column_list(8), column_list(0)));
( 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;
......@@ -48,10 +46,9 @@ drop table t1;
create table t1 (a int, b int)
partition by list column_list(a,b)
( partition p0 values in (column_list(1, NULL), column_list(2, NULL),
column_list(NULL, NULL)),
partition p1 values in (column_list(1,1), column_list(2,2)),
partition p2 values in (column_list(3, NULL), column_list(NULL, 1)));
( 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)));
#
# 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);
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 (column_list(2), column_list(1)),
partition p1 values in (column_list(4), column_list(NULL), column_list(3)));
( partition p0 values in (2, 1),
partition p1 values in (4, NULL, 3));
insert into t1 values (1);
insert into t1 values (2);
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)
subpartition by hash (to_seconds(d))
subpartitions 4
( partition p0 values less than (column_list(1, NULL, MAXVALUE, NULL)),
partition p1 values less than (column_list(1, 'a', MAXVALUE, TO_DAYS('1999-01-01'))),
partition p2 values less than (column_list(1, 'a', MAXVALUE, MAXVALUE)),
partition p3 values less than (column_list(1, MAXVALUE, MAXVALUE, MAXVALUE)));
( partition p0 values less than (1, NULL, MAXVALUE, NULL),
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));
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 (column_list(1,'abc','abc')),
partition p1 values less than (column_list(2,'abc','abc')),
partition p2 values less than (column_list(3,'abc','abc')),
partition p3 values less than (column_list(4,'abc','abc')));
( 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'));
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);
......@@ -131,8 +134,8 @@ 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 (column_list(1, 'A', 1)),
partition p1 values less than (column_list(1, 'B', 1)));
(partition p0 values less than (1, 'A', 1),
partition p1 values less than (1, 'B', 1));
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;
......@@ -140,7 +143,7 @@ drop table t1;
create table t1 (a char, b char, c char)
partition by list column_list(a)
( partition p0 values in (column_list('a')));
( partition p0 values in ('a'));
insert into t1 (a) values ('a');
select * from t1 where a = 'a';
drop table t1;
......@@ -148,36 +151,36 @@ drop table t1;
--error ER_WRONG_TYPE_COLUMN_VALUE_ERROR
create table t1 (d timestamp)
partition by range column_list(d)
( partition p0 values less than (column_list('2000-01-01')),
partition p1 values less than (column_list('2040-01-01')));
( partition p0 values less than ('2000-01-01'),
partition p1 values less than ('2040-01-01'));
create table t1 (a int, b int)
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;
create table t1 (d date)
partition by range column_list(d)
( partition p0 values less than (column_list('2000-01-01')),
partition p1 values less than (column_list('2009-01-01')));
( 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 (column_list('1999-01-01')),
partition p1 values less than (column_list('2000-01-01')));
( 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 (column_list('2000-01-01')),
partition p1 values less than (column_list('3000-01-01')));
( 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 (column_list(99,99)),
partition p1 values less than (column_list(99,999)));
(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;
......@@ -191,22 +194,22 @@ 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 (column_list(maxvalue,maxvalue)));
(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 (column_list(maxvalue,maxvalue)));
(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 (column_list(0)));
(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 (column_list('H23456')),
partition p1 values less than (column_list('M23456')));
(partition p0 values less than ('H23456'),
partition p1 values less than ('M23456'));
insert into t1 values ('F23456');
select * from t1;
drop table t1;
......@@ -214,14 +217,14 @@ drop table t1;
-- error 1054
create table t1 (a char(6))
partition by range column_list(a)
(partition p0 values less than (column_list(H23456)),
partition p1 values less than (column_list(M23456)));
(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 (column_list(23456)),
partition p1 values less than (column_list(23456)));
(partition p0 values less than (23456),
partition p1 values less than (23456));
-- error 1064
create table t1 (a int, b int)
......@@ -231,14 +234,14 @@ partition by range column_list(a,b)
-- 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 (column_list(1,1,1));
(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 (column_list(1, NULL)),
partition p1 values less than (column_list(2, maxvalue)),
partition p2 values less than (column_list(3, 3)),
partition p3 values less than (column_list(10, NULL)));
(partition p0 values less than (1, NULL),
partition p1 values less than (2, maxvalue),
partition p2 values less than (3, 3),
partition p3 values less than (10, NULL));
-- error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (10,0);
......@@ -247,57 +250,51 @@ select * from t1;
alter table t1
partition by range column_list(b,a)
(partition p0 values less than (column_list(1,2)),
partition p1 values less than (column_list(3,3)),
partition p2 values less than (column_list(9,5)));
(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 (column_list(2,2)),
partition p12 values less than (column_list(3,3)));
(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 (column_list(0,3)),
partition p02 values less than (column_list(1,1)));
(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(column_list(9,6,1)));
(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 (column_list(4,7)),
partition p22 values less than (column_list(9,5)));
(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 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)
partition by list column_list(a,b)
subpartition by hash (b)
subpartitions 2
(partition p0 values in (column_list(0,0), column_list(1,1)),
partition p1 values in (column_list(1000,1000)));
(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 (column_list('a','b','c')));
( partition p0 values less than ('a','b','c'));
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;
......@@ -11,8 +11,8 @@ drop table if exists t1;
create table t1 (a varchar(5))
engine=memory
partition by range column_list(a)
( partition p0 values less than (column_list('m')),
partition p1 values less than (column_list('za')));
( 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;
......@@ -20,8 +20,8 @@ drop table t1;
create table t1 (a varchar(5))
engine=myisam
partition by range column_list(a)
( partition p0 values less than (column_list('m')),
partition p1 values less than (column_list('za')));
( 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;
......@@ -29,8 +29,8 @@ drop table t1;
create table t1 (a varchar(5))
engine=innodb
partition by range column_list(a)
( partition p0 values less than (column_list('m')),
partition p1 values less than (column_list('za')));
( 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;
......
......@@ -64,15 +64,15 @@ create table t1 (a int, b char(20))
partition by range column_list(a,b)
(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))
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))
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 global index inx on t1 (a,b)
......@@ -82,7 +82,7 @@ drop table t1;
create table t1 (a int, b char(20))
partition by range column_list(b)
(partition p0 values less than (column_list("b")));
(partition p0 values less than ("b"));
drop table t1;
#
......
......@@ -74,6 +74,7 @@ typedef struct p_column_list_val
typedef struct p_elem_val
{
longlong value;
uint added_items;
bool null_value;
bool unsigned_flag;
part_column_list_val *col_val_array;
......
/* Copyright (C) 2006 MySQL AB
/* Copyrght (C) 2006 MySQL AB
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
......@@ -682,7 +682,7 @@ bool partition_info::check_range_constants(THD *thd)
part_elem_value *range_val= list_val_it++;
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;
memcpy(loc_range_col_array, (const void*)col_val, size_entries);
loc_range_col_array+= num_column_values;
......@@ -826,85 +826,6 @@ int partition_info::compare_column_values(const void *first_arg,
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
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++))
{
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);
}
......@@ -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));
goto end;
}
if (fix_parser_data(thd))
goto end;
}
if (unlikely(!is_sub_partitioned() &&
!(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
SYNOPSIS
......@@ -1616,4 +1514,507 @@ bool check_partition_dirs(partition_info *part_info)
}
/*
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 */
......@@ -280,11 +280,23 @@ class partition_info : public Sql_alloc
handler *file, HA_CREATE_INFO *info,
bool check_partition_function);
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();
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 init_column_part();
bool add_column_list_value(Item *item);
private:
static int list_part_cmp(const void* a, const void* b);
bool set_up_default_partitions(handler *file, HA_CREATE_INFO *info,
......@@ -294,9 +306,6 @@ class partition_info : public Sql_alloc
uint start_no);
char *create_subpartition_name(uint subpart_no, const char *part_name);
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);
......
......@@ -5822,8 +5822,6 @@ ER_SAME_NAME_PARTITION
eng "Duplicate partition name %-.192s"
ger "Doppelter Partitionsname: %-.192s"
swe "Duplicerat partitionsnamn %-.192s"
ER_SAME_NAME_PARTITION_FIELD
eng "Duplicate partition field name %-.192s"
ER_NO_BINLOG_ERROR
eng "It is not allowed to shut off binlog on this command"
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'"
ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR
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
# 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;
uint i;
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);
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))
err+= add_string(fptr, comma_str);
}
if (use_parenthesis)
err+= add_end_parenthesis(fptr);
return err;
}
......@@ -3894,10 +3898,12 @@ bool mysql_unpack_partition(THD *thd,
mem_alloc_error(sizeof(partition_info));
goto end;
}
lex.part_info->part_state= part_state;
lex.part_info->part_state_len= part_state_len;
part_info= lex.part_info;
part_info->part_state= part_state;
part_info->part_state_len= part_state_len;
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();
goto end;
......@@ -3918,7 +3924,6 @@ bool mysql_unpack_partition(THD *thd,
*/
DBUG_PRINT("info", ("Successful parse"));
part_info= lex.part_info;
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(default_db_type)));
......@@ -4370,6 +4375,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
}
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)
{
......@@ -5126,6 +5136,10 @@ the generated partition syntax in a correct manner.
{
DBUG_PRINT("info", ("partition changed"));
*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
......
......@@ -515,10 +515,10 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%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.
*/
%expect 168
%expect 169
/*
Comments for TOKENS.
......@@ -1165,9 +1165,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
......@@ -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
install uninstall partition_entry binlog_base64_event
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_value
part_column_list
server_def server_options_list server_option
definer_opt no_definer definer
END_OF_INPUT
......@@ -3818,6 +3814,7 @@ part_type_def:
{
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
......@@ -3881,8 +3878,10 @@ part_column_list:
part_func:
'(' 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; }
part_info->column_list= FALSE;
}
;
......@@ -4067,7 +4066,7 @@ opt_part_values:
else
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;
......@@ -4083,7 +4082,8 @@ opt_part_values:
else
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;
......@@ -4099,241 +4099,153 @@ opt_part_values:
else
part_info->part_type= LIST_PARTITION;
}
part_values_in {}
;
part_column_expr_list:
part_column_expr_item {}
| part_column_expr_list ',' part_column_expr_item {}
;
part_column_expr_item:
part_func_max:
MAX_VALUE_SYM
{
partition_info *part_info= Lex->part_info;
part_column_list_val *col_val;
if (part_info->part_type == LIST_PARTITION)
{
my_parse_error(ER(ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR));
MYSQL_YYABORT;
}
if (!(col_val= part_info->add_column_value()))
if (part_info->num_columns &&
part_info->num_columns != 1U)
{
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
col_val->max_value= TRUE;
}
| bit_expr
{
part_column_list_val *col_val;
LEX *lex= Lex;
if (!lex->safe_to_cache_query)
else
part_info->num_columns= 1U;
if (part_info->init_column_part())
{
my_error(ER_NO_CONST_EXPR_IN_RANGE_OR_LIST_ERROR, MYF(0));
MYSQL_YYABORT;
}
if (!(col_val= lex->part_info->add_column_value()))
if (part_info->add_max_value())
{
MYSQL_YYABORT;
}
col_val->item_expression= $1;
col_val->part_info= NULL;
}
| part_value_item {}
;
part_column_list_value:
COLUMN_LIST_SYM
part_values_in:
part_value_item
{
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())
if (part_info->num_columns != 1U)
{
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))
if (!lex->is_partition_management() ||
part_info->num_columns == 0 ||
part_info->num_columns > MAX_REF_PARTS)
{
mem_alloc_error(sizeof(part_elem_value));
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
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))))
/*
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())
{
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 ')'
}
| '(' part_value_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)
if (part_info->num_columns < 2U)
{
my_error(ER_PARTITION_COLUMN_LIST_ERROR, MYF(0));
my_parse_error(ER(ER_ROW_SINGLE_PARTITION_FIELD_ERROR));
MYSQL_YYABORT;
}
part_info->num_columns= part_info->curr_list_object;
}
;
part_func_max:
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;
if (part_info->defined_max_value)
{
my_parse_error(ER(ER_PARTITION_MAXVALUE_ERROR));
MYSQL_YYABORT;
}
if (part_info->column_list)
/* 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())
{
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
part_value_item_list {}
')'
{
LEX *lex= Lex;
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)
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_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_info->curr_list_object= 0;
}
;
part_list_func:
part_list_item {}
| part_list_func ',' part_list_item {}
part_value_item_list:
part_value_expr_item {}
| part_value_item_list ',' part_value_expr_item {}
;
part_list_item:
part_bit_expr
part_value_expr_item:
MAX_VALUE_SYM
{
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)
{
mem_alloc_error(sizeof(part_elem_value));
my_parse_error(ER(ER_MAXVALUE_IN_LIST_PARTITIONING_ERROR));
MYSQL_YYABORT;
}
if (part_info->column_list)
if (part_info->add_max_value())
{
my_parse_error(ER(ER_PARTITION_COLUMN_LIST_ERROR));
MYSQL_YYABORT;
}
}
| part_column_list_value
;
part_bit_expr:
bit_expr
| bit_expr
{
Item *part_expr= $1;
THD *thd= YYTHD;
LEX *lex= thd->lex;
LEX *lex= 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";
Item *part_expr= $1;
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))
if (!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)
if (part_info->add_column_list_value(part_expr))
{
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:
/* empty */
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment