From 9043dd7a2d380b26349bc23e904d44e9ce634cef Mon Sep 17 00:00:00 2001 From: Alexander Barkov Date: Fri, 8 Jun 2018 12:36:42 +0400 Subject: [PATCH] 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). --- mysql-test/main/func_debug.result | 119 +++++++++++++++++----- mysql-test/main/func_debug.test | 61 +++++++++--- mysql-test/main/gis.result | 24 +++++ mysql-test/main/gis.test | 20 ++++ mysql-test/main/type_date.result | 75 ++++++++++++++ mysql-test/main/type_date.test | 35 +++++++ mysql-test/main/type_datetime.result | 101 +++++++++++++++++++ mysql-test/main/type_datetime.test | 52 ++++++++++ mysql-test/main/type_decimal.result | 97 ++++++++++++++++++ mysql-test/main/type_decimal.test | 53 ++++++++++ mysql-test/main/type_float.result | 32 ++++++ mysql-test/main/type_float.test | 21 ++++ mysql-test/main/type_hex_hybrid.result | 24 +++++ mysql-test/main/type_hex_hybrid.test | 21 ++++ mysql-test/main/type_int.result | 32 ++++++ mysql-test/main/type_int.test | 20 ++++ mysql-test/main/type_time.result | 101 +++++++++++++++++++ mysql-test/main/type_time.test | 47 +++++++++ sql/item.cc | 73 ++++++-------- sql/item.h | 130 ++++++++++++++++++------- sql/sql_type.cc | 113 +++++++++++++-------- sql/sql_type.h | 54 +++++----- sql/table.cc | 3 +- 23 files changed, 1126 insertions(+), 182 deletions(-) create mode 100644 mysql-test/main/type_hex_hybrid.result create mode 100644 mysql-test/main/type_hex_hybrid.test diff --git a/mysql-test/main/func_debug.result b/mysql-test/main/func_debug.result index a394bf3c334..6a33557dca3 100644 --- a/mysql-test/main/func_debug.result +++ b/mysql-test/main/func_debug.result @@ -1665,78 +1665,66 @@ 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'?' -DROP TABLE t1; -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 -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 +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'); @@ -1744,15 +1732,92 @@ SELECT * FROM t1 WHERE a BETWEEN '0' AND '0'; a 0 Warnings: -Note 1105 eq=1 a=varchar'0' b=varchar'0' +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' +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 ' +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 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 +2001-01-01 +Warnings: +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 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 +Warnings: +Note 1105 eq=0 a=(varchar)'a' b=(hex_hybrid)'a' DROP TABLE t1; SET SESSION debug_dbug="-d,Item_basic_value"; diff --git a/mysql-test/main/func_debug.test b/mysql-test/main/func_debug.test index f9b6daab3a2..9237561500d 100644 --- a/mysql-test/main/func_debug.test +++ b/mysql-test/main/func_debug.test @@ -499,19 +499,6 @@ 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; - -# 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; -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'; -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'; @@ -520,3 +507,51 @@ 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"; + +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; + +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 ('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"; diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 1cc4e45629b..c79699bf8cf 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -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 # diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index 1bac831ac22..aacb9a6c653 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -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 # diff --git a/mysql-test/main/type_date.result b/mysql-test/main/type_date.result index 69bdf569787..897f42a2ec4 100644 --- a/mysql-test/main/type_date.result +++ b/mysql-test/main/type_date.result @@ -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((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(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((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((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((DATE'2001-01-01'),`test`.`t1`.`a`) <=> coalesce((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((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((DATE'2001-01-02'),`test`.`t1`.`a`) <=> coalesce(DATE'2001-01-01',`test`.`t1`.`a`) +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_date.test b/mysql-test/main/type_date.test index 8d29a54a26c..cbd6cc846aa 100644 --- a/mysql-test/main/type_date.test +++ b/mysql-test/main/type_date.test @@ -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 # diff --git a/mysql-test/main/type_datetime.result b/mysql-test/main/type_datetime.result index 74b761a2e8f..86dddc93a70 100644 --- a/mysql-test/main/type_datetime.result +++ b/mysql-test/main/type_datetime.result @@ -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((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(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((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((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((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((TIMESTAMP'2001-01-01 00:00:00.00'),`test`.`t1`.`a`)) +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_datetime.test b/mysql-test/main/type_datetime.test index dafa9f9456e..3c8287f8793 100644 --- a/mysql-test/main/type_datetime.test +++ b/mysql-test/main/type_datetime.test @@ -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 # diff --git a/mysql-test/main/type_decimal.result b/mysql-test/main/type_decimal.result index f96f98e7a9b..4d0f6fc12fd 100644 --- a/mysql-test/main/type_decimal.result +++ b/mysql-test/main/type_decimal.result @@ -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 (octet_length(10.0)) + `test`.`t1`.`a` <=> (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 (octet_length(10.0)) + `test`.`t1`.`a` <=> (octet_length(10.00)) + `test`.`t1`.`a` +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_decimal.test b/mysql-test/main/type_decimal.test index 903f375d1ae..dd4ba5df40d 100644 --- a/mysql-test/main/type_decimal.test +++ b/mysql-test/main/type_decimal.test @@ -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 # diff --git a/mysql-test/main/type_float.result b/mysql-test/main/type_float.result index 57cdd1561df..0ac018379d1 100644 --- a/mysql-test/main/type_float.result +++ b/mysql-test/main/type_float.result @@ -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 +# diff --git a/mysql-test/main/type_float.test b/mysql-test/main/type_float.test index 2d7c4428507..3d0131b3bb0 100644 --- a/mysql-test/main/type_float.test +++ b/mysql-test/main/type_float.test @@ -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 # diff --git a/mysql-test/main/type_hex_hybrid.result b/mysql-test/main/type_hex_hybrid.result new file mode 100644 index 00000000000..eec24f6e89e --- /dev/null +++ b/mysql-test/main/type_hex_hybrid.result @@ -0,0 +1,24 @@ +# +# 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 (octet_length(charset('a'))) + `test`.`t1`.`a` <=> (octet_length(charset(0x61))) + `test`.`t1`.`a` +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_hex_hybrid.test b/mysql-test/main/type_hex_hybrid.test new file mode 100644 index 00000000000..a39750e2635 --- /dev/null +++ b/mysql-test/main/type_hex_hybrid.test @@ -0,0 +1,21 @@ +--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 # diff --git a/mysql-test/main/type_int.result b/mysql-test/main/type_int.result index 47c859d3ffb..348d72b125b 100644 --- a/mysql-test/main/type_int.result +++ b/mysql-test/main/type_int.result @@ -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 +# diff --git a/mysql-test/main/type_int.test b/mysql-test/main/type_int.test index bcab2b20dc4..f340d9a72bd 100644 --- a/mysql-test/main/type_int.test +++ b/mysql-test/main/type_int.test @@ -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 # diff --git a/mysql-test/main/type_time.result b/mysql-test/main/type_time.result index 5cdd3b00924..51b2aecaa6b 100644 --- a/mysql-test/main/type_time.result +++ b/mysql-test/main/type_time.result @@ -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((TIME'10:20:30'),`test`.`t1`.`a`) <=> coalesce((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((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((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((TIME'00:00:00.00'),`test`.`t1`.`a`)) +DROP TABLE t1; +# +# End of 10.4 tests +# diff --git a/mysql-test/main/type_time.test b/mysql-test/main/type_time.test index d8bb66fcd5c..17494cec04f 100644 --- a/mysql-test/main/type_time.test +++ b/mysql-test/main/type_time.test @@ -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 # diff --git a/sql/item.cc b/sql/item.cc index 5cffb244030..c1ce156c98e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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'"); diff --git a/sql/item.h b/sql/item.h index c99750ca5e2..bf94896a61c 100644 --- a/sql/item.h +++ b/sql/item.h @@ -694,6 +694,20 @@ public: }; +class Item_const +{ +public: + virtual ~Item_const() {} + virtual const Type_all_attributes *get_type_all_attributes_from_const() const= 0; + virtual bool const_is_null() const { return false; } + virtual const longlong *const_ptr_longlong() const { return NULL; } + virtual const double *const_ptr_double() const { return NULL; } + virtual const my_decimal *const_ptr_my_decimal() const { return NULL; } + virtual const MYSQL_TIME *const_ptr_mysql_time() const { return NULL; } + virtual const String *const_ptr_string() const { return NULL; } +}; + + /****************************************************************************/ class Item: public Value_source, @@ -734,7 +748,6 @@ public: */ CONST_ITEM, NULL_ITEM, // Item_null or Item_param bound to NULL - VARBIN_ITEM, COPY_STR_ITEM, FIELD_AVG_ITEM, DEFAULT_VALUE_ITEM, PROC_ITEM,COND_ITEM, REF_ITEM, FIELD_STD_ITEM, FIELD_VARIANCE_ITEM, INSERT_VALUE_ITEM, @@ -1026,13 +1039,9 @@ public: { return type_handler(); } - virtual const Type_handler *cast_to_int_type_handler() const + const Type_handler *cast_to_int_type_handler() const { - return type_handler(); - } - virtual const Type_handler *type_handler_for_system_time() const - { - return real_type_handler(); + return real_type_handler()->cast_to_int_type_handler(); } /* result_type() of an item specifies how the value should be returned */ Item_result result_type() const @@ -2093,7 +2102,7 @@ public: delete this; } - virtual const Item_basic_value *get_item_basic_value() const { return NULL; } + virtual const Item_const *get_item_const() const { return NULL; } virtual Item_splocal *get_item_splocal() { return 0; } virtual Rewritable_query_parameter *get_rewritable_query_parameter() { return 0; } @@ -2278,6 +2287,25 @@ inline Item* get_item_copy (THD *thd, T* item) } +#ifndef DBUG_OFF +/** + A helper class to print the data type and the value for an Item + in debug builds. +*/ +class DbugStringItemTypeValue: public StringBuffer<128> +{ +public: + DbugStringItemTypeValue(THD *thd, const Item *item) + { + append('('); + append(item->type_handler()->name().ptr()); + append(')'); + const_cast(item)->print(this, QT_EXPLAIN); + } +}; +#endif + + /* This class is a replacement for the former member Item::with_subselect. Determines if the descendant Item is a subselect or some of @@ -2518,7 +2546,8 @@ public: /** A common class for Item_basic_constant and Item_param */ -class Item_basic_value :public Item +class Item_basic_value :public Item, + public Item_const { protected: // Value metadata, e.g. to make string processing easier @@ -2559,8 +2588,9 @@ protected: public: Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, const Tmp_field_param *param); - const Item_basic_value *get_item_basic_value() const { return this; } bool eq(const Item *item, bool binary_cmp) const; + const Type_all_attributes *get_type_all_attributes_from_const() const + { return this; } }; @@ -2569,6 +2599,7 @@ class Item_basic_constant :public Item_basic_value public: Item_basic_constant(THD *thd): Item_basic_value(thd) {}; bool check_vcol_func_processor(void *arg) { return false; } + const Item_const *get_item_const() const { return this; } virtual Item_basic_constant *make_string_literal_concat(THD *thd, const LEX_CSTRING *) { @@ -2959,7 +2990,6 @@ public: bool check_partition_func_processor(void *int_arg) { return false;} bool const_item() const { return true; } bool basic_const_item() const { return true; } - const Item_basic_value *get_item_basic_value() const { return this; } }; @@ -3202,10 +3232,6 @@ public: const Type_handler *handler= field->type_handler(); return handler->type_handler_for_item_field(); } - const Type_handler *cast_to_int_type_handler() const - { - return field->type_handler()->cast_to_int_type_handler(); - } const Type_handler *real_type_handler() const { if (field->is_created_from_null_item) @@ -3436,6 +3462,7 @@ public: const Type_handler *type_handler() const { return &type_handler_null; } bool basic_const_item() const { return 1; } Item *clone_item(THD *thd); + bool const_is_null() const { return true; } bool is_null() { return 1; } virtual inline void print(String *str, enum_query_type query_type) @@ -3698,6 +3725,39 @@ public: type_handler()->is_order_clause_position_type(); } + const Item_const *get_item_const() const + { + switch (state) { + case SHORT_DATA_VALUE: + case LONG_DATA_VALUE: + case NULL_VALUE: + return this; + case IGNORE_VALUE: + case DEFAULT_VALUE: + case NO_VALUE: + break; + } + return NULL; + } + + bool const_is_null() const { return state == NULL_VALUE; } + bool can_return_const_value(Item_result type) const + { + return can_return_value() && + value.type_handler()->cmp_type() == type && + type_handler()->cmp_type() == type; + } + const longlong *const_ptr_longlong() const + { return can_return_const_value(INT_RESULT) ? &value.integer : NULL; } + const double *const_ptr_double() const + { return can_return_const_value(REAL_RESULT) ? &value.real : NULL; } + const my_decimal *const_ptr_my_decimal() const + { return can_return_const_value(DECIMAL_RESULT) ? &value.m_decimal : NULL; } + const MYSQL_TIME *const_ptr_mysql_time() const + { return can_return_const_value(TIME_RESULT) ? &value.time : NULL; } + const String *const_ptr_string() const + { return can_return_const_value(STRING_RESULT) ? &value.m_string : NULL; } + double val_real() { return can_return_value() ? value.val_real() : 0e0; @@ -3890,6 +3950,7 @@ public: { return type_handler_long_or_longlong(); } Field *create_field_for_create_select(TABLE *table) { return tmp_table_field_from_field_type(table); } + const longlong *const_ptr_longlong() const { return &value; } longlong val_int() { return value; } longlong val_int_min() const { return value; } double val_real() { return (double) value; } @@ -3989,12 +4050,12 @@ public: double val_real(); String *val_str(String*); my_decimal *val_decimal(my_decimal *val) { return &decimal_value; } + const my_decimal *const_ptr_my_decimal() const { return &decimal_value; } int save_in_field(Field *field, bool no_conversions); Item *clone_item(THD *thd); virtual void print(String *str, enum_query_type query_type); Item *neg(THD *thd); uint decimal_precision() const { return decimal_value.precision(); } - bool eq(const Item *, bool binary_cmp) const; void set_decimal_value(my_decimal *value_par); Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -4022,6 +4083,7 @@ public: } int save_in_field(Field *field, bool no_conversions); const Type_handler *type_handler() const { return &type_handler_double; } + const double *const_ptr_double() const { return &value; } double val_real() { return value; } longlong val_int() { @@ -4146,6 +4208,10 @@ public: } double val_real(); longlong val_int(); + const String *const_ptr_string() const + { + return &str_value; + } String *val_str(String*) { return (String*) &str_value; @@ -4424,18 +4490,12 @@ public: { hex_string_init(thd, str, str_length); } - enum Type type() const { return VARBIN_ITEM; } const Type_handler *type_handler() const { return &type_handler_varchar; } virtual Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) { return const_charset_converter(thd, tocs, true); } - bool eq(const Item *item, bool binary_cmp) const - { - return item->basic_const_item() && item->type() == type() && - item->cast_to_int_type_handler() == cast_to_int_type_handler() && - str_value.bin_eq(&((Item_hex_constant*)item)->str_value); - } + const String *const_ptr_string() const { return &str_value; } String *val_str(String*) { return &str_value; } bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) { @@ -4455,6 +4515,7 @@ public: Item_hex_hybrid(THD *thd): Item_hex_constant(thd) {} Item_hex_hybrid(THD *thd, const char *str, size_t str_length): Item_hex_constant(thd, str, str_length) {} + const Type_handler *type_handler() const { return &type_handler_hex_hybrid; } uint decimal_precision() const; double val_real() { @@ -4475,14 +4536,6 @@ public: field->set_notnull(); return field->store_hex_hybrid(str_value.ptr(), str_value.length()); } - const Type_handler *cast_to_int_type_handler() const - { - return &type_handler_longlong; - } - const Type_handler *type_handler_for_system_time() const - { - return &type_handler_longlong; - } void print(String *str, enum_query_type query_type); Item *get_copy(THD *thd) { return get_item_copy(thd, this); } @@ -4558,8 +4611,8 @@ public: decimals= dec_arg; cached_time= *ltime; } - bool eq(const Item *item, bool binary_cmp) const; + const MYSQL_TIME *const_ptr_mysql_time() const { return &cached_time; } bool is_null() { return is_null_from_temporal(); } bool get_date_with_sql_mode(MYSQL_TIME *to); @@ -6220,7 +6273,7 @@ public: for any value. */ -class Item_cache: public Item_basic_value, +class Item_cache: public Item, public Type_handler_hybrid_field_type { protected: @@ -6243,7 +6296,7 @@ protected: table_map used_table_map; public: Item_cache(THD *thd): - Item_basic_value(thd), + Item(thd), Type_handler_hybrid_field_type(&type_handler_string), example(0), cached_field(0), value_cached(0), @@ -6254,7 +6307,7 @@ public: } protected: Item_cache(THD *thd, const Type_handler *handler): - Item_basic_value(thd), + Item(thd), Type_handler_hybrid_field_type(handler), example(0), cached_field(0), value_cached(0), @@ -6281,6 +6334,11 @@ public: const Type_handler *type_handler() const { return Type_handler_hybrid_field_type::type_handler(); } + Field *create_tmp_field_ex(TABLE *table, Tmp_field_src *src, + const Tmp_field_param *param) + { + return create_tmp_field_ex_simple(table, src, param); + } virtual void keep_array() {} virtual void print(String *str, enum_query_type query_type); @@ -6311,7 +6369,7 @@ public: void cleanup() { clear(); - Item_basic_value::cleanup(); + Item::cleanup(); } /** Check if saved item has a non-NULL value. diff --git a/sql/sql_type.cc b/sql/sql_type.cc index dce74d92859..66e1d2d79eb 100644 --- a/sql/sql_type.cc +++ b/sql/sql_type.cc @@ -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(a)->val_real() == - const_cast(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(a)->val_int()) == - const_cast(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(a)->val_str(NULL); - String *sb= const_cast(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(a)->val_str(NULL); - String *sb= const_cast(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; +} + + /***************************************************************************/ diff --git a/sql/sql_type.h b/sql/sql_type.h index 656c5e06e81..f9ba99e775f 100644 --- a/sql/sql_type.h +++ b/sql/sql_type.h @@ -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 @@ public: { 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: }; +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; diff --git a/sql/table.cc b/sql/table.cc index 71aea2d3c3b..73b1a6bd9b2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -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); }