← Back to team overview

maria-developers team mailing list archive

Re: [Commits] c6d172f: MDEV-11078: NULL NOT IN (non-empty subquery) should never return results

 

Hi Varun,

Things that look apparently wrong:

1. The patch checks left_expr->null_value without first having made a call 
that will fill that member.
The calling convention is something like this:

  item->val_XXX()  // val_str or val_int()
  // check item->null_value.

If one doesn't need string or integer value, there is item->is_null() call.

2. The patch checks null_value for any kind of left_expr. This is wrong. For 
example, consider a query:

  select
    t1.col IN (select t2.col FROM t2 )
  from t1

Here, it doesn't make any sense to check {t1.col}->null_value at query
planning/rewrite time.  The value (and NULL-ness) of t1.col is different for 
different rows of t1.

As discussed on Slack: please only check for NULL value for items which are 
- constant,
- and "not expensive"
and so have a fixed value which we are allowed to compute at query optimization
phase.

3. I see the patch handles single-value comparisons like

    expr IN (select inner_expr FROM ...)

but what about tuple-based comparisons like:

    (expr1, expr2) IN (select inner_expr1, inner_expr2 FROM ...)

?

I guess they should have a similar issue. If they do not, we need
- an explanation why
- test coverage

On Sun, Feb 26, 2017 at 09:04:40PM +0530, Varun wrote:
> revision-id: c6d172f785f31641832087a432d1966b67efc47a (mariadb-10.2.3-283-gc6d172f)
> parent(s): 78153cf641aea41166d3e79ae99b57b154f6a027
> author: Varun Gupta
> committer: Varun Gupta
> timestamp: 2017-02-26 21:03:29 +0530
> message:
> 
> MDEV-11078: NULL NOT IN (non-empty subquery) should never return results
> 
> Setting the value of cond guard variables during the creation of Tricond Item for null values
> 
> ---
>  mysql-test/r/subselect4.result | 31 +++++++++++++++++++++++++++++++
>  mysql-test/t/subselect4.test   | 18 ++++++++++++++++++
>  sql/item_subselect.cc          | 10 ++++++++++
>  3 files changed, 59 insertions(+)
> 
> diff --git a/mysql-test/r/subselect4.result b/mysql-test/r/subselect4.result
> index 6bbb80c..c3bd50a 100644
> --- a/mysql-test/r/subselect4.result
> +++ b/mysql-test/r/subselect4.result
> @@ -2454,3 +2454,34 @@ x
>  c1
>  1
>  drop table t1;
> +#
> +# MDEV-11078: NULL NOT IN (non-empty subquery) should never return results
> +#
> +create table t1(a int,b int);
> +create table t2(a int,b int);
> +insert into t1 value (NULL,2);
> +select 1 in (1,2, NULL);
> +1 in (1,2, NULL)
> +1
> +select (null)  in (select 1 from t1);
> +(null)  in (select 1 from t1)
> +NULL
> +select (null)  in (select 1 from t2);
> +(null)  in (select 1 from t2)
> +0
> +select 1 in (select 1 from t1);
> +1 in (select 1 from t1)
> +1
> +select 1 in (select 1 from t2);
> +1 in (select 1 from t2)
> +0
> +select 1 from dual where null in (select 1 from t1);
> +1
> +select 1 from dual where null in (select 1 from t2);
> +1
> +select 1 from dual where null not in (select 1 from t1);
> +1
> +select 1 from dual where null not in (select 1 from t2);
> +1
> +1
> +drop table t1,t2;
> diff --git a/mysql-test/t/subselect4.test b/mysql-test/t/subselect4.test
> index 253160c..785b79d 100644
> --- a/mysql-test/t/subselect4.test
> +++ b/mysql-test/t/subselect4.test
> @@ -2009,3 +2009,21 @@ insert into t1 values(2,1),(1,2);
>  select (select c1 from t1 group by c1,c2 order by c1 limit 1) as x;
>  (select c1 from t1 group by c1,c2 order by c1 limit 1);
>  drop table t1;
> +
> +--echo #
> +--echo # MDEV-11078: NULL NOT IN (non-empty subquery) should never return results
> +--echo #
> +
> +create table t1(a int,b int);
> +create table t2(a int,b int);
> +insert into t1 value (NULL,2);
> +select 1 in (1,2, NULL);
> +select (null)  in (select 1 from t1);
> +select (null)  in (select 1 from t2);
> +select 1 in (select 1 from t1);
> +select 1 in (select 1 from t2);
> +select 1 from dual where null in (select 1 from t1);
> +select 1 from dual where null in (select 1 from t2);
> +select 1 from dual where null not in (select 1 from t1);
> +select 1 from dual where null not in (select 1 from t2);
> +drop table t1,t2;
> diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
> index 94bc71c..b9c798e 100644
> --- a/sql/item_subselect.cc
> +++ b/sql/item_subselect.cc
> @@ -2113,6 +2113,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
>          We can encounter "NULL IN (SELECT ...)". Wrap the added condition
>          within a trig_cond.
>        */
> +      if(left_expr->null_value)
> +        set_cond_guard_var(0,FALSE);
>        item= new (thd->mem_root) Item_func_trig_cond(thd, item, get_cond_guard(0));
>      }
>  
> @@ -2137,6 +2139,9 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
>  	having= new (thd->mem_root) Item_is_not_null_test(thd, this, having);
>          if (left_expr->maybe_null)
>          {
> +          if(left_expr->null_value)
> +            set_cond_guard_var(0,FALSE);
> +
>            if (!(having= new (thd->mem_root) Item_func_trig_cond(thd, having,
>                                                              get_cond_guard(0))))
>              DBUG_RETURN(true);
> @@ -2155,6 +2160,9 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
>        */
>        if (!abort_on_null && left_expr->maybe_null)
>        {
> +        if(left_expr->null_value)
> +            set_cond_guard_var(0, FALSE);
> +
>          if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item,
>                                                              get_cond_guard(0))))
>            DBUG_RETURN(true);
> @@ -2184,6 +2192,8 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
>                                                    (char *)"<result>"));
>          if (!abort_on_null && left_expr->maybe_null)
>          {
> +          if(left_expr->null_value)
> +            set_cond_guard_var(0,FALSE);
>            if (!(new_having= new (thd->mem_root) Item_func_trig_cond(thd, new_having,
>                                                              get_cond_guard(0))))
>              DBUG_RETURN(true);
> _______________________________________________
> commits mailing list
> commits@xxxxxxxxxxx
> https://lists.askmonty.org/cgi-bin/mailman/listinfo/commits

-- 
BR
 Sergei
-- 
Sergei Petrunia, Software Developer
MariaDB Corporation | Skype: sergefp | Blog: http://s.petrunia.net/blog