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:
131
sql/opt_range.cc
131
sql/opt_range.cc
@ -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);
|
||||
}
|
||||
|
Reference in New Issue
Block a user