1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-09 22:24:09 +03:00

Merge branch '10.1' of https://github.com/MariaDB/server into ok-debpkg-10.1

This commit is contained in:
Otto Kekäläinen
2015-09-07 22:21:35 +03:00
45 changed files with 2199 additions and 336 deletions

View File

@@ -100,7 +100,7 @@ struct my_rnd_struct;
enum Item_result enum Item_result
{ {
STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT, STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT,
TIME_RESULT,IMPOSSIBLE_RESULT TIME_RESULT
}; };
typedef struct st_udf_args typedef struct st_udf_args
{ {

View File

@@ -547,7 +547,7 @@ struct my_rnd_struct;
enum Item_result enum Item_result
{ {
STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT, STRING_RESULT=0, REAL_RESULT, INT_RESULT, ROW_RESULT, DECIMAL_RESULT,
TIME_RESULT,IMPOSSIBLE_RESULT TIME_RESULT
}; };
typedef struct st_udf_args typedef struct st_udf_args

View File

@@ -0,0 +1,64 @@
# Trailing garbage in string literals
--eval CREATE TABLE t1 (a $TYPE);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a='2001-01-01 00:00:00x';
SELECT * FROM t1 WHERE LENGTH(a) != 20;
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x';
DROP TABLE t1;
# Leading spaces in string literals
--eval CREATE TABLE t1 (a $TYPE);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=19;
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 2001-01-01 00:00:00';
# This should not propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
DROP TABLE t1;
# Trailing fractional digits in temporal literals
--eval CREATE TABLE t1 (a $TYPE);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
SELECT * FROM t1 WHERE LENGTH(a)=19;
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
DROP TABLE t1;
# Trailing fractional digits in temporal literals, the same precision
--eval CREATE TABLE t1 (a $TYPE(6));
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
SELECT * FROM t1 WHERE LENGTH(a)=26;
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
DROP TABLE t1;
# DATETIME/TIMESTAMP column vs TIME literal
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
--eval CREATE TABLE t1 (a $TYPE);
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIME'00:00:00';
SELECT * FROM t1 WHERE LENGTH(a)=19;
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'00:00:00';
DROP TABLE t1;

View File

@@ -231,3 +231,138 @@ case t1.f1 when '00:00:00' then 1 end
1 1
NULL NULL
drop table t1; drop table t1;
#
# Start of 10.1 test
#
#
# MDEV-8752 Wrong result for SELECT..WHERE CASE enum_field WHEN 1 THEN 1 ELSE 0 END AND a='5'
#
CREATE TABLE t1 (a ENUM('5','6') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM t1 WHERE a='5';
a
5
SELECT * FROM t1 WHERE a=1;
a
5
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END;
a
5
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END AND a='5';
a
5
# Multiple comparison types in CASE, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END AND a='5';
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 ((`test`.`t1`.`a` = '5') and (case `test`.`t1`.`a` when 1 then 1 else 0 end))
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('a','b','100'));
INSERT INTO t1 VALUES ('a'),('b'),('100');
SELECT * FROM t1 WHERE a='a';
a
a
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END;
a
a
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END AND a='a';
a
a
# String comparison in CASE and in the equality, ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END AND a='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 (`test`.`t1`.`a` = 'a')
SELECT * FROM t1 WHERE a=3;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a=3;
a
100
# Integer comparison in CASE and in the equality, not ok to propagate
# ENUM does not support this type of propagation yet.
# This can change in the future. See MDEV-8748.
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a=3;
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 ((case `test`.`t1`.`a` when 3 then 1 else 0 end) and (`test`.`t1`.`a` = 3))
SELECT * FROM t1 WHERE a=3;
a
100
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END;
a
100
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END AND a=3;
a
100
# String comparison in CASE, integer comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END AND a=3;
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 ((case `test`.`t1`.`a` when '100' then 1 else 0 end) and (`test`.`t1`.`a` = 3))
SELECT * FROM t1 WHERE a='100';
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a='100';
a
100
# Integer comparison in CASE, string comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a='100';
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 ((`test`.`t1`.`a` = '100') and (case `test`.`t1`.`a` when 3 then 1 else 0 end))
SELECT * FROM t1 WHERE a='100';
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a='100';
a
100
# Multiple type comparison in CASE, string comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a='100';
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 ((`test`.`t1`.`a` = '100') and (case `test`.`t1`.`a` when 3 then 1 when '100' then 1 else 0 end))
SELECT * FROM t1 WHERE a=3;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END;
a
100
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a=3;
a
100
# Multiple type comparison in CASE, integer comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a=3;
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 ((case `test`.`t1`.`a` when 3 then 1 when '100' then 1 else 0 end) and (`test`.`t1`.`a` = 3))
DROP TABLE t1;
#
# End of MDEV-8752
#
#
# End of 10.1 test
#

View File

@@ -604,3 +604,48 @@ where coalesce(message,0) <> 0;
id message id message
drop table t1,t2; drop table t1,t2;
set optimizer_switch=@save_derived_optimizer_switch; set optimizer_switch=@save_derived_optimizer_switch;
#
# Start of 10.1 tests
#
#
# MDEV-8747 Wrong result for SELECT..WHERE derived_table_column='a' AND derived_table_column<>_latin1'A' COLLATE latin1_bin
#
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a' AND a <> _latin1'A' COLLATE latin1_bin;
a
a
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='a' AND a <> _latin1'A' COLLATE latin1_bin;
a
a
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5';
a
5
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a=1;
a
5
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5' AND a=1;
a
5
DROP TABLE t1;
#
# MDEV-8749 Wrong result for SELECT..WHERE derived_table_enum_column='number' AND derived_table_enum_column OP number2
#
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5';
a
5
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a=1;
a
5
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5' AND a=1;
a
5
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -2289,20 +2289,16 @@ field1 field2
2004-10-11 18:13:00 1 2004-10-11 18:13:00 1
2009-02-19 02:05:00 5 2009-02-19 02:05:00 5
Warnings: Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'x'
Warning 1292 Truncated incorrect DOUBLE value: 'g' Warning 1292 Truncated incorrect DOUBLE value: 'g'
Warning 1292 Truncated incorrect DOUBLE value: 'o' Warning 1292 Truncated incorrect DOUBLE value: 'o'
Warning 1292 Truncated incorrect DOUBLE value: 'g'
Warning 1292 Truncated incorrect DOUBLE value: 'v' Warning 1292 Truncated incorrect DOUBLE value: 'v'
SELECT alias2.f3 AS field1 , alias2.f1 AS field2 FROM t1 AS alias1 JOIN t1 AS alias2 ON alias2.f1 = alias1.f2 AND alias2.f1 != alias1.f4 GROUP BY field1 , field2 ; SELECT alias2.f3 AS field1 , alias2.f1 AS field2 FROM t1 AS alias1 JOIN t1 AS alias2 ON alias2.f1 = alias1.f2 AND alias2.f1 != alias1.f4 GROUP BY field1 , field2 ;
field1 field2 field1 field2
2004-10-11 18:13:00 1 2004-10-11 18:13:00 1
2009-02-19 02:05:00 5 2009-02-19 02:05:00 5
Warnings: Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'x'
Warning 1292 Truncated incorrect DOUBLE value: 'g' Warning 1292 Truncated incorrect DOUBLE value: 'g'
Warning 1292 Truncated incorrect DOUBLE value: 'o' Warning 1292 Truncated incorrect DOUBLE value: 'o'
Warning 1292 Truncated incorrect DOUBLE value: 'g'
Warning 1292 Truncated incorrect DOUBLE value: 'v' Warning 1292 Truncated incorrect DOUBLE value: 'v'
SET SESSION SQL_MODE=default; SET SESSION SQL_MODE=default;
drop table t1; drop table t1;

View File

@@ -97,6 +97,6 @@ FLUSH LOGS;
# Cleanup. # Cleanup.
# #
# reset variable value to pass testcase checks # reset variable value to pass testcase checks
SET @@global.max_allowed_packet = 1048576; SET @@global.max_allowed_packet = 4194304;
DROP TABLE t1; DROP TABLE t1;
remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_big_1.out remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_big_1.out

View File

@@ -513,3 +513,86 @@ DROP TABLE t1;
# #
# End of 10.1 tests # End of 10.1 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
#
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE a='2001-01-01x';
a
2001-01-01
Warnings:
Warning 1292 Truncated incorrect date value: '2001-01-01x'
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031';
a
2001-01-02
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031' AND a='2001-01-01x';
a
Warnings:
Warning 1292 Truncated incorrect date value: '2001-01-01x'
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031' AND a='2001-01-01x';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Warning 1292 Truncated incorrect date value: '2001-01-01x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE HEX(a)!=CONCAT('xx',RAND()) AND a='2001-01-01x';
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:
Warning 1292 Truncated incorrect date value: '2001-01-01x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01x') and (<cache>(hex(DATE'2001-01-01')) <> concat('xx',rand())))
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE LENGTH(a)=11;
a
SELECT * FROM t1 WHERE LENGTH(a)=11 AND a=' 2001-01-01';
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11 AND a=' 2001-01-01';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01') and (<cache>(length(DATE'2001-01-01')) = (11 + rand())))
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' garbage ';
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:
Warning 1292 Incorrect datetime value: ' garbage '
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (11 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='20010101';
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='20010101';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8+RAND() AND a='20010101';
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 ((`test`.`t1`.`a` = '20010101') and (<cache>(length(DATE'2001-01-01')) = (8 + rand())))
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -945,5 +945,145 @@ CAST(CAST(TIMESTAMP'0000-00-00 00:00:00.000001' AS TIME(6)) AS DATETIME(6))
SET old_mode=DEFAULT; SET old_mode=DEFAULT;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
# #
# MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
#
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a='2001-01-01 00:00:00x';
a
2001-01-01 00:00:00
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
SELECT * FROM t1 WHERE LENGTH(a) != 20;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
a
2001-01-01 00:00:00
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
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:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x';
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:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
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:
Warning 1292 Incorrect datetime value: ' garbage '
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a DATETIME(6));;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00.000000
SELECT * FROM t1 WHERE LENGTH(a)=26;
a
2001-01-01 00:00:00.000000
2001-01-01 00:00:01.000000
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00.000000
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00.000000')) = (40 + rand())))
DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
CREATE TABLE t1 (a DATETIME);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIME'00:00:00';
a
2001-01-01 00:00:00
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
DROP TABLE t1;
#
# End of 10.1 tests # End of 10.1 tests
# #

View File

@@ -2082,3 +2082,55 @@ DROP TABLE t1;
DROP TABLE t1; DROP TABLE t1;
# #
# End of 10.0 tests # End of 10.0 tests
#
#
# Start of 10.1 tests
#
#
# MDEV-8729 Wrong result for SELECT..WHERE HEX(enum_column)='61' AND enum_column='a '
#
CREATE TABLE t1 (a ENUM('a','A') CHARACTER SET latin1 COLLATE latin1_bin);
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a ';
a
a
SELECT * FROM t1 WHERE HEX(a)='61';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
a
a
# Can't propagate the equality into HEX(a), because binary collations still ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='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 ((`test`.`t1`.`a` = 'a ') and (hex(`test`.`t1`.`a`) = '61'))
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('a','a ') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('a'),('a ');
SELECT * FROM t1 WHERE a='a ';
a
a
SELECT * FROM t1 WHERE HEX(a)='61';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
a
# Ok to propagate the equality into HEX(a), because "CHARACTER SET BINARY" does not ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='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 (`test`.`t1`.`a` = 'a')
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
DROP TABLE t1;
#
# End of 10.1 tests

View File

