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

Oracle outer join syntax (+): query with condition IN and NOT IN (SELECT ...) (with view in defenition of subquery) has wrong query plan and returns wrong result

    XMLWordPrintable

Details

    • Bug
    • Status: Closed (View Workflow)
    • Critical
    • Resolution: Not a Bug
    • 12.1
    • N/A
    • OTHER
    • None
    • Not for Release Notes
    • Q3/2025 Maintenance

    Description

      The testcase below has problem when columns are "NOT NULL":
      Testcase:

      CREATE TABLE t1 (a INT NOT NULL);
      INSERT INTO t1 VALUES (4),(7),(0);
       
      CREATE TABLE t3 (c INT NOT NULL);
      INSERT INTO t3 VALUES (4),(6),(3);
       
      CREATE TABLE tv (e INT NOT NULL);
      INSERT INTO tv VALUES (1),(3);
       
      CREATE ALGORITHM=TEMPTABLE VIEW v_temptable AS SELECT * FROM tv;
       
      explain extended
      SELECT * FROM t1
      WHERE t1.a  IN ( SELECT v_temptable.e FROM t3 LEFT JOIN v_temptable ON (t3.c = v_temptable.e));
       
      explain extended
      SELECT * FROM t1
      WHERE t1.a  IN ( SELECT v_temptable.e FROM t3 , v_temptable where (t3.c = v_temptable.e(+)));
      drop view v_temptable;
      drop table t1,t3,tv;
      

      In this case, the query plan will differ in key_len for <derived 3> :

      explain extended
      SELECT * FROM t1
      WHERE t1.a  IN ( SELECT v_temptable.e FROM t3 LEFT JOIN v_temptable ON (t3.c = v_temptable.e));
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
      1	PRIMARY	<derived3>	ref	key0	key0	5	test.t1.a	1	100.00	
      1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	3	33.33	Using where; FirstMatch(t1)
      3	DERIVED	tv	ALL	NULL	NULL	NULL	NULL	2	100.00	
      Warnings:
      Note	1003	/* select#1 */ select "test"."t1"."a" AS "a" from "test"."t1" semi join ("test"."t3" join "test"."v_temptable") where "v_temptable"."e" = "test"."t1"."a" and "test"."t3"."c" = "test"."t1"."a"
       
       
      explain extended
      SELECT * FROM t1
      WHERE t1.a  IN ( SELECT v_temptable.e FROM t3 , v_temptable where (t3.c = v_temptable.e(+)));
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	
      1	PRIMARY	<derived3>	ref	key0	key0	4	test.t1.a	1	100.00	
      1	PRIMARY	t3	ALL	NULL	NULL	NULL	NULL	3	33.33	Using where; FirstMatch(t1)
      3	DERIVED	tv	ALL	NULL	NULL	NULL	NULL	2	100.00	
      Warnings:
      Note	1003	/* select#1 */ select "test"."t1"."a" AS "a" from "test"."t1" semi join ("test"."t3" join "test"."v_temptable") where "v_temptable"."e" = "test"."t1"."a" and "test"."t3"."c" = "test"."t1"."a"
      

      But if we change it to NOT IN , the query plans will have more significant differences (and there is "v_temptable". "e" is null , which looks like the problem described in MDEV-36866)

      explain extended
      SELECT * FROM t1
      WHERE t1.a  NOT IN ( SELECT v_temptable.e FROM t3 LEFT JOIN v_temptable ON (t3.c = v_temptable.e));
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
      2	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	100.00	
      2	DEPENDENT SUBQUERY	<derived3>	ref	key0	key0	5	test.t3.c	1	100.00	Using where
      3	DERIVED	tv	ALL	NULL	NULL	NULL	NULL	2	100.00	
      Warnings:
      Note	1003	/* select#1 */ select "test"."t1"."a" AS "a" from "test"."t1" where !<expr_cache><"test"."t1"."a">(<in_optimizer>("test"."t1"."a",<exists>(/* select#2 */ select "v_temptable"."e" from "test"."t3" left join "test"."v_temptable" on("v_temptable"."e" = "test"."t3"."c") where <cache>("test"."t1"."a") = "v_temptable"."e" or "v_temptable"."e" is null having "v_temptable"."e" is null)))
       
      explain extended
      SELECT * FROM t1
      WHERE t1.a  NOT IN ( SELECT v_temptable.e FROM t3 , v_temptable where (t3.c = v_temptable.e(+)));
      id	select_type	table	type	possible_keys	key	key_len	ref	rows	filtered	Extra
      1	PRIMARY	t1	ALL	NULL	NULL	NULL	NULL	3	100.00	Using where
      2	DEPENDENT SUBQUERY	t3	ALL	NULL	NULL	NULL	NULL	3	100.00	
      2	DEPENDENT SUBQUERY	<derived3>	ref	key0	key0	4	test.t3.c	1	100.00	Using where
      3	DERIVED	tv	ALL	NULL	NULL	NULL	NULL	2	100.00	
      Warnings:
      Note	1003	/* select#1 */ select "test"."t1"."a" AS "a" from "test"."t1" where !<expr_cache><"test"."t1"."a">(<in_optimizer>("test"."t1"."a",<exists>(/* select#2 */ select "v_temptable"."e" from "test"."t3" left join "test"."v_temptable" on("v_temptable"."e" = "test"."t3"."c") where <cache>("test"."t1"."a") = "v_temptable"."e")))
      

      Attachments

        Issue Links

          Activity

            People

              sanja Oleksandr Byelkin
              lstartseva Lena Startseva
              Votes:
              0 Vote for this issue
              Watchers:
              5 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

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