Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/bb-10.2-ext' into 10.3
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexander Barkov committed Jan 13, 2017
2 parents 8a5de51 + 59c58f6 commit c846ebe
Show file tree
Hide file tree
Showing 7 changed files with 168 additions and 79 deletions.
15 changes: 9 additions & 6 deletions mysql-test/r/gis.result
Expand Up @@ -2199,8 +2199,11 @@ c
1
DROP TABLE t1;
#
# Start of 10.3 tests
#
#
# MDEV-11478 Result data type aggregation for pluggable data types
#
CREATE PROCEDURE p2(query TEXT)
BEGIN
DECLARE errcount INT DEFAULT 0;
Expand Down Expand Up @@ -2451,23 +2454,23 @@ CREATE TABLE t1 (a SMALLINT, b Point)

CREATE TABLE t2 AS SELECT CASE WHEN TRUE THEN a ELSE b END FROM t1
ERROR:
Illegal parameter data types shortint and geometry for operation 'case'
Illegal parameter data types smallint and geometry for operation 'case'

CREATE TABLE t2 AS SELECT COALESCE(a,b) FROM t1
ERROR:
Illegal parameter data types shortint and geometry for operation 'coalesce'
Illegal parameter data types smallint and geometry for operation 'coalesce'

CREATE TABLE t2 AS SELECT IF(TRUE,a,b) FROM t1
ERROR:
Illegal parameter data types shortint and geometry for operation 'if'
Illegal parameter data types smallint and geometry for operation 'if'

CREATE TABLE t2 AS SELECT IFNULL(a,b) FROM t1
ERROR:
Illegal parameter data types shortint and geometry for operation 'ifnull'
Illegal parameter data types smallint and geometry for operation 'ifnull'

CREATE TABLE t2 AS SELECT a FROM t1 UNION SELECT b FROM t1
ERROR:
Illegal parameter data types shortint and geometry for operation 'UNION'
Illegal parameter data types smallint and geometry for operation 'UNION'
-------------------------------------
CREATE TABLE t1 (a MEDIUMINT, b Point)

Expand Down Expand Up @@ -2811,5 +2814,5 @@ DROP TABLE t1;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
#
# End of 10.2 tests
# End of 10.3 tests
#
6 changes: 5 additions & 1 deletion mysql-test/t/gis.test
Expand Up @@ -1717,7 +1717,11 @@ SELECT c FROM t1;
DROP TABLE t1;

--echo #
--echo # Start of 10.3 tests
--echo #

--echo #
--echo # MDEV-11478 Result data type aggregation for pluggable data types
--echo #

DELIMITER $$;
Expand Down Expand Up @@ -1796,5 +1800,5 @@ DROP PROCEDURE p2;


