You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Bug#21574933 Extra rows with derived table in subquery + XOR
This problem stems from the transformation of IN subqueries
in Item_in_subselect::single_value_in_to_exists_transformer().
The source of the regression is the fix for bug no. 14358878, which
wrapped all selected columns from a derived table that was on the
inner side of an outer join in Item_direct_view_ref objects.
The purpose of the wrapping was to make the columns nullable and
nullability depending on some table from the derived table.
single_value_in_to_exists_transformer() calculated orig_item from one
such column. Prior to the wrapping, nullability information was present
in orig_item. But after the bugfix, real_item() would pass the
Item_direct_view_ref object and return the underlying Item object,
which is not necessarily nullable.
real_item() was originally used so that we do not build a permanent
subquery transformation on top of a runtime item. The wrapped
Item_direct_view_ref objects are runtime objects, meaning that
they cannot be used in a permanent transformation.
The solution is a kludge: If the Item_direct_view_ref object is
nullable, we set the item being pointed to from the
Item_direct_view_ref as nullable as well. This means that we pick up
correct nullability, but the item does not correctly reflect the
nullability of the datum. However, we have not been able to identify
a situation where this causes erroneous or non-optimal execution.
Further on, this means that NULL values from outer joined tables
are included in the query result, meaning that the IN subquery
can return NULL instead of FALSE in cases like this.
2 DEPENDENT SUBQUERY innr2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where
8045
+
2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (Block Nested Loop)
8046
+
Warnings:
8047
+
Note 1276 Field or reference 'test.outr.col_int_key' of SELECT #2 was resolved in SELECT #1
8048
+
Note 1003 /* select#1 */ select `test`.`outr`.`pk` AS `pk`,<in_optimizer>(`test`.`outr`.`col_int`,<exists>(/* select#2 */ select 1 from `test`.`t1` `innr2` left join (`test`.`t2`) on((`test`.`innr2`.`col_date` <> `test`.`t2`.`col_date`)) where ((`test`.`outr`.`col_int_key` < 6) and <if>(outer_field_is_not_null, ((<cache>(`test`.`outr`.`col_int`) = `test`.`t2`.`pk`) or isnull(`test`.`t2`.`pk`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`pk`), true))) AS `x` from `test`.`t3` `outr`
8049
+
SELECT pk,
8050
+
col_int IN
8051
+
(SELECT innr1.pk
8052
+
FROM t1 AS innr2
8053
+
LEFT JOIN (SELECT pk, col_date FROM t2) AS innr1
8054
+
ON innr2.col_date <> innr1.col_date
8055
+
WHERE outr.col_int_key < 6) AS x
8056
+
FROM t3 AS outr;
8057
+
pk x
8058
+
4 NULL
8059
+
SELECT pk,
8060
+
col_int IN
8061
+
(SELECT innr1.pk
8062
+
FROM t1 AS innr2
8063
+
LEFT JOIN (SELECT pk, date'2015-01-01' AS d FROM t2) AS innr1
2 DEPENDENT SUBQUERY innr2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where
8046
+
2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (Block Nested Loop)
8047
+
Warnings:
8048
+
Note 1276 Field or reference 'test.outr.col_int_key' of SELECT #2 was resolved in SELECT #1
8049
+
Note 1003 /* select#1 */ select `test`.`outr`.`pk` AS `pk`,<in_optimizer>(`test`.`outr`.`col_int`,<exists>(/* select#2 */ select 1 from `test`.`t1` `innr2` left join (`test`.`t2`) on((`test`.`innr2`.`col_date` <> `test`.`t2`.`col_date`)) where ((`test`.`outr`.`col_int_key` < 6) and <if>(outer_field_is_not_null, ((<cache>(`test`.`outr`.`col_int`) = `test`.`t2`.`pk`) or isnull(`test`.`t2`.`pk`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`pk`), true))) AS `x` from `test`.`t3` `outr`
8050
+
SELECT pk,
8051
+
col_int IN
8052
+
(SELECT innr1.pk
8053
+
FROM t1 AS innr2
8054
+
LEFT JOIN (SELECT pk, col_date FROM t2) AS innr1
8055
+
ON innr2.col_date <> innr1.col_date
8056
+
WHERE outr.col_int_key < 6) AS x
8057
+
FROM t3 AS outr;
8058
+
pk x
8059
+
4 NULL
8060
+
SELECT pk,
8061
+
col_int IN
8062
+
(SELECT innr1.pk
8063
+
FROM t1 AS innr2
8064
+
LEFT JOIN (SELECT pk, date'2015-01-01' AS d FROM t2) AS innr1
2 DEPENDENT SUBQUERY innr2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where
8046
+
2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where
8047
+
Warnings:
8048
+
Note 1276 Field or reference 'test.outr.col_int_key' of SELECT #2 was resolved in SELECT #1
8049
+
Note 1003 /* select#1 */ select `test`.`outr`.`pk` AS `pk`,<in_optimizer>(`test`.`outr`.`col_int`,<exists>(/* select#2 */ select 1 from `test`.`t1` `innr2` left join (`test`.`t2`) on((`test`.`innr2`.`col_date` <> `test`.`t2`.`col_date`)) where ((`test`.`outr`.`col_int_key` < 6) and <if>(outer_field_is_not_null, ((<cache>(`test`.`outr`.`col_int`) = `test`.`t2`.`pk`) or isnull(`test`.`t2`.`pk`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`pk`), true))) AS `x` from `test`.`t3` `outr`
8050
+
SELECT pk,
8051
+
col_int IN
8052
+
(SELECT innr1.pk
8053
+
FROM t1 AS innr2
8054
+
LEFT JOIN (SELECT pk, col_date FROM t2) AS innr1
8055
+
ON innr2.col_date <> innr1.col_date
8056
+
WHERE outr.col_int_key < 6) AS x
8057
+
FROM t3 AS outr;
8058
+
pk x
8059
+
4 NULL
8060
+
SELECT pk,
8061
+
col_int IN
8062
+
(SELECT innr1.pk
8063
+
FROM t1 AS innr2
8064
+
LEFT JOIN (SELECT pk, date'2015-01-01' AS d FROM t2) AS innr1
2 DEPENDENT SUBQUERY innr2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where
8045
+
2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (Block Nested Loop)
8046
+
Warnings:
8047
+
Note 1276 Field or reference 'test.outr.col_int_key' of SELECT #2 was resolved in SELECT #1
8048
+
Note 1003 /* select#1 */ select `test`.`outr`.`pk` AS `pk`,<in_optimizer>(`test`.`outr`.`col_int`,<exists>(/* select#2 */ select 1 from `test`.`t1` `innr2` left join (`test`.`t2`) on((`test`.`innr2`.`col_date` <> `test`.`t2`.`col_date`)) where ((`test`.`outr`.`col_int_key` < 6) and <if>(outer_field_is_not_null, ((<cache>(`test`.`outr`.`col_int`) = `test`.`t2`.`pk`) or isnull(`test`.`t2`.`pk`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`pk`), true))) AS `x` from `test`.`t3` `outr`
8049
+
SELECT pk,
8050
+
col_int IN
8051
+
(SELECT innr1.pk
8052
+
FROM t1 AS innr2
8053
+
LEFT JOIN (SELECT pk, col_date FROM t2) AS innr1
8054
+
ON innr2.col_date <> innr1.col_date
8055
+
WHERE outr.col_int_key < 6) AS x
8056
+
FROM t3 AS outr;
8057
+
pk x
8058
+
4 NULL
8059
+
SELECT pk,
8060
+
col_int IN
8061
+
(SELECT innr1.pk
8062
+
FROM t1 AS innr2
8063
+
LEFT JOIN (SELECT pk, date'2015-01-01' AS d FROM t2) AS innr1
2 DEPENDENT SUBQUERY innr2 NULL ALL NULL NULL NULL NULL 2 100.00 Using where
8046
+
2 DEPENDENT SUBQUERY t2 NULL ALL NULL NULL NULL NULL 1 100.00 Using where; Using join buffer (Block Nested Loop)
8047
+
Warnings:
8048
+
Note 1276 Field or reference 'test.outr.col_int_key' of SELECT #2 was resolved in SELECT #1
8049
+
Note 1003 /* select#1 */ select `test`.`outr`.`pk` AS `pk`,<in_optimizer>(`test`.`outr`.`col_int`,<exists>(/* select#2 */ select 1 from `test`.`t1` `innr2` left join (`test`.`t2`) on((`test`.`innr2`.`col_date` <> `test`.`t2`.`col_date`)) where ((`test`.`outr`.`col_int_key` < 6) and <if>(outer_field_is_not_null, ((<cache>(`test`.`outr`.`col_int`) = `test`.`t2`.`pk`) or isnull(`test`.`t2`.`pk`)), true)) having <if>(outer_field_is_not_null, <is_not_null_test>(`test`.`t2`.`pk`), true))) AS `x` from `test`.`t3` `outr`
8050
+
SELECT pk,
8051
+
col_int IN
8052
+
(SELECT innr1.pk
8053
+
FROM t1 AS innr2
8054
+
LEFT JOIN (SELECT pk, col_date FROM t2) AS innr1
8055
+
ON innr2.col_date <> innr1.col_date
8056
+
WHERE outr.col_int_key < 6) AS x
8057
+
FROM t3 AS outr;
8058
+
pk x
8059
+
4 NULL
8060
+
SELECT pk,
8061
+
col_int IN
8062
+
(SELECT innr1.pk
8063
+
FROM t1 AS innr2
8064
+
LEFT JOIN (SELECT pk, date'2015-01-01' AS d FROM t2) AS innr1
0 commit comments