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

Change of behaviour of OR in IF-conditions 10.2 -> 10.3

Details

    • Bug
    • Status: Closed (View Workflow)
    • Critical
    • Resolution: Fixed
    • 10.3.11, 10.2(EOL), 10.3(EOL), 10.4(EOL)
    • 10.2.23
    • Optimizer
    • Windows 10, Windows Server 2008

    Description

      The behavior of the OR operator in the IF condition has changed from MariaDB 10.2 to 10.3.
      now I noticed that the following syntax doesn't work in SELECT statements anymore:

      SELECT * FROM tab t WHERE IF(@a = 1, t.a = 1 OR t.b = 1,1=1)
      

      Now I'd have to write:

      SELECT * FROM tab t WHERE (IF(@a = 1, t.a = 1, 1=1) OR IF(@a = 1, t.b = 1, 1=1))
      

      Is it a bug or a deliberate change? Is there a setting with which I can reactivate the previous behavior?

      Attachments

        Issue Links

          Activity

            FriedemannS Friedemann Schmidt created issue -

            Addendum: I have further investigated the problem. It only appears when using views in which a session variable @var is queried in the WHERE condition. I'll upload an example later.

            FriedemannS Friedemann Schmidt added a comment - Addendum: I have further investigated the problem. It only appears when using views in which a session variable @var is queried in the WHERE condition. I'll upload an example later.
            elenst Elena Stepanova made changes -
            Field Original Value New Value
            Labels IF OR SELECT IF OR SELECT need_feedback

            here is an example that shows the difference between 10.2 and 10.3

             
            CREATE TABLE p1 (id int, p_name char(2), o_id int);
            INSERT INTO p1 VALUES(1,'p1',1),(2,'p2',2);
             
            CREATE TABLE t1 (id int, t_name char(2));
            INSERT INTO t1 VALUES (1, 't1'),(2,'t2');
             
            CREATE TABLE f1 (id int, p_id int, t_id int, b_id int);
            INSERT INTO f1 VALUES (1,1,1,2),(2,1,2,2),(3,2,1,1),(4,2,2,2);
             
            CREATE TABLE o1 (id int, o_name char(2));
            INSERT INTO o1 VALUES (1, 'aa'), (2,'bb');
             
            CREATE VIEW v1 AS SELECT 
                                     p_name,
                                     o_id,
                                     f1.id AS f_id,
                                     p_id,
                                     t_id,
                                     b_id FROM p1 JOIN f1 ON p1.id = f1.p_id;
             
            CREATE VIEW v2 AS SELECT 
                                     p_name,
                                     o_id,
                                     f1.id AS f_id,
                                     p_id,
                                     t_id,
                                     b_id,
                                     o_name FROM p1 JOIN f1 ON p1.id = f1.p_id JOIN o1 ON o1.id = p1.o_id GROUP BY p_id;
             
            //unexpected output in 10.3: 0 rows
            //normal output in 10.2: 2 rows
            SELECT v2.p_name,
                   t.t_name,
                   b.t_name AS b_name
                   
              FROM v2 
              JOIN v1 ON v2.f_id = v1.f_id
              LEFT JOIN o1 AS o ON o.id = v2.o_id  
              LEFT JOIN t1 AS t ON t.id = v1.t_id
              LEFT JOIN t1 AS b ON b.id = v1.b_id
             
            WHERE IF('a' LIKE 'a',t.id = 1 OR b.id = 1, 1=1);
             
            //solution1: drop the IF-Condition in WHERE-statement
            SELECT v2.p_name,
                   t.t_name,
                   b.t_name AS b_name
                   
              FROM v2 
              JOIN v1 ON v2.f_id = v1.f_id
              LEFT JOIN o1 AS o ON o.id = v2.o_id  
              LEFT JOIN t1 AS t ON t.id = v1.t_id
              LEFT JOIN t1 AS b ON b.id = v1.b_id
             
             
            WHERE t.id = 1 OR b.id = 1;
             
            //Solution2: o1-join after t1-joins
            SELECT v2.p_name,
                   t.t_name,
                   b.t_name AS b_name
                   
              FROM v2 
              JOIN v1 ON v2.f_id = v1.f_id
              #LEFT JOIN o1 AS o ON o.id = v2.o_id  
              LEFT JOIN t1 AS t ON t.id = v1.t_id
              LEFT JOIN t1 AS b ON b.id = v1.b_id
              LEFT JOIN o1 AS o ON o.id = v2.o_id 
             
            WHERE IF('a' LIKE 'a',t.id = 1 OR b.id = 1,1=1);
             
            //solution3: Change of the If-Condition
            SELECT v2.p_name,
                   t.t_name,
                   b.t_name AS b_name
                   
              FROM v2 
              JOIN v1 ON v2.f_id = v1.f_id
              LEFT JOIN o1 AS o ON o.id = v2.o_id  
              LEFT JOIN t1 AS t ON t.id = v1.t_id
              LEFT JOIN t1 AS b ON b.id = v1.b_id
             
            WHERE IF('a' LIKE 'a',t.id = 1,1=1) OR IF('a' LIKE 'a',b.id = 1, 1=1);
             
            //Cleanup
            DROP TABLE p1;
            DROP TABLE t1;
            DROP TABLE f1;
            DROP TABLE o1;
            DROP VIEW v1;
            DROP VIEW v2;
            
            

            FriedemannS Friedemann Schmidt added a comment - here is an example that shows the difference between 10.2 and 10.3   CREATE TABLE p1 (id int , p_name char ( 2 ), o_id int ); INSERT INTO p1 VALUES( 1 , 'p1' , 1 ),( 2 , 'p2' , 2 );   CREATE TABLE t1 (id int , t_name char ( 2 )); INSERT INTO t1 VALUES ( 1 , 't1' ),( 2 , 't2' );   CREATE TABLE f1 (id int , p_id int , t_id int , b_id int ); INSERT INTO f1 VALUES ( 1 , 1 , 1 , 2 ),( 2 , 1 , 2 , 2 ),( 3 , 2 , 1 , 1 ),( 4 , 2 , 2 , 2 );   CREATE TABLE o1 (id int , o_name char ( 2 )); INSERT INTO o1 VALUES ( 1 , 'aa' ), ( 2 , 'bb' );   CREATE VIEW v1 AS SELECT p_name, o_id, f1.id AS f_id, p_id, t_id, b_id FROM p1 JOIN f1 ON p1.id = f1.p_id;   CREATE VIEW v2 AS SELECT p_name, o_id, f1.id AS f_id, p_id, t_id, b_id, o_name FROM p1 JOIN f1 ON p1.id = f1.p_id JOIN o1 ON o1.id = p1.o_id GROUP BY p_id;   //unexpected output in 10.3: 0 rows //normal output in 10.2: 2 rows SELECT v2.p_name, t.t_name, b.t_name AS b_name FROM v2 JOIN v1 ON v2.f_id = v1.f_id LEFT JOIN o1 AS o ON o.id = v2.o_id LEFT JOIN t1 AS t ON t.id = v1.t_id LEFT JOIN t1 AS b ON b.id = v1.b_id   WHERE IF( 'a' LIKE 'a' ,t.id = 1 OR b.id = 1 , 1 = 1 );   //solution1: drop the IF-Condition in WHERE-statement SELECT v2.p_name, t.t_name, b.t_name AS b_name FROM v2 JOIN v1 ON v2.f_id = v1.f_id LEFT JOIN o1 AS o ON o.id = v2.o_id LEFT JOIN t1 AS t ON t.id = v1.t_id LEFT JOIN t1 AS b ON b.id = v1.b_id     WHERE t.id = 1 OR b.id = 1 ;   //Solution2: o1-join after t1-joins SELECT v2.p_name, t.t_name, b.t_name AS b_name FROM v2 JOIN v1 ON v2.f_id = v1.f_id #LEFT JOIN o1 AS o ON o.id = v2.o_id LEFT JOIN t1 AS t ON t.id = v1.t_id LEFT JOIN t1 AS b ON b.id = v1.b_id LEFT JOIN o1 AS o ON o.id = v2.o_id   WHERE IF( 'a' LIKE 'a' ,t.id = 1 OR b.id = 1 , 1 = 1 );   //solution3: Change of the If-Condition SELECT v2.p_name, t.t_name, b.t_name AS b_name FROM v2 JOIN v1 ON v2.f_id = v1.f_id LEFT JOIN o1 AS o ON o.id = v2.o_id LEFT JOIN t1 AS t ON t.id = v1.t_id LEFT JOIN t1 AS b ON b.id = v1.b_id   WHERE IF( 'a' LIKE 'a' ,t.id = 1 , 1 = 1 ) OR IF( 'a' LIKE 'a' ,b.id = 1 , 1 = 1 );   //Cleanup DROP TABLE p1; DROP TABLE t1; DROP TABLE f1; DROP TABLE o1; DROP VIEW v1; DROP VIEW v2;
            elenst Elena Stepanova made changes -
            Labels IF OR SELECT need_feedback IF OR SELECT
            elenst Elena Stepanova made changes -
            Assignee Alice Sherepa [ alice ]
            Labels IF OR SELECT need_verification

            the problem occurs only if the view has a group by statement.

            FriedemannS Friedemann Schmidt added a comment - the problem occurs only if the view has a group by statement.
            alice Alice Sherepa added a comment -

            Thanks for the report and the test case!
            Reproducible on current 10.2-10.4, (after 10.2.18). Introduced by commit

            commit 0de3c423cc51d362c3a9b4dc8fa90d549ce0754e
            Author: Galina Shalygina <galina.shalygina@mariadb.com>
            Date:   Mon Aug 20 17:42:49 2018 +0300
             
                MDEV-16765: Missing rows with pushdown condition defined with CASE using Item_cond
                
                The bug appears because of the wrong pushdown into the WHERE clause of the
                materialized derived table/view work. For the excl_dep_on_grouping_fields()
                method that checks if the condition can be pushed into the WHERE clause
                the case when Item_cond is used is missing. For Item_cond elements this
                method always returns positive result (that condition can be pushed).
                So this condition is pushed even if is shouldn't be pushed.
                
                To fix it new Item_cond::excl_dep_on_grouping_fields() method is added.
            

            alice Alice Sherepa added a comment - Thanks for the report and the test case! Reproducible on current 10.2-10.4, (after 10.2.18). Introduced by commit commit 0de3c423cc51d362c3a9b4dc8fa90d549ce0754e Author: Galina Shalygina <galina.shalygina@mariadb.com> Date: Mon Aug 20 17:42:49 2018 +0300   MDEV-16765: Missing rows with pushdown condition defined with CASE using Item_cond The bug appears because of the wrong pushdown into the WHERE clause of the materialized derived table/view work. For the excl_dep_on_grouping_fields() method that checks if the condition can be pushed into the WHERE clause the case when Item_cond is used is missing. For Item_cond elements this method always returns positive result (that condition can be pushed). So this condition is pushed even if is shouldn't be pushed. To fix it new Item_cond::excl_dep_on_grouping_fields() method is added.
            alice Alice Sherepa made changes -
            Affects Version/s 10.2 [ 14601 ]
            Affects Version/s 10.3 [ 22126 ]
            Affects Version/s 10.4 [ 22408 ]
            alice Alice Sherepa made changes -
            Fix Version/s 10.2 [ 14601 ]
            Fix Version/s 10.3 [ 22126 ]
            Fix Version/s 10.4 [ 22408 ]
            alice Alice Sherepa made changes -
            Status Open [ 1 ] Confirmed [ 10101 ]
            alice Alice Sherepa made changes -
            Labels need_verification
            alice Alice Sherepa made changes -
            Component/s OTHER [ 10125 ]
            alice Alice Sherepa made changes -
            Assignee Alice Sherepa [ alice ] Galina Shalygina [ shagalla ]
            alice Alice Sherepa made changes -
            Labels regression
            FriedemannS Friedemann Schmidt added a comment - Is there a relation to https://jira.mariadb.org/browse/MDEV-18605 too ?
            alice Alice Sherepa added a comment -

            FriedemannS No, I guess not. MDEV-18605 is not repeatable on the latest 10.2

            alice Alice Sherepa added a comment - FriedemannS No, I guess not. MDEV-18605 is not repeatable on the latest 10.2
            shagalla Galina Shalygina (Inactive) made changes -
            Status Confirmed [ 10101 ] In Progress [ 3 ]

            This bug occurs because the condition that shouldn't be pushed is pushed into the derived table.
            This issue is similar with MDEV-16765.

            In this special case OR-condition inside the IF-function is defined as dependent only on fields
            of the derived table while it is not. It happens because Item_cond::excl_dep_on_table() is missing.

            When going through the IF-function virtual function excl_dep_on_table() reaches OR condition
            it defines it as Item_func element and tries to take its arguments. It tries to take them from 'args' array.
            Item_cond has empty 'args' array. All its elements are stored in the list 'list'.
            So 'args' array is empty and this function defines that this OR condition depends only on the fields of the derived table and it can be pushed.
            That causes a wrong result.

            To fix it Item_cond::excl_dep_on_table() needs to be added.

            shagalla Galina Shalygina (Inactive) added a comment - This bug occurs because the condition that shouldn't be pushed is pushed into the derived table. This issue is similar with MDEV-16765 . In this special case OR-condition inside the IF-function is defined as dependent only on fields of the derived table while it is not. It happens because Item_cond::excl_dep_on_table() is missing. When going through the IF-function virtual function excl_dep_on_table() reaches OR condition it defines it as Item_func element and tries to take its arguments. It tries to take them from 'args' array. Item_cond has empty 'args' array. All its elements are stored in the list 'list'. So 'args' array is empty and this function defines that this OR condition depends only on the fields of the derived table and it can be pushed. That causes a wrong result. To fix it Item_cond::excl_dep_on_table() needs to be added.
            shagalla Galina Shalygina (Inactive) made changes -
            shagalla Galina Shalygina (Inactive) made changes -
            Assignee Galina Shalygina [ shagalla ] Igor Babaev [ igor ]
            Status In Progress [ 3 ] In Review [ 10002 ]

            Ok to push after a minor correction in the patch comment.

            igor Igor Babaev (Inactive) added a comment - Ok to push after a minor correction in the patch comment.
            igor Igor Babaev (Inactive) made changes -
            Status In Review [ 10002 ] Stalled [ 10000 ]
            igor Igor Babaev (Inactive) made changes -
            Assignee Igor Babaev [ igor ] Galina Shalygina [ shagalla ]

            Pushed in 10.2

            shagalla Galina Shalygina (Inactive) added a comment - Pushed in 10.2
            shagalla Galina Shalygina (Inactive) made changes -
            Fix Version/s 10.2.23 [ 23307 ]
            Fix Version/s 10.2 [ 14601 ]
            Fix Version/s 10.3 [ 22126 ]
            Fix Version/s 10.4 [ 22408 ]
            Resolution Fixed [ 1 ]
            Status Stalled [ 10000 ] Closed [ 6 ]
            serg Sergei Golubchik made changes -
            Workflow MariaDB v3 [ 92066 ] MariaDB v4 [ 155590 ]

            People

              shagalla Galina Shalygina (Inactive)
              FriedemannS Friedemann Schmidt
              Votes:
              0 Vote for this issue
              Watchers:
              6 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.