maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #10423
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