Bug #118862 MySQL Returns Incorrect Results for Complex Query with Set Operations
Submitted: 20 Aug 14:05 Modified: 21 Aug 6:27
Reporter: Aaditya Dubey Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Optimizer Severity:S3 (Non-critical)
Version:8.0.x, 8.4.x, 8.0.43 OS:Any
Assigned to: CPU Architecture:Any

[20 Aug 14:05] Aaditya Dubey
Description:
MySQL incorrectly returns rows when using IN (IFNULL(<arg1>, <arg2>)) in a JOIN condition, even when no matching values exist in the joined table.

Eg:

Query 1: 

mysql [localhost:8042] {msandbox} (database41) > SELECT DISTINCT 
    t1.c0 AS ref0, 
    t0.c0 AS ref1
FROM t0
INNER JOIN t1 
    ON (t1.c0) IN (
        IFNULL('0.3792086453751513', "qR\r")
    );
+-------------------------------------+-------------+
| ref0                                | ref1        |
+-------------------------------------+-------------+
| 00000000000000000000000000000000000 |  -539730000 |
| 00000000000000000000000000000000000 |           0 |
| 00000000000000000000000000000000000 |  1500280000 |
| 00000000000000000000000000000000000 |    0.112448 |
| 00000000000000000000000000000000000 | -1822370000 |
| 00000000000000000000000000000000000 |    0.861014 |
| 00000000000000000000000000000000000 |  -767464000 |
| 00000000000000000000000000000000000 |  1280360000 |
| 00000000000000000000000000000000000 |   991116000 |
| 00000000000000000000000000000000000 |    0.383531 |
| 00000000000000000000000000000000000 |   767095000 |
| 00000000000000000000000000000000000 |    0.673761 |
| 00000000000000000000000000000000000 | -1496060000 |
+-------------------------------------+-------------+
13 rows in set (0.00 sec)

As you can see in the t1 table, the value 0.3792086453751513 does not exist in column c0, yet it is still being matched and returning incorrect results.

mysql [localhost:8042] {msandbox} (database41) > select * from t1;
+-------------------------------------+
| c0                                  |
+-------------------------------------+
| 00000000000000000000000000000000001 |
| 00000000000000000000000000000000001 |
| 00000000000000000000000000000000001 |
| 00000000000000000000000000000000001 |
| 00000000000000000000000000000000000 |
| 00000000000000000000000000000000000 |
+-------------------------------------+
6 rows in set (0.00 sec)

Query 2: 