@@ -532,3 +532,98 @@ DROP TABLE t1,t2;
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# MDEV-8704 Wrong result for SELECT..WHERE LENGTH(double_column)!=6 AND double_column=100e0
#
CREATE TABLE t1 (a DOUBLE(9,2));
INSERT INTO t1 VALUES (100),(110);
SELECT * FROM t1 WHERE LENGTH(a)!=6;
a
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
a
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (100),(110);
SELECT * FROM t1 WHERE LENGTH(a)!=6;
a
100
110
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
a
100
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
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 (`test`.`t1`.`a` = 100e0)
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=100e0;
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 ((`test`.`t1`.`a` = 100e0) and (<cache>(length(100)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
a
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10e0;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
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 ((`test`.`t1`.`a` = 1.10e0) and (<cache>(length(1.1)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
a
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10e0;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
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 ((`test`.`t1`.`a` = 1.10e0) and (<cache>(length(1.10)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DOUBLE(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
a
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10e0;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10e0;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
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 ((`test`.`t1`.`a` = 1.10e0) and (<cache>(length(1.100)) <> rand()))
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -2078,3 +2078,72 @@ DROP TABLE t1,t2;
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
#
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
a
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
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 ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.1)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
a
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
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 ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.10)) <> rand()))
DROP TABLE t1;
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
a
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
# Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
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 ((`test`.`t1`.`a` = 1.10) and (<cache>(length(1.100)) <> rand()))
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -263,3 +263,55 @@ DROP TABLE t1;
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-8729 Wrong result for SELECT..WHERE HEX(enum_column)='61' AND enum_column='a '
#
CREATE TABLE t1 (a SET('a','A') CHARACTER SET latin1 COLLATE latin1_bin);
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a ';
a
a
SELECT * FROM t1 WHERE HEX(a)='61';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
a
a
# Can't propagate the equality into HEX(a), because binary collations still ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='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 ((`test`.`t1`.`a` = 'a ') and (hex(`test`.`t1`.`a`) = '61'))
DROP TABLE t1;
CREATE TABLE t1 (a SET('a','a ') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('a'),('a ');
SELECT * FROM t1 WHERE a='a ';
a
a
SELECT * FROM t1 WHERE HEX(a)='61';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
a
a
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
a
# Ok to propagate the equality into HEX(a), because "CHARACTER SET BINARY" does not ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='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 (`test`.`t1`.`a` = 'a')
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -393,3 +393,152 @@ SET timestamp=DEFAULT;
# #
# End of 10.0 tests # End of 10.0 tests
# #
#
# Start of 10.1 tests
#
#
# MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
#
# Trailing garbage in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
00:00:00
00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00x';
a
00:00:00
Warnings:
Warning 1292 Truncated incorrect time value: '00:00:00x'
Warning 1292 Truncated incorrect time value: '00:00:00x'
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00x';
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:
Warning 1292 Truncated incorrect time value: '00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '00:00:00x')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00x';
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:
Warning 1292 Truncated incorrect time value: '00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '00:00:00x') and (<cache>(length(TIME'00:00:00')) = (30 + rand())))
DROP TABLE t1;
# Trailing fractional digits in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
00:00:00
00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00.000000';
a
00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00.000000';
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 (`test`.`t1`.`a` = '00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00.000000';
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 ((`test`.`t1`.`a` = '00:00:00.000000') and (<cache>(length(TIME'00:00:00')) = (30 + rand())))
DROP TABLE t1;
# Trailing fractional digits in temporal literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
00:00:00
00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
a
00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
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 (`test`.`t1`.`a` = TIME'00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
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 ((`test`.`t1`.`a` = TIME'00:00:00.000000') and (<cache>(length(TIME'00:00:00')) = (30 + rand())))
DROP TABLE t1;
# Trailing fractional digits in temporal literals, same precision
CREATE TABLE t1 (a TIME(6));
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
a
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where 0
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
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 ((`test`.`t1`.`a` = TIME'00:00:00.000000') and (<cache>(length(TIME'00:00:00.000000')) = (30 + rand())))
DROP TABLE t1;
# Leading spaces in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
00:00:00
00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=' 00:00:00';
a
00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 00:00:00')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 00:00:00') and (<cache>(length(TIME'00:00:00')) = (30 + rand())))
DROP TABLE t1;
# Numeric format in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
a
00:00:00
00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='000000';
a
00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='000000';
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 (`test`.`t1`.`a` = '000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='000000';
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 ((`test`.`t1`.`a` = '000000') and (<cache>(length(TIME'00:00:00')) = (30 + rand())))
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -800,5 +800,145 @@ DROP TABLE t1;
# End of MDEV-8373 Zero date can be inserted in strict no-zero mode through CREATE TABLE AS SELECT timestamp_field # End of MDEV-8373 Zero date can be inserted in strict no-zero mode through CREATE TABLE AS SELECT timestamp_field
# #
# #
# MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
#
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a='2001-01-01 00:00:00x';
a
2001-01-01 00:00:00
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
SELECT * FROM t1 WHERE LENGTH(a) != 20;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
a
2001-01-01 00:00:00
Warnings:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a) != 20 AND a='2001-01-01 00:00:00x';
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:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = '2001-01-01 00:00:00x')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=30+RAND() AND a='2001-01-01 00:00:00x';
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:
Warning 1292 Truncated incorrect datetime value: '2001-01-01 00:00:00x'
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = '2001-01-01 00:00:00x') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) <> (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 2001-01-01 00:00:00';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = ' 2001-01-01 00:00:00')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19+RAND() AND a=' 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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' 2001-01-01 00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (19 + rand())))
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' garbage ';
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:
Warning 1292 Incorrect datetime value: ' garbage '
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = ' garbage ') and (length(`test`.`t1`.`a`) = (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (30 + rand())))
DROP TABLE t1;
CREATE TABLE t1 (a TIMESTAMP(6));;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00.000000'),('2001-01-01 00:00:01.000000');
SELECT * FROM t1 WHERE a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00.000000
SELECT * FROM t1 WHERE LENGTH(a)=26;
a
2001-01-01 00:00:00.000000
2001-01-01 00:00:01.000000
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
a
2001-01-01 00:00:00.000000
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=26 AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 (`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIMESTAMP'2001-01-01 00:00:00.000000';
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 ((`test`.`t1`.`a` = TIMESTAMP'2001-01-01 00:00:00.000000') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00.000000')) = (40 + rand())))
DROP TABLE t1;
SET timestamp=UNIX_TIMESTAMP('2001-01-01 10:20:30');
CREATE TABLE t1 (a TIMESTAMP);;
INSERT INTO t1 VALUES ('2001-01-01 00:00:00'),('2001-01-01 00:00:01');
SELECT * FROM t1 WHERE a=TIME'00:00:00';
a
2001-01-01 00:00:00
SELECT * FROM t1 WHERE LENGTH(a)=19;
a
2001-01-01 00:00:00
2001-01-01 00:00:01
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'00:00:00';
a
2001-01-01 00:00:00
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=19 AND a=TIME'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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` = TIME'00:00:00')
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=40+RAND() AND a=TIME'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 2 100.00 Using where
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` = TIME'00:00:00') and (<cache>(length(TIMESTAMP'2001-01-01 00:00:00')) = (40 + rand())))
DROP TABLE t1;
#
# End of 10.1 tests # End of 10.1 tests
# #

View File

@@ -4430,36 +4430,58 @@ CREATE TABLE t1 (a varchar(10), KEY (a)) ;
INSERT INTO t1 VALUES INSERT INTO t1 VALUES
('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM'); ('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM');
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
# t1 and v1 should return the same result set
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
a a
KK KK
MM MM
ZZ ZZ
ZZ ZZ
Warnings: SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
Warning 1292 Truncated incorrect DOUBLE value: 'VV' a
KK
MM
ZZ
ZZ
# t1 and v1 should propagate constants in the same way
EXPLAIN EXTENDED EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings: Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'VV' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` > 'JJ') or ((`test`.`t1`.`a` = 'VV') and (`test`.`t1`.`a` <> 0)))
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ') EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` > 'JJ') or ((`test`.`t1`.`a` = 'VV') and (`test`.`t1`.`a` <> 0)))
# t1 and v1 should return the same result set
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
a a
KK KK
MM MM
ZZ ZZ
ZZ ZZ
Warnings: SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV';
Warning 1292 Truncated incorrect DOUBLE value: 'VV' a
KK
MM
ZZ
ZZ
# t1 and v1 should propagate constants in the same way
EXPLAIN EXTENDED EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index 1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings: Warnings:
Warning 1292 Truncated incorrect DOUBLE value: 'VV' Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` > 'JJ') or ((`test`.`t1`.`a` = 'VV') and (`test`.`t1`.`a` <> 0)))
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where (`test`.`t1`.`a` > 'JJ') EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV';
id select_type table type possible_keys key key_len ref rows filtered Extra
1 SIMPLE t1 range a a 13 NULL 4 100.00 Using where; Using index
Warnings:
Note 1003 select `test`.`t1`.`a` AS `a` from `test`.`t1` where ((`test`.`t1`.`a` > 'JJ') or ((`test`.`t1`.`a` = 'VV') and (`test`.`t1`.`a` <> 0)))
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1; DROP TABLE t1;
# #
@@ -5571,3 +5593,66 @@ drop view v3;
# -- End of 10.0 tests. # -- End of 10.0 tests.
# ----------------------------------------------------------------- # -----------------------------------------------------------------
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
#
# Start of 10.1 tests
#
#
# MDEV-8747 Wrong result for SELECT..WHERE derived_table_column='a' AND derived_table_column<>_latin1'A' COLLATE latin1_bin
#
CREATE TABLE t1 (a varchar(10) character set cp1251 collate cp1251_ukrainian_ci, KEY (a)) ;
INSERT INTO t1 VALUES ('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM'),('`1');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a <> 0 AND a = ' 1';
a
SELECT * FROM v1 WHERE a <> 0 AND a = ' 1';
a
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a='5' AND a<2;
a
5
SELECT * FROM v1 WHERE a='5' AND a<2;
a
5
DROP VIEW v1;
DROP TABLE t1;
#
# MDEV-8749 Wrong result for SELECT..WHERE derived_table_enum_column='number' AND derived_table_enum_column OP number2
#
CREATE TABLE t1 (a varchar(10) character set cp1251 collate cp1251_ukrainian_ci, KEY (a));
INSERT INTO t1 VALUES ('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM'),('`1');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a <> 0 AND a = ' 1';
a
SELECT * FROM v1 WHERE a <> 0 AND a = ' 1';
a
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a='5' AND a<2;
a
5
SELECT * FROM v1 WHERE a='5' AND a<2;
a
5
DROP VIEW v1;
DROP TABLE t1;
#
# MDEV-8742 Wrong result for SELECT..WHERE view_latin1_swedish_ci_field='a' COLLATE latin1_bin
#
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
INSERT INTO t1 VALUES ('a'),('A');
CREATE VIEW v1 AS SELECT * FROM t1 WHERE a='a';
SELECT * FROM v1 WHERE a=_latin1'a' COLLATE latin1_bin;
a
a
DROP VIEW v1;
DROP TABLE t1;
#
# End of 10.1 tests
#

View File

@@ -3,6 +3,7 @@ call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1
call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file."); call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file.");
call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem.");
call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*");
call mtr.add_suppression("Couldn't load plugins from 'file_key_management*");
CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4; CREATE TABLE t1 (pk INT PRIMARY KEY, f VARCHAR(8)) ENGINE=InnoDB ENCRYPTION_KEY_ID=4;
INSERT INTO t1 VALUES (1,'foo'),(2,'bar'); INSERT INTO t1 VALUES (1,'foo'),(2,'bar');
select * from t1; select * from t1;

View File

