Commit 0f0e514f authored by unknown's avatar unknown

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.
parent 4f1d7b7d
...@@ -177,9 +177,8 @@ bool Item_ident::remove_dependence_processor(byte * arg) ...@@ -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)
......
...@@ -1455,8 +1455,6 @@ public: ...@@ -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: ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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() ...@@ -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) ...@@ -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) ...@@ -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; return TRUE;
if (insert_dynamic(&min_max_ranges, (gptr)&range)) if (insert_dynamic(&min_max_ranges, (gptr)&range))
return FALSE;
return TRUE; return TRUE;
return FALSE;
} }
......
...@@ -5020,7 +5020,6 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) ...@@ -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));
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment