summaryrefslogtreecommitdiff
path: root/sql/sql_partition.cc
diff options
context:
space:
mode:
authorAditya A <aditya.a@oracle.com>2013-01-11 16:36:44 +0530
committerAditya A <aditya.a@oracle.com>2013-01-11 16:36:44 +0530
commitb11fe1b83a1ccf4a0bf9962eafa6e3523c2160c1 (patch)
treeb672dd19a0f3aaae16e09910a49b8091f39e4271 /sql/sql_partition.cc
parentfeb36554b21065e5c23c3f02758d96261d19d522 (diff)
parent01094a4b13095175080b073e804866621377a16e (diff)
downloadmariadb-git-b11fe1b83a1ccf4a0bf9962eafa6e3523c2160c1.tar.gz
Bug#15843818 PARTITIONING BY RANGE WITH TO_DAYS ALWAYS
INCLUDES FIRST PARTITION WHEN PRUNING [Merge from 5.1 to 5.5]
Diffstat (limited to 'sql/sql_partition.cc')
-rw-r--r--sql/sql_partition.cc48
1 files changed, 44 insertions, 4 deletions
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 8f946b02747..066262c3919 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -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
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)
IMPLEMENTATION
- There are two available interval analyzer functions:
- (1) get_part_iter_for_interval_via_mapping
+ There are three available interval analyzer functions:
+ (1) get_part_iter_for_interval_via_mapping
(2) get_part_iter_for_interval_cols_via_map
(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
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);
bool can_match_multiple_values; /* is not '=' */
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_ASSERT(!is_subpart);
(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 */
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);
}
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)
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);
bool include_endp= !test(flags & NEAR_MAX);
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 &&
!part_iter->ret_null_part)
DBUG_RETURN(0); /* No partitions */