Commit 9043dd7a authored by Alexander Barkov's avatar Alexander Barkov

MDEV-11361 Equal condition propagation does not work for DECIMAL and temporal...

MDEV-11361 Equal condition propagation does not work for DECIMAL and temporal dynamic SQL parameters
MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
A cleanup for MDEV-14630: fixing a crash in Item_decimal::eq().

Problems:
- old implementations of Item_decimal::eq() and
  Item_temporal_literal::eq() were not symmetric
  with Item_param::eq(), this caused MDEV-11361.

- old implementations for DECIMAL and temporal data types
  did not take into account that in case when eq() is called
  with binary_cmp==true, {{eq()}} should check not only equality
  of the two values, but also equality if their decimal precision.
  This cuases MDEV-16426.

- Item_decimal::eq() crashes with "item" pointing
  to a non-DECIMAL value. Before MDEV-14630
  non-DECIMAL values were filtered out by the test:
    type() == item->type()
  as literals of different types had different type().
  After MDEV-14630 type() for literals of all data types return CONST_ITEM.
  This caused failures in tests:
    ./mtr engines/iuds.insert_number
    ./mtr --ps --embedded main.explain_slowquerylog
  (revealed by buildbot)

The essence of the fix:
Making literals and Item_param reuse the same code to avoid
asymmetries between Item_param::eq(Item_literal) and
Item_literal::eq(Item_param), now and in the future, and to
avoid code duplication between Item_literal and Item_param.
Adding tests for "decimals" for DECIMAL and temporal data types,
to treat constants of different scale as not equal when "binary_cmp"
is "true".

Details:
1. Adding a helper class Item_const to extract constant values from Items easier
2. Deriving Item_basic_value from Item_const
3. Joining Type_handler::Item_basic_value_eq() and Item_basic_value_bin_eq()
   into a single method with an extra "binary_cmp" argument
   (it looks simple this way) and renaming the new method to Item_const_eq().
   Modifying its implementations to operate with
   Item_const instead of Item_basic_value.
4. Adding a new class Type_handler_hex_hybrid,
   to handle hex constants like 0x616263.
5. Removing Item::VARBIN_ITEM and fixing Item_hex_constant to
   use type_handler_hex_hybrid instead of type_handler_varchar.
   Item_hex_hybrid::type() now returns CONST_ITEM, like all
   other literals do.
6. Move virtual methods Item::type_handler_for_system_time() and
   Item::cast_to_int_type_handler() from Item to Type_handler.
7. Removing Item_decimal::eq() and Item_temporal_literal::eq().
   These classes are now handled by the generic Item_basic_value::eq().
8. Implementing Type_handler_temporal_result::Item_const_eq()
   and Type_handler_decimal_result::Item_const_eq(),
   this fixes MDEV-11361.
9. Adding tests for "decimals" into
   Type_handler_decimal_result::Item_const_eq() and
   Type_handler_temporal_result::Item_const_eq()
   in case if "binary_cmp" is true.
   This fixes MDEV-16426.
10. Moving Item_cache out of Item_basic_value.
   They share nothing. It simplifies implementation
   of Item_basic_value::eq(). Deriving Item_cache
   directly from Item.

11. Adding class DbugStringItemTypeValue, which
    used Item::print() internally, and using
    in instead of the old debug printing code.
    This gives nicer output in func_debug.result.

