Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-40877

Wrong result from NOT IN with a NULL in a materialized subquery

    XMLWordPrintable

Details

    Description

      A NOT IN subquery whose result contains a NULL returns rows. A NULL in the subquery makes every comparison UNKNOWN, so the predicate can never be TRUE and no row qualifies. MySQL returns no rows for both testcases below, on every version tested.

      The wrong answer appears only once the subquery is materialized. With four rows in the outer table the plan is MATERIALIZED and the row is returned. With three rows the plan is DEPENDENT SUBQUERY and the answer is correct. Setting materialization=off, or turning off both partial_match_rowid_merge and partial_match_table_scan, also gives the correct answer, so the defect is in the partial-matching path for a materialized NOT IN.

      The row that comes back is always one whose value lies outside the range of the subquery column's type. 9999 against a TINYINT column reproduces it, and a value the TINYINT can hold does not. With no NULL in the subquery the same query is answered correctly, so the range check is only wrong in the presence of a NULL. The bug is engine-independent: it reproduces on InnoDB, MyISAM, Aria and MEMORY.

      Both the single-column and the two-column form are affected.

      CLI Testcase, single column:

      CREATE TABLE t1 (c1 TINYINT);
      INSERT INTO t1 VALUES(21),(NULL);
      CREATE TABLE t2 (c1 INT);
      INSERT INTO t2 VALUES(1),(2),(3),(9999);
      SELECT * FROM t2 WHERE c1 NOT IN (SELECT c1 FROM t1);
      

      CLI Testcase, two columns:

      CREATE TABLE t1 (c1 TINYINT, c2 TINYINT);
      INSERT INTO t1 VALUES(21,21),(NULL,NULL);
      CREATE TABLE t2 (c1 INT, c2 INT);
      INSERT INTO t2 VALUES(1,1),(2,2),(3,3),(9999,9999);
      SELECT * FROM t2 WHERE (c1,c2) NOT IN (SELECT c1,c2 FROM t1);
      

      MTR Testcase, both forms:

      CREATE TABLE t1 (c1 TINYINT);
      INSERT INTO t1 VALUES(21),(NULL);
      CREATE TABLE t2 (c1 INT);
      INSERT INTO t2 VALUES(1),(2),(3),(9999);
      SELECT COUNT(*) INTO @n FROM t2 WHERE c1 NOT IN (SELECT c1 FROM t1);
      --let $n= query_get_value(SELECT @n AS n, n, 1)
      if ($n != 0) {
      --die Single column: NOT IN with a NULL in the subquery returned $n row(s), expected 0
      }
      CREATE TABLE t3 (c1 TINYINT, c2 TINYINT);
      INSERT INTO t3 VALUES(21,21),(NULL,NULL);
      CREATE TABLE t4 (c1 INT, c2 INT);
      INSERT INTO t4 VALUES(1,1),(2,2),(3,3),(9999,9999);
      SELECT COUNT(*) INTO @m FROM t4 WHERE (c1,c2) NOT IN (SELECT c1,c2 FROM t3);
      --let $m= query_get_value(SELECT @m AS m, m, 1)
      if ($m != 0) {
      --die Two columns: NOT IN with a NULL row in the subquery returned $m row(s), expected 0
      }
      DROP TABLE t1, t2, t3, t4;
      

      The MTR testcase is a reverse gate: it fails while the bug is present and passes once the result is correct.

      Leads to, single column:

      CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Optimized)

      c1
      9999
      

      Leads to, two columns:

      CS 13.1.0 da18481158c81ca94689702073c3e04aad85a6a3 (Optimized)

      c1	c2
      9999	9999
      

      Expected in both cases, and what every MySQL build returns: no rows.

      EXPLAIN, four rows in t2, wrong result

      id  select_type   table  type  possible_keys  key   key_len  ref   rows  Extra
      1   PRIMARY       t2     ALL   NULL           NULL  NULL     NULL  4     Using where
      2   MATERIALIZED  t1     ALL   NULL           NULL  NULL     NULL  2
      

      EXPLAIN, three rows in t2, correct result

      id  select_type         table  type  possible_keys  key   key_len  ref   rows  Extra
      1   PRIMARY             t2     ALL   NULL           NULL  NULL     NULL  3     Using where
      2   DEPENDENT SUBQUERY  t1     ALL   NULL           NULL  NULL     NULL  2     Using where
      

      Optimizer switch results, four-row testcase

      optimizer_switch                                            Rows returned  Correct
      default                                                     1              no
      materialization=off                                         0              yes
      partial_match_rowid_merge=off,partial_match_table_scan=off  0              yes
      

      Bug Detection Matrix

          Rel    o/d  Build   Commit                                    Diff observed
      CS  10.11  dbg  180826  8f00e6caca633c783140db86d3a48a96de67cf38  DIFF: RESULT
      CS  10.11  opt  180826  8f00e6caca633c783140db86d3a48a96de67cf38  DIFF: RESULT
      CS  11.4   dbg  180826  1a052f27e374fc9b4cb5b1fd098cf10f0e1381cc  DIFF: RESULT
      CS  11.4   opt  180826  1a052f27e374fc9b4cb5b1fd098cf10f0e1381cc  DIFF: RESULT
      CS  11.8   dbg  180826  d26f9ab217a7fcf9d4eccc62c01020ff275ff42e  DIFF: RESULT
      CS  11.8   opt  180826  d26f9ab217a7fcf9d4eccc62c01020ff275ff42e  DIFF: RESULT
      CS  12.3   dbg  180826  add63991988734383c5e942de2a19c6c45f511f7  DIFF: RESULT
      CS  12.3   opt  180826  add63991988734383c5e942de2a19c6c45f511f7  DIFF: RESULT
      CS  13.0   dbg  180826  a848493c6fe031f23606144420c1ca1e467cbd81  DIFF: RESULT
      CS  13.0   opt  180826  a848493c6fe031f23606144420c1ca1e467cbd81  DIFF: RESULT
      CS  13.1   dbg  180826  da18481158c81ca94689702073c3e04aad85a6a3  DIFF: RESULT
      CS  13.1   opt  180826  da18481158c81ca94689702073c3e04aad85a6a3  DIFF: RESULT
      ES  10.6   dbg  180826  fcecb2620f25965723d640decede7c018bcb1dcc  DIFF: RESULT
      ES  10.6   opt  180826  fcecb2620f25965723d640decede7c018bcb1dcc  DIFF: RESULT
      ES  11.4   dbg  180826  3b34189bfe675c18c4ced3ef531d016ea74c76f4  DIFF: RESULT
      ES  11.4   opt  180826  3b34189bfe675c18c4ced3ef531d016ea74c76f4  DIFF: RESULT
      ES  11.8   dbg  180826  4694e931d10fecf733c34f83ea2146d31b708eb3  DIFF: RESULT
      ES  11.8   opt  180826  4694e931d10fecf733c34f83ea2146d31b708eb3  DIFF: RESULT
      ES  12.3   dbg  180826  f513f503feacabfb219d4a6f965b5f72b86d4db0  DIFF: RESULT
      ES  12.3   opt  180826  f513f503feacabfb219d4a6f965b5f72b86d4db0  DIFF: RESULT
      MS  5.5    dbg  070123  bac287c315b1792e7ae33f91add6a60292f9bae8  No diff found
      MS  5.5    opt  070123  bac287c315b1792e7ae33f91add6a60292f9bae8  No diff found
      MS  5.6    dbg  070123  dab95781a1244104d6b87020ac2fc4d190ba2946  No diff found
      MS  5.6    opt  070123  dab95781a1244104d6b87020ac2fc4d190ba2946  No diff found
      MS  5.7    dbg  070525  f7680e98b6bbe3500399fbad465d08a6b75d7a5c  No diff found
      MS  5.7    opt  070525  f7680e98b6bbe3500399fbad465d08a6b75d7a5c  No diff found
      MS  8.0    dbg  060224  49ef33f7edadef3ae04665e73d1babd40179a4f1  No diff found
      MS  8.0    opt  060224  49ef33f7edadef3ae04665e73d1babd40179a4f1  No diff found
      MS  9.1    dbg  211024  61a3a1d8ef15512396b4c2af46e922a19bf2b174  No diff found
      MS  9.1    opt  211024  61a3a1d8ef15512396b4c2af46e922a19bf2b174  BASE/SOURCE
      

      MDEV-3509 and MDEV-3033 are the closest earlier bugs. Both are two-column NOT IN under partial matching, and both dropped rows that should have qualified. Their own testcases return the correct result on 13.1.0, so this is not a re-emergence of either. This defect runs the other way, keeps a row that cannot qualify, needs no non-default optimizer_switch, and reproduces under the switch settings those two used.

      Attachments

        Issue Links

          Activity

            People

              psergei Sergei Petrunia
              Roel Roel Van de Paar
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:

                Time Tracking

                  Estimated:
                  Original Estimate - Not Specified
                  Not Specified
                  Remaining:
                  Remaining Estimate - Not Specified
                  Not Specified
                  Logged:
                  Time Spent - 1h
                  1h

                  Git Integration

                    Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.