Bug#15843818 PARTITIONING BY RANGE WITH TO_DAYS ALWAYS
INCLUDES FIRST PARTITION WHEN PRUNING [Merge from 5.1 to 5.5]
This commit is contained in:
commit
b11fe1b83a
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
|
/* Copyright (c) 2005, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@ -7131,12 +7131,12 @@ void make_used_partitions_str(partition_info *part_info, String *parts_str)
|
|||||||
definition)
|
definition)
|
||||||
|
|
||||||
IMPLEMENTATION
|
IMPLEMENTATION
|
||||||
There are two available interval analyzer functions:
|
There are three available interval analyzer functions:
|
||||||
(1) get_part_iter_for_interval_via_mapping
|
(1) get_part_iter_for_interval_via_mapping
|
||||||
(2) get_part_iter_for_interval_cols_via_map
|
(2) get_part_iter_for_interval_cols_via_map
|
||||||
(3) get_part_iter_for_interval_via_walking
|
(3) get_part_iter_for_interval_via_walking
|
||||||
|
|
||||||
They both have limited applicability:
|
They all have limited applicability:
|
||||||
(1) is applicable for "PARTITION BY <RANGE|LIST>(func(t.field))", where
|
(1) is applicable for "PARTITION BY <RANGE|LIST>(func(t.field))", where
|
||||||
func is a monotonic function.
|
func is a monotonic function.
|
||||||
|
|
||||||
@ -7509,6 +7509,9 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
|||||||
get_endpoint_func UNINIT_VAR(get_endpoint);
|
get_endpoint_func UNINIT_VAR(get_endpoint);
|
||||||
bool can_match_multiple_values; /* is not '=' */
|
bool can_match_multiple_values; /* is not '=' */
|
||||||
uint field_len= field->pack_length_in_rec();
|
uint field_len= field->pack_length_in_rec();
|
||||||
|
MYSQL_TIME start_date;
|
||||||
|
bool check_zero_dates= false;
|
||||||
|
bool zero_in_start_date= true;
|
||||||
DBUG_ENTER("get_part_iter_for_interval_via_mapping");
|
DBUG_ENTER("get_part_iter_for_interval_via_mapping");
|
||||||
DBUG_ASSERT(!is_subpart);
|
DBUG_ASSERT(!is_subpart);
|
||||||
(void) store_length_array;
|
(void) store_length_array;
|
||||||
@ -7565,6 +7568,7 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
|||||||
{
|
{
|
||||||
/* col is NOT NULL, but F(col) can return NULL, add NULL partition */
|
/* col is NOT NULL, but F(col) can return NULL, add NULL partition */
|
||||||
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
|
part_iter->ret_null_part= part_iter->ret_null_part_orig= TRUE;
|
||||||
|
check_zero_dates= true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7608,6 +7612,19 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
|||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
part_iter->part_nums.cur= part_iter->part_nums.start;
|
part_iter->part_nums.cur= part_iter->part_nums.start;
|
||||||
|
if (check_zero_dates && !part_info->part_expr->null_value)
|
||||||
|
{
|
||||||
|
if (!(flags & NO_MAX_RANGE) &&
|
||||||
|
(field->type() == MYSQL_TYPE_DATE ||
|
||||||
|
field->type() == MYSQL_TYPE_DATETIME))
|
||||||
|
{
|
||||||
|
/* Monotonic, but return NULL for dates with zeros in month/day. */
|
||||||
|
zero_in_start_date= field->get_date(&start_date, 0);
|
||||||
|
DBUG_PRINT("info", ("zero start %u %04d-%02d-%02d",
|
||||||
|
zero_in_start_date, start_date.year,
|
||||||
|
start_date.month, start_date.day));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (part_iter->part_nums.start == max_endpoint_val)
|
if (part_iter->part_nums.start == max_endpoint_val)
|
||||||
DBUG_RETURN(0); /* No partitions */
|
DBUG_RETURN(0); /* No partitions */
|
||||||
}
|
}
|
||||||
@ -7621,6 +7638,29 @@ int get_part_iter_for_interval_via_mapping(partition_info *part_info,
|
|||||||
store_key_image_to_rec(field, max_value, field_len);
|
store_key_image_to_rec(field, max_value, field_len);
|
||||||
bool include_endp= !test(flags & NEAR_MAX);
|
bool include_endp= !test(flags & NEAR_MAX);
|
||||||
part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp);
|
part_iter->part_nums.end= get_endpoint(part_info, 0, include_endp);
|
||||||
|
if (check_zero_dates &&
|
||||||
|
!zero_in_start_date &&
|
||||||
|
!part_info->part_expr->null_value)
|
||||||
|
{
|
||||||
|
MYSQL_TIME end_date;
|
||||||
|
bool zero_in_end_date= field->get_date(&end_date, 0);
|
||||||
|
/*
|
||||||
|
This is an optimization for TO_DAYS()/TO_SECONDS() to avoid scanning
|
||||||
|
the NULL partition for ranges that cannot include a date with 0 as
|
||||||
|
month/day.
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("info", ("zero end %u %04d-%02d-%02d",
|
||||||
|
zero_in_end_date,
|
||||||
|
end_date.year, end_date.month, end_date.day));
|
||||||
|
DBUG_ASSERT(!memcmp(((Item_func*) part_info->part_expr)->func_name(),
|
||||||
|
"to_days", 7) ||
|
||||||
|
!memcmp(((Item_func*) part_info->part_expr)->func_name(),
|
||||||
|
"to_seconds", 10));
|
||||||
|
if (!zero_in_end_date &&
|
||||||
|
start_date.month == end_date.month &&
|
||||||
|
start_date.year == end_date.year)
|
||||||
|
part_iter->ret_null_part= part_iter->ret_null_part_orig= false;
|
||||||
|
}
|
||||||
if (part_iter->part_nums.start >= part_iter->part_nums.end &&
|
if (part_iter->part_nums.start >= part_iter->part_nums.end &&
|
||||||
!part_iter->ret_null_part)
|
!part_iter->ret_null_part)
|
||||||
DBUG_RETURN(0); /* No partitions */
|
DBUG_RETURN(0); /* No partitions */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user