Changes N5 and N6 do not directly relate to the bugs fixed,
but make the code fully symmetric across all literal types.
Without a new handler Type_handler_hex_hybrid we'd have
to keep two code branches (for regular literals and for
hex hybrid literals).
parent 05441259
......@@ -1665,94 +1665,159 @@ SELECT * FROM t1 WHERE a BETWEEN 1 AND 1.0;
a
1
Warnings:
Note 1105 bin_eq=0 a=int'1' b=decimal'1.0'
Note 1105 bin_eq=0 a=(int)1 b=(decimal)1.0
SELECT * FROM t1 WHERE a BETWEEN 1 AND 1;
a
1
Warnings:
Note 1105 bin_eq=1 a=int'1' b=int'1'
Note 1105 bin_eq=1 a=(int)1 b=(int)1
SELECT * FROM t1 WHERE a BETWEEN 0 AND 1;
a
1
Warnings:
Note 1105 bin_eq=0 a=int'0' b=int'1'
Note 1105 bin_eq=0 a=(int)0 b=(int)1
SELECT * FROM t1 WHERE a BETWEEN 0 AND -1;
a
Warnings:
Note 1105 bin_eq=0 a=int'0' b=int''
Note 1105 bin_eq=0 a=(int)0 b=(int)-1
SELECT * FROM t1 WHERE a BETWEEN -1 AND -1;
a
Warnings:
Note 1105 bin_eq=1 a=int'' b=int''
Note 1105 bin_eq=1 a=(int)-1 b=(int)-1
SELECT * FROM t1 WHERE a BETWEEN -0000000000000001 AND -1;
a
Warnings:
Note 1105 bin_eq=1 a=bigint'' b=int''
Note 1105 bin_eq=1 a=(bigint)-1 b=(int)-1
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551615;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=bigint'18446744073709551615'
Note 1105 bin_eq=0 a=(int)-1 b=(bigint)18446744073709551615
SELECT * FROM t1 WHERE a BETWEEN -1 AND 18446744073709551616;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=decimal'18446744073709551616'
Note 1105 bin_eq=0 a=(int)-1 b=(decimal)18446744073709551616
SELECT * FROM t1 WHERE a BETWEEN 1e2 AND 100e0;
a
Warnings:
Note 1105 bin_eq=1 a=double'1e2' b=double'100e0'
Note 1105 bin_eq=1 a=(double)1e2 b=(double)100e0
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1 AND ?' USING 1;
a
1
Warnings:
Note 1105 bin_eq=1 a=int'1' b=int'?'
Note 1105 bin_eq=1 a=(int)1 b=(int)1
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551615;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=bigint'?'
Note 1105 bin_eq=0 a=(int)-1 b=(bigint)18446744073709551615
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616;
a
1
2
3
Warnings:
Note 1105 bin_eq=0 a=int'' b=decimal'?'
Note 1105 bin_eq=0 a=(int)-1 b=(decimal)18446744073709551616
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
a
0
Warnings:
Note 1105 eq=1 a=(varchar)'0' b=(varchar)'0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
a
Warnings:
Note 1105 eq=0 a=(varchar)'0' b=(varchar)' 0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
a
0
Warnings:
Note 1105 eq=1 a=(varchar)'0' b=(varchar)'0 '
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
SET SESSION debug_dbug="+d,Item_basic_value";
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0;
a
1.000
Warnings:
Note 1105 bin_eq=1 a=(decimal)1.0 b=(decimal)1.0
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1.0 AND ?' USING 1.0;
a
1.000
Warnings:
Note 1105 bin_eq=1 a=(decimal)1.0 b=(decimal)1.0
DROP TABLE t1;
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00';
a
00:00:00
Warnings:
Note 1105 bin_eq=1 a=(time)TIME'00:00:00' b=(time)TIME'00:00:00'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIME''00:00:00'' AND ?' USING TIME'00:00:00';
a
00:00:00
Warnings:
Note 1105 bin_eq=1 a=(time)TIME'00:00:00' b=(time)TIME'00:00:00'
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE a BETWEEN DATE'2001-01-01' AND DATE'2001-01-01';
a
0
2001-01-01
Warnings:
Note 1105 eq=1 a=varchar'0' b=varchar'0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
Note 1105 bin_eq=1 a=(date)DATE'2001-01-01' b=(date)DATE'2001-01-01'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN DATE''2001-01-01'' AND ?' USING DATE'2001-01-01';
a
2001-01-01
Warnings:
Note 1105 eq=0 a=varchar'0' b=varchar'0'
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
Note 1105 bin_eq=1 a=(date)DATE'2001-01-01' b=(date)DATE'2001-01-01'
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:00');
SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP'2001-01-01 00:00:00' AND TIMESTAMP'2001-01-01 00:00:00';
a
2001-01-01 00:00:00
2001-01-01 00:00:00
Warnings:
Note 1105 bin_eq=1 a=(datetime)TIMESTAMP'2001-01-01 00:00:00' b=(datetime)TIMESTAMP'2001-01-01 00:00:00'
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP''2001-01-01 00:00:00'' AND ?' USING TIMESTAMP'2001-01-01 00:00:00';
a
2001-01-01 00:00:00
2001-01-01 00:00:00
Warnings:
Note 1105 bin_eq=1 a=(datetime)TIMESTAMP'2001-01-01 00:00:00' b=(datetime)TIMESTAMP'2001-01-01 00:00:00'
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
#
# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
#
SET SESSION debug_dbug="+d,Item_basic_value";
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('a'),('b'),('c');
SELECT * FROM t1 WHERE a BETWEEN 'a' AND 0x61;
a
a
Warnings:
Note 1105 eq=0 a=(varchar)'a' b=(hex_hybrid)0x61
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN ''a'' AND ?' USING 0x61;
a
a
0
Warnings:
Note 1105 eq=1 a=varchar'0' b=varchar'0 '
Note 1105 eq=0 a=(varchar)'a' b=(hex_hybrid)'a'
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
......@@ -499,24 +499,59 @@ EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 184467440737
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN -1 AND ?' USING 18446744073709551616;
DROP TABLE t1;
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
SET SESSION debug_dbug="+d,Item_basic_value";
# DECIMAL does not work yet
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1),(2),(3);
SELECT * FROM t1 WHERE a BETWEEN 1.0 AND 1.0;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN 1.0 AND ?' USING 1.0;
DROP TABLE t1;
# Temporal types do not work yet
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE a BETWEEN TIME'00:00:00' AND TIME'00:00:00';
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIME''00:00:00'' AND ?' USING TIME'00:00:00';
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE a BETWEEN DATE'2001-01-01' AND DATE'2001-01-01';
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN DATE''2001-01-01'' AND ?' USING DATE'2001-01-01';
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:00');
SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP'2001-01-01 00:00:00' AND TIMESTAMP'2001-01-01 00:00:00';
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN TIMESTAMP''2001-01-01 00:00:00'' AND ?' USING TIMESTAMP'2001-01-01 00:00:00';
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
--echo #
--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
--echo #
SET SESSION debug_dbug="+d,Item_basic_value";
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('0'),('1'),('2');
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND ' 0';
SELECT * FROM t1 WHERE a BETWEEN '0' AND '0 ';
INSERT INTO t1 VALUES ('a'),('b'),('c');
SELECT * FROM t1 WHERE a BETWEEN 'a' AND 0x61;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE a BETWEEN ''a'' AND ?' USING 0x61;
DROP TABLE t1;
SET SESSION debug_dbug="-d,Item_basic_value";
......@@ -4940,5 +4940,29 @@ SELECT ST_SRID((SELECT MAX(a>3) FROM t1));
ERROR HY000: Illegal parameter data type boolean for operation 'srid'
DROP TABLE t1;
#
# Mixing GEOMETRY with HEX hybrid
#
SELECT 0x60=POINT(1,1), POINT(1,1)=0x60;
0x60=POINT(1,1) POINT(1,1)=0x60
0 0
CREATE TABLE t1 AS SELECT
COALESCE(0x60,POINT(1,1)),
COALESCE(POINT(1,1),0x60),
LEAST(0x60,POINT(1,1)),
LEAST(POINT(1,1),0x60);
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(0x60,POINT(1,1))` longblob DEFAULT NULL,
`COALESCE(POINT(1,1),0x60)` longblob DEFAULT NULL,
`LEAST(0x60,POINT(1,1))` longblob DEFAULT NULL,
`LEAST(POINT(1,1),0x60)` longblob DEFAULT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
SELECT 0x60+POINT(1,1);
ERROR HY000: Illegal parameter data types bigint and geometry for operation '+'
SELECT POINT(1,1)+0x60;
ERROR HY000: Illegal parameter data types geometry and bigint for operation '+'
#
# End of 10.4 tests
#
......@@ -3013,6 +3013,26 @@ SELECT ST_SRID(MAX(a>3)) FROM t1;
SELECT ST_SRID((SELECT MAX(a>3) FROM t1));
DROP TABLE t1;
--echo #
--echo # Mixing GEOMETRY with HEX hybrid
--echo #
SELECT 0x60=POINT(1,1), POINT(1,1)=0x60;
CREATE TABLE t1 AS SELECT
COALESCE(0x60,POINT(1,1)),
COALESCE(POINT(1,1),0x60),
LEAST(0x60,POINT(1,1)),
LEAST(POINT(1,1),0x60);
SHOW CREATE TABLE t1;
DROP TABLE t1;
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT 0x60+POINT(1,1);
--error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION
SELECT POINT(1,1)+0x60;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -889,3 +889,78 @@ DROP TABLE t1;
#
# End of 10.3 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'),('2001-01-03');
# Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(DATE'2001-01-01',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
# Equal values but of different data types (should not propagate)
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-01'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-01',`test`.`t1`.`a`)
# Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001-01-01',a)<=>COALESCE(DATE'2001-01-02',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-02',`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-02';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-01'),`test`.`t1`.`a`) <=> coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-02';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(DATE'2001-01-01',`test`.`t1`.`a`) <=> coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-02';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(DATE'2001-01-02'),`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-01',`test`.`t1`.`a`)
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -614,3 +614,38 @@ DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02'),('2001-01-03');
--echo # Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(DATE'2001-01-01',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-01';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-01';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-01';
--echo # Equal values but of different data types (should not propagate)
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001:01:01',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',TIMESTAMP'2001-01-01 00:00:00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING TIMESTAMP'2001-01-01 00:00:00';
--echo # Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE'2001-01-01',a)<=>COALESCE(DATE'2001-01-02',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING DATE'2001-01-01',DATE'2001-01-02';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(DATE''2001-01-01'',a)<=>COALESCE(?,a)' USING DATE'2001-01-02';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(DATE''2001-01-01'',a)' USING DATE'2001-01-02';
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -1301,3 +1301,104 @@ DROP TABLE t1;
#
# End of 10.3 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-02 00:00:00'),('2001-01-03 00:00:00');
# Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
# Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:01',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:01',`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`) <=> coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:01'),`test`.`t1`.`a`) <=> coalesce(TIMESTAMP'2001-01-01 00:00:00',`test`.`t1`.`a`)
DROP TABLE t1;
#
# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
#
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'),('2001-01-01 00:00:02');
Equal values
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a));
a
2001-01-01 00:00:00
2001-01-01 00:00:01
2001-01-01 00:00:02
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0';
a
2001-01-01 00:00:00
2001-01-01 00:00:01
2001-01-01 00:00:02
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00.0'),`test`.`t1`.`a`))
Values with different formats
SELECT LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)),LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)) FROM t1;
LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)) LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a))
21 22
21 22
21 22
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a));
a
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIMESTAMP'2001-01-01 00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(TIMESTAMP'2001-01-01 00:00:00.00',`test`.`t1`.`a`))
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00';
a
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIMESTAMP'2001-01-01 00:00:00.00'),`test`.`t1`.`a`))
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -849,3 +849,55 @@ DROP TABLE t1;
--echo #
--echo # End of 10.3 tests
--echo #
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-02 00:00:00'),('2001-01-03 00:00:00');
--echo # Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:00',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:00';
--echo # Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP'2001:01:01 00:00:00',a)<=>COALESCE(TIMESTAMP'2001-01-01 00:00:01',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:00',TIMESTAMP'2001-01-01 00:00:01';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)<=>COALESCE(?,a)' USING TIMESTAMP'2001-01-01 00:00:01';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIMESTAMP''2001-01-01 00:00:00'',a)' USING TIMESTAMP'2001-01-01 00:00:01';
DROP TABLE t1;
--echo #
--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
--echo #
CREATE TABLE t1 (a DATETIME);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01'),('2001-01-01 00:00:02');
--echo Equal values
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a));
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a));
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.0';
--echo Values with different formats
SELECT LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a)),LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a)) FROM t1;
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a));
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.0',a))<=>LENGTH(COALESCE(TIMESTAMP'2001-01-01 00:00:00.00',a));
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIMESTAMP'2001-01-01 00:00:00.00';
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -1084,3 +1084,100 @@ t2 CREATE TABLE `t2` (
DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t1dec102;
#
# End of 10.3 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL dynamic SQL parameters
#
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1),(2),(3);
# Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.0+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
# Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.1+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a`
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a`
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.0 + `test`.`t1`.`a` <=> 1.1 + `test`.`t1`.`a`
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1.1 + `test`.`t1`.`a` <=> 1.0 + `test`.`t1`.`a`
DROP TABLE t1;
#
# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
#
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (10.0),(10.1);
Equal values
SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a;
a
10.000
10.100
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0;
a
10.000
10.100
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
Values with different formats
SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a;
a
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(10.0)) + `test`.`t1`.`a` <=> <cache>(octet_length(10.00)) + `test`.`t1`.`a`
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00;
a
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(10.0)) + `test`.`t1`.`a` <=> <cache>(octet_length(10.00)) + `test`.`t1`.`a`
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -673,3 +673,56 @@ DROP TABLE t2;
DROP TABLE t1;
DROP TABLE t1dec102;
--echo #
--echo # End of 10.3 tests
--echo #
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL dynamic SQL parameters
--echo #
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1),(2),(3);
--echo # Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.0+a;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.0;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.0;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.0;
--echo # Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>1.1+a;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1.0,1.1;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1.0+a<=>?+a' USING 1.1;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1.0+a' USING 1.1;
DROP TABLE t1;
--echo #
--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
--echo #
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (10.0),(10.1);
--echo Equal values
SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.0)+a;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.0;
--echo Values with different formats
SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(10.00)+a;
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(10.0)+a<=>LENGTH(?)+a' USING 10.00;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -800,3 +800,35 @@ DROP TABLE t1;
#
# End of 10.2 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (1),(2),(3);
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>1e0+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1e0,1e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1e0+a' USING 1e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>?+a' USING 1e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -551,3 +551,24 @@ DROP TABLE t1;
--echo #
--echo # End of 10.2 tests
--echo #
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (1),(2),(3);
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>1e0+a;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1e0,1e0;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1e0+a' USING 1e0;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1e0+a<=>?+a' USING 1e0;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
#
# Start of 10.4 tests
#
#
# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
#
SET NAMES utf8;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (10.0),(10.1);
SELECT CHARSET('a'),CHARSET(0x61),LENGTH(CHARSET('a'))+a,LENGTH(CHARSET(0x61))+a FROM t1;
CHARSET('a') CHARSET(0x61) LENGTH(CHARSET('a'))+a LENGTH(CHARSET(0x61))+a
utf8 binary 14.000 16.000
utf8 binary 14.100 16.100
SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
a
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where <cache>(octet_length(charset('a'))) + `test`.`t1`.`a` <=> <cache>(octet_length(charset(0x61))) + `test`.`t1`.`a`
DROP TABLE t1;
#
# End of 10.4 tests
#
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
--echo #
# It's important for CHARSET('a') and CHARSET(0x61) to have different lengths in this test.
# 'latin1' and 'binary' have same lengths, so using 'utf8'.
SET NAMES utf8;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (10.0),(10.1);
SELECT CHARSET('a'),CHARSET(0x61),LENGTH(CHARSET('a'))+a,LENGTH(CHARSET(0x61))+a FROM t1;
SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(CHARSET('a'))+a<=>LENGTH(CHARSET(0x61))+a;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -225,3 +225,35 @@ DROP FUNCTION sint64;
#
# End of 10.3 tests
#
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>1+a;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1,1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1+a' USING 1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>?+a' USING 1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -167,3 +167,23 @@ DROP FUNCTION sint64;
--echo #
--echo # End of 10.3 tests
--echo #
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1),(2),(3);
EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>1+a;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>?+a' USING 1,1;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE ?+a<=>1+a' USING 1;
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE 1+a<=>?+a' USING 1;
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -1953,3 +1953,104 @@ a filler
-838:00:04.1 yes
-838:00:03.1 yes
DROP TABLE t1;
#
# Start of 10.4 tests
#
#
# MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
#
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES (1),(2),(3);
# Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:30',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:30';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:30';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:30';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
# Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:31',a);
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIME'10:20:30',`test`.`t1`.`a`) <=> coalesce(TIME'10:20:31',`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:31';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIME'10:20:30'),`test`.`t1`.`a`) <=> coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:31';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(TIME'10:20:30',`test`.`t1`.`a`) <=> coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`)
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:31';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where coalesce(<cache>(TIME'10:20:31'),`test`.`t1`.`a`) <=> coalesce(TIME'10:20:30',`test`.`t1`.`a`)
DROP TABLE t1;
#
# MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
#
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'),('00:00:02');
Equal values
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a));
a
00:00:00
00:00:01
00:00:02
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0';
a
00:00:00
00:00:01
00:00:02
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 1
Values with different formats
SELECT LENGTH(COALESCE(TIME'00:00:00.0',a)),LENGTH(COALESCE(TIME'00:00:00.00',a)) FROM t1;
LENGTH(COALESCE(TIME'00:00:00.0',a)) LENGTH(COALESCE(TIME'00:00:00.00',a))
10 11
10 11
10 11
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a));
a
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a));
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(TIME'00:00:00.00',`test`.`t1`.`a`))
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00';
a
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 ALL NULL NULL NULL NULL 3 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where octet_length(coalesce(TIME'00:00:00.0',`test`.`t1`.`a`)) <=> octet_length(coalesce(<cache>(TIME'00:00:00.00'),`test`.`t1`.`a`))
DROP TABLE t1;
#
# End of 10.4 tests
#
......@@ -1290,3 +1290,50 @@ INSERT INTO t1 VALUES ('-838:00:04.1', 'yes');
EXPLAIN SELECT * FROM t1 WHERE a NOT IN ('-838:00:01.1','-838:00:02.1');
SELECT * FROM t1 WHERE a NOT IN ('-838:00:01.1','-838:00:02.1');
DROP TABLE t1;
--echo #
--echo # Start of 10.4 tests
--echo #
--echo #
--echo # MDEV-11362 True condition elimination does not work for DECIMAL and temporal dynamic SQL parameters
--echo #
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES (1),(2),(3);
--echo # Equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:30',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:30';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:30';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:30';
--echo # Not equal values
EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME'10:20:30',a)<=>COALESCE(TIME'10:20:31',a);
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(?,a)' USING TIME'10:20:30',TIME'10:20:31';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(TIME''10:20:30'',a)<=>COALESCE(?,a)' USING TIME'10:20:31';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE COALESCE(?,a)<=>COALESCE(TIME''10:20:30'',a)' USING TIME'10:20:31';
DROP TABLE t1;
--echo #
--echo # MDEV-16426 Optimizer erroneously treats equal constants of different formats as same
--echo #
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01'),('00:00:02');
--echo Equal values
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a));
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.0',a));
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.0';
--echo Values with different formats
SELECT LENGTH(COALESCE(TIME'00:00:00.0',a)),LENGTH(COALESCE(TIME'00:00:00.00',a)) FROM t1;
SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a));
EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME'00:00:00.0',a))<=>LENGTH(COALESCE(TIME'00:00:00.00',a));
EXECUTE IMMEDIATE 'SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00';
EXECUTE IMMEDIATE 'EXPLAIN EXTENDED SELECT * FROM t1 WHERE LENGTH(COALESCE(TIME''00:00:00.0'',a))<=>LENGTH(COALESCE(?,a))' USING TIME'00:00:00.00';
DROP TABLE t1;
--echo #
--echo # End of 10.4 tests
--echo #
......@@ -3634,24 +3634,40 @@ longlong Item_field::val_int_endpoint(bool left_endp, bool *incl_endp)
bool Item_basic_value::eq(const Item *item, bool binary_cmp) const
{
const Item_basic_value *other= item->get_item_basic_value();
// Exclude CACHE_ITEM and VARBIN_ITEM
if (!other || type() != other->type())
return false;
const Type_handler *h= type_handler()->type_handler_for_comparison();
bool res= (h == other->type_handler()->type_handler_for_comparison()) &&
(binary_cmp ? h->Item_basic_value_bin_eq(this, other) :
h->Item_basic_value_eq(this, other));
const Item_const *c0, *c1;
const Type_handler *h0, *h1;
/*
- Test get_item_const() for NULL filters out Item_param
bound in a way that needs a data type conversion
(e.g. non-integer value in a LIMIT clause).
Item_param::get_item_const() return NULL in such cases.
- Test for type_handler_for_comparison() equality makes sure
that values of different data type groups do not get detected
as equal (e.g. numbers vs strings, time vs datetime).
- Test for cast_to_int_type_handler() equality distinguishes
values with dual properties. For example, VARCHAR 'abc' and hex
hybrid 0x616263 are equal in string context, but they are not equal
if the hybrid appears in integer context (it behaves as integer then).
Here we have no full information about the context, so treat them
as not equal.
QQ: We could pass Value_source::Context here instead of
"bool binary_cmp", to make substitution more delicate.
See Field::get_equal_const_item().
*/
bool res= (c0= get_item_const()) &&
(c1= item->get_item_const()) &&
(h0= type_handler())->type_handler_for_comparison() ==
(h1= item->type_handler())->type_handler_for_comparison() &&
h0->cast_to_int_type_handler()->type_handler_for_comparison() ==
h1->cast_to_int_type_handler()->type_handler_for_comparison() &&
h0->Item_const_eq(c0, c1, binary_cmp);
DBUG_EXECUTE_IF("Item_basic_value",
push_warning_printf(current_thd,
Sql_condition::WARN_LEVEL_NOTE,
ER_UNKNOWN_ERROR, "%seq=%d a=%s'%.*s' b=%s'%.*s'",
binary_cmp ? "bin_" : "",
(int) res,
type_handler()->name().ptr(),
(int) name.length, name.str,
other->type_handler()->name().ptr(),
(int) other->name.length, other->name.str
ER_UNKNOWN_ERROR, "%seq=%d a=%s b=%s",
binary_cmp ? "bin_" : "", (int) res,
DbugStringItemTypeValue(current_thd, this).c_ptr(),
DbugStringItemTypeValue(current_thd, item).c_ptr()
););
return res;
}
......@@ -3837,24 +3853,6 @@ void Item_decimal::print(String *str, enum_query_type query_type)
}
bool Item_decimal::eq(const Item *item, bool binary_cmp) const
{
if (type() == item->type() && item->basic_const_item())
{
/*
We need to cast off const to call val_decimal(). This should
be OK for a basic constant. Additionally, we can pass 0 as
a true decimal constant will return its internal decimal
storage and ignore the argument.
*/
Item *arg= (Item*) item;
my_decimal *value= arg->val_decimal(0);
return !my_decimal_cmp(&decimal_value, value);
}
return 0;
}
void Item_decimal::set_decimal_value(my_decimal *value_par)
{
my_decimal2decimal(value_par, &decimal_value);
......@@ -7279,15 +7277,6 @@ Item_bin_string::Item_bin_string(THD *thd, const char *str, size_t str_length):
}
bool Item_temporal_literal::eq(const Item *item, bool binary_cmp) const
{
return
item->basic_const_item() && type() == item->type() &&
field_type() == ((Item_temporal_literal *) item)->field_type() &&
!my_time_compare(&cached_time,
&((Item_temporal_literal *) item)->cached_time);
}
void Item_date_literal::print(String *str, enum_query_type query_type)
{
str->append("DATE'");
......
This diff is collapsed.
......@@ -57,6 +57,7 @@ Type_handler_set type_handler_set;
Type_handler_string type_handler_string;
Type_handler_var_string type_handler_var_string;
Type_handler_varchar type_handler_varchar;
Type_handler_hex_hybrid type_handler_hex_hybrid;
static Type_handler_varchar_compressed type_handler_varchar_compressed;
Type_handler_tiny_blob type_handler_tiny_blob;
......@@ -91,6 +92,9 @@ bool Type_handler_data::init()
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_geometry,
&type_handler_geometry) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_hex_hybrid,
&type_handler_long_blob) ||
m_type_aggregator_for_result.add(&type_handler_geometry,
&type_handler_tiny_blob,
&type_handler_long_blob) ||
......@@ -434,6 +438,7 @@ const Name
Type_handler_string::m_name_char(STRING_WITH_LEN("char")),
Type_handler_var_string::m_name_var_string(STRING_WITH_LEN("varchar")),
Type_handler_varchar::m_name_varchar(STRING_WITH_LEN("varchar")),
Type_handler_hex_hybrid::m_name_hex_hybrid(STRING_WITH_LEN("hex_hybrid")),
Type_handler_tiny_blob::m_name_tinyblob(STRING_WITH_LEN("tinyblob")),
Type_handler_medium_blob::m_name_mediumblob(STRING_WITH_LEN("mediumblob")),
Type_handler_long_blob::m_name_longblob(STRING_WITH_LEN("longblob")),
......@@ -6357,64 +6362,92 @@ bool Type_handler_general_purpose_string::
/***************************************************************************/
bool Type_handler_null::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
bool Type_handler_null::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
return a->basic_const_item() &&
b->basic_const_item();
return true;
}
bool Type_handler_real_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
bool Type_handler_real_result::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
return a->basic_const_item() &&
b->basic_const_item() &&
const_cast<Item_basic_value*>(a)->val_real() ==
const_cast<Item_basic_value*>(b)->val_real();
const double *va= a->const_ptr_double();
const double *vb= b->const_ptr_double();
return va[0] == vb[0];
}
bool Type_handler_int_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
bool Type_handler_int_result::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
longlong value;
return a->basic_const_item() &&
b->basic_const_item() &&
(value= const_cast<Item_basic_value*>(a)->val_int()) ==
const_cast<Item_basic_value*>(b)->val_int() &&
(value >= 0 || a->unsigned_flag == b->unsigned_flag);
const longlong *va= a->const_ptr_longlong();
const longlong *vb= b->const_ptr_longlong();
bool res= va[0] == vb[0] &&
(va[0] >= 0 ||
(a->get_type_all_attributes_from_const()->unsigned_flag ==
b->get_type_all_attributes_from_const()->unsigned_flag));
return res;
}
bool Type_handler_string_result::Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
bool Type_handler_string_result::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
if (!a->basic_const_item() ||
!b->basic_const_item() ||
a->collation.collation != b->collation.collation)
return false;
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
return sa->eq(sb, a->collation.collation);
const String *sa= a->const_ptr_string();
const String *sb= b->const_ptr_string();
return binary_cmp ? sa->bin_eq(sb) :
a->get_type_all_attributes_from_const()->collation.collation ==
b->get_type_all_attributes_from_const()->collation.collation &&
sa->eq(sb, a->get_type_all_attributes_from_const()->collation.collation);
}
bool
Type_handler_string_result::Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b)
const
Type_handler_decimal_result::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
if (!a->basic_const_item() ||
!b->basic_const_item())
return false;
String *sa= const_cast<Item_basic_value*>(a)->val_str(NULL);
String *sb= const_cast<Item_basic_value*>(b)->val_str(NULL);
return sa->bin_eq(sb);
const my_decimal *da= a->const_ptr_my_decimal();
const my_decimal *db= b->const_ptr_my_decimal();
return !my_decimal_cmp(da, db) &&
(!binary_cmp ||
a->get_type_all_attributes_from_const()->decimals ==
b->get_type_all_attributes_from_const()->decimals);
}
bool
Type_handler_temporal_result::Item_const_eq(const Item_const *a,
const Item_const *b,
bool binary_cmp) const
{
const MYSQL_TIME *ta= a->const_ptr_mysql_time();
const MYSQL_TIME *tb= b->const_ptr_mysql_time();
return !my_time_compare(ta, tb) &&
(!binary_cmp ||
a->get_type_all_attributes_from_const()->decimals ==
b->get_type_all_attributes_from_const()->decimals);
}
/***************************************************************************/
const Type_handler *
Type_handler_hex_hybrid::cast_to_int_type_handler() const
{
return &type_handler_longlong;
}
const Type_handler *
Type_handler_hex_hybrid::type_handler_for_system_time() const
{
return &type_handler_longlong;
}
/***************************************************************************/
......@@ -30,7 +30,7 @@ class Field;
class Column_definition;
class Column_definition_attributes;
class Item;
class Item_basic_value;
class Item_const;
class Item_param;
class Item_cache;
class Item_func_or_sum;
......@@ -1168,6 +1168,10 @@ class Type_handler
{
return this;
}
virtual const Type_handler *type_handler_for_system_time() const
{
return this;
}
virtual CHARSET_INFO *charset_for_protocol(const Item *item) const;
virtual const Type_handler*
type_handler_adjusted_to_max_octet_length(uint max_octet_length,
......@@ -1391,16 +1395,11 @@ class Type_handler
return NULL;
}
virtual bool set_comparator_func(Arg_comparator *cmp) const= 0;
virtual bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const
virtual bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const
{
return false;
}
virtual bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Item_basic_value_eq(a, b);
}
virtual bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name,
Type_handler_hybrid_field_type *,
......@@ -1877,8 +1876,8 @@ class Type_handler_real_result: public Type_handler_numeric
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
......@@ -1956,6 +1955,8 @@ class Type_handler_decimal_result: public Type_handler_numeric
uint32 max_display_length(const Item *item) const;
Item *create_typecast_item(THD *thd, Item *item,
const Type_cast_attributes &attr) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
void Item_param_set_param_func(Item_param *param,
......@@ -2158,8 +2159,8 @@ class Type_handler_int_result: public Type_handler_numeric
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_decimal_precision(const Item *item) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_param_set_from_value(THD *thd,
......@@ -2239,6 +2240,8 @@ class Type_handler_temporal_result: public Type_handler
void sortlength(THD *thd,
const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
bool Item_param_set_from_value(THD *thd,
Item_param *param,
const Type_all_attributes *attr,
......@@ -2323,10 +2326,8 @@ class Type_handler_string_result: public Type_handler
const Schema_specification_st *schema)
const;
uint32 max_display_length(const Item *item) const;
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
uint Item_time_precision(Item *item) const
{
return Item_temporal_precision(item, true);
......@@ -3315,13 +3316,8 @@ class Type_handler_null: public Type_handler_general_purpose_string
const Type_handler *type_handler_for_union(const Item *) const;
uint32 max_display_length(const Item *item) const { return 0; }
uint32 calc_pack_length(uint32 length) const { return 0; }
bool Item_basic_value_eq(const Item_basic_value *a,
const Item_basic_value *b) const;
bool Item_basic_value_bin_eq(const Item_basic_value *a,
const Item_basic_value *b) const
{
return Type_handler_null::Item_basic_value_eq(a, b);
}
bool Item_const_eq(const Item_const *a, const Item_const *b,
bool binary_cmp) const;
bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
......@@ -3468,6 +3464,17 @@ class Type_handler_varchar: public Type_handler_longstr
};
class Type_handler_hex_hybrid: public Type_handler_varchar
{
static const Name m_name_hex_hybrid;
public:
virtual ~Type_handler_hex_hybrid() {}
const Name name() const { return m_name_hex_hybrid; }
const Type_handler *cast_to_int_type_handler() const;
const Type_handler *type_handler_for_system_time() const;
};
class Type_handler_varchar_compressed: public Type_handler_varchar
{
public:
......@@ -3871,6 +3878,7 @@ extern MYSQL_PLUGIN_IMPORT Type_handler_set type_handler_set;
extern MYSQL_PLUGIN_IMPORT Type_handler_string type_handler_string;
extern MYSQL_PLUGIN_IMPORT Type_handler_var_string type_handler_var_string;
extern MYSQL_PLUGIN_IMPORT Type_handler_varchar type_handler_varchar;
extern MYSQL_PLUGIN_IMPORT Type_handler_hex_hybrid type_handler_hex_hybrid;
extern MYSQL_PLUGIN_IMPORT Type_handler_tiny_blob type_handler_tiny_blob;
extern MYSQL_PLUGIN_IMPORT Type_handler_medium_blob type_handler_medium_blob;
......
......@@ -8732,7 +8732,8 @@ bool Vers_history_point::resolve_unit(THD *thd)
return false;
if (item->fix_fields_if_needed(thd, &item))
return true;
return item->this_item()->type_handler_for_system_time()->
return item->this_item()->real_type_handler()->
type_handler_for_system_time()->
Vers_history_point_resolve_unit(thd, this);
}
......
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