[MDEV-11078] NULL NOT IN (non-empty subquery) should never return results Created: 2016-10-18 Updated: 2017-03-05 Resolved: 2017-03-05 |
|
| Status: | Closed |
| Project: | MariaDB Server |
| Component/s: | Data Manipulation - Subquery |
| Affects Version/s: | 10.1.18, 5.5, 10.0, 10.1, 10.2 |
| Fix Version/s: | 5.5.55 |
| Type: | Bug | Priority: | Major |
| Reporter: | Roel Harbers | Assignee: | Varun Gupta (Inactive) |
| Resolution: | Fixed | Votes: | 0 |
| Labels: | None | ||
| Environment: |
OS X El Capitan, MariaDB installed through Homebrew |
||
| Sprint: | 10.0.30 |
| Description |
|
I'm confused by the behaviour of `NULL` in a `NOT IN` expression. (MariaDB 10.1.18):
This is as I expected, since `NULL` is not equal or unequal to anything.
Huh? How can that be? Maybe it's because I can't read the mysql.user table?
No, it returns a value. When selecting the one from a actual table, not `dual`, or an inline list expression, the behaviour is different. Is this a bug in MariaDB? An old MySQL server (5.5.40) I tried this with gave the expected empty set for all queries. |
| Comments |
| Comment by Elena Stepanova [ 2016-10-18 ] | |||||||||||||||
|
Thanks for the report and test case. | |||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2017-02-19 ] | |||||||||||||||
|
| |||||||||||||||
| Comment by Sergei Petrunia [ 2017-02-22 ] | |||||||||||||||
|
Results of investigation discussion: This should not happen (as the subquery produces rows). However it does happen: IN->EXISTS rewrite changes the subquery to be
The trig_cond is "enabled" at optimization phase, the optimizer sees it as constant, evaluates it, finds it to be NULL, and concludes that the subquery has "Impossible WHERE". | |||||||||||||||
| Comment by Sergei Petrunia [ 2017-02-22 ] | |||||||||||||||
|
That is, Subquery's left expression is NULL. This means that trig_cond should be disabled when we evaluate the subquery. However, subquery optimization code assumes it to be enabled, and produces a wrong query result. | |||||||||||||||
| Comment by Sergei Petrunia [ 2017-02-22 ] | |||||||||||||||
|
More details: I stop here in the subquery:
Then, the trigcond is moved into join->exec_const_cond, and we reach this code:
where is_expensive()=false, and cond->val_int()==0. | |||||||||||||||
| Comment by Sergei Petrunia [ 2017-02-22 ] | |||||||||||||||
|
So, for trigcond(const_expr), we have 1. const_item() = FALSE #1 seems to be correct (as the value may change during the statement execution, depending on whether trigger is ON or OFF) #2 seems to be incorrect. Should it be OUTER_REF_TABLE_BIT instead? | |||||||||||||||
| Comment by Varun Gupta (Inactive) [ 2017-02-22 ] | |||||||||||||||
|
According to documentation: For our query the above condition holds "SELECT 1 from dual where NULL in (select t1 from t1)" |