summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMattias Jonsson <mattias.jonsson@oracle.com>2012-08-09 12:51:37 +0200
committerMattias Jonsson <mattias.jonsson@oracle.com>2012-08-09 12:51:37 +0200
commit6592afd5c28c0e7519d76c8c894658a4a17515c0 (patch)
tree3faf961ee13adcecaa6a59cac456417e69fd62be /sql
parent51672ec2d4d37e701b595ac74cde9abc37916a2d (diff)
downloadmariadb-git-6592afd5c28c0e7519d76c8c894658a4a17515c0.tar.gz
Bug#14342883: SELECT QUERY RETURNS NOT ALL
ROWS THAT ARE EXPECTED For non range/list partitioned tables (i.e. HASH/KEY): When prune_partitions finds a multi-range list (or in this test '<>') for a field of the partition index, even if it cannot make any use of the multi-range, it will continue with the next field of the partition index and use that for pruning (even if it the previous field could not be used). This results in partitions is pruned away, leaving partitions that only matches the last field in the partition index, and will exclude partitions which might match any previous fields. Fixed by skipping rest of partitioning key fields/parts if current key field/part could not be used. Also notice it is the order of the fields in the CREATE TABLE statement that triggers this bug, not the order of fields in primary/unique key or PARTITION BY KEY (). It must not be the last field in the partitioning expression that is not equal (or have a non single point range). I.e. the partitioning index is created with the same field order as in the CREATE TABLE. And for the bug to appear the last field must be a single point and some previous field must be a multi-point range.
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_range.cc40
1 files changed, 24 insertions, 16 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 03f444c22b5..8d221af392b 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3071,27 +3071,28 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part];
*(ppar->arg_stack_end++)= key_tree;
+ if (ignore_part_fields)
+ {
+ /*
+ We come here when a condition on the first partitioning
+ fields led to evaluating the partitioning condition
+ (due to finding a condition of the type a < const or
+ b > const). Thus we must ignore the rest of the
+ partitioning fields but we still want to analyse the
+ subpartitioning fields.
+ */
+ if (key_tree->next_key_part)
+ res= find_used_partitions(ppar, key_tree->next_key_part);
+ else
+ res= -1;
+ goto pop_and_go_right;
+ }
+
if (key_tree->type == SEL_ARG::KEY_RANGE)
{
if (ppar->part_info->get_part_iter_for_interval &&
key_tree->part <= ppar->last_part_partno)
{
- if (ignore_part_fields)
- {
- /*
- We come here when a condition on the first partitioning
- fields led to evaluating the partitioning condition
- (due to finding a condition of the type a < const or
- b > const). Thus we must ignore the rest of the
- partitioning fields but we still want to analyse the
- subpartitioning fields.
- */
- if (key_tree->next_key_part)
- res= find_used_partitions(ppar, key_tree->next_key_part);
- else
- res= -1;
- goto pop_and_go_right;
- }
/* Collect left and right bound, their lengths and flags */
uchar *min_key= ppar->cur_min_key;
uchar *max_key= ppar->cur_max_key;
@@ -3332,6 +3333,13 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
res= -1;
goto pop_and_go_right;
}
+ /*
+ No meaning in continuing with rest of partitioning key parts.
+ Will try to continue with subpartitioning key parts.
+ */
+ ppar->ignore_part_fields= true;
+ did_set_ignore_part_fields= true;
+ goto process_next_key_part;
}
}