Commit 42bc08b3 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-8229 GROUP_MIN_MAX is erroneously applied for BETWEEN in some cases

parent 1f4a89b1
...@@ -3779,5 +3779,95 @@ id MIN(a) MAX(a) ...@@ -3779,5 +3779,95 @@ id MIN(a) MAX(a)
4 2001-01-04 2001-01-04 4 2001-01-04 2001-01-04
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-8229 GROUP_MIN_MAX is erroneously applied for BETWEEN in some cases
#
SET NAMES latin1;
CREATE TABLE t1 (id INT NOT NULL, a VARCHAR(20)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'2001-01-01');
INSERT INTO t1 VALUES (1,'2001-01-02');
INSERT INTO t1 VALUES (1,'2001-01-03');
INSERT INTO t1 VALUES (1,' 2001-01-04');
INSERT INTO t1 VALUES (2,'2001-01-01');
INSERT INTO t1 VALUES (2,'2001-01-02');
INSERT INTO t1 VALUES (2,'2001-01-03');
INSERT INTO t1 VALUES (2,' 2001-01-04');
INSERT INTO t1 VALUES (3,'2001-01-01');
INSERT INTO t1 VALUES (3,'2001-01-02');
INSERT INTO t1 VALUES (3,'2001-01-03');
INSERT INTO t1 VALUES (3,' 2001-01-04');
INSERT INTO t1 VALUES (4,'2001-01-01');
INSERT INTO t1 VALUES (4,'2001-01-02');
INSERT INTO t1 VALUES (4,'2001-01-03');
INSERT INTO t1 VALUES (4,' 2001-01-04');
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-03
2 2001-01-04 2001-01-03
3 2001-01-04 2001-01-03
4 2001-01-04 2001-01-03
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
ALTER TABLE t1 ADD KEY(id,a);
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-03
2 2001-01-04 2001-01-03
3 2001-01-04 2001-01-03
4 2001-01-04 2001-01-03
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id MIN(a) MAX(a)
1 2001-01-04 2001-01-04
2 2001-01-04 2001-01-04
3 2001-01-04 2001-01-04
4 2001-01-04 2001-01-04
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL id 27 NULL 9 Using where; Using index for group-by
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range NULL id 27 NULL 9 Using where; Using index for group-by
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL id 27 NULL 16 Using where; Using index
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL id 27 NULL 16 Using where; Using index
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index NULL id 27 NULL 16 Using where; Using index
DROP TABLE t1;
#
# End of 10.1 tests # End of 10.1 tests
# #
...@@ -1557,6 +1557,46 @@ SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104.0 GROUP BY id; ...@@ -1557,6 +1557,46 @@ SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104.0 GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id; SELECT id,MIN(a),MAX(a) FROM t1 WHERE a>=20010104e0 GROUP BY id;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-8229 GROUP_MIN_MAX is erroneously applied for BETWEEN in some cases
--echo #
SET NAMES latin1;
CREATE TABLE t1 (id INT NOT NULL, a VARCHAR(20)) ENGINE=MyISAM;
INSERT INTO t1 VALUES (1,'2001-01-01');
INSERT INTO t1 VALUES (1,'2001-01-02');
INSERT INTO t1 VALUES (1,'2001-01-03');
INSERT INTO t1 VALUES (1,' 2001-01-04');
INSERT INTO t1 VALUES (2,'2001-01-01');
INSERT INTO t1 VALUES (2,'2001-01-02');
INSERT INTO t1 VALUES (2,'2001-01-03');
INSERT INTO t1 VALUES (2,' 2001-01-04');
INSERT INTO t1 VALUES (3,'2001-01-01');
INSERT INTO t1 VALUES (3,'2001-01-02');
INSERT INTO t1 VALUES (3,'2001-01-03');
INSERT INTO t1 VALUES (3,' 2001-01-04');
INSERT INTO t1 VALUES (4,'2001-01-01');
INSERT INTO t1 VALUES (4,'2001-01-02');
INSERT INTO t1 VALUES (4,'2001-01-03');
INSERT INTO t1 VALUES (4,' 2001-01-04');
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
ALTER TABLE t1 ADD KEY(id,a);
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN ' 2001-01-04' AND '2001-01-05' GROUP BY id;
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND '2001-01-05' GROUP BY id;
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND DATE'2001-01-05' GROUP BY id;
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN DATE'2001-01-04' AND '2001-01-05' GROUP BY id;
EXPLAIN SELECT id,MIN(a),MAX(a) FROM t1 WHERE a BETWEEN '2001-01-04' AND DATE'2001-01-05' GROUP BY id;
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #
...@@ -1261,7 +1261,7 @@ bool Field::can_optimize_keypart_ref(const Item_func *cond, ...@@ -1261,7 +1261,7 @@ bool Field::can_optimize_keypart_ref(const Item_func *cond,
/* /*
This handles all numeric and BIT data types. This handles all numeric and BIT data types.
*/ */
bool Field::can_optimize_group_min_max(const Item_bool_func2 *cond, bool Field::can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const const Item *const_item) const
{ {
DBUG_ASSERT(cmp_type() != STRING_RESULT); DBUG_ASSERT(cmp_type() != STRING_RESULT);
...@@ -5289,7 +5289,7 @@ bool Field_temporal::can_optimize_keypart_ref(const Item_func *cond, ...@@ -5289,7 +5289,7 @@ bool Field_temporal::can_optimize_keypart_ref(const Item_func *cond,
} }
bool Field_temporal::can_optimize_group_min_max(const Item_bool_func2 *cond, bool Field_temporal::can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const const Item *const_item) const
{ {
return true; // Field is of TIME_RESULT, which supersedes everything else. return true; // Field is of TIME_RESULT, which supersedes everything else.
...@@ -6506,7 +6506,7 @@ bool Field_longstr::can_optimize_hash_join(const Item_func *cond, ...@@ -6506,7 +6506,7 @@ bool Field_longstr::can_optimize_hash_join(const Item_func *cond,
} }
bool Field_longstr::can_optimize_group_min_max(const Item_bool_func2 *cond, bool Field_longstr::can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const const Item *const_item) const
{ {
/* /*
......
...@@ -40,7 +40,7 @@ class Field; ...@@ -40,7 +40,7 @@ class Field;
class Column_statistics; class Column_statistics;
class Column_statistics_collected; class Column_statistics_collected;
class Item_func; class Item_func;
class Item_bool_func2; class Item_bool_func;
enum enum_check_fields enum enum_check_fields
{ {
...@@ -986,7 +986,7 @@ public: ...@@ -986,7 +986,7 @@ public:
{ {
return can_optimize_keypart_ref(cond, item); return can_optimize_keypart_ref(cond, item);
} }
virtual bool can_optimize_group_min_max(const Item_bool_func2 *cond, virtual bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const; const Item *const_item) const;
bool can_optimize_outer_join_table_elimination(const Item_func *cond, bool can_optimize_outer_join_table_elimination(const Item_func *cond,
const Item *item) const const Item *item) const
...@@ -1191,7 +1191,7 @@ public: ...@@ -1191,7 +1191,7 @@ public:
bool match_collation_to_optimize_range() const { return true; } bool match_collation_to_optimize_range() const { return true; }
bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const; bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const;
bool can_optimize_hash_join(const Item_func *cond, const Item *item) const; bool can_optimize_hash_join(const Item_func *cond, const Item *item) const;
bool can_optimize_group_min_max(const Item_bool_func2 *cond, bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const; const Item *const_item) const;
}; };
...@@ -1625,7 +1625,7 @@ public: ...@@ -1625,7 +1625,7 @@ public:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return false; return false;
} }
bool can_optimize_group_min_max(const Item_bool_func2 *cond, bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const const Item *const_item) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
...@@ -1664,7 +1664,7 @@ public: ...@@ -1664,7 +1664,7 @@ public:
return pos_in_interval_val_real(min, max); return pos_in_interval_val_real(min, max);
} }
bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const; bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const;
bool can_optimize_group_min_max(const Item_bool_func2 *cond, bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const; const Item *const_item) const;
}; };
...@@ -2721,7 +2721,7 @@ public: ...@@ -2721,7 +2721,7 @@ public:
const uchar *from_end, uint param_data); const uchar *from_end, uint param_data);
bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const; bool can_optimize_keypart_ref(const Item_func *cond, const Item *item) const;
bool can_optimize_group_min_max(const Item_bool_func2 *cond, bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const const Item *const_item) const
{ {
/* /*
......
...@@ -136,11 +136,6 @@ public: ...@@ -136,11 +136,6 @@ public:
bool is_bool_type() { return true; } bool is_bool_type() { return true; }
void fix_length_and_dec() { decimals=0; max_length=1; } void fix_length_and_dec() { decimals=0; max_length=1; }
uint decimal_precision() const { return 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;
}
}; };
...@@ -338,12 +333,6 @@ public: ...@@ -338,12 +333,6 @@ public:
Item_bool_func2::cleanup(); Item_bool_func2::cleanup();
cmp.cleanup(); cmp.cleanup();
} }
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);
}
void add_key_fields(JOIN *join, KEY_FIELD **key_fields, void add_key_fields(JOIN *join, KEY_FIELD **key_fields,
uint *and_level, table_map usable_tables, uint *and_level, table_map usable_tables,
SARGABLE_PARAM **sargables) SARGABLE_PARAM **sargables)
......
...@@ -13455,14 +13455,23 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item, ...@@ -13455,14 +13455,23 @@ check_group_min_max_predicates(Item *cond, Item_field *min_max_arg_item,
if (!simple_pred(pred, args, &inv)) if (!simple_pred(pred, args, &inv))
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
if (args[0] && args[1] && !args[2]) // this is a binary function if (args[0] && args[1]) // this is a binary function or BETWEEN
{ {
DBUG_ASSERT(pred->is_bool_type()); DBUG_ASSERT(pred->is_bool_type());
Item_bool_func *bool_func= (Item_bool_func*) pred; Item_bool_func *bool_func= (Item_bool_func*) pred;
if (!bool_func->can_optimize_group_min_max(min_max_arg_item, Field *field= min_max_arg_item->field;
args[1])) if (!args[2]) // this is a binary function
{
if (!field->can_optimize_group_min_max(bool_func, args[1]))
DBUG_RETURN(FALSE); DBUG_RETURN(FALSE);
} }
else // this is BETWEEN
{
if (!field->can_optimize_group_min_max(bool_func, args[1]) ||
!field->can_optimize_group_min_max(bool_func, args[2]))
DBUG_RETURN(FALSE);
}
}
} }
else else
has_other= true; has_other= true;
......
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