summaryrefslogtreecommitdiff
path: root/sql/sql_partition.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/sql_partition.cc')
-rw-r--r--sql/sql_partition.cc231
1 files changed, 229 insertions, 2 deletions
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index e294a43c774..5d071c5591c 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -2478,17 +2478,96 @@ bool get_partition_id_list(partition_info *part_info,
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 {
+ }
+ else
+ {
*part_id= (uint32)list_array[list_index].partition_id;
DBUG_RETURN(FALSE);
}
}
+notfound:
*part_id= 0;
DBUG_RETURN(TRUE);
}
+/*
+ Find the sub-array part_info->list_array that corresponds to given interval
+
+ SYNOPSIS
+ get_list_array_idx_for_endpoint()
+ part_info Partitioning info (partitioning type must be LIST)
+ left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
+ FALSE - the interval is (-inf; a] or (-inf; a)
+ include_endpoint TRUE iff the interval includes the endpoint
+
+ DESCRIPTION
+ This function finds the sub-array of part_info->list_array where values of
+ list_array[idx].list_value are contained within the specifed interval.
+ list_array is ordered by list_value, so
+ 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
+ sought sub-array starts at some index idx and continues till array end.
+ The function returns first number idx, such that
+ list_array[idx].list_value is contained within the passed interval.
+
+ 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
+ sought sub-array starts at array start and continues till some last
+ index idx.
+ The function returns first number idx, such that
+ list_array[idx].list_value is NOT contained within the passed interval.
+ If all array elements are contained, part_info->no_list_values is
+ returned.
+
+ NOTE
+ The caller will call this function and then will run along the sub-array of
+ list_array to collect partition ids. If the number of list values is
+ significantly higher then number of partitions, this could be slow and
+ we could invent some other approach. The "run over list array" part is
+ already wrapped in a get_next()-like function.
+
+ RETURN
+ The edge of corresponding sub-array of part_info->list_array
+*/
+
+uint32 get_list_array_idx_for_endpoint(partition_info *part_info,
+ bool left_endpoint,
+ bool include_endpoint)
+{
+ DBUG_ENTER("get_list_array_idx_for_endpoint");
+ LIST_PART_ENTRY *list_array= part_info->list_array;
+ uint list_index;
+ longlong list_value;
+ uint min_list_index= 0, max_list_index= part_info->no_list_values - 1;
+ /* Get the partitioning function value for the endpoint */
+ longlong part_func_value= part_info->part_expr->val_int();
+ while (max_list_index >= min_list_index)
+ {
+ list_index= (max_list_index + min_list_index) >> 1;
+ list_value= list_array[list_index].list_value;
+ 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
+ {
+ DBUG_RETURN(list_index + test(left_endpoint ^ include_endpoint));
+ }
+ }
+notfound:
+ if (list_value < part_func_value)
+ list_index++;
+ DBUG_RETURN(list_index);
+}
+
+
bool get_partition_id_range(partition_info *part_info,
uint32 *part_id)
{
@@ -2517,6 +2596,89 @@ bool get_partition_id_range(partition_info *part_info,
DBUG_RETURN(FALSE);
}
+
+/*
+ Find the sub-array of part_info->range_int_array that covers given interval
+
+ SYNOPSIS
+ get_partition_id_range_for_endpoint()
+ part_info Partitioning info (partitioning type must be RANGE)
+ left_endpoint TRUE - the interval is [a; +inf) or (a; +inf)
+ FALSE - the interval is (-inf; a] or (-inf; a).
+ include_endpoint TRUE <=> the endpoint itself is included in the
+ interval
+
+ DESCRIPTION
+ This function finds the sub-array of part_info->range_int_array where the
+ elements have non-empty intersections with the given interval.
+
+ A range_int_array element at index idx represents the interval
+
+ [range_int_array[idx-1], range_int_array[idx]),
+
+ intervals are disjoint and ordered by their right bound, so
+
+ 1. For [a; +inf) or (a; +inf)-type intervals (left_endpoint==TRUE), the
+ sought sub-array starts at some index idx and continues till array end.
+ The function returns first number idx, such that the interval
+ represented by range_int_array[idx] has non empty intersection with
+ the passed interval.
+
+ 2. For (-inf; a] or (-inf; a)-type intervals (left_endpoint==FALSE), the
+ sought sub-array starts at array start and continues till some last
+ index idx.
+ The function returns first number idx, such that the interval
+ represented by range_int_array[idx] has EMPTY intersection with the
+ passed interval.
+ If the interval represented by the last array element has non-empty
+ intersection with the passed interval, part_info->no_parts is
+ returned.
+
+ RETURN
+ The edge of corresponding part_info->range_int_array sub-array.
+*/
+
+uint32 get_partition_id_range_for_endpoint(partition_info *part_info,
+ bool left_endpoint,
+ bool include_endpoint)
+{
+ DBUG_ENTER("get_partition_id_range_for_endpoint");
+ longlong *range_array= part_info->range_int_array;
+ uint max_partition= part_info->no_parts - 1;
+ uint min_part_id= 0, max_part_id= max_partition, loc_part_id;
+ /* Get the partitioning function value for the endpoint */
+ longlong part_func_value= part_info->part_expr->val_int();
+ while (max_part_id > min_part_id)
+ {
+ loc_part_id= (max_part_id + min_part_id + 1) >> 1;
+ if (range_array[loc_part_id] < part_func_value)
+ min_part_id= loc_part_id + 1;
+ else
+ max_part_id= loc_part_id - 1;
+ }
+ loc_part_id= max_part_id;
+ if (loc_part_id < max_partition &&
+ part_func_value >= range_array[loc_part_id+1])
+ {
+ 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++;
+ }
+ DBUG_RETURN(loc_part_id);
+}
+
+
bool get_partition_id_hash_nosub(partition_info *part_info,
uint32 *part_id)
{
@@ -3205,10 +3367,16 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
*/
uint part_func_len= part_info->part_func_len;
uint subpart_func_len= part_info->subpart_func_len;
+ uint bitmap_bits= part_info->no_subparts?
+ (part_info->no_subparts* part_info->no_parts):
+ part_info->no_parts;
+ uint bitmap_bytes= bitmap_buffer_size(bitmap_bits);
+ uint32 *bitmap_buf;
char *part_func_string, *subpart_func_string= NULL;
if (!((part_func_string= thd->alloc(part_func_len))) ||
(subpart_func_len &&
- !((subpart_func_string= thd->alloc(subpart_func_len)))))
+ !((subpart_func_string= thd->alloc(subpart_func_len)))) ||
+ !((bitmap_buf= (uint32*)thd->alloc(bitmap_bytes))))
{
my_error(ER_OUTOFMEMORY, MYF(0), part_func_len);
free_items(thd->free_list);
@@ -3221,6 +3389,8 @@ bool mysql_unpack_partition(THD *thd, const uchar *part_buf,
subpart_func_len);
part_info->part_func_string= part_func_string;
part_info->subpart_func_string= subpart_func_string;
+
+ bitmap_init(&part_info->used_partitions, bitmap_buf, bitmap_bytes*8, FALSE);
}
result= FALSE;
@@ -3294,3 +3464,60 @@ void set_key_field_ptr(KEY *key_info, const byte *new_buf,
} while (++i < key_parts);
DBUG_VOID_RETURN;
}
+
+
+/*
+ Fill the string comma-separated line of used partitions names
+ SYNOPSIS
+ make_used_partitions_str()
+ part_info IN Partitioning info
+ parts_str OUT The string to fill
+*/
+
+void make_used_partitions_str(partition_info *part_info, String *parts_str)
+{
+ parts_str->length(0);
+ partition_element *pe;
+ uint partition_id= 0;
+ List_iterator<partition_element> it(part_info->partitions);
+
+ if (part_info->subpart_type != NOT_A_PARTITION)
+ {
+ partition_element *head_pe;
+ while ((head_pe= it++))
+ {
+ List_iterator<partition_element> it2(head_pe->subpartitions);
+ while ((pe= it2++))
+ {
+ if (bitmap_is_set(&part_info->used_partitions, partition_id))
+ {
+ if (parts_str->length())
+ parts_str->append(',');
+ parts_str->append(head_pe->partition_name,
+ strlen(head_pe->partition_name),
+ system_charset_info);
+ parts_str->append('_');
+ parts_str->append(pe->partition_name,
+ strlen(pe->partition_name),
+ system_charset_info);
+ }
+ partition_id++;
+ }
+ }
+ }
+ else
+ {
+ while ((pe= it++))
+ {
+ if (bitmap_is_set(&part_info->used_partitions, partition_id))
+ {
+ if (parts_str->length())
+ parts_str->append(',');
+ parts_str->append(pe->partition_name, strlen(pe->partition_name),
+ system_charset_info);
+ }
+ partition_id++;
+ }
+ }
+}
+