Fixes for WL#1724 required by the third code review.
sql/item.cc: Document actual behavior. sql/opt_range.cc: - Added a test for range predicates comparing incomparable argumens - Removed TRP_GROUP_MIN_MAX class members that are not used. - Uncommented CPU cost - More standard function return values sql/sql_select.cc: Remove unnecessary test.
This commit is contained in:
parent
4f1d7b7dae
commit
0f0e514fda
@ -177,9 +177,8 @@ bool Item_ident::remove_dependence_processor(byte * arg)
|
|||||||
arguments in a condition the method must return false.
|
arguments in a condition the method must return false.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
false on success (force the evaluation of collect_item_field_processor
|
false to force the evaluation of collect_item_field_processor
|
||||||
for the subsequent items.)
|
for the subsequent items.
|
||||||
true o/w (stop evaluation of subsequent items.)
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool Item_field::collect_item_field_processor(byte *arg)
|
bool Item_field::collect_item_field_processor(byte *arg)
|
||||||
|
103
sql/opt_range.cc
103
sql/opt_range.cc
@ -1455,8 +1455,6 @@ public:
|
|||||||
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
|
class TRP_GROUP_MIN_MAX : public TABLE_READ_PLAN
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
JOIN *join;
|
|
||||||
TABLE* table;
|
|
||||||
bool have_min, have_max;
|
bool have_min, have_max;
|
||||||
KEY_PART_INFO *min_max_arg_part;
|
KEY_PART_INFO *min_max_arg_part;
|
||||||
uint group_prefix_len;
|
uint group_prefix_len;
|
||||||
@ -1473,12 +1471,12 @@ private:
|
|||||||
public:
|
public:
|
||||||
ha_rows quick_prefix_records;
|
ha_rows quick_prefix_records;
|
||||||
public:
|
public:
|
||||||
TRP_GROUP_MIN_MAX(JOIN *join, TABLE* table, bool have_min, bool have_max,
|
TRP_GROUP_MIN_MAX(bool have_min, bool have_max,
|
||||||
KEY_PART_INFO *min_max_arg_part, uint group_prefix_len,
|
KEY_PART_INFO *min_max_arg_part, uint group_prefix_len,
|
||||||
uint used_key_parts, uint group_key_parts, KEY *index_info,
|
uint used_key_parts, uint group_key_parts, KEY *index_info,
|
||||||
uint index, uint key_infix_len, byte *key_infix,
|
uint index, uint key_infix_len, byte *key_infix,
|
||||||
SEL_TREE *tree, SEL_ARG *index_tree, uint param_idx,
|
SEL_TREE *tree, SEL_ARG *index_tree, uint param_idx,
|
||||||
ha_rows quick_prefix_records, PARAM *param);
|
ha_rows quick_prefix_records);
|
||||||
|
|
||||||
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
|
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
|
||||||
MEM_ROOT *parent_alloc);
|
MEM_ROOT *parent_alloc);
|
||||||
@ -6369,7 +6367,8 @@ get_constant_key_infix(KEY *index_info, SEL_ARG *index_range_tree,
|
|||||||
byte *key_infix, uint *key_infix_len,
|
byte *key_infix, uint *key_infix_len,
|
||||||
KEY_PART_INFO **first_non_infix_part);
|
KEY_PART_INFO **first_non_infix_part);
|
||||||
static bool
|
static bool
|
||||||
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item);
|
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
|
||||||
|
Field::imagetype image_type);
|
||||||
|
|
||||||
static void
|
static void
|
||||||
cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
|
cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
|
||||||
@ -6778,25 +6777,26 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||||||
next_index:
|
next_index:
|
||||||
cur_group_key_parts= 0;
|
cur_group_key_parts= 0;
|
||||||
cur_group_prefix_len= 0;
|
cur_group_prefix_len= 0;
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
if (!index_info) /* No usable index found. */
|
if (!index_info) /* No usable index found. */
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
|
|
||||||
/* Check (SA3,WA1) for the where clause. */
|
/* Check (SA3,WA1) for the where clause. */
|
||||||
if (!check_group_min_max_predicates(join->conds, min_max_arg_item))
|
if (!check_group_min_max_predicates(join->conds, min_max_arg_item,
|
||||||
|
(index_info->flags & HA_SPATIAL) ?
|
||||||
|
Field::itMBR : Field::itRAW))
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
/* The query passes all tests, so construct a new TRP object. */
|
/* The query passes all tests, so construct a new TRP object. */
|
||||||
read_plan= new (param->mem_root)
|
read_plan= new (param->mem_root)
|
||||||
TRP_GROUP_MIN_MAX(join, table, have_min, have_max,
|
TRP_GROUP_MIN_MAX(have_min, have_max, min_max_arg_part,
|
||||||
min_max_arg_part, group_prefix_len,
|
group_prefix_len, used_key_parts,
|
||||||
used_key_parts, group_key_parts, index_info,
|
group_key_parts, index_info, index,
|
||||||
index, key_infix_len,
|
key_infix_len,
|
||||||
(key_infix_len > 0) ? key_infix : NULL,
|
(key_infix_len > 0) ? key_infix : NULL,
|
||||||
tree, best_index_tree, best_param_idx,
|
tree, best_index_tree, best_param_idx,
|
||||||
best_quick_prefix_records, param);
|
best_quick_prefix_records);
|
||||||
if (read_plan)
|
if (read_plan)
|
||||||
{
|
{
|
||||||
if (tree && read_plan->quick_prefix_records == 0)
|
if (tree && read_plan->quick_prefix_records == 0)
|
||||||
@ -6823,12 +6823,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||||||
cond tree (or subtree) describing all or part of the WHERE
|
cond tree (or subtree) describing all or part of the WHERE
|
||||||
clause being analyzed
|
clause being analyzed
|
||||||
min_max_arg_item the field referenced by the MIN/MAX function(s)
|
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
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
The function walks recursively over the cond tree representing a WHERE
|
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
|
clause, and checks condition (SA3) - if a field is referenced by a MIN/MAX
|
||||||
aggregate function, it is referenced only by the following predicates:
|
aggregate function, it is referenced only by one of the following
|
||||||
{=, !=, <, <=, >, >=, between, is null, is not null}.
|
predicates: {=, !=, <, <=, >, >=, between, is null, is not null}.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
TRUE if cond passes the test
|
TRUE if cond passes the test
|
||||||
@ -6836,7 +6837,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item)
|
check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item,
|
||||||
|
Field::imagetype image_type)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("check_group_min_max_predicates");
|
DBUG_ENTER("check_group_min_max_predicates");
|
||||||
if (!cond) /* If no WHERE clause, then all is OK. */
|
if (!cond) /* If no WHERE clause, then all is OK. */
|
||||||
@ -6850,7 +6852,8 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item)
|
|||||||
Item *and_or_arg;
|
Item *and_or_arg;
|
||||||
while ((and_or_arg= li++))
|
while ((and_or_arg= li++))
|
||||||
{
|
{
|
||||||
if(!check_group_min_max_predicates(and_or_arg, min_max_arg_item))
|
if(!check_group_min_max_predicates(and_or_arg, min_max_arg_item,
|
||||||
|
image_type))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
@ -6890,15 +6893,36 @@ check_group_min_max_predicates(COND *cond, Item_field *min_max_arg_item)
|
|||||||
|
|
||||||
/* Check that pred compares min_max_arg_item with a constant. */
|
/* Check that pred compares min_max_arg_item with a constant. */
|
||||||
Item *args[3];
|
Item *args[3];
|
||||||
|
bzero(args, 3 * sizeof(Item*));
|
||||||
bool inv;
|
bool inv;
|
||||||
/* Test if this is a comparison of a field and a constant. */
|
/* Test if this is a comparison of a field and a constant. */
|
||||||
if (!simple_pred(pred, args, &inv))
|
if (!simple_pred(pred, args, &inv))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
|
/* Check for compatible string comparisons - similar to get_mm_leaf. */
|
||||||
|
if (args[0] && args[1] && !args[2] && // this is a binary function
|
||||||
|
min_max_arg_item->result_type() == STRING_RESULT &&
|
||||||
|
/*
|
||||||
|
Don't use an index when comparing strings of different collations.
|
||||||
|
*/
|
||||||
|
((args[1]->result_type() == STRING_RESULT &&
|
||||||
|
image_type == Field::itRAW &&
|
||||||
|
((Field_str*) min_max_arg_item->field)->charset() !=
|
||||||
|
pred->compare_collation())
|
||||||
|
||
|
||||||
|
/*
|
||||||
|
We can't always use indexes when comparing a string index to a
|
||||||
|
number.
|
||||||
|
*/
|
||||||
|
(args[1]->result_type() != STRING_RESULT &&
|
||||||
|
min_max_arg_item->field->cmp_type() != args[1]->result_type())))
|
||||||
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (cur_arg->type() == Item::FUNC_ITEM)
|
else if (cur_arg->type() == Item::FUNC_ITEM)
|
||||||
{
|
{
|
||||||
if(!check_group_min_max_predicates(cur_arg, min_max_arg_item))
|
if(!check_group_min_max_predicates(cur_arg, min_max_arg_item,
|
||||||
|
image_type))
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
else if (cur_arg->const_item())
|
else if (cur_arg->const_item())
|
||||||
@ -7083,24 +7107,22 @@ SEL_ARG * get_index_range_tree(uint index, SEL_TREE* range_tree, PARAM *param,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
TRP_GROUP_MIN_MAX::TRP_GROUP_MIN_MAX(JOIN *join, TABLE* table,
|
TRP_GROUP_MIN_MAX::TRP_GROUP_MIN_MAX(bool have_min, bool have_max,
|
||||||
bool have_min, bool have_max,
|
|
||||||
KEY_PART_INFO *min_max_arg_part,
|
KEY_PART_INFO *min_max_arg_part,
|
||||||
uint group_prefix_len, uint used_key_parts,
|
uint group_prefix_len, uint used_key_parts,
|
||||||
uint group_key_parts, KEY *index_info,
|
uint group_key_parts, KEY *index_info,
|
||||||
uint index, uint key_infix_len,
|
uint index, uint key_infix_len,
|
||||||
byte *key_infix, SEL_TREE *tree,
|
byte *key_infix, SEL_TREE *tree,
|
||||||
SEL_ARG *index_tree, uint param_idx,
|
SEL_ARG *index_tree, uint param_idx,
|
||||||
ha_rows quick_prefix_records, PARAM *param)
|
ha_rows quick_prefix_records)
|
||||||
: join(join), table(table), have_min(have_min), have_max(have_max),
|
: have_min(have_min), have_max(have_max), min_max_arg_part(min_max_arg_part),
|
||||||
min_max_arg_part(min_max_arg_part), group_prefix_len(group_prefix_len),
|
group_prefix_len(group_prefix_len), used_key_parts(used_key_parts),
|
||||||
used_key_parts(used_key_parts), group_key_parts(group_key_parts),
|
group_key_parts(group_key_parts), index_info(index_info), index(index),
|
||||||
index_info(index_info), index(index), key_infix_len(key_infix_len),
|
key_infix_len(key_infix_len), range_tree(tree), index_tree(index_tree),
|
||||||
range_tree(tree), index_tree(index_tree), param_idx(param_idx),
|
param_idx(param_idx), quick_prefix_records(quick_prefix_records)
|
||||||
quick_prefix_records(quick_prefix_records)
|
|
||||||
{
|
{
|
||||||
if (key_infix_len)
|
if (key_infix_len)
|
||||||
memcpy(this->key_infix, key_infix, MAX_KEY_LENGTH);
|
memcpy(this->key_infix, key_infix, key_infix_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -7233,7 +7255,7 @@ void cost_group_min_max(TABLE* table, KEY *index_info, uint used_key_parts,
|
|||||||
*/
|
*/
|
||||||
cpu_cost= (double) num_groups / TIME_FOR_COMPARE;
|
cpu_cost= (double) num_groups / TIME_FOR_COMPARE;
|
||||||
|
|
||||||
*read_cost= io_cost /*+ cpu_cost*/;
|
*read_cost= io_cost + cpu_cost;
|
||||||
*records= num_groups;
|
*records= num_groups;
|
||||||
|
|
||||||
DBUG_PRINT("info",
|
DBUG_PRINT("info",
|
||||||
@ -7273,11 +7295,12 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
|
|||||||
|
|
||||||
DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick");
|
DBUG_ENTER("TRP_GROUP_MIN_MAX::make_quick");
|
||||||
|
|
||||||
quick= new QUICK_GROUP_MIN_MAX_SELECT(table, join, have_min, have_max,
|
quick= new QUICK_GROUP_MIN_MAX_SELECT(param->table,
|
||||||
min_max_arg_part, group_prefix_len,
|
param->thd->lex->select_lex.join,
|
||||||
used_key_parts, index_info, index,
|
have_min, have_max, min_max_arg_part,
|
||||||
read_cost, records, key_infix_len,
|
group_prefix_len, used_key_parts,
|
||||||
key_infix, parent_alloc);
|
index_info, index, read_cost, records,
|
||||||
|
key_infix_len, key_infix, parent_alloc);
|
||||||
if (!quick)
|
if (!quick)
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
|
|
||||||
@ -7317,7 +7340,7 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
|
|||||||
/* Create an array of QUICK_RANGEs for the MIN/MAX argument. */
|
/* Create an array of QUICK_RANGEs for the MIN/MAX argument. */
|
||||||
while (min_max_range)
|
while (min_max_range)
|
||||||
{
|
{
|
||||||
if (!quick->add_range(min_max_range))
|
if (quick->add_range(min_max_range))
|
||||||
{
|
{
|
||||||
delete quick;
|
delete quick;
|
||||||
quick= NULL;
|
quick= NULL;
|
||||||
@ -7514,8 +7537,8 @@ QUICK_GROUP_MIN_MAX_SELECT::~QUICK_GROUP_MIN_MAX_SELECT()
|
|||||||
a quick range.
|
a quick range.
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
TRUE on success
|
FALSE on success
|
||||||
FALSE otherwise
|
TRUE otherwise
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
|
bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
|
||||||
@ -7525,7 +7548,7 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
|
|||||||
|
|
||||||
/* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
|
/* Skip (-inf,+inf) ranges, e.g. (x < 5 or x > 4). */
|
||||||
if((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
|
if((range_flag & NO_MIN_RANGE) && (range_flag & NO_MAX_RANGE))
|
||||||
return TRUE;
|
return FALSE;
|
||||||
|
|
||||||
if (!(sel_range->min_flag & NO_MIN_RANGE) &&
|
if (!(sel_range->min_flag & NO_MIN_RANGE) &&
|
||||||
!(sel_range->max_flag & NO_MAX_RANGE))
|
!(sel_range->max_flag & NO_MAX_RANGE))
|
||||||
@ -7541,10 +7564,10 @@ bool QUICK_GROUP_MIN_MAX_SELECT::add_range(SEL_ARG *sel_range)
|
|||||||
sel_range->max_value, min_max_arg_len,
|
sel_range->max_value, min_max_arg_len,
|
||||||
range_flag);
|
range_flag);
|
||||||
if (!range)
|
if (!range)
|
||||||
return FALSE;
|
|
||||||
if (insert_dynamic(&min_max_ranges, (gptr)&range))
|
|
||||||
return FALSE;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
if (insert_dynamic(&min_max_ranges, (gptr)&range))
|
||||||
|
return TRUE;
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -5020,7 +5020,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
|
|||||||
}
|
}
|
||||||
if (tmp || !cond)
|
if (tmp || !cond)
|
||||||
{
|
{
|
||||||
if (tmp)
|
|
||||||
DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
|
DBUG_EXECUTE("where",print_where(tmp,tab->table->table_name););
|
||||||
SQL_SELECT *sel=tab->select=(SQL_SELECT*)
|
SQL_SELECT *sel=tab->select=(SQL_SELECT*)
|
||||||
join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
|
join->thd->memdup((gptr) select, sizeof(SQL_SELECT));
|
||||||
|
Loading…
x
Reference in New Issue
Block a user