1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

10.0-base merge

This commit is contained in:
Sergei Golubchik
2013-04-15 15:09:22 +02:00
976 changed files with 38123 additions and 26781 deletions

View File

@ -132,7 +132,12 @@
static int sel_cmp(Field *f,uchar *a,uchar *b,uint8 a_flag,uint8 b_flag);
static uchar is_null_string[2]= {1,0};
/*
this should be long enough so that any memcmp with a string that
starts from '\0' won't cross is_null_string boundaries, even
if the memcmp is optimized to compare 4- 8- or 16- bytes at once
*/
static uchar is_null_string[20]= {1,0};
class RANGE_OPT_PARAM;
/*
@ -2000,7 +2005,7 @@ int QUICK_ROR_INTERSECT_SELECT::init()
1 error
*/
int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler, MEM_ROOT *alloc)
{
handler *save_file= file, *org_file;
my_bool org_key_read;
@ -2028,7 +2033,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
DBUG_RETURN(0);
}
if (!(file= head->file->clone(head->s->normalized_path.str, thd->mem_root)))
if (!(file= head->file->clone(head->s->normalized_path.str, alloc)))
{
/*
Manually set the error flag. Note: there seems to be quite a few
@ -2129,7 +2134,8 @@ failure:
0 OK
other error code
*/
int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler,
MEM_ROOT *alloc)
{
List_iterator_fast<QUICK_SELECT_WITH_RECORD> quick_it(quick_selects);
QUICK_SELECT_WITH_RECORD *cur;
@ -2146,7 +2152,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
There is no use of this->file. Use it for the first of merged range
selects.
*/
int error= quick->init_ror_merged_scan(TRUE);
int error= quick->init_ror_merged_scan(TRUE, alloc);
if (error)
DBUG_RETURN(error);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
@ -2158,7 +2164,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
const MY_BITMAP * const save_read_set= quick->head->read_set;
const MY_BITMAP * const save_write_set= quick->head->write_set;
#endif
if (quick->init_ror_merged_scan(FALSE))
if (quick->init_ror_merged_scan(FALSE, alloc))
DBUG_RETURN(1);
quick->file->extra(HA_EXTRA_KEYREAD_PRESERVE_FIELDS);
@ -2192,7 +2198,7 @@ int QUICK_ROR_INTERSECT_SELECT::init_ror_merged_scan(bool reuse_handler)
int QUICK_ROR_INTERSECT_SELECT::reset()
{
DBUG_ENTER("QUICK_ROR_INTERSECT_SELECT::reset");
if (!scans_inited && init_ror_merged_scan(TRUE))
if (!scans_inited && init_ror_merged_scan(TRUE, &alloc))
DBUG_RETURN(1);
scans_inited= TRUE;
List_iterator_fast<QUICK_SELECT_WITH_RECORD> it(quick_selects);
@ -2329,7 +2335,7 @@ int QUICK_ROR_UNION_SELECT::reset()
List_iterator_fast<QUICK_SELECT_I> it(quick_selects);
while ((quick= it++))
{
if (quick->init_ror_merged_scan(FALSE))
if (quick->init_ror_merged_scan(FALSE, &alloc))
DBUG_RETURN(1);
}
scans_inited= TRUE;
@ -7373,8 +7379,10 @@ static SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param,COND *cond)
DBUG_RETURN(tree);
}
/* Here when simple cond */
if (cond->const_item() && !cond->is_expensive())
if (cond->const_item())
{
if (cond->is_expensive())
DBUG_RETURN(0);
/*
During the cond->val_int() evaluation we can come across a subselect
item which may allocate memory on the thd->mem_root and assumes
@ -11691,7 +11699,8 @@ static bool get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
KEY_PART_INFO **first_non_infix_part);
static bool
check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
Field::imagetype image_type);
Field::imagetype image_type,
bool *has_min_max_fld, bool *has_other_fld);
static void
cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
@ -12031,6 +12040,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
else
goto next_index;
}
/*
This function is called on the precondition that the index is covering.
Therefore if the GROUP BY list contains more elements than the index,
these are duplicates. The GROUP BY list cannot be a prefix of the index.
*/
if (cur_part == end_part && tmp_group)
goto next_index;
}
/*
Check (GA2) if this is a DISTINCT query.
@ -12084,7 +12100,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
cur_parts have bits set for only used keyparts.
*/
ulonglong all_parts, cur_parts;
all_parts= (1<<max_key_part) - 1;
all_parts= (1ULL << max_key_part) - 1;
cur_parts= used_key_parts_map.to_ulonglong() >> 1;
if (all_parts != cur_parts)
goto next_index;
@ -12241,10 +12257,12 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
DBUG_RETURN(NULL);
/* Check (SA3) for the where clause. */
bool has_min_max_fld= false, has_other_fld= false;
if (join->conds && min_max_arg_item &&
!check_group_min_max_predicates(join->conds, min_max_arg_item,
(index_info->flags & HA_SPATIAL) ?
Field::itMBR : Field::itRAW))
Field::itMBR : Field::itRAW,
&has_min_max_fld, &has_other_fld))
DBUG_RETURN(NULL);
/*
@ -12292,16 +12310,24 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
SYNOPSIS
check_group_min_max_predicates()
cond tree (or subtree) describing all or part of the WHERE
clause being analyzed
min_max_arg_item the field referenced by the MIN/MAX function(s)
min_max_arg_part the keypart of the MIN/MAX argument if any
cond [in] the expression tree being analyzed
min_max_arg [in] the field referenced by the MIN/MAX function(s)
image_type [in]
has_min_max_arg [out] true if the subtree being analyzed references min_max_arg
has_other_arg [out] true if the subtree being analyzed references a column
other min_max_arg
DESCRIPTION
The function walks recursively over the cond tree representing a WHERE
clause, and checks condition (SA3) - if a field is referenced by a MIN/MAX
aggregate function, it is referenced only by one of the following
predicates: {=, !=, <, <=, >, >=, between, is null, is not null}.
predicates $FUNC$:
{=, !=, <, <=, >, >=, between, is [not] null, multiple equal}.
In addition the function checks that the WHERE condition is equivalent to
"cond1 AND cond2" where :
cond1 - does not use min_max_column at all.
cond2 - is an AND/OR tree with leaves in form
"$FUNC$(min_max_column[, const])".
RETURN
TRUE if cond passes the test
@ -12310,7 +12336,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree, double read_time)
static bool
check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
Field::imagetype image_type)
Field::imagetype image_type,
bool *has_min_max_arg, bool *has_other_arg)
{
DBUG_ENTER("check_group_min_max_predicates");
DBUG_ASSERT(cond && min_max_arg_item);
@ -12322,12 +12349,24 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
DBUG_PRINT("info", ("Analyzing: %s", ((Item_func*) cond)->func_name()));
List_iterator_fast<Item> li(*((Item_cond*) cond)->argument_list());
Item *and_or_arg;
Item_func::Functype func_type= ((Item_cond*) cond)->functype();
bool has_min_max= false, has_other= false;
while ((and_or_arg= li++))
{
if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item,
image_type))
/*
The WHERE clause doesn't pass the condition if:
(1) any subtree doesn't pass the condition or
(2) the subtree passes the test, but it is an OR and it references both
the min/max argument and other columns.
*/
if (!check_group_min_max_predicates(and_or_arg, min_max_arg_item, //1
image_type,
&has_min_max, &has_other) ||
(func_type == Item_func::COND_OR_FUNC && has_min_max && has_other))//2
DBUG_RETURN(FALSE);
}
*has_min_max_arg= has_min_max || *has_min_max_arg;
*has_other_arg= has_other || *has_other_arg;
DBUG_RETURN(TRUE);
}
@ -12361,6 +12400,10 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
if (cond_type == Item::FIELD_ITEM)
{
DBUG_PRINT("info", ("Analyzing: %s", cond->full_name()));
if (min_max_arg_item->eq((Item_field*)cond, 1))
*has_min_max_arg= true;
else
*has_other_arg= true;
DBUG_RETURN(TRUE);
}
@ -12369,9 +12412,33 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
/* Test if cond references only group-by or non-group fields. */
Item_func *pred= (Item_func*) cond;
Item_func::Functype pred_type= pred->functype();
DBUG_PRINT("info", ("Analyzing: %s", pred->func_name()));
if (pred_type == Item_func::MULT_EQUAL_FUNC)
{
/*
Check that each field in a multiple equality is either a constant or
it is a reference to the min/max argument, or it doesn't contain the
min/max argument at all.
*/
Item_equal_fields_iterator eq_it(*((Item_equal*)pred));
Item *eq_item;
bool has_min_max= false, has_other= false;
while ((eq_item= eq_it++))
{
if (min_max_arg_item->eq(eq_item->real_item(), 1))
has_min_max= true;
else
has_other= true;
}
*has_min_max_arg= has_min_max || *has_min_max_arg;
*has_other_arg= has_other || *has_other_arg;
DBUG_RETURN(!(has_min_max && has_other));
}
Item **arguments= pred->arguments();
Item *cur_arg;
DBUG_PRINT("info", ("Analyzing: %s", pred->func_name()));
bool has_min_max= false, has_other= false;
for (uint arg_idx= 0; arg_idx < pred->argument_count (); arg_idx++)
{
cur_arg= arguments[arg_idx]->real_item();
@ -12380,11 +12447,11 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
{
if (min_max_arg_item->eq(cur_arg, 1))
{
/*
If pred references the MIN/MAX argument, check whether pred is a range
condition that compares the MIN/MAX argument with a constant.
*/
Item_func::Functype pred_type= pred->functype();
has_min_max= true;
/*
If pred references the MIN/MAX argument, check whether pred is a range
condition that compares the MIN/MAX argument with a constant.
*/
if (pred_type != Item_func::EQUAL_FUNC &&
pred_type != Item_func::LT_FUNC &&
pred_type != Item_func::LE_FUNC &&
@ -12424,14 +12491,16 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
min_max_arg_item->field->cmp_type() != args[1]->result_type())))
DBUG_RETURN(FALSE);
}
else
has_other= true;
}
else if (cur_arg->type() == Item::FUNC_ITEM)
{
if (!check_group_min_max_predicates(cur_arg, min_max_arg_item,
image_type))
if (!check_group_min_max_predicates(cur_arg, min_max_arg_item, image_type,
&has_min_max, &has_other))
DBUG_RETURN(FALSE);
}
else if (cur_arg->const_item())
else if (cur_arg->const_item() && !cur_arg->is_expensive())
{
/*
For predicates of the form "const OP expr" we also have to check 'expr'
@ -12441,7 +12510,11 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
}
else
DBUG_RETURN(FALSE);
if(has_min_max && has_other)
DBUG_RETURN(FALSE);
}
*has_min_max_arg= has_min_max || *has_min_max_arg;
*has_other_arg= has_other || *has_other_arg;
DBUG_RETURN(TRUE);
}