@@ -12,6 +12,8 @@ call mtr.add_suppression("InnoDB: However key management plugin or used key_id 1
call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file."); call mtr.add_suppression("InnoDB: Marking tablespace as missing. You may drop this table or install correct key management plugin and key file.");
call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem."); call mtr.add_suppression(".*InnoDB: Cannot open table test/.* from the internal data dictionary of InnoDB though the .frm file for the table exists. See .* for how you can resolve the problem.");
call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*"); call mtr.add_suppression("InnoDB: .ibd file is missing for table test/.*");
# Suppression for builds where file_key_management plugin is linked statically
call mtr.add_suppression("Couldn't load plugins from 'file_key_management*");
--exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect --exec echo "wait" > $MYSQLTEST_VARDIR/tmp/mysqld.1.expect
--shutdown_server --shutdown_server

View File

@@ -68,7 +68,8 @@ a
SELECT FOUND_ROWS(); SELECT FOUND_ROWS();
FOUND_ROWS() FOUND_ROWS()
3 3
SET GLOBAL query_cache_size = 1024*1024; SET GLOBAL query_cache_type = ON;
SET query_cache_type = ON;
SELECT SQL_CACHE * FROM t1, t2; SELECT SQL_CACHE * FROM t1, t2;
a b a b a b a b
1 z 1 z 1 z 1 z
@@ -89,7 +90,7 @@ a b a b
200 bar 100 foobar 200 bar 100 foobar
200 bar 200 bar 200 bar 200 bar
200 bar 200 bar 200 bar 200 bar
SET GLOBAL query_cache_size = 0; SET GLOBAL query_cache_type = DEFAULT;
SELECT a+10 AS field1, CONCAT(b,':',b) AS field2 FROM t1 SELECT a+10 AS field1, CONCAT(b,':',b) AS field2 FROM t1
WHERE b > 'b' AND a IS NOT NULL WHERE b > 'b' AND a IS NOT NULL
GROUP BY 2 DESC, field1 ASC GROUP BY 2 DESC, field1 ASC

View File

@@ -45,11 +45,11 @@ SELECT SQL_BIG_RESULT SQL_CALC_FOUND_ROWS DISTINCT(t2.a)
FROM t1 t1_1, t2, t1 t1_2; FROM t1 t1_1, t2, t1 t1_2;
SELECT FOUND_ROWS(); SELECT FOUND_ROWS();
let $query_cache = `SELECT @@query_cache_size`; SET GLOBAL query_cache_type = ON;
SET GLOBAL query_cache_size = 1024*1024; SET query_cache_type = ON;
--sorted_result --sorted_result
SELECT SQL_CACHE * FROM t1, t2; SELECT SQL_CACHE * FROM t1, t2;
eval SET GLOBAL query_cache_size = $query_cache; SET GLOBAL query_cache_type = DEFAULT;
# Combination of main clauses # Combination of main clauses

View File

@@ -193,3 +193,75 @@ insert t1 values ('00:00:00'),('00:01:00');
select case t1.f1 when '00:00:00' then 1 end from t1; select case t1.f1 when '00:00:00' then 1 end from t1;
drop table t1; drop table t1;
--echo #
--echo # Start of 10.1 test
--echo #
--echo #
--echo # MDEV-8752 Wrong result for SELECT..WHERE CASE enum_field WHEN 1 THEN 1 ELSE 0 END AND a='5'
--echo #
CREATE TABLE t1 (a ENUM('5','6') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM t1 WHERE a='5';
SELECT * FROM t1 WHERE a=1;
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END AND a='5';
--echo # Multiple comparison types in CASE, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 1 THEN 1 ELSE 0 END AND a='5';
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('a','b','100'));
INSERT INTO t1 VALUES ('a'),('b'),('100');
SELECT * FROM t1 WHERE a='a';
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END AND a='a';
--echo # String comparison in CASE and in the equality, ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 'a' THEN 1 ELSE 0 END AND a='a';
SELECT * FROM t1 WHERE a=3;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a=3;
--echo # Integer comparison in CASE and in the equality, not ok to propagate
--echo # ENUM does not support this type of propagation yet.
--echo # This can change in the future. See MDEV-8748.
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a=3;
SELECT * FROM t1 WHERE a=3;
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END AND a=3;
--echo # String comparison in CASE, integer comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN '100' THEN 1 ELSE 0 END AND a=3;
SELECT * FROM t1 WHERE a='100';
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a='100';
--echo # Integer comparison in CASE, string comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 ELSE 0 END AND a='100';
SELECT * FROM t1 WHERE a='100';
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a='100';
--echo # Multiple type comparison in CASE, string comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a='100';
SELECT * FROM t1 WHERE a=3;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END;
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a=3;
--echo # Multiple type comparison in CASE, integer comparison in the equality, not Ok to propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE CASE a WHEN 3 THEN 1 WHEN '100' THEN 1 ELSE 0 END AND a=3;
DROP TABLE t1;
--echo #
--echo # End of MDEV-8752
--echo #
--echo #
--echo # End of 10.1 test
--echo #

View File

@@ -539,3 +539,37 @@ where coalesce(message,0) <> 0;
drop table t1,t2; drop table t1,t2;
set optimizer_switch=@save_derived_optimizer_switch; set optimizer_switch=@save_derived_optimizer_switch;
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8747 Wrong result for SELECT..WHERE derived_table_column='a' AND derived_table_column<>_latin1'A' COLLATE latin1_bin
--echo #
CREATE TABLE t1 (a VARCHAR(10));
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a' AND a <> _latin1'A' COLLATE latin1_bin;
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='a' AND a <> _latin1'A' COLLATE latin1_bin;
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5';
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a=1;
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5' AND a=1;
DROP TABLE t1;
--echo #
--echo # MDEV-8749 Wrong result for SELECT..WHERE derived_table_enum_column='number' AND derived_table_enum_column OP number2
--echo #
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5';
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a=1;
SELECT * FROM (SELECT * FROM t1) AS table1 WHERE a='5' AND a=1;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -403,6 +403,55 @@ EXPLAIN EXTENDED SELECT * FROM t1 WHERE a='2001-01-01' AND a IN ('2001-01-01','2
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
--echo #
# Trailing garbage in string literals
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE a='2001-01-01x';
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031';
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031' AND a='2001-01-01x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE HEX(a)!='323030312D30312D3031' AND a='2001-01-01x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE HEX(a)!=CONCAT('xx',RAND()) AND a='2001-01-01x';
DROP TABLE t1;
# Leading spaces in string literals
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-02');
SELECT * FROM t1 WHERE LENGTH(a)=11;
SELECT * FROM t1 WHERE LENGTH(a)=11 AND a=' 2001-01-01';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11 AND a=' 2001-01-01';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' 2001-01-01';
# This should not propagate
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=11+RAND() AND a=' garbage ';
DROP TABLE t1;
# Numeric format in string literals
CREATE TABLE t1 (a DATE);
INSERT INTO t1 VALUES ('2001-01-01'),('2001-01-01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='20010101';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='20010101';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8+RAND() AND a='20010101';
DROP TABLE t1;
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@@ -649,6 +649,12 @@ SELECT CAST(CAST(TIMESTAMP'0000-00-00 00:00:00.000001' AS TIME(6)) AS DATETIME(6
SET old_mode=DEFAULT; SET old_mode=DEFAULT;
SET sql_mode=DEFAULT; SET sql_mode=DEFAULT;
--echo #
--echo # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
--echo #
--let $TYPE= DATETIME
--source include/equal_fields_propagation_datetime.inc
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@@ -357,3 +357,34 @@ DROP TABLE t1;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8729 Wrong result for SELECT..WHERE HEX(enum_column)='61' AND enum_column='a '
--echo #
CREATE TABLE t1 (a ENUM('a','A') CHARACTER SET latin1 COLLATE latin1_bin);
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a ';
SELECT * FROM t1 WHERE HEX(a)='61';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
--echo # Can't propagate the equality into HEX(a), because binary collations still ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('a','a ') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('a'),('a ');
SELECT * FROM t1 WHERE a='a ';
SELECT * FROM t1 WHERE HEX(a)='61';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
--echo # Ok to propagate the equality into HEX(a), because "CHARACTER SET BINARY" does not ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests

View File

@@ -385,3 +385,67 @@ DROP TABLE t1,t2;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # MDEV-8704 Wrong result for SELECT..WHERE LENGTH(double_column)!=6 AND double_column=100e0
--echo #
# The original test case from the bug report
CREATE TABLE t1 (a DOUBLE(9,2));
INSERT INTO t1 VALUES (100),(110);
SELECT * FROM t1 WHERE LENGTH(a)!=6;
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
DROP TABLE t1;
# DOUBLE with no specific precision
CREATE TABLE t1 (a DOUBLE);
INSERT INTO t1 VALUES (100),(110);
SELECT * FROM t1 WHERE LENGTH(a)!=6;
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=6 AND a=100e0;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=100e0;
DROP TABLE t1;
# The constant scale is bigger than the field scale
CREATE TABLE t1 (a DOUBLE(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10e0;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10e0;
--echo # Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
DROP TABLE t1;
# The constant scale is equal to the field scale
CREATE TABLE t1 (a DOUBLE(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10e0;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10e0;
--echo # Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
DROP TABLE t1;
# The constant scale is smaller than the field scale
CREATE TABLE t1 (a DOUBLE(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10e0;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10e0;
--echo # Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=RAND() AND a=1.10e0;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -1622,3 +1622,52 @@ DROP TABLE t1,t2;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8703 Wrong result for SELECT..WHERE LENGTH(decimal_10_1_column)!=3 AND decimal_10_1_column=1.10
--echo #
# The constant scale is bigger than the field scale
CREATE TABLE t1 (a DECIMAL(10,1));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=3;
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=3 AND a=1.10;
--echo # Notice 1.1 instead of 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
# The constant scale is equal to the field scale
CREATE TABLE t1 (a DECIMAL(10,2));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=4;
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=4 AND a=1.10;
--echo # Notice 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
# The constant scale is smaller than the field scale
CREATE TABLE t1 (a DECIMAL(10,3));
INSERT INTO t1 VALUES (1.1),(1.2),(1.3);
SELECT * FROM t1 WHERE LENGTH(a)!=5;
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=5 AND a=1.10;
--echo # Notice 1.100 rather than 1.10 in the final WHERE condition
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)!=rand() AND a=1.10;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -185,3 +185,35 @@ DROP TABLE t1;
--echo # --echo #
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8729 Wrong result for SELECT..WHERE HEX(enum_column)='61' AND enum_column='a '
--echo #
CREATE TABLE t1 (a SET('a','A') CHARACTER SET latin1 COLLATE latin1_bin);
INSERT INTO t1 VALUES ('a'),('A');
SELECT * FROM t1 WHERE a='a ';
SELECT * FROM t1 WHERE HEX(a)='61';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
--echo # Can't propagate the equality into HEX(a), because binary collations still ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
DROP TABLE t1;
CREATE TABLE t1 (a SET('a','a ') CHARACTER SET BINARY);
INSERT INTO t1 VALUES ('a'),('a ');
SELECT * FROM t1 WHERE a='a ';
SELECT * FROM t1 WHERE HEX(a)='61';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
--echo # Ok to propagate the equality into HEX(a), because "CHARACTER SET BINARY" does not ignore trailing spaces
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a';
EXPLAIN EXTENDED SELECT * FROM t1 WHERE HEX(a)='61' AND a='a ';
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -276,3 +276,82 @@ SET timestamp=DEFAULT;
--echo # End of 10.0 tests --echo # End of 10.0 tests
--echo # --echo #
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
--echo #
--echo # Trailing garbage in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00x';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00x';
DROP TABLE t1;
--echo # Trailing fractional digits in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='00:00:00.000000';
DROP TABLE t1;
--echo # Trailing fractional digits in temporal literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
DROP TABLE t1;
--echo # Trailing fractional digits in temporal literals, same precision
CREATE TABLE t1 (a TIME(6));
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=TIME'00:00:00.000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=TIME'00:00:00.000000';
DROP TABLE t1;
--echo # Leading spaces in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=' 00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a=' 00:00:00';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a=' 00:00:00';
DROP TABLE t1;
--echo # Numeric format in string literals
CREATE TABLE t1 (a TIME);
INSERT INTO t1 VALUES ('00:00:00'),('00:00:01');
SELECT * FROM t1 WHERE LENGTH(a)=8;
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=8 AND a='000000';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE LENGTH(a)=30+RAND() AND a='000000';
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -538,6 +538,12 @@ let type=TIMESTAMP;
let defval='0000-00-00 00:00:00'; let defval='0000-00-00 00:00:00';
--source include/type_temporal_zero_default.inc --source include/type_temporal_zero_default.inc
--echo #
--echo # MDEV-8699 Wrong result for SELECT..WHERE HEX(date_column)!='323030312D30312D3031' AND date_column='2001-01-01x'
--echo #
--let $TYPE=TIMESTAMP
--source include/equal_fields_propagation_datetime.inc
--echo # --echo #
--echo # End of 10.1 tests --echo # End of 10.1 tests
--echo # --echo #

View File

@@ -4318,13 +4318,23 @@ INSERT INTO t1 VALUES
CREATE VIEW v1 AS SELECT * FROM t1; CREATE VIEW v1 AS SELECT * FROM t1;
--echo # t1 and v1 should return the same result set
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
--echo # t1 and v1 should propagate constants in the same way
EXPLAIN EXTENDED EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a > 'JJ' OR a <> 0 AND a = 'VV';
--echo # t1 and v1 should return the same result set
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV';
--echo # t1 and v1 should propagate constants in the same way
EXPLAIN EXTENDED EXPLAIN EXTENDED
SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV'; SELECT * FROM v1 WHERE a > 'JJ' OR a AND a = 'VV';
EXPLAIN EXTENDED
SELECT * FROM t1 WHERE a > 'JJ' OR a AND a = 'VV';
DROP VIEW v1; DROP VIEW v1;
DROP TABLE t1; DROP TABLE t1;
@@ -5450,3 +5460,60 @@ drop view v3;
--echo # -- End of 10.0 tests. --echo # -- End of 10.0 tests.
--echo # ----------------------------------------------------------------- --echo # -----------------------------------------------------------------
SET optimizer_switch=@save_optimizer_switch; SET optimizer_switch=@save_optimizer_switch;
--echo #
--echo # Start of 10.1 tests
--echo #
--echo #
--echo # MDEV-8747 Wrong result for SELECT..WHERE derived_table_column='a' AND derived_table_column<>_latin1'A' COLLATE latin1_bin
--echo #
CREATE TABLE t1 (a varchar(10) character set cp1251 collate cp1251_ukrainian_ci, KEY (a)) ;
INSERT INTO t1 VALUES ('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM'),('`1');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a <> 0 AND a = ' 1';
SELECT * FROM v1 WHERE a <> 0 AND a = ' 1';
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a='5' AND a<2;
SELECT * FROM v1 WHERE a='5' AND a<2;
DROP VIEW v1;
DROP TABLE t1;
--echo #
--echo # MDEV-8749 Wrong result for SELECT..WHERE derived_table_enum_column='number' AND derived_table_enum_column OP number2
--echo #
CREATE TABLE t1 (a varchar(10) character set cp1251 collate cp1251_ukrainian_ci, KEY (a));
INSERT INTO t1 VALUES ('DD'), ('ZZ'), ('ZZ'), ('KK'), ('FF'), ('HH'),('MM'),('`1');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a <> 0 AND a = ' 1';
SELECT * FROM v1 WHERE a <> 0 AND a = ' 1';
DROP VIEW v1;
DROP TABLE t1;
CREATE TABLE t1 (a ENUM('5','6'));
INSERT INTO t1 VALUES ('5'),('6');
CREATE VIEW v1 AS SELECT * FROM t1;
SELECT * FROM t1 WHERE a='5' AND a<2;
SELECT * FROM v1 WHERE a='5' AND a<2;
DROP VIEW v1;
DROP TABLE t1;
--echo #
--echo # MDEV-8742 Wrong result for SELECT..WHERE view_latin1_swedish_ci_field='a' COLLATE latin1_bin
--echo #
CREATE TABLE t1 (a VARCHAR(10) CHARACTER SET latin1);
INSERT INTO t1 VALUES ('a'),('A');
CREATE VIEW v1 AS SELECT * FROM t1 WHERE a='a';
SELECT * FROM v1 WHERE a=_latin1'a' COLLATE latin1_bin;
DROP VIEW v1;
DROP TABLE t1;
--echo #
--echo # End of 10.1 tests
--echo #

View File

@@ -1261,6 +1261,61 @@ bool Field::test_if_equality_guarantees_uniqueness(const Item *item) const
} }
/**
Check whether a field item can be substituted for an equal item
@details
The function checks whether a substitution of a field item for
an equal item is valid.
@param arg *arg != NULL <-> the field is in the context
where substitution for an equal item is valid
@note
The following statement is not always true:
@n
x=y => F(x)=F(x/y).
@n
This means substitution of an item for an equal item not always
yields an equavalent condition. Here's an example:
@code
'a'='a '
(LENGTH('a')=1) != (LENGTH('a ')=2)
@endcode
Such a substitution is surely valid if either the substituted
field is not of a STRING type or if it is an argument of
a comparison predicate.
@retval
TRUE substitution is valid
@retval
FALSE otherwise
*/
bool Field::can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal)
{
DBUG_ASSERT(item_equal->compare_type() != STRING_RESULT);
DBUG_ASSERT(cmp_type() != STRING_RESULT);
switch (ctx.subst_constraint()) {
case ANY_SUBST:
/*
Disable const propagation for items used in different comparison contexts.
This must be done because, for example, Item_hex_string->val_int() is not
the same as (Item_hex_string->val_str() in BINARY column)->val_int().
We cannot simply disable the replacement in a particular context (
e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since
Items don't know the context they are in and there are functions like
IF (<hex_string>, 'yes', 'no').
*/
return ctx.compare_type() == item_equal->compare_type();
case IDENTITY_SUBST:
return true;
}
return false;
}
/* /*
This handles all numeric and BIT data types. This handles all numeric and BIT data types.
*/ */
@@ -1303,7 +1358,7 @@ Field_num::Field_num(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
} }
void Field_num::prepend_zeros(String *value) void Field_num::prepend_zeros(String *value) const
{ {
int diff; int diff;
if ((diff= (int) (field_length - value->length())) > 0) if ((diff= (int) (field_length - value->length())) > 0)
@@ -1317,6 +1372,52 @@ void Field_num::prepend_zeros(String *value)
} }
} }
/**
Convert a numeric value to a zero-filled string
@param[in] thd current thread
@param[in] item the item to convert
This function converts a numeric value to a string. In this conversion
the zero-fill flag of the field is taken into account.
This is required so the resulting string value can be used instead of
the field reference when propagating equalities.
*/
Item *Field_num::convert_zerofill_number_to_string(THD *thd, Item *item) const
{
char buff[MAX_FIELD_WIDTH],*pos;
String tmp(buff,sizeof(buff),Field_num::charset()), *res;
res= item->val_str(&tmp);
if (item->is_null())
return new (thd->mem_root) Item_null(thd);
else
{
prepend_zeros(res);
pos= (char *) sql_strmake (res->ptr(), res->length());
return new (thd->mem_root) Item_string(thd, pos, res->length(), Field_num::charset());
}
}
Item *Field_num::get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
return convert_zerofill_number_to_string(thd, const_item);
case ANY_SUBST:
break;
}
DBUG_ASSERT(const_item->const_item());
DBUG_ASSERT(ctx.compare_type() != STRING_RESULT);
return field_item;
}
/** /**
Test if given number is a int. Test if given number is a int.
@@ -1884,6 +1985,23 @@ bool Field_str::test_if_equality_guarantees_uniqueness(const Item *item) const
} }
bool Field_str::can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal)
{
DBUG_ASSERT(item_equal->compare_type() == STRING_RESULT);
switch (ctx.subst_constraint()) {
case ANY_SUBST:
return ctx.compare_type() == item_equal->compare_type() &&
(ctx.compare_type() != STRING_RESULT ||
ctx.compare_collation() == item_equal->compare_collation());
case IDENTITY_SUBST:
return ((charset()->state & MY_CS_BINSORT) &&
(charset()->state & MY_CS_NOPAD));
}
return false;
}
void Field_num::make_field(Send_field *field) void Field_num::make_field(Send_field *field)
{ {
Field::make_field(field); Field::make_field(field);
@@ -3172,6 +3290,38 @@ Field_new_decimal::unpack(uchar* to, const uchar *from, const uchar *from_end,
return from+len; return from+len;
} }
Item *Field_new_decimal::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
if (flags & ZEROFILL_FLAG)
return Field_num::get_equal_zerofill_const_item(thd, ctx,
field_item, const_item);
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if (const_item->field_type() != MYSQL_TYPE_NEWDECIMAL ||
const_item->decimal_scale() != decimals())
{
my_decimal *val, val_buffer, val_buffer2;
if (!(val= const_item->val_decimal(&val_buffer)))
{
DBUG_ASSERT(0);
return const_item;
}
/* Truncate or extend the decimal value to the scale of the field */
my_decimal_round(E_DEC_FATAL_ERROR, val, decimals(), true, &val_buffer2);
return new (thd->mem_root) Item_decimal(thd, field_name, &val_buffer2,
decimals(), field_length);
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec_arg) int Field_num::store_time_dec(MYSQL_TIME *ltime, uint dec_arg)
{ {
longlong v= TIME_to_ulonglong(ltime); longlong v= TIME_to_ulonglong(ltime);
@@ -4489,6 +4639,28 @@ bool Field_real::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
} }
Item *Field_real::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
if (flags & ZEROFILL_FLAG)
return Field_num::get_equal_zerofill_const_item(thd, ctx,
field_item, const_item);
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if (const_item->decimal_scale() != Field_real::decimals())
{
double val= const_item->val_real();
return new (thd->mem_root) Item_float(thd, val, Field_real::decimals());
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
String *Field_double::val_str(String *val_buffer, String *Field_double::val_str(String *val_buffer,
String *val_ptr __attribute__((unused))) String *val_ptr __attribute__((unused)))
{ {
@@ -5343,6 +5515,32 @@ bool Field_temporal::can_optimize_group_min_max(const Item_bool_func *cond,
} }
Item *Field_temporal::get_equal_const_item_datetime(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if ((const_item->field_type() != MYSQL_TYPE_DATETIME &&
const_item->field_type() != MYSQL_TYPE_TIMESTAMP) ||
const_item->decimals != decimals())
{
MYSQL_TIME ltime;
if (const_item->field_type() == MYSQL_TYPE_TIME ?
const_item->get_date_with_conversion(&ltime, 0) :
const_item->get_date(&ltime, 0))
return NULL;
return new (thd->mem_root) Item_datetime_literal(thd, &ltime,
decimals());
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
/**************************************************************************** /****************************************************************************
** time type ** time type
** In string context: HH:MM:SS ** In string context: HH:MM:SS
@@ -5635,6 +5833,29 @@ int Field_time::store_decimal(const my_decimal *d)
return store_TIME_with_warning(&ltime, &str, was_cut, have_smth_to_conv); return store_TIME_with_warning(&ltime, &str, was_cut, have_smth_to_conv);
} }
Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if (const_item->field_type() != MYSQL_TYPE_TIME ||
const_item->decimals != decimals())
{
MYSQL_TIME ltime;
if (const_item->get_date(&ltime, TIME_TIME_ONLY))
return NULL;
return new (thd->mem_root) Item_time_literal(thd, &ltime, decimals());
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
uint32 Field_time_hires::pack_length() const uint32 Field_time_hires::pack_length() const
{ {
return time_hires_bytes[dec]; return time_hires_bytes[dec];
@@ -6067,6 +6288,29 @@ void Field_newdate::sql_type(String &res) const
} }
Item *Field_newdate::get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item)
{
switch (ctx.subst_constraint()) {
case IDENTITY_SUBST:
if (const_item->field_type() != MYSQL_TYPE_DATE)
{
MYSQL_TIME ltime;
if (const_item->field_type() == MYSQL_TYPE_TIME ?
const_item->get_date_with_conversion(&ltime, 0) :
const_item->get_date(&ltime, 0))
return NULL;
return new (thd->mem_root) Item_date_literal(thd, &ltime);
}
break;
case ANY_SUBST:
break;
}
return const_item;
}
/**************************************************************************** /****************************************************************************
** datetime type ** datetime type
** In string context: YYYY-MM-DD HH:MM:DD ** In string context: YYYY-MM-DD HH:MM:DD
@@ -8616,7 +8860,6 @@ bool Field_enum::can_optimize_keypart_ref(const Item_bool_func *cond,
return true; return true;
case STRING_RESULT: case STRING_RESULT:
return charset() == cond->compare_collation(); return charset() == cond->compare_collation();
case IMPOSSIBLE_RESULT:
case ROW_RESULT: case ROW_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
break; break;

View File

@@ -41,6 +41,7 @@ class Column_statistics;
class Column_statistics_collected; class Column_statistics_collected;
class Item_func; class Item_func;
class Item_bool_func; class Item_bool_func;
class Item_equal;
enum enum_check_fields enum enum_check_fields
{ {
@@ -50,6 +51,77 @@ enum enum_check_fields
}; };
/*
Common declarations for Field and Item
*/
class Value_source
{
public:
/*
The enumeration Subst_constraint is currently used only in implementations
of the virtual function subst_argument_checker.
*/
enum Subst_constraint
{
ANY_SUBST, /* Any substitution for a field is allowed */
IDENTITY_SUBST /* Substitution for a field is allowed if any two
different values of the field type are not equal */
};
/*
Item context attributes.
Comparison functions pass their attributes to propagate_equal_fields().
For exmple, for string comparison, the collation of the comparison
operation is important inside propagate_equal_fields().
*/
class Context
{
/*
Which type of propagation is allowed:
- ANY_SUBST (loose equality, according to the collation), or
- IDENTITY_SUBST (strict binary equality).
*/
Subst_constraint m_subst_constraint;
/*
Comparison type.
Impostant only when ANY_SUBSTS.
*/
Item_result m_compare_type;
/*
Collation of the comparison operation.
Important only when ANY_SUBST.
*/
CHARSET_INFO *m_compare_collation;
public:
Context(Subst_constraint subst, Item_result type, CHARSET_INFO *cs)
:m_subst_constraint(subst),
m_compare_type(type),
m_compare_collation(cs) { }
Subst_constraint subst_constraint() const { return m_subst_constraint; }
Item_result compare_type() const
{
DBUG_ASSERT(m_subst_constraint == ANY_SUBST);
return m_compare_type;
}
CHARSET_INFO *compare_collation() const
{
DBUG_ASSERT(m_subst_constraint == ANY_SUBST);
return m_compare_collation;
}
};
class Context_identity: public Context
{ // Use this to request only exact value, no invariants.
public:
Context_identity()
:Context(IDENTITY_SUBST, STRING_RESULT, &my_charset_bin) { }
};
class Context_boolean: public Context
{ // Use this when an item is [a part of] a boolean expression
public:
Context_boolean() :Context(ANY_SUBST, INT_RESULT, &my_charset_bin) { }
};
};
enum Derivation enum Derivation
{ {
DERIVATION_IGNORABLE= 6, DERIVATION_IGNORABLE= 6,
@@ -61,6 +133,7 @@ enum Derivation
DERIVATION_EXPLICIT= 0 DERIVATION_EXPLICIT= 0
}; };
#define STORAGE_TYPE_MASK 7 #define STORAGE_TYPE_MASK 7
#define COLUMN_FORMAT_MASK 7 #define COLUMN_FORMAT_MASK 7
#define COLUMN_FORMAT_SHIFT 3 #define COLUMN_FORMAT_SHIFT 3
@@ -287,7 +360,7 @@ public:
} }
}; };
class Field class Field: public Value_source
{ {
Field(const Item &); /* Prevent use of these */ Field(const Item &); /* Prevent use of these */
void operator=(Field &); void operator=(Field &);
@@ -1027,6 +1100,13 @@ public:
*/ */
virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item) virtual bool test_if_equality_guarantees_uniqueness(const Item *const_item)
const; const;
virtual bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item);
virtual Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return const_item;
}
virtual bool can_optimize_keypart_ref(const Item_bool_func *cond, virtual bool can_optimize_keypart_ref(const Item_bool_func *cond,
const Item *item) const; const Item *item) const;
virtual bool can_optimize_hash_join(const Item_bool_func *cond, virtual bool can_optimize_hash_join(const Item_bool_func *cond,
@@ -1126,6 +1206,11 @@ protected:
class Field_num :public Field { class Field_num :public Field {
protected:
Item *convert_zerofill_number_to_string(THD *thd, Item *item) const;
Item *get_equal_zerofill_const_item(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item);
public: public:
const uint8 dec; const uint8 dec;
bool zerofill,unsigned_flag; // Purify cannot handle bit fields bool zerofill,unsigned_flag; // Purify cannot handle bit fields
@@ -1137,7 +1222,14 @@ public:
enum Derivation derivation(void) const { return DERIVATION_NUMERIC; } enum Derivation derivation(void) const { return DERIVATION_NUMERIC; }
uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; } uint repertoire(void) const { return MY_REPERTOIRE_NUMERIC; }
CHARSET_INFO *charset(void) const { return &my_charset_numeric; } CHARSET_INFO *charset(void) const { return &my_charset_numeric; }
void prepend_zeros(String *value); void prepend_zeros(String *value) const;
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return (flags & ZEROFILL_FLAG) ?
get_equal_zerofill_const_item(thd, ctx, field_item, const_item) :
const_item;
}
void add_zerofill_and_unsigned(String &res) const; void add_zerofill_and_unsigned(String &res) const;
friend class Create_field; friend class Create_field;
void make_field(Send_field *); void make_field(Send_field *);
@@ -1172,6 +1264,8 @@ protected:
CHARSET_INFO *field_charset; CHARSET_INFO *field_charset;
enum Derivation field_derivation; enum Derivation field_derivation;
public: public:
bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal);
Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_str(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
const char *field_name_arg, CHARSET_INFO *charset); const char *field_name_arg, CHARSET_INFO *charset);
@@ -1269,6 +1363,8 @@ public:
my_decimal *val_decimal(my_decimal *); my_decimal *val_decimal(my_decimal *);
uint32 max_display_length() { return field_length; } uint32 max_display_length() { return field_length; }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
}; };
@@ -1354,6 +1450,8 @@ public:
uint is_equal(Create_field *new_field); uint is_equal(Create_field *new_field);
virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data); virtual const uchar *unpack(uchar* to, const uchar *from, const uchar *from_end, uint param_data);
static Field *create_from_item(MEM_ROOT *root, Item *); static Field *create_from_item(MEM_ROOT *root, Item *);
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
}; };
@@ -1690,6 +1788,10 @@ public:
class Field_temporal: public Field { class Field_temporal: public Field {
protected:
Item *get_equal_const_item_datetime(THD *thd, const Context &ctx,
Item_field *field_item,
Item *const_item);
public: public:
Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg, Field_temporal(uchar *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, utype unireg_check_arg, uchar null_bit_arg, utype unireg_check_arg,
@@ -1835,6 +1937,11 @@ public:
return unpack_int32(to, from, from_end); return unpack_int32(to, from, from_end);
} }
bool validate_value_in_record(THD *thd, const uchar *record) const; bool validate_value_in_record(THD *thd, const uchar *record) const;
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return get_equal_const_item_datetime(thd, ctx, field_item, const_item);
}
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
}; };
@@ -2023,6 +2130,8 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return Field_newdate::get_TIME(ltime, ptr, fuzzydate); } { return Field_newdate::get_TIME(ltime, ptr, fuzzydate); }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
}; };
@@ -2066,6 +2175,8 @@ public:
Field *new_key_field(MEM_ROOT *root, TABLE *new_table, Field *new_key_field(MEM_ROOT *root, TABLE *new_table,
uchar *new_ptr, uint32 length, uchar *new_ptr, uint32 length,
uchar *new_null_ptr, uint new_null_bit); uchar *new_null_ptr, uint new_null_bit);
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item);
}; };
@@ -2224,6 +2335,11 @@ public:
{ {
return unpack_int64(to, from, from_end); return unpack_int64(to, from, from_end);
} }
Item *get_equal_const_item(THD *thd, const Context &ctx,
Item_field *field_item, Item *const_item)
{
return get_equal_const_item_datetime(thd, ctx, field_item, const_item);
}
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
}; };