--echo #
--echo # End of 10.2 tests
--echo # End of 10.3 tests
--echo #
9 changes: 6 additions & 3 deletions sql/item_cmpfunc.h
Expand Up @@ -392,15 +392,15 @@ class Item_bool_func2 :public Item_bool_func
Specifies which result type the function uses to compare its arguments.
This method is used in equal field propagation.
*/
virtual Item_result compare_type() const
virtual const Type_handler *compare_type_handler() const
{
/*
Have STRING_RESULT by default, which means the function compares
val_str() results of the arguments. This is suitable for Item_func_like
and for Item_func_spatial_rel.
Note, Item_bool_rowready_func2 overrides this default behaviour.
*/
return STRING_RESULT;
return &type_handler_varchar;
}
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr)
{
Expand Down Expand Up @@ -508,7 +508,10 @@ class Item_bool_rowready_func2 :public Item_bool_func2_with_rev
return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
}
CHARSET_INFO *compare_collation() const { return cmp.compare_collation(); }
Item_result compare_type() const { return cmp.compare_type(); }
const Type_handler *compare_type_handler() const
{
return cmp.compare_type_handler();
}
Arg_comparator *get_comparator() { return &cmp; }
void cleanup()
{
Expand Down
72 changes: 6 additions & 66 deletions sql/sql_select.cc
Expand Up @@ -12927,7 +12927,7 @@ bool Item_func_eq::check_equality(THD *thd, COND_EQUAL *cond_equal,
}
return check_simple_equality(thd,
Context(ANY_SUBST,
compare_type(),
compare_type_handler()->cmp_type(),
compare_collation()),
left_item, right_item, cond_equal);
}
Expand Down Expand Up @@ -13995,71 +13995,11 @@ can_change_cond_ref_to_const(Item_bool_func2 *target,
Item_bool_func2 *source,
Item *source_expr, Item *source_const)
{
if (!target_expr->eq(source_expr,0) ||
target_value == source_const ||
target->compare_type() != source->compare_type())
return false;
if (target->compare_type() == STRING_RESULT)
{
/*
In this example:
SET NAMES utf8 COLLATE utf8_german2_ci;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8);
INSERT INTO t1 VALUES ('o-umlaut'),('oe');
SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci AND a='oe';

the query should return only the row with 'oe'.
It should not return 'o-umlaut', because 'o-umlaut' does not match
the right part of the condition: a='oe'
('o-umlaut' is not equal to 'oe' in utf8_general_ci,
which is the collation of the field "a").

If we change the right part from:
... AND a='oe'
to
... AND 'oe' COLLATE utf8_german2_ci='oe'
it will be evalulated to TRUE and removed from the condition,
so the overall query will be simplified to:

SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci;

which will erroneously start to return both 'oe' and 'o-umlaut'.
So changing "expr" to "const" is not possible if the effective
collations of "target" and "source" are not exactly the same.

Note, the code before the fix for MDEV-7152 only checked that
collations of "source_const" and "target_value" are the same.
This was not enough, as the bug report demonstrated.
*/
return
target->compare_collation() == source->compare_collation() &&
target_value->collation.collation == source_const->collation.collation;
}
if (target->compare_type() == TIME_RESULT)
{
if (target_value->cmp_type() != TIME_RESULT)
{
/*
Can't rewrite:
WHERE COALESCE(time_column)='00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
to
WHERE DATE'2015-09-11'='00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
because the left part will erroneously try to parse '00:00:00'
as DATE, not as TIME.

TODO: It could still be rewritten to:
WHERE DATE'2015-09-11'=TIME'00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
i.e. we need to replace both target_expr and target_value
at the same time. This is not supported yet.
*/
return false;
}
}
return true; // Non-string comparison
return target_expr->eq(source_expr,0) &&
target_value != source_const &&
target->compare_type_handler()->
can_change_cond_ref_to_const(target, target_expr, target_value,
source, source_expr, source_const);
}


Expand Down
95 changes: 94 additions & 1 deletion sql/sql_type.cc
Expand Up @@ -200,7 +200,7 @@ const Name

const Name
Type_handler_tiny::m_name_tiny(C_STRING_WITH_LEN("tinyint")),
Type_handler_short::m_name_short(C_STRING_WITH_LEN("shortint")),
Type_handler_short::m_name_short(C_STRING_WITH_LEN("smallint")),
Type_handler_long::m_name_int(C_STRING_WITH_LEN("int")),
Type_handler_longlong::m_name_longlong(C_STRING_WITH_LEN("bigint")),
Type_handler_int24::m_name_mediumint(C_STRING_WITH_LEN("mediumint")),
Expand Down Expand Up @@ -1057,6 +1057,99 @@ bool Type_handler_temporal_result::set_comparator_func(Arg_comparator *cmp) cons
}


/*************************************************************************/

bool Type_handler_temporal_result::
can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const)
const
{
if (source->compare_type_handler()->cmp_type() != TIME_RESULT)
return false;

/*
Can't rewrite:
WHERE COALESCE(time_column)='00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
to
WHERE DATE'2015-09-11'='00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
because the left part will erroneously try to parse '00:00:00'
as DATE, not as TIME.
TODO: It could still be rewritten to:
WHERE DATE'2015-09-11'=TIME'00:00:00'
AND COALESCE(time_column)=DATE'2015-09-11'
i.e. we need to replace both target_expr and target_value
at the same time. This is not supported yet.
*/
return target_value->cmp_type() == TIME_RESULT;
}


bool Type_handler_string_result::
can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const)
const
{
if (source->compare_type_handler()->cmp_type() != STRING_RESULT)
return false;
/*
In this example:
SET NAMES utf8 COLLATE utf8_german2_ci;
DROP TABLE IF EXISTS t1;
CREATE TABLE t1 (a CHAR(10) CHARACTER SET utf8);
INSERT INTO t1 VALUES ('o-umlaut'),('oe');
SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci AND a='oe';
the query should return only the row with 'oe'.
It should not return 'o-umlaut', because 'o-umlaut' does not match
the right part of the condition: a='oe'
('o-umlaut' is not equal to 'oe' in utf8_general_ci,
which is the collation of the field "a").
If we change the right part from:
... AND a='oe'
to
... AND 'oe' COLLATE utf8_german2_ci='oe'
it will be evalulated to TRUE and removed from the condition,
so the overall query will be simplified to:
SELECT * FROM t1 WHERE a='oe' COLLATE utf8_german2_ci;
which will erroneously start to return both 'oe' and 'o-umlaut'.
So changing "expr" to "const" is not possible if the effective
collations of "target" and "source" are not exactly the same.
Note, the code before the fix for MDEV-7152 only checked that
collations of "source_const" and "target_value" are the same.
This was not enough, as the bug report demonstrated.
*/
return
target->compare_collation() == source->compare_collation() &&
target_value->collation.collation == source_const->collation.collation;
}


