summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc32
-rw-r--r--sql/field.h26
-rw-r--r--sql/item_cmpfunc.h11
-rw-r--r--sql/opt_range.cc34
4 files changed, 73 insertions, 30 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 83560003128..57721d39d32 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1246,6 +1246,18 @@ double Field::pos_in_interval_val_str(Field *min, Field *max, uint data_offset)
}
+/*
+ This handles all numeric and BIT data types.
+*/
+bool Field::can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item)
+{
+ DBUG_ASSERT(cmp_type() != STRING_RESULT);
+ DBUG_ASSERT(cmp_type() != TIME_RESULT);
+ return const_item->cmp_type() != TIME_RESULT;
+}
+
+
/**
Numeric fields base class constructor.
*/
@@ -5257,6 +5269,14 @@ my_decimal *Field_temporal::val_decimal(my_decimal *d)
return TIME_to_my_decimal(&ltime, d);
}
+
+bool Field_temporal::can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item)
+{
+ return true; // Field is of TIME_RESULT, which supersedes everything else.
+}
+
+
/****************************************************************************
** time type
** In string context: HH:MM:SS
@@ -6448,6 +6468,18 @@ uint32 Field_longstr::max_data_length() const
}
+bool Field_longstr::can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item)
+{
+ // Can't use indexes when comparing a string to a number or a date
+ if (const_item->cmp_type() != STRING_RESULT)
+ return false;
+
+ // Don't use an index when comparing strings of different collations.
+ return charset() == ((Item_bool_func2*) cond)->compare_collation();
+}
+
+
double Field_string::val_real(void)
{
ASSERT_COLUMN_MARKED_FOR_READ;
diff --git a/sql/field.h b/sql/field.h
index cac9a156a95..ef0fa2765a4 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -39,6 +39,7 @@ class Relay_log_info;
class Field;
class Column_statistics;
class Column_statistics_collected;
+class Item_bool_func2;
enum enum_check_fields
{
@@ -963,6 +964,9 @@ public:
return (double) 0.5;
}
+ virtual bool can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item);
+
friend int cre_myisam(char * name, register TABLE *form, uint options,
ulonglong auto_increment_value);
friend class Copy_field;
@@ -1154,6 +1158,8 @@ public:
int store_decimal(const my_decimal *d);
uint32 max_data_length() const;
bool match_collation_to_optimize_range() const { return true; }
+ bool can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item);
};
/* base class for float and double and decimal (old one) */
@@ -1581,6 +1587,12 @@ public:
uint size_of() const { return sizeof(*this); }
uint32 max_display_length() { return 4; }
void move_field_offset(my_ptrdiff_t ptr_diff) {}
+ bool can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item)
+ {
+ DBUG_ASSERT(0);
+ return false;
+ }
};
@@ -1613,6 +1625,8 @@ public:
{
return pos_in_interval_val_real(min, max);
}
+ bool can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item);
};
@@ -2650,6 +2664,18 @@ public:
virtual const uchar *unpack(uchar *to, const uchar *from,
const uchar *from_end, uint param_data);
+ bool can_optimize_group_min_max(const Item_bool_func2 *cond,
+ const Item *const_item)
+ {
+ /*
+ Can't use GROUP_MIN_MAX optimization for ENUM and SET,
+ because the values are stored as numbers in index,
+ while MIN() and MAX() work as strings.
+ It would return the records with min and max enum numeric indexes.
+ "Bug#45300 MAX() and ENUM type" should be fixed first.
+ */
+ return false;
+ }
private:
int do_save_field_metadata(uchar *first_byte);
uint is_equal(Create_field *new_field);
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 685e9105aa3..7aaef893415 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -131,6 +131,11 @@ public:
bool is_bool_type() { return true; }
void fix_length_and_dec() { decimals=0; max_length=1; }
uint decimal_precision() const { return 1; }
+ virtual bool can_optimize_group_min_max(Item_field *min_max_arg_item,
+ const Item *const_item) const
+ {
+ return false;
+ }
};
@@ -419,6 +424,12 @@ public:
{
return (*arg != NULL);
}
+ bool can_optimize_group_min_max(Item_field *min_max_arg_item,
+ const Item *const_item) const
+ {
+ return min_max_arg_item->field->can_optimize_group_min_max(this,
+ const_item);
+ }
};
/**
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 3cac6e5139e..8f691f4e5dc 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -13412,39 +13412,13 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
if (!simple_pred(pred, args, &inv))
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
{
- if (args[1]->cmp_type() == TIME_RESULT &&
- min_max_arg_item->field->cmp_type() != TIME_RESULT)
+ DBUG_ASSERT(pred->is_bool_type());
+ Item_bool_func *bool_func= (Item_bool_func*) pred;
+ if (!bool_func->can_optimize_group_min_max(min_max_arg_item,
+ args[1]))
DBUG_RETURN(FALSE);
-
- /*
- Can't use GROUP_MIN_MAX optimization for ENUM and SET,
- because the values are stored as numbers in index,
- while MIN() and MAX() work as strings.
- It would return the records with min and max enum numeric indexes.
- "Bug#45300 MAX() and ENUM type" should be fixed first.
- */
- if (min_max_arg_item->field->real_type() == MYSQL_TYPE_ENUM ||
- min_max_arg_item->field->real_type() == MYSQL_TYPE_SET)
- DBUG_RETURN(FALSE);
-
- if (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 &&
- 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