View File

@@ -97,7 +97,6 @@ bool Item::val_bool()
return val_real() != 0.0; return val_real() != 0.0;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; // Wrong (but safe) return 0; // Wrong (but safe)
} }
@@ -422,7 +421,6 @@ Item::Item(THD *thd):
maybe_null=null_value=with_sum_func=with_field=0; maybe_null=null_value=with_sum_func=with_field=0;
in_rollup= 0; in_rollup= 0;
with_subselect= 0; with_subselect= 0;
cmp_context= IMPOSSIBLE_RESULT;
/* Initially this item is not attached to any JOIN_TAB. */ /* Initially this item is not attached to any JOIN_TAB. */
join_tab_idx= MAX_TABLES; join_tab_idx= MAX_TABLES;
@@ -468,8 +466,7 @@ Item::Item(THD *thd, Item *item):
with_field(item->with_field), with_field(item->with_field),
fixed(item->fixed), fixed(item->fixed),
is_autogenerated_name(item->is_autogenerated_name), is_autogenerated_name(item->is_autogenerated_name),
with_subselect(item->has_subquery()), with_subselect(item->has_subquery())
cmp_context(item->cmp_context)
{ {
next= thd->free_list; // Put in free list next= thd->free_list; // Put in free list
thd->free_list= this; thd->free_list= this;
@@ -545,7 +542,6 @@ void Item::print_value(String *str)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
} }
@@ -636,7 +632,7 @@ Item_result Item::cmp_type() const
return TIME_RESULT; return TIME_RESULT;
}; };
DBUG_ASSERT(0); DBUG_ASSERT(0);
return IMPOSSIBLE_RESULT; return STRING_RESULT;
} }
/** /**
@@ -2598,7 +2594,6 @@ bool Item_field::val_bool_result()
return result_field->val_real() != 0.0; return result_field->val_real() != 0.0;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; // Shut up compiler return 0; // Shut up compiler
} }
@@ -3398,7 +3393,6 @@ bool Item_param::set_from_user_var(THD *thd, const user_var_entry *entry)
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
set_null(); set_null();
} }
@@ -4017,7 +4011,6 @@ Item_copy *Item_copy::create(THD *thd, Item *item)
return new (mem_root) Item_copy_decimal(thd, item); return new (mem_root) Item_copy_decimal(thd, item);
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT (0); DBUG_ASSERT (0);
} }
/* should not happen */ /* should not happen */
@@ -5337,79 +5330,6 @@ Item_equal *Item_field::find_item_equal(COND_EQUAL *cond_equal)
} }
/**
Check whether a field item can be substituted for an equal item
@details
The function checks whether a substitution of a field item for
an equal item is valid.
@param arg *arg != NULL <-> the field is in the context
where substitution for an equal item is valid
@note
The following statement is not always true:
@n
x=y => F(x)=F(x/y).
@n
This means substitution of an item for an equal item not always
yields an equavalent condition. Here's an example:
@code
'a'='a '
(LENGTH('a')=1) != (LENGTH('a ')=2)
@endcode
Such a substitution is surely valid if either the substituted
field is not of a STRING type or if it is an argument of
a comparison predicate.
@retval
TRUE substitution is valid
@retval
FALSE otherwise
*/
bool Item_field::can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item_equal)
{
if (cmp_context == STRING_RESULT &&
ctx.compare_collation() != item_equal->compare_collation())
return false;
return ctx.subst_constraint() == ANY_SUBST ||
field->cmp_type() != STRING_RESULT ||
((field->charset()->state & MY_CS_BINSORT) &&
(field->charset()->state & MY_CS_NOPAD));
}
/**
Convert a numeric value to a zero-filled string
@param[in,out] item the item to operate on
@param field The field that this value is equated to
This function converts a numeric value to a string. In this conversion
the zero-fill flag of the field is taken into account.
This is required so the resulting string value can be used instead of
the field reference when propagating equalities.
*/
static void convert_zerofill_number_to_string(THD *thd, Item **item, Field_num *field)
{
char buff[MAX_FIELD_WIDTH],*pos;
String tmp(buff,sizeof(buff), field->charset()), *res;
res= (*item)->val_str(&tmp);
if ((*item)->is_null())
*item= new (thd->mem_root) Item_null(thd);
else
{
field->prepend_zeros(res);
pos= (char *) sql_strmake (res->ptr(), res->length());
*item= new (thd->mem_root) Item_string(thd, pos, res->length(), field->charset());
}
}
/** /**
Set a pointer to the multiple equality the field reference belongs to Set a pointer to the multiple equality the field reference belongs to
(if any). (if any).
@@ -5438,36 +5358,38 @@ Item *Item_field::propagate_equal_fields(THD *thd,
const Context &ctx, const Context &ctx,
COND_EQUAL *arg) COND_EQUAL *arg)
{ {
if (no_const_subst) if (no_const_subst || !(item_equal= find_item_equal(arg)))
return this; return this;
item_equal= find_item_equal((COND_EQUAL *) arg); if (!field->can_be_substituted_to_equal_item(ctx, item_equal))
Item *item= 0;
if (item_equal)
{ {
if (!can_be_substituted_to_equal_item(ctx, item_equal)) item_equal= NULL;
{ return this;
item_equal= NULL;
return this;
}
item= item_equal->get_const();
} }
/* Item *item= item_equal->get_const();
Disable const propagation for items used in different comparison contexts. if (!item)
This must be done because, for example, Item_hex_string->val_int() is not
the same as (Item_hex_string->val_str() in BINARY column)->val_int().
We cannot simply disable the replacement in a particular context (
e.g. <bin_col> = <int_col> AND <bin_col> = <hex_string>) since
Items don't know the context they are in and there are functions like
IF (<hex_string>, 'yes', 'no').
*/
if (!item || !has_compatible_context(item))
item= this;
else if (field && (field->flags & ZEROFILL_FLAG) && IS_NUM(field->type()))
{ {
if (item && (cmp_context == STRING_RESULT || cmp_context == IMPOSSIBLE_RESULT)) /*
convert_zerofill_number_to_string(thd, &item, (Field_num *)field); The found Item_equal is Okey, but it does not have a constant
else item yet. Keep this->item_equal point to the found Item_equal.
item= this; */
return this;
}
if (!(item= field->get_equal_const_item(thd, ctx, this, item)))
{
/*
Could not do safe conversion from the original constant item
to a field-compatible constant item.
For example, we tried to optimize:
WHERE date_column=' garbage ' AND LENGTH(date_column)=8;
to
WHERE date_column=' garbage ' AND LENGTH(DATE'XXXX-YY-ZZ');
but failed to create a valid DATE literal from the given string literal.
Do not do constant propagation in such cases and unlink
"this" from the found Item_equal (as this equality not usefull).
*/
item_equal= NULL;
return this;
} }
return item; return item;
} }
@@ -5521,8 +5443,19 @@ Item *Item_field::replace_equal_field(THD *thd, uchar *arg)
Item *const_item2= item_equal->get_const(); Item *const_item2= item_equal->get_const();
if (const_item2) if (const_item2)
{ {
if (!has_compatible_context(const_item2)) /*
return this; Currently we don't allow to create Item_equal with compare_type()
different from its Item_field's cmp_type().
Field_xxx::test_if_equality_guarantees_uniqueness() prevent this.
Also, Item_field::propagate_equal_fields() does not allow to assign
this->item_equal to any instances of Item_equal if "this" is used
in a non-native comparison context, or with an incompatible collation.
So the fact that we have (item_equal != NULL) means that the currently
processed function (the owner of "this") uses the field in its native
comparison context, and it's safe to replace it to the constant from
item_equal.
*/
DBUG_ASSERT(cmp_type() == item_equal->compare_type());
return const_item2; return const_item2;
} }
Item_field *subst= Item_field *subst=
@@ -5588,7 +5521,6 @@ enum_field_types Item::field_type() const
case REAL_RESULT: return MYSQL_TYPE_DOUBLE; case REAL_RESULT: return MYSQL_TYPE_DOUBLE;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return MYSQL_TYPE_VARCHAR; return MYSQL_TYPE_VARCHAR;
} }
@@ -7373,7 +7305,6 @@ bool Item_ref::val_bool_result()
return result_field->val_real() != 0.0; return result_field->val_real() != 0.0;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
} }
@@ -8737,9 +8668,6 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
(Item*) new (mem_root) Item_decimal(thd, name, result, length, decimals)); (Item*) new (mem_root) Item_decimal(thd, name, result, length, decimals));
break; break;
} }
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
break;
} }
if (new_item) if (new_item)
thd->change_item_tree(ref, new_item); thd->change_item_tree(ref, new_item);
@@ -8891,9 +8819,6 @@ Item_cache* Item_cache::get_cache(THD *thd, const Item *item,
return new (mem_root) Item_cache_row(thd); return new (mem_root) Item_cache_row(thd);
case TIME_RESULT: case TIME_RESULT:
return new (mem_root) Item_cache_temporal(thd, item->field_type()); return new (mem_root) Item_cache_temporal(thd, item->field_type());
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
break;
} }
return 0; // Impossible return 0; // Impossible
} }
@@ -9527,7 +9452,6 @@ enum_field_types Item_type_holder::get_real_type(Item *item)
return MYSQL_TYPE_NEWDECIMAL; return MYSQL_TYPE_NEWDECIMAL;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return MYSQL_TYPE_VAR_STRING; return MYSQL_TYPE_VAR_STRING;
} }

