1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

5.5.39 merge

This commit is contained in:
Sergei Golubchik
2014-08-07 18:06:56 +02:00
246 changed files with 5937 additions and 4671 deletions

View File

@@ -1,5 +1,5 @@
/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2008, 2013, Monty Program Ab.
/* Copyright (c) 2000, 2014, Oracle and/or its affiliates.
Copyright (c) 2008, 2014, Monty Program Ab.
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
@@ -359,31 +359,54 @@ public:
elements(1),use_count(1),left(0),right(0),
next_key_part(0), color(BLACK), type(type_arg)
{}
inline bool is_same(SEL_ARG *arg)
/**
returns true if a range predicate is equal. Use all_same()
to check for equality of all the predicates on this keypart.
*/
inline bool is_same(const SEL_ARG *arg) const
{
if (type != arg->type || part != arg->part)
return 0;
return false;
if (type != KEY_RANGE)
return 1;
return true;
return cmp_min_to_min(arg) == 0 && cmp_max_to_max(arg) == 0;
}
/**
returns true if all the predicates in the keypart tree are equal
*/
bool all_same(const SEL_ARG *arg) const
{
if (type != arg->type || part != arg->part)
return false;
if (type != KEY_RANGE)
return true;
if (arg == this)
return true;
const SEL_ARG *cmp_arg= arg->first();
const SEL_ARG *cur_arg= first();
for (; cur_arg && cmp_arg && cur_arg->is_same(cmp_arg);
cur_arg= cur_arg->next, cmp_arg= cmp_arg->next) ;
if (cur_arg || cmp_arg)
return false;
return true;
}
inline void merge_flags(SEL_ARG *arg) { maybe_flag|=arg->maybe_flag; }
inline void maybe_smaller() { maybe_flag=1; }
/* Return true iff it's a single-point null interval */
inline bool is_null_interval() { return maybe_null && max_value[0] == 1; }
inline int cmp_min_to_min(SEL_ARG* arg)
inline int cmp_min_to_min(const SEL_ARG* arg) const
{
return sel_cmp(field,min_value, arg->min_value, min_flag, arg->min_flag);
}
inline int cmp_min_to_max(SEL_ARG* arg)
inline int cmp_min_to_max(const SEL_ARG* arg) const
{
return sel_cmp(field,min_value, arg->max_value, min_flag, arg->max_flag);
}
inline int cmp_max_to_max(SEL_ARG* arg)
inline int cmp_max_to_max(const SEL_ARG* arg) const
{
return sel_cmp(field,max_value, arg->max_value, max_flag, arg->max_flag);
}
inline int cmp_max_to_min(SEL_ARG* arg)
inline int cmp_max_to_min(const SEL_ARG* arg) const
{
return sel_cmp(field,max_value, arg->min_value, max_flag, arg->min_flag);
}
@@ -563,6 +586,7 @@ public:
void test_use_count(SEL_ARG *root);
#endif
SEL_ARG *first();
const SEL_ARG *first() const;
SEL_ARG *last();
void make_root();
inline bool simple_key()
@@ -652,6 +676,18 @@ public:
SEL_ARG *clone_tree(RANGE_OPT_PARAM *param);
};
/**
Helper function to compare two SEL_ARG's.
*/
static bool all_same(const SEL_ARG *sa1, const SEL_ARG *sa2)
{
if (sa1 == NULL && sa2 == NULL)
return true;
if ((sa1 != NULL && sa2 == NULL) || (sa1 == NULL && sa2 != NULL))
return false;
return sa1->all_same(sa2);
}
class SEL_IMERGE;
#define CLONE_KEY1_MAYBE 1
@@ -2495,6 +2531,13 @@ SEL_ARG *SEL_ARG::clone(RANGE_OPT_PARAM *param, SEL_ARG *new_parent,
return tmp;
}
/**
This gives the first SEL_ARG in the interval list, and the minimal element
in the red-black tree
@return
SEL_ARG first SEL_ARG in the interval list
*/
SEL_ARG *SEL_ARG::first()
{
SEL_ARG *next_arg=this;
@@ -2505,6 +2548,11 @@ SEL_ARG *SEL_ARG::first()
return next_arg;
}
const SEL_ARG *SEL_ARG::first() const
{
return const_cast<SEL_ARG*>(this)->first();
}
SEL_ARG *SEL_ARG::last()
{
SEL_ARG *next_arg=this;
@@ -11043,6 +11091,7 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
uint part;
bool create_err= FALSE;
Cost_estimate cost;
uint max_used_key_len;
old_root= thd->mem_root;
/* The following call may change thd->mem_root */
@@ -11069,12 +11118,13 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
range->min_length= range->max_length= ref->key_length;
range->min_keypart_map= range->max_keypart_map=
make_prev_keypart_map(ref->key_parts);
range->flag= (ref->key_length == key_info->key_length ? EQ_RANGE : 0);
range->flag= EQ_RANGE;
if (!(quick->key_parts=key_part=(KEY_PART *)
alloc_root(&quick->alloc,sizeof(KEY_PART)*ref->key_parts)))
goto err;
max_used_key_len=0;
for (part=0 ; part < ref->key_parts ;part++,key_part++)
{
key_part->part=part;
@@ -11083,7 +11133,12 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
key_part->store_length= key_info->key_part[part].store_length;
key_part->null_bit= key_info->key_part[part].null_bit;
key_part->flag= (uint8) key_info->key_part[part].key_part_flag;
max_used_key_len +=key_info->key_part[part].store_length;
}
quick->max_used_key_length= max_used_key_len;
if (insert_dynamic(&quick->ranges,(uchar*)&range))
goto err;
@@ -12334,6 +12389,66 @@ void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names,
}
void QUICK_RANGE_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set)
{
uint key_len;
KEY_PART *part= key_parts;
for (key_len=0; key_len < max_used_key_length;
key_len += (part++)->store_length)
{
bitmap_set_bit(col_set, part->field->field_index);
}
}
void QUICK_GROUP_MIN_MAX_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set)
{
uint key_len;
KEY_PART_INFO *part= index_info->key_part;
for (key_len=0; key_len < max_used_key_length;
key_len += (part++)->store_length)
{
bitmap_set_bit(col_set, part->field->field_index);
}
}
void QUICK_ROR_INTERSECT_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set)
{
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
QUICK_SELECT_WITH_RECORD *quick;
while ((quick= it++))
{
quick->quick->add_used_key_part_to_set(col_set);
}
}
void QUICK_INDEX_SORT_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set)
{
QUICK_RANGE_SELECT *quick;
List_iterator_fast<QUICK_RANGE_SELECT> it(quick_selects);
while ((quick= it++))
{
quick->add_used_key_part_to_set(col_set);
}
if (pk_quick_select)
pk_quick_select->add_used_key_part_to_set(col_set);
}
void QUICK_ROR_UNION_SELECT::add_used_key_part_to_set(MY_BITMAP *col_set)
{
QUICK_SELECT_I *quick;
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
while ((quick= it++))
{
quick->add_used_key_part_to_set(col_set);
}
}
/*******************************************************************************
* Implementation of QUICK_GROUP_MIN_MAX_SELECT
*******************************************************************************/
@@ -12341,6 +12456,8 @@ void QUICK_ROR_UNION_SELECT::add_keys_and_lengths(String *key_names,
static inline uint get_field_keypart(KEY *index, Field *field);
static inline SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree,
PARAM *param, uint *param_idx);
static bool get_sel_arg_for_keypart(Field *field, SEL_ARG *index_range_tree,
SEL_ARG **cur_range);
static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
KEY_PART_INFO *first_non_group_part,
KEY_PART_INFO *min_max_arg_part,
@@ -12406,6 +12523,16 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
never stored after a unique key lookup in the clustered index and
furhter index_next/prev calls can not be used. So loose index scan
optimization can not be used in this case.
SA7. If Q has both AGG_FUNC(DISTINCT ...) and MIN/MAX() functions then this
access method is not used.
For above queries MIN/MAX() aggregation has to be done at
nested_loops_join (end_send_group). But with current design MIN/MAX()
is always set as part of loose index scan. Because of this mismatch
MIN() and MAX() values will be set incorrectly. For such queries to
work we need a new interface for loose index scan. This new interface
should only fetch records with min and max values and let
end_send_group to do aggregation. Until then do not use
loose_index_scan.
GA1. If Q has a GROUP BY clause, then GA is a prefix of I. That is, if
G_i = A_j => i = j.
GA2. If Q has a DISTINCT clause, then there is a permutation of SA that
@@ -12437,6 +12564,8 @@ cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
above tests. By transitivity then it also follows that each WA_i
participates in the index I (if this was already tested for GA, NGA
and C).
WA2. If there is a predicate on C, then it must be in conjunction
to all predicates on all earlier keyparts in I.
C) Overall query form:
SELECT EXPR([A_1,...,A_k], [B_1,...,B_m], [MIN(C)], [MAX(C)])
@@ -12571,6 +12700,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
DBUG_RETURN(NULL);
}
}
/* Check (SA7). */
if (is_agg_distinct && (have_max || have_min))
{
DBUG_RETURN(NULL);
}
/* Check (SA5). */
if (join->select_distinct)
{
@@ -12860,6 +12996,25 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
}
}
/**
Test WA2:If there are conditions on a column C participating in
MIN/MAX, those conditions must be conjunctions to all earlier
keyparts. Otherwise, Loose Index Scan cannot be used.
*/
if (tree && min_max_arg_item)
{
uint dummy;
SEL_ARG *index_range_tree= get_index_range_tree(cur_index, tree, param,
&dummy);
SEL_ARG *cur_range= NULL;
if (get_sel_arg_for_keypart(min_max_arg_part->field,
index_range_tree, &cur_range) ||
(cur_range && cur_range->type != SEL_ARG::KEY_RANGE))
{
goto next_index;
}
}
/* If we got to this point, cur_index_info passes the test. */
key_infix_parts= cur_key_infix_len ? (uint)
(first_non_infix_part - first_non_group_part) : 0;
@@ -13177,73 +13332,75 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
/*
Get SEL_ARG tree, if any, for the keypart covering non grouping
attribute (NGA) field 'nga_field'.
Get the SEL_ARG tree 'tree' for the keypart covering 'field', if
any. 'tree' must be a unique conjunction to ALL predicates in earlier
keyparts of 'keypart_tree'.
This function enforces the NGA3 test: If 'keypart_tree' contains a
condition for 'nga_field', there can only be one range. In the
opposite case, this function returns with error and 'cur_range'
should not be used.
E.g., if 'keypart_tree' is for a composite index (kp1,kp2) and kp2
covers 'field', all these conditions satisfies the requirement:
Note that the NGA1 and NGA2 requirements, like whether or not the
range predicate for 'nga_field' is equality, is not tested by this
function.
1. "(kp1=2 OR kp1=3) AND kp2=10" => returns "kp2=10"
2. "(kp1=2 AND kp2=10) OR (kp1=3 AND kp2=10)" => returns "kp2=10"
3. "(kp1=2 AND (kp2=10 OR kp2=11)) OR (kp1=3 AND (kp2=10 OR kp2=11))"
=> returns "kp2=10 OR kp2=11"
@param[in] nga_field The NGA field we want the SEL_ARG tree for
whereas these do not
1. "(kp1=2 AND kp2=10) OR kp1=3"
2. "(kp1=2 AND kp2=10) OR (kp1=3 AND kp2=11)"
3. "(kp1=2 AND kp2=10) OR (kp1=3 AND (kp2=10 OR kp2=11))"
This function effectively tests requirement WA2. In combination with
a test that the returned tree has no more than one range it is also
a test of NGA3.
@param[in] field The field we want the SEL_ARG tree for
@param[in] keypart_tree Root node of the SEL_ARG* tree for the index
@param[out] cur_range The SEL_ARG tree, if any, for the keypart
covering field 'keypart_field'
@retval true 'keypart_tree' contained a predicate for 'nga_field' but
multiple ranges exists. 'cur_range' should not be used.
@retval true 'keypart_tree' contained a predicate for 'field' that
is not conjunction to all predicates on earlier keyparts
@retval false otherwise
*/
static bool
get_sel_arg_for_keypart(Field *nga_field,
get_sel_arg_for_keypart(Field *field,
SEL_ARG *keypart_tree,
SEL_ARG **cur_range)
{
if(keypart_tree == NULL)
if (keypart_tree == NULL)
return false;
if(keypart_tree->field->eq(nga_field))
if (keypart_tree->field->eq(field))
{
/*
Enforce NGA3: If a condition for nga_field has been found, only
a single range is allowed.
*/
if (keypart_tree->prev || keypart_tree->next)
return true; // There are multiple ranges
*cur_range= keypart_tree;
return false;
}
SEL_ARG *found_tree= NULL;
SEL_ARG *tree_first_range= NULL;
SEL_ARG *first_kp= keypart_tree->first();
for (SEL_ARG *cur_kp= first_kp; cur_kp && !found_tree;
cur_kp= cur_kp->next)
for (SEL_ARG *cur_kp= first_kp; cur_kp; cur_kp= cur_kp->next)
{
SEL_ARG *curr_tree= NULL;
if (cur_kp->next_key_part)
{
if (get_sel_arg_for_keypart(nga_field,
if (get_sel_arg_for_keypart(field,
cur_kp->next_key_part,
&found_tree))
&curr_tree))
return true;
}
/*
Enforce NGA3: If a condition for nga_field has been found,only
a single range is allowed.
*/
if (found_tree && first_kp->next)
return true; // There are multiple ranges
Check if the SEL_ARG tree for 'field' is identical for all ranges in
'keypart_tree
*/
if (cur_kp == first_kp)
tree_first_range= curr_tree;
else if (!all_same(tree_first_range, curr_tree))
return true;
}
*cur_range= found_tree;
*cur_range= tree_first_range;
return false;
}
/*
Extract a sequence of constants from a conjunction of equality predicates.
@@ -13266,7 +13423,8 @@ get_sel_arg_for_keypart(Field *nga_field,
(const_ci = NG_i).. In addition, there can only be one range when there is
such a gap.
Thus all the NGF_i attributes must fill the 'gap' between the last group-by
attribute and the MIN/MAX attribute in the index (if present). If these
attribute and the MIN/MAX attribute in the index (if present). Also ensure
that there is only a single range on NGF_i (NGA3). If these
conditions hold, copy each constant from its corresponding predicate into
key_infix, in the order its NG_i attribute appears in the index, and update
key_infix_len with the total length of the key parts in key_infix.
@@ -13275,7 +13433,6 @@ get_sel_arg_for_keypart(Field *nga_field,
TRUE if the index passes the test
FALSE o/w
*/
static bool
get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
KEY_PART_INFO *first_non_group_part,
@@ -13295,32 +13452,42 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
{
cur_range= NULL;
/*
Find the range tree for the current keypart. We assume that
index_range_tree points to the first keypart in the index.
Check NGA3:
1. get_sel_arg_for_keypart gets the range tree for the 'field' and also
checks for a unique conjunction of this tree with all the predicates
on the earlier keyparts in the index.
2. Check for multiple ranges on the found keypart tree.
We assume that index_range_tree points to the leftmost keypart in
the index.
*/
if(get_sel_arg_for_keypart(cur_part->field, index_range_tree, &cur_range))
if (get_sel_arg_for_keypart(cur_part->field, index_range_tree,
&cur_range))
return false;
if (cur_range && cur_range->elements > 1)
return false;
if (!cur_range || cur_range->type != SEL_ARG::KEY_RANGE)
{
if (min_max_arg_part)
return FALSE; /* The current keypart has no range predicates at all. */
return false; /* The current keypart has no range predicates at all. */
else
{
*first_non_infix_part= cur_part;
return TRUE;
return true;
}
}
if ((cur_range->min_flag & NO_MIN_RANGE) ||
(cur_range->max_flag & NO_MAX_RANGE) ||
(cur_range->min_flag & NEAR_MIN) || (cur_range->max_flag & NEAR_MAX))
return FALSE;
return false;
uint field_length= cur_part->store_length;
if (cur_range->maybe_null &&
cur_range->min_value[0] && cur_range->max_value[0])
{
{
/*
cur_range specifies 'IS NULL'. In this case the argument points
to a "null value" (is_null_string) that may not always be long
@@ -13339,7 +13506,7 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
*key_infix_len+= field_length;
}
else
return FALSE;
return false;
}
if (!min_max_arg_part && (cur_part == last_part))