BUG#16002: Make partition functions that are unsigned work properly

parent ba5d08f3
drop table if exists t1; drop table if exists t1;
create table t1 (a bigint unsigned);
insert into t1 values (0xFFFFFFFFFFFFFFFD);
insert into t1 values (0xFFFFFFFFFFFFFFFE);
select * from t1 where (a + 1) < 10;
a
select * from t1 where (a + 1) > 10;
a
18446744073709551613
18446744073709551614
drop table t1;
CREATE TABLE t1 ( CREATE TABLE t1 (
a int not null, a int not null,
b int not null, b int not null,
...@@ -839,4 +849,14 @@ SHOW TABLE STATUS; ...@@ -839,4 +849,14 @@ SHOW TABLE STATUS;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 10 Dynamic 0 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned t1 MyISAM 10 Dynamic 0 0 0 0 0 0 NULL NULL NULL NULL latin1_swedish_ci NULL partitioned
DROP TABLE t1; DROP TABLE t1;
create table t1 (a bigint unsigned)
partition by list (a)
(partition p0 values in (0-1));
ERROR HY000: Partition function is unsigned, cannot have negative constants
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (10));
insert into t1 values (0xFFFFFFFFFFFFFFFF);
ERROR HY000: Table has no partition for value 18446744073709551615
drop table t1;
End of 5.1 tests End of 5.1 tests
...@@ -554,3 +554,7 @@ PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5)); ...@@ -554,3 +554,7 @@ PARTITION BY RANGE (a) (PARTITION p1 VALUES LESS THAN(5));
insert into t1 values (10); insert into t1 values (10);
ERROR HY000: Table has no partition for value 10 ERROR HY000: Table has no partition for value 10
drop table t1; drop table t1;
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (-1));
ERROR HY000: Partition function is unsigned, cannot have negative constants
...@@ -363,3 +363,15 @@ SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31'; ...@@ -363,3 +363,15 @@ SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31';
COUNT(*) COUNT(*)
10 10
DROP TABLE t1; DROP TABLE t1;
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (0),
partition p1 values less than (10));
ERROR HY000: VALUES LESS THAN value must be strictly increasing for each partition
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (2),
partition p1 values less than (10));
insert into t1 values (0xFFFFFFFFFFFFFFFF);
ERROR HY000: Table has no partition for value 18446744073709551615
drop table t1;
...@@ -9,6 +9,13 @@ ...@@ -9,6 +9,13 @@
drop table if exists t1; drop table if exists t1;
--enable_warnings --enable_warnings
create table t1 (a bigint unsigned);
insert into t1 values (0xFFFFFFFFFFFFFFFD);
insert into t1 values (0xFFFFFFFFFFFFFFFE);
select * from t1 where (a + 1) < 10;
select * from t1 where (a + 1) > 10;
drop table t1;
# #
# Partition by key no partition defined => OK # Partition by key no partition defined => OK
# #
...@@ -956,4 +963,20 @@ PARTITION p2 VALUES LESS THAN (30) ENGINE = MyISAM); ...@@ -956,4 +963,20 @@ PARTITION p2 VALUES LESS THAN (30) ENGINE = MyISAM);
SHOW TABLE STATUS; SHOW TABLE STATUS;
DROP TABLE t1; DROP TABLE t1;
#
#BUG 16002 Erroneus handling of unsigned partition functions
#
--error ER_SIGNED_PARTITION_CONSTANT_ERROR
create table t1 (a bigint unsigned)
partition by list (a)
(partition p0 values in (0-1));
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (10));
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (0xFFFFFFFFFFFFFFFF);
drop table t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -747,3 +747,8 @@ CREATE TABLE t1(a int) ...@@ -747,3 +747,8 @@ CREATE TABLE t1(a int)
--error ER_NO_PARTITION_FOR_GIVEN_VALUE --error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (10); insert into t1 values (10);
drop table t1; drop table t1;
--error ER_SIGNED_PARTITION_CONSTANT_ERROR
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (-1));
...@@ -388,3 +388,20 @@ SELECT COUNT(*) FROM t1 WHERE c3 BETWEEN '1996-12-31' AND '2000-12-31'; ...@@ -388,3 +388,20 @@ SELECT COUNT(*) FROM t1 WHERE c3 BETWEEN '1996-12-31' AND '2000-12-31';
SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31'; SELECT COUNT(*) FROM t1 WHERE c3 < '2000-12-31';
DROP TABLE t1; DROP TABLE t1;
#
# BUG 16002: Unsigned partition functions not handled correctly
#
--error ER_RANGE_NOT_INCREASING_ERROR
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (0),
partition p1 values less than (10));
create table t1 (a bigint unsigned)
partition by range (a)
(partition p0 values less than (2),
partition p1 values less than (10));
--error ER_NO_PARTITION_FOR_GIVEN_VALUE
insert into t1 values (0xFFFFFFFFFFFFFFFF);
drop table t1;
...@@ -5165,9 +5165,20 @@ void ha_partition::print_error(int error, myf errflag) ...@@ -5165,9 +5165,20 @@ void ha_partition::print_error(int error, myf errflag)
if (error == HA_ERR_NO_PARTITION_FOUND) if (error == HA_ERR_NO_PARTITION_FOUND)
{ {
char buf[100]; char buf[100];
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), longlong value= m_part_info->part_expr->val_int();
m_part_info->part_expr->null_value ? "NULL" : if (!m_part_info->part_expr->unsigned_flag ||
llstr(m_part_info->part_expr->val_int(), buf)); m_part_info->part_expr->null_value)
{
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0),
m_part_info->part_expr->null_value ? "NULL" :
llstr(m_part_info->part_expr->val_int(), buf));
}
else
{
ulonglong value= m_part_info->part_expr->val_int();
longlong2str(value, buf, 10);
my_error(ER_NO_PARTITION_FOR_GIVEN_VALUE, MYF(0), buf);
}
} }
else else
m_file[0]->print_error(error, errflag); m_file[0]->print_error(error, errflag);
......
...@@ -36,15 +36,22 @@ enum partition_state { ...@@ -36,15 +36,22 @@ enum partition_state {
PART_IS_ADDED= 8 PART_IS_ADDED= 8
}; };
typedef struct p_elem_val
{
longlong value;
bool null_value;
bool unsigned_flag;
} part_elem_value;
class partition_element :public Sql_alloc { class partition_element :public Sql_alloc {
public: public:
List<partition_element> subpartitions; List<partition_element> subpartitions;
List<longlong> list_val_list; List<part_elem_value> list_val_list;
ulonglong part_max_rows; ulonglong part_max_rows;
ulonglong part_min_rows; ulonglong part_min_rows;
longlong range_value;
char *partition_name; char *partition_name;
char *tablespace_name; char *tablespace_name;
longlong range_value;
char* part_comment; char* part_comment;
char* data_file_name; char* data_file_name;
char* index_file_name; char* index_file_name;
...@@ -52,13 +59,16 @@ class partition_element :public Sql_alloc { ...@@ -52,13 +59,16 @@ class partition_element :public Sql_alloc {
enum partition_state part_state; enum partition_state part_state;
uint16 nodegroup_id; uint16 nodegroup_id;
bool has_null_value; bool has_null_value;
bool signed_flag;
bool max_value;
partition_element() partition_element()
: part_max_rows(0), part_min_rows(0), partition_name(NULL), : part_max_rows(0), part_min_rows(0), range_value(0),
tablespace_name(NULL), range_value(0), part_comment(NULL), partition_name(NULL), tablespace_name(NULL), part_comment(NULL),
data_file_name(NULL), index_file_name(NULL), data_file_name(NULL), index_file_name(NULL),
engine_type(NULL),part_state(PART_NORMAL), engine_type(NULL), part_state(PART_NORMAL),
nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE) nodegroup_id(UNDEF_NODEGROUP), has_null_value(FALSE),
signed_flag(FALSE), max_value(FALSE)
{ {
subpartitions.empty(); subpartitions.empty();
list_val_list.empty(); list_val_list.empty();
......
...@@ -445,10 +445,12 @@ bool partition_info::check_range_constants() ...@@ -445,10 +445,12 @@ bool partition_info::check_range_constants()
{ {
partition_element* part_def; partition_element* part_def;
longlong current_largest_int= LONGLONG_MIN; longlong current_largest_int= LONGLONG_MIN;
ulonglong current_largest_uint= 0;
longlong part_range_value_int; longlong part_range_value_int;
uint i; uint i;
List_iterator<partition_element> it(partitions); List_iterator<partition_element> it(partitions);
bool result= TRUE; bool result= TRUE;
bool signed_flag= !part_expr->unsigned_flag;
DBUG_ENTER("partition_info::check_range_constants"); DBUG_ENTER("partition_info::check_range_constants");
DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts)); DBUG_PRINT("enter", ("INT_RESULT with %d parts", no_parts));
...@@ -463,19 +465,40 @@ bool partition_info::check_range_constants() ...@@ -463,19 +465,40 @@ bool partition_info::check_range_constants()
do do
{ {
part_def= it++; part_def= it++;
if ((i != (no_parts - 1)) || !defined_max_value) if (signed_flag)
part_range_value_int= part_def->range_value;
else
part_range_value_int= LONGLONG_MAX;
if (likely(current_largest_int < part_range_value_int))
{ {
current_largest_int= part_range_value_int; if ((i != (no_parts - 1)) || !defined_max_value)
range_int_array[i]= part_range_value_int; part_range_value_int= part_def->range_value;
else
part_range_value_int= LONGLONG_MAX;
if (likely(current_largest_int < part_range_value_int))
{
current_largest_int= part_range_value_int;
range_int_array[i]= part_range_value_int;
}
else
{
my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
goto end;
}
} }
else else
{ {
my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0)); ulonglong upart_range_value_int;
goto end; if ((i != (no_parts - 1)) || !defined_max_value)
upart_range_value_int= part_def->range_value;
else
upart_range_value_int= ULONGLONG_MAX;
if (likely(current_largest_uint < upart_range_value_int))
{
current_largest_uint= upart_range_value_int;
range_int_array[i]= part_range_value_int;
}
else
{
my_error(ER_RANGE_NOT_INCREASING_ERROR, MYF(0));
goto end;
}
} }
} while (++i < no_parts); } while (++i < no_parts);
result= FALSE; result= FALSE;
...@@ -485,8 +508,8 @@ bool partition_info::check_range_constants() ...@@ -485,8 +508,8 @@ bool partition_info::check_range_constants()
/* /*
A support routine for check_list_constants used by qsort to sort the Support routines for check_list_constants used by qsort to sort the
constant list expressions. constant list expressions. One routine for unsigned and one for signed.
SYNOPSIS SYNOPSIS
list_part_cmp() list_part_cmp()
...@@ -511,6 +534,18 @@ int partition_info::list_part_cmp(const void* a, const void* b) ...@@ -511,6 +534,18 @@ int partition_info::list_part_cmp(const void* a, const void* b)
return 0; return 0;
} }
int partition_info::list_part_cmp_unsigned(const void* a, const void* b)
{
ulonglong a1= ((LIST_PART_ENTRY*)a)->list_value;
ulonglong b1= ((LIST_PART_ENTRY*)b)->list_value;
if (a1 < b1)
return -1;
else if (a1 > b1)
return +1;
else
return 0;
}
/* /*
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
...@@ -536,7 +571,7 @@ bool partition_info::check_list_constants() ...@@ -536,7 +571,7 @@ bool partition_info::check_list_constants()
{ {
uint i; uint i;
uint list_index= 0; uint list_index= 0;
longlong *list_value; part_elem_value *list_value;
bool not_first; bool not_first;
bool result= TRUE; bool result= TRUE;
longlong curr_value, prev_value; longlong curr_value, prev_value;
...@@ -577,7 +612,7 @@ bool partition_info::check_list_constants() ...@@ -577,7 +612,7 @@ bool partition_info::check_list_constants()
has_null_part_id= i; has_null_part_id= i;
found_null= TRUE; found_null= TRUE;
} }
List_iterator<longlong> list_val_it1(part_def->list_val_list); List_iterator<part_elem_value> list_val_it1(part_def->list_val_list);
while (list_val_it1++) while (list_val_it1++)
no_list_values++; no_list_values++;
} while (++i < no_parts); } while (++i < no_parts);
...@@ -593,33 +628,40 @@ bool partition_info::check_list_constants() ...@@ -593,33 +628,40 @@ bool partition_info::check_list_constants()
do do
{ {
part_def= list_func_it++; part_def= list_func_it++;
List_iterator<longlong> list_val_it2(part_def->list_val_list); List_iterator<part_elem_value> list_val_it2(part_def->list_val_list);
while ((list_value= list_val_it2++)) while ((list_value= list_val_it2++))
{ {
list_array[list_index].list_value= *list_value; list_array[list_index].list_value= list_value->value;
list_array[list_index++].partition_id= i; list_array[list_index++].partition_id= i;
} }
} while (++i < no_parts); } while (++i < no_parts);
qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY), if (fixed)
&list_part_cmp);
not_first= FALSE;
i= prev_value= 0; //prev_value initialised to quiet compiler
do
{ {
curr_value= list_array[i].list_value; if (!part_expr->unsigned_flag)
if (likely(!not_first || prev_value != curr_value)) qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
{ &list_part_cmp);
prev_value= curr_value;
not_first= TRUE;
}
else else
qsort((void*)list_array, no_list_values, sizeof(LIST_PART_ENTRY),
&list_part_cmp_unsigned);
not_first= FALSE;
i= prev_value= 0; //prev_value initialised to quiet compiler
do
{ {
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0)); curr_value= list_array[i].list_value;
goto end; if (likely(!not_first || prev_value != curr_value))
} {
} while (++i < no_list_values); prev_value= curr_value;
not_first= TRUE;
}
else
{
my_error(ER_MULTIPLE_DEF_CONST_IN_LIST_PART_ERROR, MYF(0));
goto end;
}
} while (++i < no_list_values);
}
result= FALSE; result= FALSE;
end: end:
DBUG_RETURN(result); DBUG_RETURN(result);
...@@ -647,7 +689,7 @@ bool partition_info::check_list_constants() ...@@ -647,7 +689,7 @@ bool partition_info::check_list_constants()
*/ */
bool partition_info::check_partition_info(handlerton **eng_type, bool partition_info::check_partition_info(THD *thd, handlerton **eng_type,
handler *file, ulonglong max_rows) handler *file, ulonglong max_rows)
{ {
handlerton **engine_array= NULL; handlerton **engine_array= NULL;
...@@ -733,9 +775,12 @@ bool partition_info::check_partition_info(handlerton **eng_type, ...@@ -733,9 +775,12 @@ bool partition_info::check_partition_info(handlerton **eng_type,
list constants. list constants.
*/ */
if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) || if (fixed)
(part_type == LIST_PARTITION && check_list_constants()))) {
goto end; if (unlikely((part_type == RANGE_PARTITION && check_range_constants()) ||
(part_type == LIST_PARTITION && check_list_constants())))
goto end;
}
result= FALSE; result= FALSE;
end: end:
my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR)); my_free((char*)engine_array,MYF(MY_ALLOW_ZERO_PTR));
......
...@@ -163,6 +163,7 @@ class partition_info : public Sql_alloc ...@@ -163,6 +163,7 @@ class partition_info : public Sql_alloc
uint no_subpart_fields; uint no_subpart_fields;
uint no_full_part_fields; uint no_full_part_fields;
uint has_null_part_id;
/* /*
This variable is used to calculate the partition id when using This variable is used to calculate the partition id when using
LINEAR KEY/HASH. This functionality is kept in the MySQL Server LINEAR KEY/HASH. This functionality is kept in the MySQL Server
...@@ -182,7 +183,6 @@ class partition_info : public Sql_alloc ...@@ -182,7 +183,6 @@ class partition_info : public Sql_alloc
bool fixed; bool fixed;
bool from_openfrm; bool from_openfrm;
bool has_null_value; bool has_null_value;
uint has_null_part_id;
partition_info() partition_info()
...@@ -204,19 +204,13 @@ class partition_info : public Sql_alloc ...@@ -204,19 +204,13 @@ class partition_info : public Sql_alloc
no_parts(0), no_subparts(0), no_parts(0), no_subparts(0),
count_curr_subparts(0), part_error_code(0), count_curr_subparts(0), part_error_code(0),
no_list_values(0), no_part_fields(0), no_subpart_fields(0), no_list_values(0), no_part_fields(0), no_subpart_fields(0),
no_full_part_fields(0), linear_hash_mask(0), no_full_part_fields(0), has_null_part_id(0), linear_hash_mask(0),
use_default_partitions(TRUE), use_default_partitions(TRUE), use_default_no_partitions(TRUE),
use_default_no_partitions(TRUE), use_default_subpartitions(TRUE), use_default_no_subpartitions(TRUE),
use_default_subpartitions(TRUE), default_partitions_setup(FALSE), defined_max_value(FALSE),
use_default_no_subpartitions(TRUE),
default_partitions_setup(FALSE),
defined_max_value(FALSE),
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE), list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
linear_hash_ind(FALSE), linear_hash_ind(FALSE), fixed(FALSE), from_openfrm(FALSE),
fixed(FALSE), has_null_value(FALSE)
from_openfrm(FALSE),
has_null_value(FALSE),
has_null_part_id(0)
{ {
all_fields_in_PF.clear_all(); all_fields_in_PF.clear_all();
all_fields_in_PPF.clear_all(); all_fields_in_PPF.clear_all();
...@@ -248,10 +242,11 @@ class partition_info : public Sql_alloc ...@@ -248,10 +242,11 @@ class partition_info : public Sql_alloc
static bool check_engine_mix(handlerton **engine_array, uint no_parts); static bool check_engine_mix(handlerton **engine_array, uint no_parts);
bool check_range_constants(); bool check_range_constants();
bool check_list_constants(); bool check_list_constants();
bool check_partition_info(handlerton **eng_type, bool check_partition_info(THD *thd, handlerton **eng_type,
handler *file, ulonglong max_rows); handler *file, ulonglong max_rows);
private: private:
static int list_part_cmp(const void* a, const void* b); static int list_part_cmp(const void* a, const void* b);
static int list_part_cmp_unsigned(const void* a, const void* b);
bool set_up_default_partitions(handler *file, ulonglong max_rows, bool set_up_default_partitions(handler *file, ulonglong max_rows,
uint start_no); uint start_no);
bool set_up_default_subpartitions(handler *file, ulonglong max_rows); bool set_up_default_subpartitions(handler *file, ulonglong max_rows);
......
...@@ -5826,3 +5826,6 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT ...@@ -5826,3 +5826,6 @@ ER_NDB_CANT_SWITCH_BINLOG_FORMAT
eng "The NDB cluster engine does not support changing the binlog format on the fly yet" eng "The NDB cluster engine does not support changing the binlog format on the fly yet"
ER_PARTITION_NO_TEMPORARY ER_PARTITION_NO_TEMPORARY
eng "Cannot create temporary table with partitions" eng "Cannot create temporary table with partitions"
ER_SIGNED_PARTITION_CONSTANT_ERROR
eng "Partition function is unsigned, cannot have negative constants"
swe "Partitionsfunktionen r positiv, kan inte ha negativa konstanter"
...@@ -61,7 +61,6 @@ static const char *equal_str= "="; ...@@ -61,7 +61,6 @@ static const char *equal_str= "=";
static const char *end_paren_str= ")"; static const char *end_paren_str= ")";
static const char *begin_paren_str= "("; static const char *begin_paren_str= "(";
static const char *comma_str= ","; static const char *comma_str= ",";
static char buff[22];
int get_partition_id_list(partition_info *part_info, int get_partition_id_list(partition_info *part_info,
uint32 *part_id, uint32 *part_id,
...@@ -189,9 +188,9 @@ bool is_name_in_list(char *name, ...@@ -189,9 +188,9 @@ bool is_name_in_list(char *name,
SYNOPSIS SYNOPSIS
partition_default_handling() partition_default_handling()
table Table object table Table object
table_name Table name to use when getting no_parts
db_name Database name to use when getting no_parts
part_info Partition info to set up part_info Partition info to set up
is_create_table_ind Is this part of a table creation
normalized_path Normalized path name of table and database
RETURN VALUES RETURN VALUES
TRUE Error TRUE Error
...@@ -793,6 +792,43 @@ static bool handle_list_of_fields(List_iterator<char> it, ...@@ -793,6 +792,43 @@ static bool handle_list_of_fields(List_iterator<char> it,
} }
/*
Support function to check if all VALUES * (expression) is of the
right sign (no signed constants when unsigned partition function)
SYNOPSIS
check_signed_flag()
part_info Partition info object
RETURN VALUES
0 No errors due to sign errors
>0 Sign error
*/
int check_signed_flag(partition_info *part_info)
{
int error= 0;
uint i= 0;
if (part_info->part_type != HASH_PARTITION &&
part_info->part_expr->unsigned_flag)
{
List_iterator<partition_element> part_it(part_info->partitions);
do
{
partition_element *part_elem= part_it++;
if (part_elem->signed_flag)
{
my_error(ER_SIGNED_PARTITION_CONSTANT_ERROR, MYF(0));
error= ER_SIGNED_PARTITION_CONSTANT_ERROR;
break;
}
} while (++i < part_info->no_parts);
}
return error;
}
/* /*
The function uses a new feature in fix_fields where the flag The function uses a new feature in fix_fields where the flag
GET_FIXED_FIELDS_FLAG is set for all fields in the item tree. GET_FIXED_FIELDS_FLAG is set for all fields in the item tree.
...@@ -802,10 +838,11 @@ static bool handle_list_of_fields(List_iterator<char> it, ...@@ -802,10 +838,11 @@ static bool handle_list_of_fields(List_iterator<char> it,
SYNOPSIS SYNOPSIS
fix_fields_part_func() fix_fields_part_func()
thd The thread object thd The thread object
tables A list of one table, the partitioned table
func_expr The item tree reference of the partition function func_expr The item tree reference of the partition function
table The table object
part_info Reference to partitioning data structure part_info Reference to partitioning data structure
sub_part Is the table subpartitioned as well sub_part Is the table subpartitioned as well
set_up_fields Flag if we are to set-up field arrays
RETURN VALUE RETURN VALUE
TRUE An error occurred, something was wrong with the TRUE An error occurred, something was wrong with the
...@@ -828,26 +865,54 @@ static bool handle_list_of_fields(List_iterator<char> it, ...@@ -828,26 +865,54 @@ static bool handle_list_of_fields(List_iterator<char> it,
on the field object. on the field object.
*/ */
static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
Item* func_expr, partition_info *part_info, bool is_sub_part, bool is_field_to_be_setup)
bool is_sub_part)
{ {
partition_info *part_info= table->part_info;
uint dir_length, home_dir_length;
bool result= TRUE; bool result= TRUE;
TABLE *table= tables->table; TABLE_LIST tables;
TABLE_LIST *save_table_list, *save_first_table, *save_last_table; TABLE_LIST *save_table_list, *save_first_table, *save_last_table;
int error; int error;
Name_resolution_context *context; Name_resolution_context *context;
const char *save_where; const char *save_where;
char* db_name;
char db_name_string[FN_REFLEN];
DBUG_ENTER("fix_fields_part_func"); DBUG_ENTER("fix_fields_part_func");
if (part_info->fixed)
{
if (!(is_sub_part || (error= check_signed_flag(part_info))))
result= FALSE;
goto end;
}
/*
Set-up the TABLE_LIST object to be a list with a single table
Set the object to zero to create NULL pointers and set alias
and real name to table name and get database name from file name.
*/
bzero((void*)&tables, sizeof(TABLE_LIST));
tables.alias= tables.table_name= (char*) table->s->table_name.str;
tables.table= table;
tables.next_local= 0;
tables.next_name_resolution_table= 0;
strmov(db_name_string, table->s->normalized_path.str);
dir_length= dirname_length(db_name_string);
db_name_string[dir_length - 1]= 0;
home_dir_length= dirname_length(db_name_string);
db_name= &db_name_string[home_dir_length];
tables.db= db_name;
context= thd->lex->current_context(); context= thd->lex->current_context();
table->map= 1; //To ensure correct calculation of const item table->map= 1; //To ensure correct calculation of const item
table->get_fields_in_item_tree= TRUE; table->get_fields_in_item_tree= TRUE;
save_table_list= context->table_list; save_table_list= context->table_list;
save_first_table= context->first_name_resolution_table; save_first_table= context->first_name_resolution_table;
save_last_table= context->last_name_resolution_table; save_last_table= context->last_name_resolution_table;
context->table_list= tables; context->table_list= &tables;
context->first_name_resolution_table= tables; context->first_name_resolution_table= &tables;
context->last_name_resolution_table= NULL; context->last_name_resolution_table= NULL;
func_expr->walk(&Item::change_context_processor, (byte*) context); func_expr->walk(&Item::change_context_processor, (byte*) context);
save_where= thd->where; save_where= thd->where;
...@@ -859,7 +924,8 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, ...@@ -859,7 +924,8 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables,
if (unlikely(error)) if (unlikely(error))
{ {
DBUG_PRINT("info", ("Field in partition function not part of table")); DBUG_PRINT("info", ("Field in partition function not part of table"));
clear_field_flag(table); if (is_field_to_be_setup)
clear_field_flag(table);
goto end; goto end;
} }
thd->where= save_where; thd->where= save_where;
...@@ -869,7 +935,13 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables, ...@@ -869,7 +935,13 @@ static bool fix_fields_part_func(THD *thd, TABLE_LIST *tables,
clear_field_flag(table); clear_field_flag(table);
goto end; goto end;
} }
result= set_up_field_array(table, is_sub_part); if ((!is_sub_part) && (error= check_signed_flag(part_info)))
goto end;
result= FALSE;
if (is_field_to_be_setup)
result= set_up_field_array(table, is_sub_part);
if (!is_sub_part)
part_info->fixed= TRUE;
end: end:
table->get_fields_in_item_tree= FALSE; table->get_fields_in_item_tree= FALSE;
table->map= 0; //Restore old value table->map= 0; //Restore old value
...@@ -1303,7 +1375,6 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask, ...@@ -1303,7 +1375,6 @@ static uint32 get_part_id_from_linear_hash(longlong hash_value, uint mask,
SYNOPSIS SYNOPSIS
fix_partition_func() fix_partition_func()
thd The thread object thd The thread object
name The name of the partitioned table
table TABLE object for which partition fields are set-up table TABLE object for which partition fields are set-up
create_table_ind Indicator of whether openfrm was called as part of create_table_ind Indicator of whether openfrm was called as part of
CREATE or ALTER TABLE CREATE or ALTER TABLE
...@@ -1325,15 +1396,10 @@ NOTES ...@@ -1325,15 +1396,10 @@ NOTES
of an error that is not discovered until here. of an error that is not discovered until here.
*/ */
bool fix_partition_func(THD *thd, const char* name, TABLE *table, bool fix_partition_func(THD *thd, TABLE *table,
bool is_create_table_ind) bool is_create_table_ind)
{ {
bool result= TRUE; bool result= TRUE;
uint dir_length, home_dir_length;
TABLE_LIST tables;
TABLE_SHARE *share= table->s;
char db_name_string[FN_REFLEN];
char* db_name;
partition_info *part_info= table->part_info; partition_info *part_info= table->part_info;
ulong save_set_query_id= thd->set_query_id; ulong save_set_query_id= thd->set_query_id;
Item *thd_free_list= thd->free_list; Item *thd_free_list= thd->free_list;
...@@ -1345,23 +1411,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1345,23 +1411,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
} }
thd->set_query_id= 0; thd->set_query_id= 0;
DBUG_PRINT("info", ("thd->set_query_id: %d", thd->set_query_id)); DBUG_PRINT("info", ("thd->set_query_id: %d", thd->set_query_id));
/*
Set-up the TABLE_LIST object to be a list with a single table
Set the object to zero to create NULL pointers and set alias
and real name to table name and get database name from file name.
*/
bzero((void*)&tables, sizeof(TABLE_LIST));
tables.alias= tables.table_name= (char*) share->table_name.str;
tables.table= table;
tables.next_local= 0;
tables.next_name_resolution_table= 0;
strmov(db_name_string, name);
dir_length= dirname_length(db_name_string);
db_name_string[dir_length - 1]= 0;
home_dir_length= dirname_length(db_name_string);
db_name= &db_name_string[home_dir_length];
tables.db= db_name;
if (!is_create_table_ind || if (!is_create_table_ind ||
thd->lex->sql_command != SQLCOM_CREATE_TABLE) thd->lex->sql_command != SQLCOM_CREATE_TABLE)
...@@ -1391,9 +1440,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1391,9 +1440,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
} }
else else
{ {
if (unlikely(fix_fields_part_func(thd, &tables, if (unlikely(fix_fields_part_func(thd, part_info->subpart_expr,
part_info->subpart_expr, part_info, table, TRUE, TRUE)))
TRUE)))
goto end; goto end;
if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT)) if (unlikely(part_info->subpart_expr->result_type() != INT_RESULT))
{ {
...@@ -1420,8 +1468,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1420,8 +1468,8 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
} }
else else
{ {
if (unlikely(fix_fields_part_func(thd, &tables, part_info->part_expr, if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
part_info, FALSE))) table, FALSE, TRUE)))
goto end; goto end;
if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
{ {
...@@ -1434,6 +1482,9 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1434,6 +1482,9 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
else else
{ {
const char *error_str; const char *error_str;
if (unlikely(fix_fields_part_func(thd, part_info->part_expr,
table, FALSE, TRUE)))
goto end;
if (part_info->part_type == RANGE_PARTITION) if (part_info->part_type == RANGE_PARTITION)
{ {
error_str= partition_keywords[PKW_RANGE].str; error_str= partition_keywords[PKW_RANGE].str;
...@@ -1457,9 +1508,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1457,9 +1508,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str); my_error(ER_PARTITIONS_MUST_BE_DEFINED_ERROR, MYF(0), error_str);
goto end; goto end;
} }
if (unlikely(fix_fields_part_func(thd, &tables, part_info->part_expr,
part_info, FALSE)))
goto end;
if (unlikely(part_info->part_expr->result_type() != INT_RESULT)) if (unlikely(part_info->part_expr->result_type() != INT_RESULT))
{ {
my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str); my_error(ER_PARTITION_FUNC_NOT_ALLOWED_ERROR, MYF(0), part_str);
...@@ -1479,7 +1527,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table, ...@@ -1479,7 +1527,6 @@ bool fix_partition_func(THD *thd, const char* name, TABLE *table,
check_range_capable_PF(table); check_range_capable_PF(table);
set_up_partition_key_maps(table, part_info); set_up_partition_key_maps(table, part_info);
set_up_partition_func_pointers(part_info); set_up_partition_func_pointers(part_info);
part_info->fixed= TRUE;
set_up_range_analysis_info(part_info); set_up_range_analysis_info(part_info);
result= FALSE; result= FALSE;
end: end:
...@@ -1563,6 +1610,7 @@ static int add_hash(File fptr) ...@@ -1563,6 +1610,7 @@ static int add_hash(File fptr)
static int add_partition(File fptr) static int add_partition(File fptr)
{ {
char buff[22];
strxmov(buff, part_str, space_str, NullS); strxmov(buff, part_str, space_str, NullS);
return add_string(fptr, buff); return add_string(fptr, buff);
} }
...@@ -1576,6 +1624,7 @@ static int add_subpartition(File fptr) ...@@ -1576,6 +1624,7 @@ static int add_subpartition(File fptr)
static int add_partition_by(File fptr) static int add_partition_by(File fptr)
{ {
char buff[22];
strxmov(buff, part_str, space_str, by_str, space_str, NullS); strxmov(buff, part_str, space_str, by_str, space_str, NullS);
return add_string(fptr, buff); return add_string(fptr, buff);
} }
...@@ -1616,10 +1665,18 @@ static int add_key_partition(File fptr, List<char> field_list) ...@@ -1616,10 +1665,18 @@ static int add_key_partition(File fptr, List<char> field_list)
static int add_int(File fptr, longlong number) static int add_int(File fptr, longlong number)
{ {
char buff[32];
llstr(number, buff); llstr(number, buff);
return add_string(fptr, buff); return add_string(fptr, buff);
} }
static int add_uint(File fptr, ulonglong number)
{
char buff[32];
longlong2str(number, buff, 10);
return add_string(fptr, buff);
}
static int add_keyword_string(File fptr, const char *keyword, static int add_keyword_string(File fptr, const char *keyword,
bool should_use_quotes, bool should_use_quotes,
const char *keystr) const char *keystr)
...@@ -1681,28 +1738,43 @@ static int add_partition_options(File fptr, partition_element *p_elem) ...@@ -1681,28 +1738,43 @@ static int add_partition_options(File fptr, partition_element *p_elem)
} }
static int add_partition_values(File fptr, partition_info *part_info, static int add_partition_values(File fptr, partition_info *part_info,
partition_element *p_elem) partition_element *p_elem)
{ {
int err= 0; int err= 0;
if (part_info->part_type == RANGE_PARTITION) if (part_info->part_type == RANGE_PARTITION)
{ {
err+= add_string(fptr, "VALUES LESS THAN "); err+= add_string(fptr, "VALUES LESS THAN ");
if (p_elem->range_value != LONGLONG_MAX) if (p_elem->signed_flag)
{ {
err+= add_begin_parenthesis(fptr); if (!p_elem->max_value)
err+= add_int(fptr, p_elem->range_value); {
err+= add_end_parenthesis(fptr); err+= add_begin_parenthesis(fptr);
err+= add_int(fptr, p_elem->range_value);
err+= add_end_parenthesis(fptr);
}
else
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
} }
else else
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str); {
if (!p_elem->max_value)
{
err+= add_begin_parenthesis(fptr);
err+= add_uint(fptr, (ulonglong)p_elem->range_value);
err+= add_end_parenthesis(fptr);
}
else
err+= add_string(fptr, partition_keywords[PKW_MAXVALUE].str);
}
} }
else if (part_info->part_type == LIST_PARTITION) else if (part_info->part_type == LIST_PARTITION)
{ {
uint i; uint i;
List_iterator<longlong> list_val_it(p_elem->list_val_list); List_iterator<part_elem_value> list_val_it(p_elem->list_val_list);
err+= add_string(fptr, "VALUES IN "); err+= add_string(fptr, "VALUES IN ");
uint no_items= p_elem->list_val_list.elements; uint no_items= p_elem->list_val_list.elements;
err+= add_begin_parenthesis(fptr); err+= add_begin_parenthesis(fptr);
if (p_elem->has_null_value) if (p_elem->has_null_value)
{ {
...@@ -1717,8 +1789,12 @@ static int add_partition_values(File fptr, partition_info *part_info, ...@@ -1717,8 +1789,12 @@ static int add_partition_values(File fptr, partition_info *part_info,
i= 0; i= 0;
do do
{ {
longlong *list_value= list_val_it++; part_elem_value *list_value= list_val_it++;
err+= add_int(fptr, *list_value);
if (!list_value->unsigned_flag)
err+= add_int(fptr, list_value->value);
else
err+= add_uint(fptr, list_value->value);
if (i != (no_items-1)) if (i != (no_items-1))
err+= add_comma(fptr); err+= add_comma(fptr);
} while (++i < no_items); } while (++i < no_items);
...@@ -2294,15 +2370,15 @@ static uint32 get_part_id_linear_key(partition_info *part_info, ...@@ -2294,15 +2370,15 @@ static uint32 get_part_id_linear_key(partition_info *part_info,
int get_partition_id_list(partition_info *part_info, int get_partition_id_list(partition_info *part_info,
uint32 *part_id, uint32 *part_id,
longlong *func_value) longlong *func_value)
{ {
LIST_PART_ENTRY *list_array= part_info->list_array; LIST_PART_ENTRY *list_array= part_info->list_array;
int list_index; int list_index;
longlong list_value;
int min_list_index= 0; int min_list_index= 0;
int max_list_index= part_info->no_list_values - 1; int max_list_index= part_info->no_list_values - 1;
longlong part_func_value= part_val_int(part_info->part_expr); longlong part_func_value= part_val_int(part_info->part_expr);
bool unsigned_flag= part_info->part_expr->unsigned_flag;
DBUG_ENTER("get_partition_id_list"); DBUG_ENTER("get_partition_id_list");
if (part_info->part_expr->null_value) if (part_info->part_expr->null_value)
...@@ -2315,22 +2391,49 @@ int get_partition_id_list(partition_info *part_info, ...@@ -2315,22 +2391,49 @@ int get_partition_id_list(partition_info *part_info,
goto notfound; goto notfound;
} }
*func_value= part_func_value; *func_value= part_func_value;
while (max_list_index >= min_list_index) if (!unsigned_flag)
{ {
list_index= (max_list_index + min_list_index) >> 1; longlong list_value;
list_value= list_array[list_index].list_value; while (max_list_index >= min_list_index)
if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{ {
if (!list_index) list_index= (max_list_index + min_list_index) >> 1;
goto notfound; list_value= list_array[list_index].list_value;
max_list_index= list_index - 1; if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{
if (!list_index)
goto notfound;
max_list_index= list_index - 1;
}
else
{
*part_id= (uint32)list_array[list_index].partition_id;
DBUG_RETURN(0);
}
} }
else }
else
{
ulonglong ulist_value;
ulonglong upart_func_value= part_func_value;
while (max_list_index >= min_list_index)
{ {
*part_id= (uint32)list_array[list_index].partition_id; list_index= (max_list_index + min_list_index) >> 1;
DBUG_RETURN(0); ulist_value= list_array[list_index].list_value;
if (ulist_value < upart_func_value)
min_list_index= list_index + 1;
else if (ulist_value > upart_func_value)
{
if (!list_index)
goto notfound;
max_list_index= list_index - 1;
}
else
{
*part_id= (uint32)list_array[list_index].partition_id;
DBUG_RETURN(0);
}
} }
} }
notfound: notfound:
...@@ -2381,34 +2484,65 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, ...@@ -2381,34 +2484,65 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
bool left_endpoint, bool left_endpoint,
bool include_endpoint) bool include_endpoint)
{ {
DBUG_ENTER("get_list_array_idx_for_endpoint");
LIST_PART_ENTRY *list_array= part_info->list_array; LIST_PART_ENTRY *list_array= part_info->list_array;
uint list_index; uint list_index;
longlong list_value;
uint min_list_index= 0, max_list_index= part_info->no_list_values - 1; uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
/* Get the partitioning function value for the endpoint */ /* Get the partitioning function value for the endpoint */
longlong part_func_value= part_val_int(part_info->part_expr); longlong part_func_value= part_val_int(part_info->part_expr);
while (max_list_index >= min_list_index) bool unsigned_flag= part_info->part_expr->unsigned_flag;
DBUG_ENTER("get_list_array_idx_for_endpoint");
if (!unsigned_flag)
{ {
list_index= (max_list_index + min_list_index) >> 1; longlong list_value;
list_value= list_array[list_index].list_value; while (max_list_index >= min_list_index)
if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{ {
if (!list_index) list_index= (max_list_index + min_list_index) >> 1;
goto notfound; list_value= list_array[list_index].list_value;
max_list_index= list_index - 1; if (list_value < part_func_value)
min_list_index= list_index + 1;
else if (list_value > part_func_value)
{
if (!list_index)
goto notfound_signed;
max_list_index= list_index - 1;
}
else
{
DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
}
} }
else notfound_signed:
if (list_value < part_func_value)
list_index++;
DBUG_RETURN(list_index);
}
else
{
ulonglong upart_func_value= part_func_value;
ulonglong ulist_value;
while (max_list_index >= min_list_index)
{ {
DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint)); list_index= (max_list_index + min_list_index) >> 1;
ulist_value= list_array[list_index].list_value;
if (ulist_value < upart_func_value)
min_list_index= list_index + 1;
else if (ulist_value > upart_func_value)
{
if (!list_index)
goto notfound_unsigned;
max_list_index= list_index - 1;
}
else
{
DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
}
} }
notfound_unsigned:
if (ulist_value < upart_func_value)
list_index++;
DBUG_RETURN(list_index);
} }
notfound:
if (list_value < part_func_value)
list_index++;
DBUG_RETURN(list_index);
} }
...@@ -2422,6 +2556,7 @@ int get_partition_id_range(partition_info *part_info, ...@@ -2422,6 +2556,7 @@ int get_partition_id_range(partition_info *part_info,
uint max_part_id= max_partition; uint max_part_id= max_partition;
uint loc_part_id; uint loc_part_id;
longlong part_func_value= part_val_int(part_info->part_expr); longlong part_func_value= part_val_int(part_info->part_expr);
bool unsigned_flag= part_info->part_expr->unsigned_flag;
DBUG_ENTER("get_partition_id_int_range"); DBUG_ENTER("get_partition_id_int_range");
if (part_info->part_expr->null_value) if (part_info->part_expr->null_value)
...@@ -2429,24 +2564,52 @@ int get_partition_id_range(partition_info *part_info, ...@@ -2429,24 +2564,52 @@ int get_partition_id_range(partition_info *part_info,
*part_id= 0; *part_id= 0;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
while (max_part_id > min_part_id) *func_value= part_func_value;
if (!unsigned_flag)
{ {
loc_part_id= (max_part_id + min_part_id + 1) >> 1; while (max_part_id > min_part_id)
if (range_array[loc_part_id] <= part_func_value) {
min_part_id= loc_part_id + 1; loc_part_id= (max_part_id + min_part_id + 1) >> 1;
else if (range_array[loc_part_id] <= part_func_value)
max_part_id= loc_part_id - 1; min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
}
loc_part_id= max_part_id;
if (part_func_value >= range_array[loc_part_id])
if (loc_part_id != max_partition)
loc_part_id++;
*part_id= (uint32)loc_part_id;
if (loc_part_id == max_partition)
if (range_array[loc_part_id] != LONGLONG_MAX)
if (part_func_value >= range_array[loc_part_id])
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
}
else
{
ulonglong upart_func_value= part_func_value;
ulonglong urange_value;
while (max_part_id > min_part_id)
{
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
urange_value= range_array[loc_part_id];
if (urange_value <= upart_func_value)
min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
}
loc_part_id= max_part_id;
urange_value= range_array[loc_part_id];
if (upart_func_value >= urange_value)
if (loc_part_id != max_partition)
loc_part_id++;
*part_id= (uint32)loc_part_id;
urange_value= range_array[loc_part_id];
if (loc_part_id == max_partition)
if (urange_value != ULONGLONG_MAX)
if (upart_func_value >= urange_value)
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
} }
loc_part_id= max_part_id;
if (part_func_value >= range_array[loc_part_id])
if (loc_part_id != max_partition)
loc_part_id++;
*part_id= (uint32)loc_part_id;
*func_value= part_func_value;
if (loc_part_id == max_partition)
if (range_array[loc_part_id] != LONGLONG_MAX)
if (part_func_value >= range_array[loc_part_id])
DBUG_RETURN(HA_ERR_NO_PARTITION_FOUND);
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -2496,39 +2659,79 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info, ...@@ -2496,39 +2659,79 @@ uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
bool left_endpoint, bool left_endpoint,
bool include_endpoint) bool include_endpoint)
{ {
DBUG_ENTER("get_partition_id_range_for_endpoint");
longlong *range_array= part_info->range_int_array; longlong *range_array= part_info->range_int_array;
uint max_partition= part_info->no_parts - 1; uint max_partition= part_info->no_parts - 1;
uint min_part_id= 0, max_part_id= max_partition, loc_part_id; uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
/* Get the partitioning function value for the endpoint */ /* Get the partitioning function value for the endpoint */
longlong part_func_value= part_val_int(part_info->part_expr); longlong part_func_value= part_val_int(part_info->part_expr);
bool unsigned_flag= part_info->part_expr->unsigned_flag;
DBUG_ENTER("get_partition_id_range_for_endpoint");
while (max_part_id > min_part_id) if (!unsigned_flag)
{ {
loc_part_id= (max_part_id + min_part_id + 1) >> 1; while (max_part_id > min_part_id)
if (range_array[loc_part_id] <= part_func_value) {
min_part_id= loc_part_id + 1; loc_part_id= (max_part_id + min_part_id + 1) >> 1;
else if (range_array[loc_part_id] <= part_func_value)
max_part_id= loc_part_id - 1; min_part_id= loc_part_id + 1;
} else
loc_part_id= max_part_id; max_part_id= loc_part_id - 1;
if (loc_part_id < max_partition && }
part_func_value >= range_array[loc_part_id+1]) loc_part_id= max_part_id;
{ if (loc_part_id < max_partition &&
loc_part_id++; part_func_value >= range_array[loc_part_id+1])
} {
if (left_endpoint) loc_part_id++;
{ }
if (part_func_value >= range_array[loc_part_id]) if (left_endpoint)
{
if (part_func_value >= range_array[loc_part_id])
loc_part_id++;
}
else
{
if (part_func_value == range_array[loc_part_id])
loc_part_id += test(include_endpoint);
else if (part_func_value > range_array[loc_part_id])
loc_part_id++;
loc_part_id++; loc_part_id++;
}
} }
else else
{ {
if (part_func_value == range_array[loc_part_id]) ulonglong upart_func_value= part_func_value;
loc_part_id += test(include_endpoint); ulonglong urange_value;
else if (part_func_value > range_array[loc_part_id]) while (max_part_id > min_part_id)
{
loc_part_id= (max_part_id + min_part_id + 1) >> 1;
urange_value= range_array[loc_part_id];
if (urange_value <= upart_func_value)
min_part_id= loc_part_id + 1;
else
max_part_id= loc_part_id - 1;
}
loc_part_id= max_part_id;
urange_value= range_array[loc_part_id+1];
if (loc_part_id < max_partition &&
upart_func_value >= urange_value)
{
loc_part_id++;
}
if (left_endpoint)
{
urange_value= range_array[loc_part_id];
if (upart_func_value >= urange_value)
loc_part_id++;
}
else
{
urange_value= range_array[loc_part_id];
if (upart_func_value == urange_value)
loc_part_id += test(include_endpoint);
else if (upart_func_value > urange_value)
loc_part_id++;
loc_part_id++; loc_part_id++;
loc_part_id++; }
} }
DBUG_RETURN(loc_part_id); DBUG_RETURN(loc_part_id);
} }
...@@ -4497,8 +4700,8 @@ the generated partition syntax in a correct manner. ...@@ -4497,8 +4700,8 @@ the generated partition syntax in a correct manner.
tab_part_info->use_default_subpartitions= FALSE; tab_part_info->use_default_subpartitions= FALSE;
tab_part_info->use_default_no_subpartitions= FALSE; tab_part_info->use_default_no_subpartitions= FALSE;
} }
if (tab_part_info->check_partition_info((handlerton**)NULL, if (tab_part_info->check_partition_info(thd, (handlerton**)NULL,
table->file, ULL(0))) table->file, ULL(0)))
{ {
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
......
...@@ -65,9 +65,8 @@ int get_part_for_delete(const byte *buf, const byte *rec0, ...@@ -65,9 +65,8 @@ int get_part_for_delete(const byte *buf, const byte *rec0,
partition_info *part_info, uint32 *part_id); partition_info *part_info, uint32 *part_id);
void prune_partition_set(const TABLE *table, part_id_range *part_spec); void prune_partition_set(const TABLE *table, part_id_range *part_spec);
bool check_partition_info(partition_info *part_info,handlerton **eng_type, bool check_partition_info(partition_info *part_info,handlerton **eng_type,
handler *file, ulonglong max_rows); TABLE *table, handler *file, ulonglong max_rows);
bool fix_partition_func(THD *thd, const char *name, TABLE *table, bool fix_partition_func(THD *thd, TABLE *table, bool create_table_ind);
bool create_table_ind);
char *generate_partition_syntax(partition_info *part_info, char *generate_partition_syntax(partition_info *part_info,
uint *buf_length, bool use_sql_alloc, uint *buf_length, bool use_sql_alloc,
bool write_all); bool write_all);
...@@ -91,6 +90,8 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info, ...@@ -91,6 +90,8 @@ uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
uint32 get_partition_id_range_for_endpoint(partition_info *part_info, uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
bool left_endpoint, bool left_endpoint,
bool include_endpoint); bool include_endpoint);
bool fix_fields_part_func(THD *thd, Item* func_expr, TABLE *table,
bool is_sub_part, bool is_field_to_be_setup);
/* /*
A "Get next" function for partition iterator. A "Get next" function for partition iterator.
......
...@@ -3851,8 +3851,8 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, ...@@ -3851,8 +3851,8 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
} }
else if (part_info->part_type == LIST_PARTITION) else if (part_info->part_type == LIST_PARTITION)
{ {
List_iterator<longlong> list_val_it(part_elem->list_val_list); List_iterator<part_elem_value> list_val_it(part_elem->list_val_list);
longlong *list_value; part_elem_value *list_value;
uint no_items= part_elem->list_val_list.elements; uint no_items= part_elem->list_val_list.elements;
tmp_str.length(0); tmp_str.length(0);
tmp_res.length(0); tmp_res.length(0);
...@@ -3864,7 +3864,10 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables, ...@@ -3864,7 +3864,10 @@ static int get_schema_partitions_record(THD *thd, struct st_table_list *tables,
} }
while ((list_value= list_val_it++)) while ((list_value= list_val_it++))
{ {
tmp_res.set(*list_value, cs); if (!list_value->unsigned_flag)
tmp_res.set(list_value->value, cs);
else
tmp_res.set((ulonglong)list_value->value, cs);
tmp_str.append(tmp_res); tmp_str.append(tmp_res);
if (--no_items != 0) if (--no_items != 0)
tmp_str.append(","); tmp_str.append(",");
......
...@@ -2141,8 +2141,8 @@ bool mysql_create_table_internal(THD *thd, ...@@ -2141,8 +2141,8 @@ bool mysql_create_table_internal(THD *thd,
} }
DBUG_PRINT("info", ("db_type = %d", DBUG_PRINT("info", ("db_type = %d",
ha_legacy_type(part_info->default_engine_type))); ha_legacy_type(part_info->default_engine_type)));
if (part_info->check_partition_info( &engine_type, file, if (part_info->check_partition_info(thd, &engine_type, file,
create_info->max_rows)) create_info->max_rows))
goto err; goto err;
part_info->default_engine_type= engine_type; part_info->default_engine_type= engine_type;
......
...@@ -42,12 +42,6 @@ ...@@ -42,12 +42,6 @@
#include <myisam.h> #include <myisam.h>
#include <myisammrg.h> #include <myisammrg.h>
typedef struct p_elem_val
{
longlong value;
bool null_value;
} part_elem_value;
int yylex(void *yylval, void *yythd); int yylex(void *yylval, void *yythd);
const LEX_STRING null_lex_str={0,0}; const LEX_STRING null_lex_str={0,0};
...@@ -3712,6 +3706,7 @@ part_func_max: ...@@ -3712,6 +3706,7 @@ part_func_max:
YYABORT; YYABORT;
} }
lex->part_info->defined_max_value= TRUE; lex->part_info->defined_max_value= TRUE;
lex->part_info->curr_part_elem->max_value= TRUE;
lex->part_info->curr_part_elem->range_value= LONGLONG_MAX; lex->part_info->curr_part_elem->range_value= LONGLONG_MAX;
} }
| part_range_func | part_range_func
...@@ -3727,7 +3722,10 @@ part_func_max: ...@@ -3727,7 +3722,10 @@ part_func_max:
part_range_func: part_range_func:
'(' part_bit_expr ')' '(' part_bit_expr ')'
{ {
Lex->part_info->curr_part_elem->range_value= $2->value; 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;
} }
; ;
...@@ -3740,9 +3738,12 @@ part_list_item: ...@@ -3740,9 +3738,12 @@ part_list_item:
part_bit_expr part_bit_expr
{ {
part_elem_value *value_ptr= $1; 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 && if (!value_ptr->null_value &&
Lex->part_info->curr_part_elem-> part_info->curr_part_elem->
list_val_list.push_back((longlong*) &value_ptr->value)) list_val_list.push_back(value_ptr))
{ {
mem_alloc_error(sizeof(part_elem_value)); mem_alloc_error(sizeof(part_elem_value));
YYABORT; YYABORT;
...@@ -3783,6 +3784,10 @@ part_bit_expr: ...@@ -3783,6 +3784,10 @@ part_bit_expr:
} }
thd->where= save_where; thd->where= save_where;
value_ptr->value= part_expr->val_int(); 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 ((value_ptr->null_value= part_expr->null_value))
{ {
if (Lex->part_info->curr_part_elem->has_null_value) if (Lex->part_info->curr_part_elem->has_null_value)
......
...@@ -1488,8 +1488,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, ...@@ -1488,8 +1488,7 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
Fix the partition functions and ensure they are not constant Fix the partition functions and ensure they are not constant
functions functions
*/ */
if (fix_partition_func(thd, share->normalized_path.str, outparam, if (fix_partition_func(thd, outparam, is_create_table))
is_create_table))
goto err; goto err;
} }
#endif #endif
......
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