View File

@@ -602,7 +602,7 @@ public:
}; };
class Item: public Type_std_attributes class Item: public Value_source, public Type_std_attributes
{ {
Item(const Item &); /* Prevent use of these */ Item(const Item &); /* Prevent use of these */
void operator=(Item &); void operator=(Item &);
@@ -693,7 +693,6 @@ public:
bool with_subselect; /* If this item is a subselect or some bool with_subselect; /* If this item is a subselect or some
of its arguments is or contains a of its arguments is or contains a
subselect */ subselect */
Item_result cmp_context; /* Comparison context */
// alloc & destruct is done as start of select using sql_alloc // alloc & destruct is done as start of select using sql_alloc
Item(THD *thd); Item(THD *thd);
/* /*
@@ -1418,47 +1417,6 @@ public:
return FALSE; return FALSE;
} }
/*
The enumeration Subst_constraint is currently used only in implementations
of the virtual function subst_argument_checker.
*/
enum Subst_constraint
{
ANY_SUBST, /* Any substitution for a field is allowed */
IDENTITY_SUBST /* Substitution for a field is allowed if any two
different values of the field type are not equal */
};
/*
Item context attributes.
Comparison functions pass their attributes to propagate_equal_fields().
For exmple, for string comparison, the collation of the comparison
operation is important inside propagate_equal_fields().
TODO: We should move Item::cmp_context to from Item to Item::Context
eventually.
*/
class Context
{
/*
Which type of propagation is allowed:
- SUBST_ANY (loose equality, according to the collation), or
- SUBST_IDENTITY (strict binary equality).
*/
Subst_constraint m_subst_constraint;
/*
Collation of the comparison operation.
Important only when SUBST_ANY.
*/
CHARSET_INFO *m_compare_collation;
public:
Context(Subst_constraint subst, CHARSET_INFO *cs)
:m_subst_constraint(subst), m_compare_collation(cs) { }
Context(Subst_constraint subst)
:m_subst_constraint(subst), m_compare_collation(&my_charset_bin) { }
Subst_constraint subst_constraint() const { return m_subst_constraint; }
CHARSET_INFO *compare_collation() const { return m_compare_collation; }
};
virtual Item* propagate_equal_fields(THD*, const Context &, COND_EQUAL *) virtual Item* propagate_equal_fields(THD*, const Context &, COND_EQUAL *)
{ {
return this; return this;
@@ -1620,18 +1578,6 @@ public:
{ {
return 0; return 0;
} }
/**
Check whether this and the given item has compatible comparison context.
Used by the equality propagation. See Item_field::propagate_equal_fields()
@return
TRUE if the context is the same
FALSE otherwise.
*/
inline bool has_compatible_context(Item *item) const
{
return cmp_context == IMPOSSIBLE_RESULT || item->cmp_context == cmp_context;
}
/** /**
Test whether an expression is expensive to compute. Used during Test whether an expression is expensive to compute. Used during
optimization to avoid computing expensive expressions during this optimization to avoid computing expensive expressions during this
@@ -2302,8 +2248,6 @@ public:
class Item_field :public Item_ident class Item_field :public Item_ident
{ {
bool can_be_substituted_to_equal_item(const Context &ctx,
const Item_equal *item);
protected: protected:
void set_field(Field *field); void set_field(Field *field);
public: public:

View File

@@ -482,9 +482,8 @@ void Item_func::convert_const_compared_to_int_field(THD *thd)
{ {
Item_field *field_item= (Item_field*) (args[field]->real_item()); Item_field *field_item= (Item_field*) (args[field]->real_item());
if ((field_item->field_type() == MYSQL_TYPE_LONGLONG || if ((field_item->field_type() == MYSQL_TYPE_LONGLONG ||
field_item->field_type() == MYSQL_TYPE_YEAR) && field_item->field_type() == MYSQL_TYPE_YEAR))
convert_const_to_int(thd, field_item, &args[!field])) convert_const_to_int(thd, field_item, &args[!field]);
args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
} }
} }
} }
@@ -499,8 +498,6 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp)
agg_arg_charsets_for_comparison(cmp->cmp_collation, args, 2)) agg_arg_charsets_for_comparison(cmp->cmp_collation, args, 2))
return true; return true;
args[0]->cmp_context= args[1]->cmp_context= item_cmp_type(args[0], args[1]);
// Convert constants when compared to int/year field // Convert constants when compared to int/year field
DBUG_ASSERT(functype() != LIKE_FUNC); DBUG_ASSERT(functype() != LIKE_FUNC);
convert_const_compared_to_int_field(thd); convert_const_compared_to_int_field(thd);
@@ -551,10 +548,8 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1; return 1;
} }
if (comparators[i].set_cmp_func_and_arg_cmp_context(owner, if (comparators[i].set_cmp_func(owner, (*a)->addr(i),
(*a)->addr(i), (*b)->addr(i), set_null))
(*b)->addr(i),
set_null))
return 1; return 1;
} }
break; break;
@@ -617,9 +612,6 @@ int Arg_comparator::set_compare_func(Item_func_or_sum *item, Item_result type)
} }
break; break;
} }
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
break;
} }
return 0; return 0;
} }
@@ -736,6 +728,7 @@ int Arg_comparator::set_cmp_func(Item_func_or_sum *owner_arg,
set_null= set_null && owner_arg; set_null= set_null && owner_arg;
a= a1; a= a1;
b= a2; b= a2;
m_compare_type= type;
if (type == STRING_RESULT && if (type == STRING_RESULT &&
(*a)->result_type() == STRING_RESULT && (*a)->result_type() == STRING_RESULT &&
@@ -2199,8 +2192,7 @@ void Item_func_between::fix_length_and_dec()
return; return;
if (agg_cmp_type(&m_compare_type, args, 3)) if (agg_cmp_type(&m_compare_type, args, 3))
return; return;
args[0]->cmp_context= args[1]->cmp_context= args[2]->cmp_context=
m_compare_type;
if (m_compare_type == STRING_RESULT && if (m_compare_type == STRING_RESULT &&
agg_arg_charsets_for_comparison(cmp_collation, args, 3)) agg_arg_charsets_for_comparison(cmp_collation, args, 3))
return; return;
@@ -2363,7 +2355,6 @@ longlong Item_func_between::val_int()
break; break;
} }
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
null_value= 1; null_value= 1;
return 0; return 0;
@@ -2422,7 +2413,6 @@ Item_func_case_abbreviation2::fix_length_and_dec2(Item **args)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
fix_char_length(char_length); fix_char_length(char_length);
@@ -2779,7 +2769,7 @@ Item_func_nullif::is_null()
Item_func_case::Item_func_case(THD *thd, List<Item> &list, Item_func_case::Item_func_case(THD *thd, List<Item> &list,
Item *first_expr_arg, Item *else_expr_arg): Item *first_expr_arg, Item *else_expr_arg):
Item_func_hybrid_field_type(thd), first_expr_num(-1), else_expr_num(-1), Item_func_hybrid_field_type(thd), first_expr_num(-1), else_expr_num(-1),
left_cmp_type(INT_RESULT), case_item(0) left_cmp_type(INT_RESULT), case_item(0), m_found_types(0)
{ {
ncases= list.elements; ncases= list.elements;
if (first_expr_arg) if (first_expr_arg)
@@ -3010,9 +3000,9 @@ void Item_func_case::fix_length_and_dec()
{ {
Item **agg= arg_buffer; Item **agg= arg_buffer;
uint nagg; uint nagg;
uint found_types= 0;
THD *thd= current_thd; THD *thd= current_thd;
m_found_types= 0;
if (else_expr_num == -1 || args[else_expr_num]->maybe_null) if (else_expr_num == -1 || args[else_expr_num]->maybe_null)
maybe_null= 1; maybe_null= 1;
@@ -3079,14 +3069,14 @@ void Item_func_case::fix_length_and_dec()
for (nagg= 0; nagg < ncases/2 ; nagg++) for (nagg= 0; nagg < ncases/2 ; nagg++)
agg[nagg+1]= args[nagg*2]; agg[nagg+1]= args[nagg*2];
nagg++; nagg++;
if (!(found_types= collect_cmp_types(agg, nagg))) if (!(m_found_types= collect_cmp_types(agg, nagg)))
return; return;
Item *date_arg= 0; Item *date_arg= 0;
if (found_types & (1U << TIME_RESULT)) if (m_found_types & (1U << TIME_RESULT))
date_arg= find_date_time_item(args, arg_count, 0); date_arg= find_date_time_item(args, arg_count, 0);
if (found_types & (1U << STRING_RESULT)) if (m_found_types & (1U << STRING_RESULT))
{ {
/* /*
If we'll do string comparison, we also need to aggregate If we'll do string comparison, we also need to aggregate
@@ -3127,7 +3117,7 @@ void Item_func_case::fix_length_and_dec()
for (i= 0; i <= (uint)TIME_RESULT; i++) for (i= 0; i <= (uint)TIME_RESULT; i++)
{ {
if (found_types & (1U << i) && !cmp_items[i]) if (m_found_types & (1U << i) && !cmp_items[i])
{ {
DBUG_ASSERT((Item_result)i != ROW_RESULT); DBUG_ASSERT((Item_result)i != ROW_RESULT);
@@ -3137,18 +3127,93 @@ void Item_func_case::fix_length_and_dec()
return; return;
} }
} }
/*
Set cmp_context of all WHEN arguments. This prevents
Item_field::propagate_equal_fields() from transforming a
zerofill argument into a string constant. Such a change would
require rebuilding cmp_items.
*/
for (i= 0; i < ncases; i+= 2)
args[i]->cmp_context= item_cmp_type(left_cmp_type, args[i]);
} }
} }
Item* Item_func_case::propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
if (first_expr_num == -1)
{
// None of the arguments are in a comparison context
Item_args::propagate_equal_fields(thd, Context_identity(), cond);
return this;
}
for (uint i= 0; i < arg_count; i++)
{
/*
Even "i" values cover items that are in a comparison context:
CASE x0 WHEN x1 .. WHEN x2 .. WHEN x3 ..
Odd "i" values cover items that are not in comparison:
CASE ... THEN y1 ... THEN y2 ... THEN y3 ... ELSE y4 END
*/
Item *new_item= 0;
if ((int) i == first_expr_num) // Then CASE (the switch) argument
{
/*
Cannot replace the CASE (the switch) argument if
there are multiple comparison types were found, or found a single
comparison type that is not equal to args[0]->cmp_type().
- Example: multiple comparison types, can't propagate:
WHERE CASE str_column
WHEN 'string' THEN TRUE
WHEN 1 THEN TRUE
ELSE FALSE END;
- Example: a single incompatible comparison type, can't propagate:
WHERE CASE str_column
WHEN DATE'2001-01-01' THEN TRUE
ELSE FALSE END;
- Example: a single incompatible comparison type, can't propagate:
WHERE CASE str_column
WHEN 1 THEN TRUE
ELSE FALSE END;
- Example: a single compatible comparison type, ok to propagate:
WHERE CASE str_column
WHEN 'str1' THEN TRUE
WHEN 'str2' THEN TRUE
ELSE FALSE END;
*/
if (m_found_types == (1UL << left_cmp_type))
new_item= args[i]->propagate_equal_fields(thd,
Context(
ANY_SUBST,
left_cmp_type,
cmp_collation.collation),
cond);
}
else if ((i % 2) == 0) // WHEN arguments
{
/*
These arguments are in comparison.
Allow invariants of the same value during propagation.
Note, as we pass ANY_SUBST, none of the WHEN arguments will be
replaced to zero-filled constants (only IDENTITY_SUBST allows this).
Such a change for WHEN arguments would require rebuilding cmp_items.
*/
Item_result tmp_cmp_type= item_cmp_type(args[first_expr_num], args[i]);
new_item= args[i]->propagate_equal_fields(thd,
Context(
ANY_SUBST,
tmp_cmp_type,
cmp_collation.collation),
cond);
}
else // THEN and ELSE arguments (they are not in comparison)
{
new_item= args[i]->propagate_equal_fields(thd, Context_identity(), cond);
}
if (new_item && new_item != args[i])
thd->change_item_tree(&args[i], new_item);
}
return this;
}
uint Item_func_case::decimal_precision() const uint Item_func_case::decimal_precision() const
{ {
int max_int_part=0; int max_int_part=0;
@@ -3305,7 +3370,6 @@ void Item_func_coalesce::fix_length_and_dec()
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
} }
@@ -3669,9 +3733,6 @@ cmp_item* cmp_item::get_comparator(Item_result type, Item *warn_item,
case TIME_RESULT: case TIME_RESULT:
DBUG_ASSERT(warn_item); DBUG_ASSERT(warn_item);
return new cmp_item_datetime(warn_item); return new cmp_item_datetime(warn_item);
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
break;
} }
return 0; // to satisfy compiler :) return 0; // to satisfy compiler :)
} }
@@ -4000,7 +4061,6 @@ void Item_func_in::fix_length_and_dec()
if (m_compare_type == STRING_RESULT && if (m_compare_type == STRING_RESULT &&
agg_arg_charsets_for_comparison(cmp_collation, args, arg_count)) agg_arg_charsets_for_comparison(cmp_collation, args, arg_count))
return; return;
args[0]->cmp_context= m_compare_type;
arg_types_compatible= TRUE; arg_types_compatible= TRUE;
if (m_compare_type == ROW_RESULT) if (m_compare_type == ROW_RESULT)
@@ -4095,9 +4155,6 @@ void Item_func_in::fix_length_and_dec()
date_arg= find_date_time_item(args, arg_count, 0); date_arg= find_date_time_item(args, arg_count, 0);
array= new (thd->mem_root) in_datetime(date_arg, arg_count - 1); array= new (thd->mem_root) in_datetime(date_arg, arg_count - 1);
break; break;
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0);
break;
} }
if (array && !(thd->is_fatal_error)) // If not EOM if (array && !(thd->is_fatal_error)) // If not EOM
{ {
@@ -4132,16 +4189,6 @@ void Item_func_in::fix_length_and_dec()
} }
} }
} }
/*
Set cmp_context of all arguments. This prevents
Item_field::propagate_equal_fields() from transforming a zerofill integer
argument into a string constant. Such a change would require rebuilding
cmp_itmes.
*/
for (arg= args + 1, arg_end= args + arg_count; arg != arg_end ; arg++)
{
arg[0]->cmp_context= item_cmp_type(left_cmp_type, arg[0]);
}
max_length= 1; max_length= 1;
} }
@@ -4609,7 +4656,7 @@ Item *Item_cond::propagate_equal_fields(THD *thd,
is not important at this point. Item_func derivants will create and is not important at this point. Item_func derivants will create and
pass their own context to the arguments. pass their own context to the arguments.
*/ */
Item *new_item= item->propagate_equal_fields(thd, ANY_SUBST, cond); Item *new_item= item->propagate_equal_fields(thd, Context_boolean(), cond);
if (new_item && new_item != item) if (new_item && new_item != item)
thd->change_item_tree(li.ref(), new_item); thd->change_item_tree(li.ref(), new_item);
} }
@@ -5810,6 +5857,7 @@ Item_equal::Item_equal(THD *thd, Item *f1, Item *f2, bool with_const_item):
equal_items.push_back(f1, thd->mem_root); equal_items.push_back(f1, thd->mem_root);
equal_items.push_back(f2, thd->mem_root); equal_items.push_back(f2, thd->mem_root);
compare_as_dates= with_const_item && f2->cmp_type() == TIME_RESULT; compare_as_dates= with_const_item && f2->cmp_type() == TIME_RESULT;
cmp.set_compare_type(item_cmp_type(f1, f2));
upper_levels= NULL; upper_levels= NULL;
} }
@@ -5839,6 +5887,7 @@ Item_equal::Item_equal(THD *thd, Item_equal *item_equal):
} }
with_const= item_equal->with_const; with_const= item_equal->with_const;
compare_as_dates= item_equal->compare_as_dates; compare_as_dates= item_equal->compare_as_dates;
cmp.set_compare_type(item_equal->cmp.compare_type());
cond_false= item_equal->cond_false; cond_false= item_equal->cond_false;
upper_levels= item_equal->upper_levels; upper_levels= item_equal->upper_levels;
} }

