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

Wrong result: "t.a = e.b OR e.b <=> t.a" with e.b NULL from a const table matches rows where the NOT NULL indexed column t.a is 0

    XMLWordPrintable

Details

    • Hide
      When a LEFT JOIN's inner table was a const table with an impossible ON condition, a WHERE condition of the form "t.a = e.b OR e.b <=> t.a" could return rows whose value of t.a was 0 (or the empty string), if t.a was a NOT NULL column with an index. e.b is NULL in every result row, so no row should match.
      Show
      When a LEFT JOIN's inner table was a const table with an impossible ON condition, a WHERE condition of the form "t.a = e.b OR e.b <=> t.a" could return rows whose value of t.a was 0 (or the empty string), if t.a was a NOT NULL column with an index. e.b is NULL in every result row, so no row should match.

    Description

      e is empty and joined with ON e.b IS NULL on a NOT NULL column, so the plan marks it "Impossible ON condition" and e.b is NULL in every result row. The condition t.a = e.b OR e.b <=> t.a is then NULL OR FALSE for every row, because t.a is never NULL. The query nevertheless returns the two rows with t.a = 0.

      The warning after EXPLAIN EXTENDED shows the condition rewritten to t.a = NULL or NULL <=> t.a, and the plan reads t by ref access on key a with ref=const. It looks as if the NULL constant is stored into the key buffer of the NOT NULL column, where it becomes 0.

      The result is correct (empty) with IGNORE INDEX, with only e.b <=> t.a, with only t.a = e.b, and when t.a is nullable. With a VARCHAR NOT NULL column the rows with '' are returned. MySQL 26.7.1 returns the correct empty result.

      How to reproduce

      CREATE TABLE t (a INT NOT NULL, KEY (a));
      INSERT INTO t VALUES (0), (0), (1);
      CREATE TABLE e (b INT NOT NULL PRIMARY KEY);
       
      SELECT t.a, e.b FROM t LEFT JOIN e ON e.b IS NULL;
      -- (0,NULL), (0,NULL), (1,NULL)
       
      SELECT t.a, e.b FROM t LEFT JOIN e ON e.b IS NULL WHERE t.a = e.b OR e.b <=> t.a;
      -- expected: Empty set
      -- actual:   (0,NULL), (0,NULL)
       
      SELECT t.a, e.b FROM t IGNORE INDEX (a) LEFT JOIN e ON e.b IS NULL WHERE t.a = e.b OR e.b <=> t.a;
      -- Empty set   correct
       
      SELECT t.a, e.b FROM t LEFT JOIN e ON e.b IS NULL WHERE e.b <=> t.a;
      -- Empty set   correct
       
      EXPLAIN EXTENDED SELECT t.a, e.b FROM t LEFT JOIN e ON e.b IS NULL WHERE t.a = e.b OR e.b <=> t.a;
      -- e  const  PRIMARY  Impossible ON condition
      -- t  ref    a        ref=const  Using index
      SHOW WARNINGS;
      -- ... where `t`.`a` = NULL or NULL <=> `t`.`a`
      

      Attachments

        Issue Links

          Activity

            People

              psergei Sergei Petrunia
              Ann C Ann C
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:

                Git Integration

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