mysql [localhost:8042] {msandbox} (database41) > (SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
 FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r"))
 UNION
 SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
 FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r")))
EXCEPT
(
   (SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
    FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r"))
    EXCEPT
    SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
    FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r")))
   UNION
   (SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
    FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r"))
    EXCEPT
    SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1
    FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR\t\r")))
);
Empty set (0.01 sec)

It appears to be an optimizer defect that should be thoroughly checked and tested.

How to repeat:
DROP DATABASE IF EXISTS database41;
CREATE DATABASE database41;
USE database41;
CREATE TABLE t0(c0 FLOAT  COMMENT 'asdf'    NOT NULL) ;
CREATE TABLE t1(c0 SMALLINT(35) ZEROFILL   NOT NULL) INSERT_METHOD = LAST, DELAY_KEY_WRITE = 0;
INSERT   INTO t1(c0) VALUES(0.1824230226382254);
INSERT  IGNORE INTO t1(c0) VALUES(NULL);
INSERT  IGNORE INTO t0(c0) VALUES(NULL);
INSERT INTO t0(c0) VALUES(-1669661514);
INSERT INTO t1(c0) VALUES(0.7472309988598856);
DELETE QUICK IGNORE FROM t1 WHERE (((t1.c0) AND (t1.c0)) IN (CAST(1777329468 AS SIGNED))) && (2013524628);
INSERT  IGNORE INTO t1(c0) VALUES(963834148);
REPLACE INTO t0(c0) VALUES(1239037716);
REPLACE INTO t1(c0) VALUES(0.43602613101159104);
INSERT  IGNORE INTO t1(c0) VALUES("'>");
INSERT  IGNORE INTO t1(c0) VALUES(0.9934674085398288);
REPLACE INTO t0(c0) VALUES(0.6740703907035186);
INSERT  IGNORE INTO t1(c0) VALUES(NULL);
REPLACE INTO t0(c0) VALUES(-1.769451152E9);
REPLACE INTO t1(c0) VALUES(0.4749621371179693);
REPLACE INTO t0(c0) VALUES(-30021013);
INSERT IGNORE INTO t0(c0) VALUES(0.24731106863745167), (1778147985), (0.09838507952625908), ('0.4660497943510168'), (0.8122674816254841);
INSERT IGNORE INTO t0(c0) VALUES(-1632610407);
INSERT IGNORE INTO t0(c0) VALUES(NULL);
INSERT INTO t0(c0) VALUES(2081612921);
INSERT  INTO t0(c0) VALUES(0.990338853192909);
# UPDATE t1 SET c0=0;
REPLACE INTO t1(c0) VALUES(0.8431550115185268);
INSERT  IGNORE INTO t0(c0) VALUES(1754857090), (NULL), ("");
INSERT  IGNORE INTO t1(c0) VALUES('i6棘^T');
INSERT INTO t1(c0) VALUES(0.18962959651986877);
INSERT  IGNORE INTO t1(c0) VALUES(549730166);
# ALTER TABLE t1 FORCE, PACK_KEYS 0;
REPLACE INTO t0(c0) VALUES(0.189489284896317), (0.851502970255646), (0.2104462311614259);
REPLACE INTO t0(c0) VALUES(-2.086789819E9);
INSERT  IGNORE INTO t0(c0) VALUES(0.1841282621952196);
REPLACE INTO t0(c0) VALUES(-1130577659);
REPLACE INTO t1(c0) VALUES(0.15226799749882614);
INSERT INTO t0(c0) VALUES(-2054644770);
INSERT  IGNORE INTO t0(c0) VALUES(1440616587);
INSERT  IGNORE INTO t0(c0) VALUES(-85986860), ('Wf}R'), (876191032);
INSERT  IGNORE INTO t0(c0) VALUES(0.27867858994878725);
CREATE INDEX i0 ON t1(c0 DESC);
INSERT  IGNORE INTO t0(c0) VALUES(NULL), (NULL), ('OZDᛁ');
REPLACE INTO t0(c0) VALUES(-1667117131);
REPLACE INTO t0(c0) VALUES('-1197856791');
INSERT  IGNORE INTO t1(c0) VALUES('65651547');
REPLACE INTO t0(c0) VALUES("0.942870114792822");
INSERT IGNORE INTO t1(c0) VALUES(1951500315);
REPLACE INTO t1(c0) VALUES(0.5509397793910037);
INSERT  IGNORE INTO t0(c0) VALUES(NULL);
REPLACE INTO t1(c0) VALUES(0.4770861185062949);
INSERT  IGNORE INTO t0(c0) VALUES(0.5715570769353812);
INSERT  IGNORE INTO t1(c0) VALUES(-1920324395);
REPLACE INTO t1(c0) VALUES(0.025000575724580476);
INSERT  IGNORE INTO t0(c0) VALUES(NULL);
REPLACE INTO t0(c0) VALUES(0.31210399912364317);
INSERT INTO t0(c0) VALUES(1818547475);
REPLACE INTO t0(c0) VALUES(-1979499865);
REPLACE INTO t0(c0) VALUES(0.10764013051980781), (-1766427762), (0.8988106227622641);
INSERT  IGNORE INTO t1(c0) VALUES(NULL);
# CHECKSUM TABLE t0;
INSERT INTO t1(c0) VALUES(0.07064190860033626);
UPDATE t1 SET c0= EXISTS (SELECT 1) WHERE t1.c0;
INSERT INTO t1(c0) VALUES(0.5447848109638285);
INSERT  IGNORE INTO t1(c0) VALUES(0.1560826941734691);
REPLACE INTO t0(c0) VALUES(332832373);
INSERT  IGNORE INTO t0(c0) VALUES(0.28772261646954056);
INSERT  IGNORE INTO t1(c0) VALUES(0.6913662847041423);
INSERT IGNORE INTO t1(c0) VALUES(0.8219073663240016);
UPDATE t0 SET c0='-539730446';
INSERT  IGNORE INTO t0(c0) VALUES('');
DELETE LOW_PRIORITY FROM t1;
INSERT IGNORE INTO t1(c0) VALUES(1197056235);
INSERT  IGNORE INTO t0(c0) VALUES(1500279666);
INSERT  INTO t0(c0) VALUES("0.11244760007773402");
REPLACE INTO t0(c0) VALUES(-1.822372953E9);
INSERT  IGNORE INTO t0(c0) VALUES('');
REPLACE INTO t0(c0) VALUES(0.8610140574800775);
# ALTER TABLE t0 STATS_AUTO_RECALC 1;
INSERT  IGNORE INTO t1(c0) VALUES('&MﲶI');
REPLACE INTO t0(c0) VALUES('-767464133');
INSERT  IGNORE INTO t1(c0) VALUES('[_'), (NULL), (65651547);
REPLACE INTO t0(c0) VALUES(1280356003);
DELETE LOW_PRIORITY QUICK FROM t1;
REPLACE INTO t1(c0) VALUES(0.5705589591860675);
INSERT  IGNORE INTO t0(c0) VALUES('');
REPLACE INTO t0(c0) VALUES(991115748);
REPLACE INTO t1(c0) VALUES(0.7737006902214526), (0.8520837366965166), (0.016662214021319732);
REPLACE INTO t0(c0) VALUES(0.3835309206587264);
INSERT IGNORE INTO t1(c0) VALUES(NULL);
INSERT  IGNORE INTO t0(c0) VALUES(NULL);
REPLACE INTO t1(c0) VALUES(0.8736937294158336);
REPLACE INTO t0(c0) VALUES(767094793);
REPLACE INTO t0(c0) VALUES("0.6737605706328825");
INSERT  IGNORE INTO t0(c0) VALUES('-1496062311');

-- cardinality: 0

(SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r")) UNION SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r"))) EXCEPT ((SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r")) EXCEPT SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r"))) UNION (SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 RIGHT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r")) EXCEPT SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 LEFT JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r"))));

-- cardinality: 13
SELECT DISTINCT t1.c0 AS ref0, t0.c0 AS ref1 FROM t0 INNER JOIN t1 ON (t1.c0) IN (IFNULL('0.3792086453751513', "qR	\r"));
[21 Aug 6:27] MySQL Verification Team
Hello Aaditya,

Thank you for the report and feedback.
Verified as described.

regards,
Umesh