View File

@@ -47,6 +47,7 @@ typedef int (*Item_field_cmpfunc)(Item *f1, Item *f2, void *arg);
class Arg_comparator: public Sql_alloc class Arg_comparator: public Sql_alloc
{ {
Item **a, **b; Item **a, **b;
Item_result m_compare_type;
arg_cmp_func func; arg_cmp_func func;
Item_func_or_sum *owner; Item_func_or_sum *owner;
bool set_null; // TRUE <=> set owner->null_value bool set_null; // TRUE <=> set owner->null_value
@@ -68,9 +69,11 @@ public:
/* Allow owner function to use string buffers. */ /* Allow owner function to use string buffers. */
String value1, value2; String value1, value2;
Arg_comparator(): set_null(TRUE), comparators(0), thd(0), Arg_comparator(): m_compare_type(STRING_RESULT),
set_null(TRUE), comparators(0), thd(0),
a_cache(0), b_cache(0) {}; a_cache(0), b_cache(0) {};
Arg_comparator(Item **a1, Item **a2): a(a1), b(a2), set_null(TRUE), Arg_comparator(Item **a1, Item **a2): a(a1), b(a2),
m_compare_type(STRING_RESULT), set_null(TRUE),
comparators(0), thd(0), a_cache(0), b_cache(0) {}; comparators(0), thd(0), a_cache(0), b_cache(0) {};
private: private:
@@ -78,23 +81,16 @@ private:
Item **a1, Item **a2, Item **a1, Item **a2,
Item_result type); Item_result type);
public: public:
void set_compare_type(Item_result type)
{
m_compare_type= type;
}
inline int set_cmp_func(Item_func_or_sum *owner_arg, inline int set_cmp_func(Item_func_or_sum *owner_arg,
Item **a1, Item **a2, bool set_null_arg) Item **a1, Item **a2, bool set_null_arg)
{ {
set_null= set_null_arg; set_null= set_null_arg;
return set_cmp_func(owner_arg, a1, a2, item_cmp_type(*a1, *a2)); return set_cmp_func(owner_arg, a1, a2, item_cmp_type(*a1, *a2));
} }
int set_cmp_func_and_arg_cmp_context(Item_func_or_sum *owner_arg,
Item **a1, Item **a2,
bool set_null_arg)
{
set_null= set_null_arg;
Item_result type= item_cmp_type(*a1, *a2);
int rc= set_cmp_func(owner_arg, a1, a2, type);
if (!rc)
(*a1)->cmp_context= (*a2)->cmp_context= type;
return rc;
}
inline int compare() { return (this->*func)(); } inline int compare() { return (this->*func)(); }
int compare_string(); // compare args[0] & args[1] int compare_string(); // compare args[0] & args[1]
@@ -128,6 +124,7 @@ public:
return (owner->type() == Item::FUNC_ITEM && return (owner->type() == Item::FUNC_ITEM &&
((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC); ((Item_func*)owner)->functype() == Item_func::EQUAL_FUNC);
} }
Item_result compare_type() const { return m_compare_type; }
void cleanup() void cleanup()
{ {
delete [] comparators; delete [] comparators;
@@ -367,6 +364,20 @@ public:
COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value, COND *remove_eq_conds(THD *thd, Item::cond_result *cond_value,
bool top_level); bool top_level);
bool count_sargable_conds(uchar *arg); bool count_sargable_conds(uchar *arg);
/*
Specifies which result type the function uses to compare its arguments.
This method is used in equal field propagation.
*/
virtual Item_result compare_type() const
{
/*
Have STRING_RESULT by default, which means the function compares
val_str() results of the arguments. This is suitable for Item_func_like
and for Item_func_spatial_rel.
Note, Item_bool_rowready_func2 overrides this default behaviour.
*/
return STRING_RESULT;
}
}; };
class Item_bool_rowready_func2 :public Item_bool_func2 class Item_bool_rowready_func2 :public Item_bool_func2
@@ -388,7 +399,9 @@ public:
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ {
Item_args::propagate_equal_fields(thd, Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST, compare_collation()), Context(ANY_SUBST,
cmp.compare_type(),
compare_collation()),
cond); cond);
return this; return this;
} }
@@ -397,16 +410,9 @@ public:
{ {
return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true); return cmp.set_cmp_func(this, tmp_arg, tmp_arg + 1, true);
} }
bool set_cmp_func_and_arg_cmp_context()
{
if (set_cmp_func())
return true;
tmp_arg[0]->cmp_context= tmp_arg[1]->cmp_context=
item_cmp_type(tmp_arg[0], tmp_arg[1]);
return false;
}
CHARSET_INFO *compare_collation() const CHARSET_INFO *compare_collation() const
{ return cmp.cmp_collation.collation; } { return cmp.cmp_collation.collation; }
Item_result compare_type() const { return cmp.compare_type(); }
Arg_comparator *get_comparator() { return &cmp; } Arg_comparator *get_comparator() { return &cmp; }
void cleanup() void cleanup()
{ {
@@ -439,14 +445,9 @@ public:
Item *neg_transformer(THD *thd); Item *neg_transformer(THD *thd);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ {
Item_args::propagate_equal_fields(thd, ANY_SUBST, cond); Item_args::propagate_equal_fields(thd, Context_boolean(), cond);
return this; return this;
} }
void fix_length_and_dec()
{
Item_bool_func::fix_length_and_dec();
args[0]->cmp_context= args[1]->cmp_context= INT_RESULT;
}
}; };
class Item_func_not :public Item_bool_func class Item_func_not :public Item_bool_func
@@ -729,13 +730,7 @@ public:
} }
bool eq(const Item *item, bool binary_cmp) const; bool eq(const Item *item, bool binary_cmp) const;
CHARSET_INFO *compare_collation() const { return cmp_collation.collation; } CHARSET_INFO *compare_collation() const { return cmp_collation.collation; }
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) = 0;
{
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST, compare_collation()),
cond);
return this;
}
}; };
@@ -762,6 +757,15 @@ public:
uint *and_level, table_map usable_tables, uint *and_level, table_map usable_tables,
SARGABLE_PARAM **sargables); SARGABLE_PARAM **sargables);
SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr); SEL_TREE *get_mm_tree(RANGE_OPT_PARAM *param, Item **cond_ptr);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST,
m_compare_type,
compare_collation()),
cond);
return this;
}
}; };
@@ -931,6 +935,15 @@ public:
table_map not_null_tables() const { return 0; } table_map not_null_tables() const { return 0; }
bool is_null(); bool is_null();
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{
Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST,
cmp.compare_type(),
cmp.cmp_collation.collation),
cond);
return this;
}
}; };
@@ -1331,6 +1344,7 @@ class Item_func_case :public Item_func_hybrid_field_type
cmp_item *cmp_items[6]; /* For all result types */ cmp_item *cmp_items[6]; /* For all result types */
cmp_item *case_item; cmp_item *case_item;
Item **arg_buffer; Item **arg_buffer;
uint m_found_types;
public: public:
Item_func_case(THD *thd, List<Item> &list, Item *first_expr_arg, Item_func_case(THD *thd, List<Item> &list, Item *first_expr_arg,
Item *else_expr_arg); Item *else_expr_arg);
@@ -1350,6 +1364,7 @@ public:
void cleanup(); void cleanup();
void agg_str_lengths(Item *arg); void agg_str_lengths(Item *arg);
void agg_num_lengths(Item *arg); void agg_num_lengths(Item *arg);
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond);
}; };
/* /*
@@ -1416,16 +1431,19 @@ public:
Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) Item* propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond)
{ {
/* /*
In case when arg_types_compatible is false, TODO: enable propagation of the args[i>0] arguments even if
fix_length_and_dec() leaves args[0]->cmp_context equal to !arg_types_compatible. See MDEV-8755.
IMPOSSIBLE_CONTEXT. In this case it's not safe to replace the field to an Note, we pass ANY_SUBST, this makes sure that non of the args
equal constant, because Item_field::can_be_substituted_to_equal_item() will be replaced to a zero-filled Item_string.
won't be able to check compatibility between Such a change would require rebuilding of cmp_items.
Item_equal->compare_collation() and this->compare_collation().
*/ */
return arg_types_compatible ? if (arg_types_compatible)
Item_func_opt_neg::propagate_equal_fields(thd, ctx, cond) : Item_args::propagate_equal_fields(thd,
this; Context(ANY_SUBST,
m_compare_type,
compare_collation()),
cond);
return this;
} }
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
enum Functype functype() const { return IN_FUNC; } enum Functype functype() const { return IN_FUNC; }
@@ -1684,7 +1702,8 @@ public:
if ((flags & MY_CS_NOPAD) && !(flags & MY_CS_NON1TO1)) if ((flags & MY_CS_NOPAD) && !(flags & MY_CS_NON1TO1))
Item_args::propagate_equal_fields(thd, Item_args::propagate_equal_fields(thd,
Context(ANY_SUBST, Context(ANY_SUBST,
compare_collation()), STRING_RESULT,
compare_collation()),
cond); cond);
return this; return this;
} }
@@ -1693,7 +1712,6 @@ public:
void fix_length_and_dec() void fix_length_and_dec()
{ {
max_length= 1; max_length= 1;
args[0]->cmp_context= args[1]->cmp_context= STRING_RESULT;
agg_arg_charsets_for_comparison(cmp_collation, args, 2); agg_arg_charsets_for_comparison(cmp_collation, args, 2);
} }
void cleanup(); void cleanup();
@@ -2084,6 +2102,7 @@ public:
bool walk(Item_processor processor, bool walk_subquery, uchar *arg); bool walk(Item_processor processor, bool walk_subquery, uchar *arg);
Item *transform(THD *thd, Item_transformer transformer, uchar *arg); Item *transform(THD *thd, Item_transformer transformer, uchar *arg);
virtual void print(String *str, enum_query_type query_type); virtual void print(String *str, enum_query_type query_type);
Item_result compare_type() const { return cmp.compare_type(); }
CHARSET_INFO *compare_collation() const; CHARSET_INFO *compare_collation() const;
void set_context_field(Item_field *ctx_field) { context_field= ctx_field; } void set_context_field(Item_field *ctx_field) { context_field= ctx_field; }

