mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
BUG#15408: Partitions: subpartition names are not unique
Also, moved some of the code out of handler.h and into partition specific files for better separation. Also, moved some of the C funcs into partition_info as formal C++ methods mysql-test/r/partition_mgm_err.result: result block for test of bug # 15408 mysql-test/t/partition_mgm_err.test: test for duplicate subpartition names sql/Makefile.am: adding sql_partition.h, partition_info.cpp, partition_info.h, and partition_element.h to the makefile sql/ha_partition.cc: using the new members of partition_info sql/ha_partition.h: using the new members of partition_info sql/handler.h: moved this code into sql_partition.h sql/mysql_priv.h: including sql_partition.h also now sql/opt_range.cc: using the new members of partition_info sql/sql_partition.cc: moved some of the functions out and into the partition_info class using the new members of partition_info sql/sql_show.cc: using the new members of partition_info win/cmakefiles/sql: added partition_info.cpp to the sql cmake file sql/partition_element.h: New BitKeeper file ``sql/partition_element.h'' sql/partition_info.h: New BitKeeper file ``sql/partition_info.h'' sql/sql_partition.h: New BitKeeper file ``sql/sql_partition.h''
This commit is contained in:
496
sql/handler.h
496
sql/handler.h
@@ -95,13 +95,6 @@
|
||||
#define HA_ANY_INDEX_MAY_BE_UNIQUE (1 << 30)
|
||||
#define HA_NO_COPY_ON_ALTER (1 << 31)
|
||||
|
||||
/* Flags for partition handlers */
|
||||
#define HA_CAN_PARTITION (1 << 0) /* Partition support */
|
||||
#define HA_CAN_UPDATE_PARTITION_KEY (1 << 1)
|
||||
#define HA_CAN_PARTITION_UNIQUE (1 << 2)
|
||||
#define HA_USE_AUTO_PARTITION (1 << 3)
|
||||
|
||||
|
||||
/* bits in index_flags(index_number) for what you can do with index */
|
||||
#define HA_READ_NEXT 1 /* TODO really use this flag */
|
||||
#define HA_READ_PREV 2 /* supports ::index_prev */
|
||||
@@ -134,34 +127,6 @@
|
||||
#define HA_ONLINE_DROP_UNIQUE_INDEX (1L << 9) /*drop uniq. online*/
|
||||
#define HA_ONLINE_ADD_PK_INDEX (1L << 10)/*add prim. online*/
|
||||
#define HA_ONLINE_DROP_PK_INDEX (1L << 11)/*drop prim. online*/
|
||||
/*
|
||||
HA_PARTITION_FUNCTION_SUPPORTED indicates that the function is
|
||||
supported at all.
|
||||
HA_FAST_CHANGE_PARTITION means that optimised variants of the changes
|
||||
exists but they are not necessarily done online.
|
||||
|
||||
HA_ONLINE_DOUBLE_WRITE means that the handler supports writing to both
|
||||
the new partition and to the old partitions when updating through the
|
||||
old partitioning schema while performing a change of the partitioning.
|
||||
This means that we can support updating of the table while performing
|
||||
the copy phase of the change. For no lock at all also a double write
|
||||
from new to old must exist and this is not required when this flag is
|
||||
set.
|
||||
This is actually removed even before it was introduced the first time.
|
||||
The new idea is that handlers will handle the lock level already in
|
||||
store_lock for ALTER TABLE partitions.
|
||||
|
||||
HA_PARTITION_ONE_PHASE is a flag that can be set by handlers that take
|
||||
care of changing the partitions online and in one phase. Thus all phases
|
||||
needed to handle the change are implemented inside the storage engine.
|
||||
The storage engine must also support auto-discovery since the frm file
|
||||
is changed as part of the change and this change must be controlled by
|
||||
the storage engine. A typical engine to support this is NDB (through
|
||||
WL #2498).
|
||||
*/
|
||||
#define HA_PARTITION_FUNCTION_SUPPORTED (1L << 12)
|
||||
#define HA_FAST_CHANGE_PARTITION (1L << 13)
|
||||
#define HA_PARTITION_ONE_PHASE (1L << 14)
|
||||
|
||||
/*
|
||||
Index scan will not return records in rowid order. Not guaranteed to be
|
||||
@@ -618,33 +583,6 @@ enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
|
||||
|
||||
enum ndb_distribution { ND_KEYHASH= 0, ND_LINHASH= 1 };
|
||||
|
||||
typedef struct {
|
||||
uint32 start_part;
|
||||
uint32 end_part;
|
||||
} part_id_range;
|
||||
|
||||
|
||||
/**
|
||||
* An enum and a struct to handle partitioning and subpartitioning.
|
||||
*/
|
||||
enum partition_type {
|
||||
NOT_A_PARTITION= 0,
|
||||
RANGE_PARTITION,
|
||||
HASH_PARTITION,
|
||||
LIST_PARTITION
|
||||
};
|
||||
|
||||
enum partition_state {
|
||||
PART_NORMAL= 0,
|
||||
PART_IS_DROPPED= 1,
|
||||
PART_TO_BE_DROPPED= 2,
|
||||
PART_TO_BE_ADDED= 3,
|
||||
PART_TO_BE_REORGED= 4,
|
||||
PART_REORGED_DROPPED= 5,
|
||||
PART_CHANGED= 6,
|
||||
PART_IS_CHANGED= 7,
|
||||
PART_IS_ADDED= 8
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ulonglong data_file_length;
|
||||
@@ -662,400 +600,12 @@ typedef struct {
|
||||
#define UNDEF_NODEGROUP 65535
|
||||
class Item;
|
||||
|
||||
class partition_element :public Sql_alloc {
|
||||
public:
|
||||
List<partition_element> subpartitions;
|
||||
List<longlong> list_val_list;
|
||||
ulonglong part_max_rows;
|
||||
ulonglong part_min_rows;
|
||||
char *partition_name;
|
||||
char *tablespace_name;
|
||||
longlong range_value;
|
||||
char* part_comment;
|
||||
char* data_file_name;
|
||||
char* index_file_name;
|
||||
handlerton *engine_type;
|
||||
enum partition_state part_state;
|
||||
uint16 nodegroup_id;
|
||||
|
||||
partition_element()
|
||||
: part_max_rows(0), part_min_rows(0), partition_name(NULL),
|
||||
tablespace_name(NULL), range_value(0), part_comment(NULL),
|
||||
data_file_name(NULL), index_file_name(NULL),
|
||||
engine_type(NULL),part_state(PART_NORMAL),
|
||||
nodegroup_id(UNDEF_NODEGROUP)
|
||||
{
|
||||
subpartitions.empty();
|
||||
list_val_list.empty();
|
||||
}
|
||||
~partition_element() {}
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
longlong list_value;
|
||||
uint32 partition_id;
|
||||
} LIST_PART_ENTRY;
|
||||
|
||||
class partition_info;
|
||||
|
||||
typedef int (*get_part_id_func)(partition_info *part_info,
|
||||
uint32 *part_id,
|
||||
longlong *func_value);
|
||||
typedef uint32 (*get_subpart_id_func)(partition_info *part_info);
|
||||
|
||||
|
||||
struct st_partition_iter;
|
||||
#define NOT_A_PARTITION_ID ((uint32)-1)
|
||||
|
||||
/*
|
||||
A "Get next" function for partition iterator.
|
||||
SYNOPSIS
|
||||
partition_iter_func()
|
||||
part_iter Partition iterator, you call only "iter.get_next(&iter)"
|
||||
|
||||
RETURN
|
||||
NOT_A_PARTITION_ID if there are no more partitions.
|
||||
[sub]partition_id of the next partition
|
||||
*/
|
||||
|
||||
typedef uint32 (*partition_iter_func)(st_partition_iter* part_iter);
|
||||
|
||||
|
||||
/*
|
||||
Partition set iterator. Used to enumerate a set of [sub]partitions
|
||||
obtained in partition interval analysis (see get_partitions_in_range_iter).
|
||||
|
||||
For the user, the only meaningful field is get_next, which may be used as
|
||||
follows:
|
||||
part_iterator.get_next(&part_iterator);
|
||||
|
||||
Initialization is done by any of the following calls:
|
||||
- get_partitions_in_range_iter-type function call
|
||||
- init_single_partition_iterator()
|
||||
- init_all_partitions_iterator()
|
||||
Cleanup is not needed.
|
||||
*/
|
||||
|
||||
typedef struct st_partition_iter
|
||||
{
|
||||
partition_iter_func get_next;
|
||||
|
||||
struct st_part_num_range
|
||||
{
|
||||
uint32 start;
|
||||
uint32 end;
|
||||
};
|
||||
|
||||
struct st_field_value_range
|
||||
{
|
||||
longlong start;
|
||||
longlong end;
|
||||
};
|
||||
|
||||
union
|
||||
{
|
||||
struct st_part_num_range part_nums;
|
||||
struct st_field_value_range field_vals;
|
||||
};
|
||||
partition_info *part_info;
|
||||
} PARTITION_ITERATOR;
|
||||
|
||||
|
||||
/*
|
||||
Get an iterator for set of partitions that match given field-space interval
|
||||
|
||||
SYNOPSIS
|
||||
get_partitions_in_range_iter()
|
||||
part_info Partitioning info
|
||||
is_subpart
|
||||
min_val Left edge, field value in opt_range_key format.
|
||||
max_val Right edge, field value in opt_range_key format.
|
||||
flags Some combination of NEAR_MIN, NEAR_MAX, NO_MIN_RANGE,
|
||||
NO_MAX_RANGE.
|
||||
part_iter Iterator structure to be initialized
|
||||
|
||||
DESCRIPTION
|
||||
Functions with this signature are used to perform "Partitioning Interval
|
||||
Analysis". This analysis is applicable for any type of [sub]partitioning
|
||||
by some function of a single fieldX. The idea is as follows:
|
||||
Given an interval "const1 <=? fieldX <=? const2", find a set of partitions
|
||||
that may contain records with value of fieldX within the given interval.
|
||||
|
||||
The min_val, max_val and flags parameters specify the interval.
|
||||
The set of partitions is returned by initializing an iterator in *part_iter
|
||||
|
||||
NOTES
|
||||
There are currently two functions of this type:
|
||||
- get_part_iter_for_interval_via_walking
|
||||
- get_part_iter_for_interval_via_mapping
|
||||
|
||||
RETURN
|
||||
0 - No matching partitions, iterator not initialized
|
||||
1 - Some partitions would match, iterator intialized for traversing them
|
||||
-1 - All partitions would match, iterator not initialized
|
||||
*/
|
||||
|
||||
typedef int (*get_partitions_in_range_iter)(partition_info *part_info,
|
||||
bool is_subpart,
|
||||
char *min_val, char *max_val,
|
||||
uint flags,
|
||||
PARTITION_ITERATOR *part_iter);
|
||||
|
||||
|
||||
class partition_info : public Sql_alloc
|
||||
{
|
||||
public:
|
||||
/*
|
||||
* Here comes a set of definitions needed for partitioned table handlers.
|
||||
*/
|
||||
List<partition_element> partitions;
|
||||
List<partition_element> temp_partitions;
|
||||
|
||||
List<char> part_field_list;
|
||||
List<char> subpart_field_list;
|
||||
|
||||
/*
|
||||
If there is no subpartitioning, use only this func to get partition ids.
|
||||
If there is subpartitioning, use the this func to get partition id when
|
||||
you have both partition and subpartition fields.
|
||||
*/
|
||||
get_part_id_func get_partition_id;
|
||||
|
||||
/* Get partition id when we don't have subpartition fields */
|
||||
get_part_id_func get_part_partition_id;
|
||||
|
||||
/*
|
||||
Get subpartition id when we have don't have partition fields by we do
|
||||
have subpartition ids.
|
||||
Mikael said that for given constant tuple
|
||||
{subpart_field1, ..., subpart_fieldN} the subpartition id will be the
|
||||
same in all subpartitions
|
||||
*/
|
||||
get_subpart_id_func get_subpartition_id;
|
||||
|
||||
/* NULL-terminated array of fields used in partitioned expression */
|
||||
Field **part_field_array;
|
||||
/* NULL-terminated array of fields used in subpartitioned expression */
|
||||
Field **subpart_field_array;
|
||||
|
||||
/*
|
||||
Array of all fields used in partition and subpartition expression,
|
||||
without duplicates, NULL-terminated.
|
||||
*/
|
||||
Field **full_part_field_array;
|
||||
|
||||
Item *part_expr;
|
||||
Item *subpart_expr;
|
||||
|
||||
Item *item_free_list;
|
||||
|
||||
/*
|
||||
A bitmap of partitions used by the current query.
|
||||
Usage pattern:
|
||||
* The handler->extra(HA_EXTRA_RESET) call at query start/end sets all
|
||||
partitions to be unused.
|
||||
* Before index/rnd_init(), partition pruning code sets the bits for used
|
||||
partitions.
|
||||
*/
|
||||
MY_BITMAP used_partitions;
|
||||
|
||||
union {
|
||||
longlong *range_int_array;
|
||||
LIST_PART_ENTRY *list_array;
|
||||
};
|
||||
|
||||
/********************************************
|
||||
* INTERVAL ANALYSIS
|
||||
********************************************/
|
||||
/*
|
||||
Partitioning interval analysis function for partitioning, or NULL if
|
||||
interval analysis is not supported for this kind of partitioning.
|
||||
*/
|
||||
get_partitions_in_range_iter get_part_iter_for_interval;
|
||||
/*
|
||||
Partitioning interval analysis function for subpartitioning, or NULL if
|
||||
interval analysis is not supported for this kind of partitioning.
|
||||
*/
|
||||
get_partitions_in_range_iter get_subpart_iter_for_interval;
|
||||
|
||||
/*
|
||||
Valid iff
|
||||
get_part_iter_for_interval=get_part_iter_for_interval_via_walking:
|
||||
controls how we'll process "field < C" and "field > C" intervals.
|
||||
If the partitioning function F is strictly increasing, then for any x, y
|
||||
"x < y" => "F(x) < F(y)" (*), i.e. when we get interval "field < C"
|
||||
we can perform partition pruning on the equivalent "F(field) < F(C)".
|
||||
|
||||
If the partitioning function not strictly increasing (it is simply
|
||||
increasing), then instead of (*) we get "x < y" => "F(x) <= F(y)"
|
||||
i.e. for interval "field < C" we can perform partition pruning for
|
||||
"F(field) <= F(C)".
|
||||
*/
|
||||
bool range_analysis_include_bounds;
|
||||
/********************************************
|
||||
* INTERVAL ANALYSIS ENDS
|
||||
********************************************/
|
||||
|
||||
char* part_info_string;
|
||||
|
||||
char *part_func_string;
|
||||
char *subpart_func_string;
|
||||
|
||||
uchar *part_state;
|
||||
|
||||
partition_element *curr_part_elem;
|
||||
partition_element *current_partition;
|
||||
/*
|
||||
These key_map's are used for Partitioning to enable quick decisions
|
||||
on whether we can derive more information about which partition to
|
||||
scan just by looking at what index is used.
|
||||
*/
|
||||
key_map all_fields_in_PF, all_fields_in_PPF, all_fields_in_SPF;
|
||||
key_map some_fields_in_PF;
|
||||
|
||||
handlerton *default_engine_type;
|
||||
Item_result part_result_type;
|
||||
partition_type part_type;
|
||||
partition_type subpart_type;
|
||||
|
||||
uint part_info_len;
|
||||
uint part_state_len;
|
||||
uint part_func_len;
|
||||
uint subpart_func_len;
|
||||
|
||||
uint no_parts;
|
||||
uint no_subparts;
|
||||
uint count_curr_subparts;
|
||||
|
||||
uint part_error_code;
|
||||
|
||||
uint no_list_values;
|
||||
|
||||
uint no_part_fields;
|
||||
uint no_subpart_fields;
|
||||
uint no_full_part_fields;
|
||||
|
||||
/*
|
||||
This variable is used to calculate the partition id when using
|
||||
LINEAR KEY/HASH. This functionality is kept in the MySQL Server
|
||||
but mainly of use to handlers supporting partitioning.
|
||||
*/
|
||||
uint16 linear_hash_mask;
|
||||
|
||||
bool use_default_partitions;
|
||||
bool use_default_no_partitions;
|
||||
bool use_default_subpartitions;
|
||||
bool use_default_no_subpartitions;
|
||||
bool default_partitions_setup;
|
||||
bool defined_max_value;
|
||||
bool list_of_part_fields;
|
||||
bool list_of_subpart_fields;
|
||||
bool linear_hash_ind;
|
||||
bool fixed;
|
||||
bool from_openfrm;
|
||||
|
||||
partition_info()
|
||||
: get_partition_id(NULL), get_part_partition_id(NULL),
|
||||
get_subpartition_id(NULL),
|
||||
part_field_array(NULL), subpart_field_array(NULL),
|
||||
full_part_field_array(NULL),
|
||||
part_expr(NULL), subpart_expr(NULL), item_free_list(NULL),
|
||||
list_array(NULL),
|
||||
part_info_string(NULL),
|
||||
part_func_string(NULL), subpart_func_string(NULL),
|
||||
part_state(NULL),
|
||||
curr_part_elem(NULL), current_partition(NULL),
|
||||
default_engine_type(NULL),
|
||||
part_result_type(INT_RESULT),
|
||||
part_type(NOT_A_PARTITION), subpart_type(NOT_A_PARTITION),
|
||||
part_info_len(0), part_state_len(0),
|
||||
part_func_len(0), subpart_func_len(0),
|
||||
no_parts(0), no_subparts(0),
|
||||
count_curr_subparts(0), part_error_code(0),
|
||||
no_list_values(0), no_part_fields(0), no_subpart_fields(0),
|
||||
no_full_part_fields(0), linear_hash_mask(0),
|
||||
use_default_partitions(TRUE),
|
||||
use_default_no_partitions(TRUE),
|
||||
use_default_subpartitions(TRUE),
|
||||
use_default_no_subpartitions(TRUE),
|
||||
default_partitions_setup(FALSE),
|
||||
defined_max_value(FALSE),
|
||||
list_of_part_fields(FALSE), list_of_subpart_fields(FALSE),
|
||||
linear_hash_ind(FALSE),
|
||||
fixed(FALSE),
|
||||
from_openfrm(FALSE)
|
||||
{
|
||||
all_fields_in_PF.clear_all();
|
||||
all_fields_in_PPF.clear_all();
|
||||
all_fields_in_SPF.clear_all();
|
||||
some_fields_in_PF.clear_all();
|
||||
partitions.empty();
|
||||
temp_partitions.empty();
|
||||
part_field_list.empty();
|
||||
subpart_field_list.empty();
|
||||
}
|
||||
~partition_info() {}
|
||||
};
|
||||
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
uint32 get_next_partition_id_range(struct st_partition_iter* part_iter);
|
||||
|
||||
/* Initialize the iterator to return a single partition with given part_id */
|
||||
|
||||
static inline void init_single_partition_iterator(uint32 part_id,
|
||||
PARTITION_ITERATOR *part_iter)
|
||||
{
|
||||
part_iter->part_nums.start= part_id;
|
||||
part_iter->part_nums.end= part_id+1;
|
||||
part_iter->get_next= get_next_partition_id_range;
|
||||
}
|
||||
|
||||
/* Initialize the iterator to enumerate all partitions */
|
||||
static inline
|
||||
void init_all_partitions_iterator(partition_info *part_info,
|
||||
PARTITION_ITERATOR *part_iter)
|
||||
{
|
||||
part_iter->part_nums.start= 0;
|
||||
part_iter->part_nums.end= part_info->no_parts;
|
||||
part_iter->get_next= get_next_partition_id_range;
|
||||
}
|
||||
|
||||
/*
|
||||
Answers the question if subpartitioning is used for a certain table
|
||||
SYNOPSIS
|
||||
is_sub_partitioned()
|
||||
part_info A reference to the partition_info struct
|
||||
RETURN VALUE
|
||||
Returns true if subpartitioning used and false otherwise
|
||||
DESCRIPTION
|
||||
A routine to check for subpartitioning for improved readability of code
|
||||
*/
|
||||
static inline
|
||||
bool is_sub_partitioned(partition_info *part_info)
|
||||
{ return (part_info->subpart_type == NOT_A_PARTITION ? FALSE : TRUE); }
|
||||
|
||||
|
||||
/*
|
||||
Returns the total number of partitions on the leaf level.
|
||||
SYNOPSIS
|
||||
get_tot_partitions()
|
||||
part_info A reference to the partition_info struct
|
||||
RETURN VALUE
|
||||
Returns the number of partitions
|
||||
DESCRIPTION
|
||||
A routine to check for number of partitions for improved readability
|
||||
of code
|
||||
*/
|
||||
static inline
|
||||
uint get_tot_partitions(partition_info *part_info)
|
||||
{
|
||||
return part_info->no_parts *
|
||||
(is_sub_partitioned(part_info) ? part_info->no_subparts : 1);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct st_ha_create_information
|
||||
{
|
||||
@@ -1100,52 +650,6 @@ typedef struct st_ha_check_opt
|
||||
} HA_CHECK_OPT;
|
||||
|
||||
|
||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||
bool is_partition_in_list(char *part_name, List<char> list_part_names);
|
||||
char *are_partitions_in_table(partition_info *new_part_info,
|
||||
partition_info *old_part_info);
|
||||
bool check_reorganise_list(partition_info *new_part_info,
|
||||
partition_info *old_part_info,
|
||||
List<char> list_part_names);
|
||||
bool set_up_defaults_for_partitioning(partition_info *part_info,
|
||||
handler *file,
|
||||
ulonglong max_rows,
|
||||
uint start_no);
|
||||
handler *get_ha_partition(partition_info *part_info);
|
||||
int get_parts_for_update(const byte *old_data, byte *new_data,
|
||||
const byte *rec0, partition_info *part_info,
|
||||
uint32 *old_part_id, uint32 *new_part_id,
|
||||
longlong *func_value);
|
||||
int get_part_for_delete(const byte *buf, const byte *rec0,
|
||||
partition_info *part_info, uint32 *part_id);
|
||||
bool check_partition_info(partition_info *part_info,handlerton **eng_type,
|
||||
handler *file, ulonglong max_rows);
|
||||
bool fix_partition_func(THD *thd, const char *name, TABLE *table,
|
||||
bool create_table_ind);
|
||||
char *generate_partition_syntax(partition_info *part_info,
|
||||
uint *buf_length, bool use_sql_alloc,
|
||||
bool write_all);
|
||||
bool partition_key_modified(TABLE *table, List<Item> &fields);
|
||||
void get_partition_set(const TABLE *table, byte *buf, const uint index,
|
||||
const key_range *key_spec,
|
||||
part_id_range *part_spec);
|
||||
void get_full_part_id_from_key(const TABLE *table, byte *buf,
|
||||
KEY *key_info,
|
||||
const key_range *key_spec,
|
||||
part_id_range *part_spec);
|
||||
bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
|
||||
uint part_info_len,
|
||||
uchar *part_state, uint part_state_len,
|
||||
TABLE *table, bool is_create_table_ind,
|
||||
handlerton *default_db_type);
|
||||
void make_used_partitions_str(partition_info *part_info, String *parts_str);
|
||||
uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint);
|
||||
uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
|
||||
bool left_endpoint,
|
||||
bool include_endpoint);
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user