bool Type_handler_numeric::
can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const)
const
{
/*
The collations of "target" and "source" do not make sense for numeric
data types.
*/
return target->compare_type_handler() == source->compare_type_handler();
}


/*************************************************************************/

Item_cache *
Expand Down
46 changes: 46 additions & 0 deletions sql/sql_type.h
Expand Up @@ -32,6 +32,7 @@ class Item_func_hex;
class Item_hybrid_func;
class Item_func_min_max;
class Item_func_hybrid_field_type;
class Item_bool_func2;
class Item_func_between;
class Item_func_in;
class cmp_item;
Expand Down Expand Up @@ -346,6 +347,31 @@ class Type_handler
virtual uint32 max_display_length(const Item *item) const= 0;
virtual int Item_save_in_field(Item *item, Field *field,
bool no_conversions) const= 0;
/**
Check if
WHERE expr=value AND expr=const
can be rewritten as:
WHERE const=value AND expr=const
"this" is the comparison handler that is used by "target".
@param target - the predicate expr=value,
whose "expr" argument will be replaced to "const".
@param target_expr - the target's "expr" which will be replaced to "const".
@param target_value - the target's second argument, it will remain unchanged.
@param source - the equality predicate expr=const (or expr<=>const)
that can be used to rewrite the "target" part
(under certain conditions, see the code).
@param source_expr - the source's "expr". It should be exactly equal to
the target's "expr" to make condition rewrite possible.
@param source_const - the source's "const" argument, it will be inserted
into "target" instead of "expr".
*/
virtual bool
can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const) const= 0;
virtual Item_cache *Item_get_cache(THD *thd, const Item *item) const= 0;
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Expand Down Expand Up @@ -455,6 +481,14 @@ class Type_handler_row: public Type_handler
DBUG_ASSERT(0);
return 1;
}
bool can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const) const
{
DBUG_ASSERT(0);
return false;
}
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Expand Down Expand Up @@ -558,6 +592,10 @@ class Type_handler_numeric: public Type_handler
bool Item_func_min_max_get_date(Item_func_min_max*,
MYSQL_TIME *, ulonglong fuzzydate) const;
virtual ~Type_handler_numeric() { }
bool can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const) const;
};


Expand Down Expand Up @@ -699,6 +737,10 @@ class Type_handler_temporal_result: public Type_handler
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
bool can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_sum_hybrid_fix_length_and_dec(Item_sum_hybrid *func) const;
Expand Down Expand Up @@ -746,6 +788,10 @@ class Type_handler_string_result: public Type_handler
SORT_FIELD_ATTR *attr) const;
uint32 max_display_length(const Item *item) const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
bool can_change_cond_ref_to_const(Item_bool_func2 *target,
Item *target_expr, Item *target_value,
Item_bool_func2 *source,
Item *source_expr, Item *source_const) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool set_comparator_func(Arg_comparator *cmp) const;
bool Item_hybrid_func_fix_attributes(THD *thd, Item_hybrid_func *func,
Expand Down
4 changes: 2 additions & 2 deletions storage/heap/hp_block.c
Expand Up @@ -71,9 +71,9 @@ int hp_get_new_block(HP_SHARE *info, HP_BLOCK *block, size_t *alloc_length)
lower levels.
For example, for level 0, we allocate data for X rows.
When level 0 is full, we allocate data for HPTRS_IN_NODE + X rows.
When level 0 is full, we allocate data for HP_PTRS_IN_NOD + X rows.
Next time we allocate data for X rows.
When level 1 is full, we allocate data for HPTRS_IN_NODE at level 2 and 1
When level 1 is full, we allocate data for HP_PTRS_IN_NOD at level 2 and 1
+ X rows at level 0.
*/
*alloc_length= (sizeof(HP_PTRS) * ((i == block->levels) ? i : i - 1) +
Expand Down

0 comments on commit c846ebe

Please sign in to comment.