Commit 74891ed2 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-11514, MDEV-11497, MDEV-11554, MDEV-11555 - IN and CASE type aggregation problems

This patch fixes a number of data type aggregation problems in IN and CASE:
- MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
- MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
- MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
- MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result

1. The problem reported in MDEV-11514 and MDEV-11555 was in the wrong assumption
that items having the same cmp_type() can reuse the same cmp_item instance.
So Item_func_case and Item_func_in used a static array of cmp_item*,
one element per one XXX_RESULT.

TIME and DATETIME cannot reuse the same cmp_item, because arguments of
these types are compared very differently. TIME and DATETIME must have
different instances in the cmp_item array. Reusing the same cmp_item
for TIME and DATETIME leads to unexpected result and unexpected warnings.

Note, after adding more data types soon (e.g. INET6), the problem would
become more serious, as INET6 will most likely have STRING_RESULT, but
it won't be able to reuse the same cmp_item with VARCHAR/TEXT.

This patch introduces a new class Predicant_to_list_comparator,
which maintains an array of cmp_items, one element per distinct
Type_handler rather than one element per XXX_RESULT.

2. The problem reported in MDEV-11497 and MDEV-11554 happened because
Item_func_in and Item_func_case did not take into account the fact
that UNSIGNED and SIGNED values must be compared as DECIMAL rather than INT,
because they used item_cmp_type() to aggregate the arguments.
The relevant code now resides in Predicant_to_list_comparator::add_value()
and uses Type_handler_hybrid_field_type::aggregate_for_comparison(),
like Item_func_between does.
parent 191c3f49
......@@ -379,3 +379,63 @@ DROP TABLE t1;
#
# End of 10.1 test
#
#
# Start of 10.3 tests
#
#
# MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
#
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT
CASE -1
WHEN -9223372036854775808 THEN 'one'
WHEN 18446744073709551615 THEN 'two'
END AS c;
c
NULL
PREPARE stmt FROM "SELECT
CASE -1
WHEN -9223372036854775808 THEN 'one'
WHEN 18446744073709551615 THEN 'two'
END AS c";
EXECUTE stmt;
c
NULL
EXECUTE stmt;
c
NULL
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
#
# MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
#
SELECT
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
END AS good,
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
END AS was_bad_now_good;
good was_bad_now_good
one one
PREPARE stmt FROM "SELECT
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
END AS good,
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
END AS was_bad_now_good";
EXECUTE stmt;
good was_bad_now_good
one one
EXECUTE stmt;
good was_bad_now_good
one one
DEALLOCATE PREPARE stmt;
This diff is collapsed.
......@@ -855,3 +855,34 @@ id select_type table type possible_keys key key_len ref rows filtered Extra
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where `test`.`t1`.`a` = 1 and `test`.`t1`.`a` in (1,2,'3')
DROP TABLE t1;
#
# Start of 10.3 tests
#
#
# MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
#
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
1
PREPARE stmt FROM "SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
EXECUTE stmt;
TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
1
EXECUTE stmt;
TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
1
DEALLOCATE PREPARE stmt;
#
# MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
#
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT * FROM t1 WHERE -1 IN (a,b);
a b
PREPARE stmt FROM 'SELECT * FROM t1 WHERE -1 IN (a,b)';
EXECUTE stmt;
a b
EXECUTE stmt;
a b
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
......@@ -1246,3 +1246,25 @@ DROP TABLE t1,t2;
#
# End of 10.2 tests
#
#
# Start of 10.3 tests
#
#
# MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
#
SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31');
TIME'10:20:30' IN (102030,TIME'10:20:31')
1
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')
1
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32');
SELECT a FROM t1 WHERE a IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') ORDER BY a;
a
10:20:30
10:20:31
10:20:32
DROP TABLE t1;
SET timestamp=DEFAULT;
......@@ -275,3 +275,58 @@ DROP TABLE t1;
--echo #
--echo # End of 10.1 test
--echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
--echo #
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT
CASE -1
WHEN -9223372036854775808 THEN 'one'
WHEN 18446744073709551615 THEN 'two'
END AS c;
PREPARE stmt FROM "SELECT
CASE -1
WHEN -9223372036854775808 THEN 'one'
WHEN 18446744073709551615 THEN 'two'
END AS c";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
--echo #
--echo # MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
--echo #
SELECT
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
END AS good,
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
END AS was_bad_now_good;
PREPARE stmt FROM "SELECT
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
END AS good,
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
END AS was_bad_now_good";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
--source include/have_debug.inc
SET SESSION debug_dbug="+d,Item_func_in";
SET SESSION debug_dbug="+d,Predicant_to_list_comparator";
--echo # Constant predicant, compatible types, bisect
SELECT 1 IN (1,2);
......@@ -41,11 +42,22 @@ SELECT DATE'2001-01-01' NOT IN ('2001-01-01','2001-02-02',NULL);
--echo # Column predicant, compatible types, bisect
# Special case: mixture of unsigned, signed and decimal
CREATE TABLE t1 (a INT UNSIGNED);
# a=1.0 is done as decimal, because decimal bits int
# a=1 is done as decimal as well, because of different unsigned flag
SELECT a IN (1.0, 1) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a INT);
SELECT a IN (1,2,3) FROM t1;
SELECT a IN (1,2,3,NULL) FROM t1;
SELECT a IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
SELECT a IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
SELECT a NOT IN (1,2,3) FROM t1;
SELECT a NOT IN (1,2,3,NULL) FROM t1;
SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED)) FROM t1;
SELECT a NOT IN (1.0, CAST(1 AS UNSIGNED),NULL) FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE);
......@@ -163,12 +175,33 @@ SELECT 'a' IN ('a',2,NULL);
SELECT 'a' NOT IN ('a',2);
SELECT 'a' NOT IN ('a',2,NULL);
SELECT TIME'10:20:30' IN (1,TIME'10:20:30');
SELECT TIME'10:20:30' IN (1,TIME'10:20:30',NULL);
SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
SELECT TIME'10:20:30' IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
SELECT TIME'10:20:30' IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30');
SELECT TIME'10:20:30' NOT IN (1,TIME'10:20:30',NULL);
SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
SELECT TIME'10:20:30' NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32');
SELECT TIME'10:20:30' NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL);
--echo # Column predicant, incompatible types, no bisect
CREATE TABLE t1 (a INT);
SELECT a IN (1,1e0) FROM t1;
SELECT a IN (1,1e0,NULL) FROM t1;
SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
SELECT a IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
SELECT a IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
SELECT a NOT IN (1,1e0) FROM t1;
SELECT a NOT IN (1,1e0,NULL) FROM t1;
SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
SELECT a NOT IN (CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED)) FROM t1;
SELECT a NOT IN (CAST(1 AS DECIMAL),CAST(1 AS SIGNED), CAST(1 AS UNSIGNED),NULL) FROM t1;
SELECT a IN (1,1.0) FROM t1;
SELECT a IN (1,1.0,NULL) FROM t1;
......@@ -227,6 +260,17 @@ SELECT a NOT IN ('a',1) FROM t1;
SELECT a NOT IN ('a',TIME'10:20:30') FROM t1;
DROP TABLE t1;
CREATE TABLE t1 (a TIME);
SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
SELECT a IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
SELECT a IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
SELECT a NOT IN (102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32') FROM t1;
SELECT a NOT IN (102030, 102030, TIME'10:20:30',TIMESTAMP'2001-01-01 10:20:32',NULL) FROM t1;
DROP TABLE t1;
#
# ROW tests
#
......@@ -366,5 +410,68 @@ SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,NULL)));
SELECT 1 FROM t1 WHERE ROW(a,(a,a)) IN ((1,(1,1)),(2,(2,2)));
DROP TABLE t1;
--echo #
--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
--echo #
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
PREPARE stmt FROM "SELECT
TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('A'),('B'),('A');
# Compatible types
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A');
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b);
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a);
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b);
# Incompatible types
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,'A',10);
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN ('A',b,10);
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (b,a,10);
SELECT a,NULL AS b FROM t1 GROUP BY a HAVING 'A' IN (a,b,10);
DROP TABLE t1;
--echo #
--echo # MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
--echo #
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT * FROM t1 WHERE -1 IN (a,b);
DROP TABLE t1;
--echo #
--echo # MDEV-11554 Wrong result for CASE on a mixture of signed and unsigned expressions
--echo #
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT
CASE -1
WHEN -9223372036854775808 THEN 'one'
WHEN 18446744073709551615 THEN 'two'
END AS c;
DROP TABLE t1;
--echo #
--echo # MDEV-11555 CASE with a mixture of TIME and DATETIME returns a wrong result
--echo #
SELECT
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
END AS good,
CASE TIME'10:20:30'
WHEN 102030 THEN 'one'
WHEN TIME'10:20:31' THEN 'two'
WHEN TIMESTAMP'2001-01-01 10:20:32' THEN 'three'
END AS was_bad_now_good;
SET SESSION debug_dbug="-d,Predicant_to_list_comparator";
SET SESSION debug_dbug="-d,Item_func_in";
......@@ -641,3 +641,29 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1 AND 1 IN (1,a,'3');
--echo # Not Ok to propagate equalities into the left IN argument in case of multiple comparison types
EXPLAIN EXTENDED SELECT * FROM t1 WHERE a=1 AND a IN (1,2,'3');
DROP TABLE t1;
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
--echo #
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
PREPARE stmt FROM "SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32')";
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
--echo #
--echo # MDEV-11497 Wrong result for (int_expr IN (mixture of signed and unsigned expressions))
--echo #
CREATE TABLE t1 (a BIGINT, b BIGINT UNSIGNED);
INSERT INTO t1 VALUES (-9223372036854775808,18446744073709551615);
SELECT * FROM t1 WHERE -1 IN (a,b);
PREPARE stmt FROM 'SELECT * FROM t1 WHERE -1 IN (a,b)';
EXECUTE stmt;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
......@@ -748,3 +748,19 @@ DROP TABLE t1,t2;
--echo #
--echo # End of 10.2 tests
--echo #
--echo #
--echo # Start of 10.3 tests
--echo #
--echo #
--echo # MDEV-11514 IN with a mixture of TIME and DATETIME returns a wrong result
--echo #
SET timestamp=UNIX_TIMESTAMP('2001-01-01 00:00:00');
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31');
SELECT TIME'10:20:30' IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32');
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('10:20:30'),('10:20:31'),('10:20:32');
SELECT a FROM t1 WHERE a IN (102030,TIME'10:20:31',TIMESTAMP'2001-01-01 10:20:32') ORDER BY a;
DROP TABLE t1;
SET timestamp=DEFAULT;
......@@ -1280,11 +1280,6 @@ class Item: public Value_source,
return MYSQL_TYPE_DATETIME;
}
}
// Get a temporal value to compare to another Item
longlong val_temporal_packed(const Item *other)
{
return val_temporal_packed(field_type_for_temporal_comparison(other));
}
bool get_seconds(ulonglong *sec, ulong *sec_part);
virtual bool get_date_result(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return get_date(ltime,fuzzydate); }
......
This diff is collapsed.
This diff is collapsed.
......@@ -123,6 +123,49 @@ Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
}
/***************************************************************************/
const Type_handler *Type_handler_int_result::type_handler_for_comparison() const
{
return &type_handler_longlong;
}
const Type_handler *Type_handler_string_result::type_handler_for_comparison() const
{
return &type_handler_long_blob;
}
const Type_handler *Type_handler_decimal_result::type_handler_for_comparison() const
{
return &type_handler_newdecimal;
}
const Type_handler *Type_handler_real_result::type_handler_for_comparison() const
{
return &type_handler_double;
}
const Type_handler *Type_handler_time_common::type_handler_for_comparison() const
{
return &type_handler_time;
}
const Type_handler *Type_handler_temporal_with_date::type_handler_for_comparison() const
{
return &type_handler_datetime;
}
const Type_handler *Type_handler_row::type_handler_for_comparison() const
{
return &type_handler_row;
}
/**
Collect built-in data type handlers for comparison.
This method is very similar to item_cmp_type() defined in item.cc.
......@@ -135,6 +178,8 @@ Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
void
Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
{
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
DBUG_ASSERT(h == h->type_handler_for_comparison());
Item_result a= cmp_type();
Item_result b= h->cmp_type();
if (a == STRING_RESULT && b == STRING_RESULT)
......@@ -170,9 +215,12 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)
}
else
m_type_handler= &type_handler_double;
DBUG_ASSERT(m_type_handler == m_type_handler->type_handler_for_comparison());
}
/***************************************************************************/
const Type_handler *
Type_handler::get_handler_by_field_type(enum_field_types type)
{
......@@ -1263,6 +1311,51 @@ longlong Type_handler_decimal_result::
/***************************************************************************/
cmp_item *Type_handler_int_result::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_int;
}
cmp_item *Type_handler_real_result::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_real;
}
cmp_item *Type_handler_decimal_result::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_decimal;
}
cmp_item *Type_handler_string_result::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_sort_string(cs);
}
cmp_item *Type_handler_row::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_row;
}
cmp_item *Type_handler_time_common::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_time;
}
cmp_item *Type_handler_temporal_with_date::make_cmp_item(THD *thd,
CHARSET_INFO *cs) const
{
return new (thd->mem_root) cmp_item_datetime;
}
/***************************************************************************/
static int srtcmp_in(CHARSET_INFO *cs, const String *x,const String *y)
{
return cs->coll->strnncollsp(cs,
......@@ -1342,7 +1435,8 @@ bool Type_handler_string_result::
func->fix_for_scalar_comparison_using_bisection(thd);
}
return
func->fix_for_scalar_comparison_using_cmp_items(1U << (uint) STRING_RESULT);
func->fix_for_scalar_comparison_using_cmp_items(thd,
1U << (uint) STRING_RESULT);
}
......@@ -1356,7 +1450,8 @@ bool Type_handler_int_result::
*/
return func->compatible_types_scalar_bisection_possible() ?
func->fix_for_scalar_comparison_using_bisection(thd) :
func->fix_for_scalar_comparison_using_cmp_items(1U << (uint) INT_RESULT);
func->fix_for_scalar_comparison_using_cmp_items(thd,
1U << (uint) INT_RESULT);
}
......@@ -1367,7 +1462,8 @@ bool Type_handler_real_result::
return func->compatible_types_scalar_bisection_possible() ?
(func->value_list_convert_const_to_int(thd) ||
func->fix_for_scalar_comparison_using_bisection(thd)) :
func->fix_for_scalar_comparison_using_cmp_items(1U << (uint) REAL_RESULT);
func->fix_for_scalar_comparison_using_cmp_items(thd,
1U << (uint) REAL_RESULT);
}
......@@ -1378,7 +1474,8 @@ bool Type_handler_decimal_result::
return func->compatible_types_scalar_bisection_possible() ?
(func->value_list_convert_const_to_int(thd) ||
func->fix_for_scalar_comparison_using_bisection(thd)) :
func->fix_for_scalar_comparison_using_cmp_items(1U << (uint) DECIMAL_RESULT);
func->fix_for_scalar_comparison_using_cmp_items(thd,
1U << (uint) DECIMAL_RESULT);
}
......@@ -1389,7 +1486,8 @@ bool Type_handler_temporal_result::
return func->compatible_types_scalar_bisection_possible() ?
(func->value_list_convert_const_to_int(thd) ||
func->fix_for_scalar_comparison_using_bisection(thd)) :
func->fix_for_scalar_comparison_using_cmp_items(1U << (uint) TIME_RESULT);
func->fix_for_scalar_comparison_using_cmp_items(thd,
1U << (uint) TIME_RESULT);
}
......
......@@ -31,6 +31,7 @@ class Item_func_hex;
class Item_func_hybrid_field_type;
class Item_func_between;
class Item_func_in;
class cmp_item;
class in_vector;
class Type_std_attributes;
class Sort_param;
......@@ -243,6 +244,7 @@ class Type_handler
virtual enum_field_types real_field_type() const { return field_type(); }
virtual Item_result result_type() const= 0;
virtual Item_result cmp_type() const= 0;
virtual const Type_handler *type_handler_for_comparison() const= 0;
virtual const Type_handler*
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const
......@@ -321,6 +323,9 @@ class Type_handler
virtual longlong
Item_func_between_val_int(Item_func_between *func) const= 0;
virtual cmp_item *
make_cmp_item(THD *thd, CHARSET_INFO *cs) const= 0;
virtual in_vector *
make_in_vector(THD *thd, const Item_func_in *func, uint nargs) const= 0;
......@@ -350,6 +355,7 @@ class Type_handler_row: public Type_handler
{
return ROW_RESULT;
}
const Type_handler *type_handler_for_comparison() const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const
{
DBUG_ASSERT(0);
......@@ -429,6 +435,7 @@ class Type_handler_row: public Type_handler
}
longlong Item_func_between_val_int(Item_func_between *func) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *thd, const Item_func_in *f, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd,
Item_func_in *) const;
......@@ -457,6 +464,7 @@ class Type_handler_real_result: public Type_handler_numeric
Item_result result_type() const { return REAL_RESULT; }
Item_result cmp_type() const { return REAL_RESULT; }
virtual ~Type_handler_real_result() {}
const Type_handler *type_handler_for_comparison() const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
void sortlength(THD *thd,
......@@ -480,6 +488,7 @@ class Type_handler_real_result: public Type_handler_numeric
MYSQL_TIME *,
ulonglong fuzzydate) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd,
Item_func_in *) const;
......@@ -493,6 +502,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
Item_result result_type() const { return DECIMAL_RESULT; }
Item_result cmp_type() const { return DECIMAL_RESULT; }
virtual ~Type_handler_decimal_result() {};
const Type_handler *type_handler_for_comparison() const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
......@@ -518,6 +528,7 @@ class Type_handler_decimal_result: public Type_handler_numeric
MYSQL_TIME *,
ulonglong fuzzydate) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd,
Item_func_in *) const;
......@@ -530,6 +541,7 @@ class Type_handler_int_result: public Type_handler_numeric
Item_result result_type() const { return INT_RESULT; }
Item_result cmp_type() const { return INT_RESULT; }
virtual ~Type_handler_int_result() {}
const Type_handler *type_handler_for_comparison() const;
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
void make_sort_key(uchar *to, Item *item, const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const;
......@@ -554,6 +566,7 @@ class Type_handler_int_result: public Type_handler_numeric
MYSQL_TIME *,
ulonglong fuzzydate) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd,
Item_func_in *) const;
......@@ -600,6 +613,7 @@ class Type_handler_string_result: public Type_handler
Item_result result_type() const { return STRING_RESULT; }
Item_result cmp_type() const { return STRING_RESULT; }
virtual ~Type_handler_string_result() {}
const Type_handler *type_handler_for_comparison() const;
const Type_handler *
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
CHARSET_INFO *cs) const;
......@@ -627,6 +641,7 @@ class Type_handler_string_result: public Type_handler
MYSQL_TIME *,
ulonglong fuzzydate) const;
longlong Item_func_between_val_int(Item_func_between *func) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
bool Item_func_in_fix_comparator_compatible_types(THD *thd,
Item_func_in *) const;
......@@ -761,7 +776,9 @@ class Type_handler_time_common: public Type_handler_temporal_result
public:
virtual ~Type_handler_time_common() { }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
const Type_handler *type_handler_for_comparison() const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
};
......@@ -789,7 +806,9 @@ class Type_handler_temporal_with_date: public Type_handler_temporal_result
{
public:
virtual ~Type_handler_temporal_with_date() {}
const Type_handler *type_handler_for_comparison() const;
int Item_save_in_field(Item *item, Field *field, bool no_conversions) const;
cmp_item *make_cmp_item(THD *thd, CHARSET_INFO *cs) const;
in_vector *make_in_vector(THD *, const Item_func_in *, uint nargs) const;
};
......
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