View File

@@ -545,7 +545,6 @@ Field *Item_func::tmp_table_field(TABLE *table)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
// This case should never be chosen // This case should never be chosen
DBUG_ASSERT(0); DBUG_ASSERT(0);
field= 0; field= 0;
@@ -859,7 +858,6 @@ void Item_func_num1::fix_length_and_dec()
max_length= args[0]->max_length; max_length= args[0]->max_length;
break; break;
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
DBUG_PRINT("info", ("Type: %s", DBUG_PRINT("info", ("Type: %s",
@@ -920,7 +918,6 @@ String *Item_func_hybrid_result_type::val_str(String *str)
return str_op(&str_value); return str_op(&str_value);
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return str; return str;
@@ -969,7 +966,6 @@ double Item_func_hybrid_result_type::val_real()
} }
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return 0.0; return 0.0;
@@ -1018,7 +1014,6 @@ longlong Item_func_hybrid_result_type::val_int()
} }
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return 0; return 0;
@@ -1070,7 +1065,6 @@ my_decimal *Item_func_hybrid_result_type::val_decimal(my_decimal *decimal_value)
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
return val; return val;
@@ -1124,7 +1118,6 @@ bool Item_func_hybrid_result_type::get_date(MYSQL_TIME *ltime,
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
@@ -1876,7 +1869,6 @@ void Item_func_div::fix_length_and_dec()
case STRING_RESULT: case STRING_RESULT:
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
maybe_null= 1; // devision by zero maybe_null= 1; // devision by zero
@@ -2452,7 +2444,6 @@ void Item_func_int_val::fix_length_and_dec()
} }
break; break;
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
DBUG_PRINT("info", ("Type: %s", DBUG_PRINT("info", ("Type: %s",
@@ -2634,7 +2625,6 @@ void Item_func_round::fix_length_and_dec()
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); /* This result type isn't handled */ DBUG_ASSERT(0); /* This result type isn't handled */
} }
} }
@@ -3016,7 +3006,6 @@ String *Item_func_min_max::val_str(String *str)
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
return 0; return 0;
} }
@@ -3614,7 +3603,6 @@ udf_handler::fix_fields(THD *thd, Item_func_or_sum *func,
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }
@@ -3693,7 +3681,6 @@ bool udf_handler::get_arguments()
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }
@@ -4530,7 +4517,6 @@ longlong Item_func_benchmark::val_int()
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
return 0; return 0;
} }
@@ -4969,7 +4955,6 @@ double user_var_entry::val_real(bool *null_value)
return my_atof(value); // This is null terminated return my_atof(value); // This is null terminated
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible DBUG_ASSERT(0); // Impossible
break; break;
} }
@@ -5002,7 +4987,6 @@ longlong user_var_entry::val_int(bool *null_value) const
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible DBUG_ASSERT(0); // Impossible
break; break;
} }
@@ -5037,7 +5021,6 @@ String *user_var_entry::val_str(bool *null_value, String *str,
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible DBUG_ASSERT(0); // Impossible
break; break;
} }
@@ -5066,7 +5049,6 @@ my_decimal *user_var_entry::val_decimal(bool *null_value, my_decimal *val)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // Impossible DBUG_ASSERT(0); // Impossible
break; break;
} }
@@ -5125,7 +5107,6 @@ Item_func_set_user_var::check(bool use_result_field)
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }
@@ -5160,7 +5141,6 @@ void Item_func_set_user_var::save_item_result(Item *item)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }
@@ -5228,7 +5208,6 @@ Item_func_set_user_var::update()
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }
@@ -5684,7 +5663,6 @@ void Item_func_get_user_var::fix_length_and_dec()
break; break;
case ROW_RESULT: // Keep compiler happy case ROW_RESULT: // Keep compiler happy
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); // This case should never be chosen DBUG_ASSERT(0); // This case should never be chosen
break; break;
} }

View File

@@ -348,7 +348,7 @@ public:
are never equal is allowed in the arguments of a function. are never equal is allowed in the arguments of a function.
This is overruled for the direct arguments of comparison functions. This is overruled for the direct arguments of comparison functions.
*/ */
Item_args::propagate_equal_fields(thd, IDENTITY_SUBST, cond); Item_args::propagate_equal_fields(thd, Context_identity(), cond);
return this; return this;
} }

View File

@@ -526,7 +526,6 @@ Field *Item_sum::create_tmp_field(bool group, TABLE *table,
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
// This case should never be choosen // This case should never be choosen
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; return 0;
@@ -1202,7 +1201,6 @@ Item_sum_hybrid::fix_fields(THD *thd, Item **ref)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
}; };
setup_hybrid(thd, args[0], NULL); setup_hybrid(thd, args[0], NULL);
@@ -1380,7 +1378,6 @@ void Item_sum_sum::fix_length_and_dec()
break; break;
} }
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
DBUG_PRINT("info", ("Type: %s (%d, %d)", DBUG_PRINT("info", ("Type: %s (%d, %d)",
@@ -1871,7 +1868,6 @@ void Item_sum_variance::fix_length_and_dec()
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals)); DBUG_PRINT("info", ("Type: REAL_RESULT (%d, %d)", max_length, (int)decimals));
@@ -2314,7 +2310,6 @@ void Item_sum_hybrid::reset_field()
} }
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
DBUG_ASSERT(0); DBUG_ASSERT(0);
} }
} }

View File

@@ -3395,7 +3395,6 @@ int select_max_min_finder_subselect::send_data(List<Item> &items)
break; break;
case ROW_RESULT: case ROW_RESULT:
case TIME_RESULT: case TIME_RESULT:
case IMPOSSIBLE_RESULT:
// This case should never be choosen // This case should never be choosen
DBUG_ASSERT(0); DBUG_ASSERT(0);
op= 0; op= 0;

View File

@@ -12762,7 +12762,7 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
{ {
Item_func_eq *eq_item; Item_func_eq *eq_item;
if (!(eq_item= new (thd->mem_root) Item_func_eq(thd, left_item, right_item)) || if (!(eq_item= new (thd->mem_root) Item_func_eq(thd, left_item, right_item)) ||
eq_item->set_cmp_func_and_arg_cmp_context()) eq_item->set_cmp_func())
return FALSE; return FALSE;
eq_item->quick_fix_field(); eq_item->quick_fix_field();
eq_list->push_back(eq_item, thd->mem_root); eq_list->push_back(eq_item, thd->mem_root);
@@ -13096,7 +13096,7 @@ COND *Item_func::build_equal_items(THD *thd, COND_EQUAL *inherited,
as soon the field is not of a string type or the field reference is as soon the field is not of a string type or the field reference is
an argument of a comparison predicate. an argument of a comparison predicate.
*/ */
COND *cond= propagate_equal_fields(thd, ANY_SUBST, inherited); COND *cond= propagate_equal_fields(thd, Context_boolean(), inherited);
cond->update_used_tables(); cond->update_used_tables();
DBUG_ASSERT(cond == this); DBUG_ASSERT(cond == this);
DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]); DBUG_ASSERT(!cond_equal_ref || !cond_equal_ref[0]);
@@ -13875,9 +13875,9 @@ can_change_cond_ref_to_const(Item_bool_func2 *target,
{ {
if (!target_expr->eq(source_expr,0) || if (!target_expr->eq(source_expr,0) ||
target_value == source_const || target_value == source_const ||
target_expr->cmp_context != source_expr->cmp_context) target->compare_type() != source->compare_type())
return false; return false;
if (target_expr->cmp_context == STRING_RESULT) if (target->compare_type() == STRING_RESULT)
{ {
/* /*
In this example: In this example:
@@ -14921,7 +14921,8 @@ void propagate_new_equalities(THD *thd, Item *cond,
} }
else else
{ {
cond= cond->propagate_equal_fields(thd, Item::ANY_SUBST, inherited); cond= cond->propagate_equal_fields(thd,
Item::Context_boolean(), inherited);
cond->update_used_tables(); cond->update_used_tables();
} }
} }

View File

@@ -129,7 +129,6 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
break; break;
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
default: default:
// What should we do here ? // What should we do here ?
break; break;
@@ -167,7 +166,6 @@ static my_bool CalcLen(UDF_ARGS *args, my_bool obj,
break; break;
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
default: default:
// What should we do here ? // What should we do here ?
break; break;
@@ -271,7 +269,6 @@ static PJVAL MakeValue(PGLOBAL g, UDF_ARGS *args, int i)
break; break;
case TIME_RESULT: case TIME_RESULT:
case ROW_RESULT: case ROW_RESULT:
case IMPOSSIBLE_RESULT:
default: default:
break; break;
} // endswitch arg_type } // endswitch arg_type

View File

@@ -590,8 +590,8 @@ DECLARE_THREAD(buf_dump_thread)(
srv_buf_dump_thread_active = TRUE; srv_buf_dump_thread_active = TRUE;
buf_dump_status(STATUS_INFO, "not started"); buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started");
buf_load_status(STATUS_INFO, "not started"); buf_load_status(STATUS_INFO, "Loading buffer pool(s) not yet started");
if (srv_buffer_pool_load_at_startup) { if (srv_buffer_pool_load_at_startup) {
buf_load(); buf_load();

View File

@@ -590,8 +590,8 @@ DECLARE_THREAD(buf_dump_thread)(
srv_buf_dump_thread_active = TRUE; srv_buf_dump_thread_active = TRUE;
buf_dump_status(STATUS_INFO, "not started"); buf_dump_status(STATUS_INFO, "Dumping buffer pool(s) not yet started");
buf_load_status(STATUS_INFO, "not started"); buf_load_status(STATUS_INFO, "Loading buffer pool(s) not yet started");
if (srv_buffer_pool_load_at_startup) { if (srv_buffer_pool_load_at_startup) {
buf_load(); buf_load();