select * from t1 -- #1
|
where t1c in
|
(
|
select * from -- #2
|
(
|
select t2a from t2 -- #3
|
where t2a in
|
(
|
select t3a from (select * from t3) table3 -- #4, #5
|
where t3a in
|
(
|
select t4a from t4 -- #6
|
where t4a < any(select t5c from t5 where t5a > t3a) -- #7
|
)
|
)
|
) dt
|
)
|
run as a prepared statement, this causes the server to crash on 2nd execution.
During JOIN::prepare on select #7 (innermost one) we run fix_fields on our where clause (t5a>t3a).
(re)fixing t5a, we attempt name resolution, search the fields context for the table containing the
field t3a. During the 1st execution, we "saved" the TABLE_LIST pointing to "table3" in item->cached_table,
so we search this table reference, finding our field.
During the first execution, after resolving the field t3a we need to mark as dependent, all the selects
between where the object is used and where the object is resolved. Prior to optimization, this is
select #7 (used) and select #4 (resolved).
During optimization in the 1st execution, selects # 1, 3, 4 & 5 are all collapsed into a semijoin
select t1.t1a AS t1a,t1.t1b AS t1b,t1.t1c AS t1c from ((((t4) join (t3)) join t2)) join t1 where t1.t1c in (subquery#2)
|
Our table list pointer has a select_lex from select #1
as we are fixing an outer reference, we now mark all the selects from where t3a is used (select #7) to where it is found (select #1)
as dependent in mark_select_range_as_dependent().
We start with select #7 and mark the containing item's used_tables_cache with OUTER_REF_TABLE_BIT and iterate outward.
The next most outwards using this->context.outer_select() is select #6. This is marked as above.
The next most outwards using this->context.outer_select() is select #4. This is marked as above.
The next most outwards using this->context.outer_select() is select #3.
this is a merged derived table dt, it has been merged into select #2, master_unit()->item is null
there is no containing item for the unit, so we crash trying to follow a null pointer.
The simplest fix for this is to encapsulate context->select_lex and use accessor functions that skip merged selects.
(
(
(
(
)
)
) dt
)
run as a prepared statement, this causes the server to crash on 2nd execution.
During JOIN::prepare on select #7 (innermost one) we run fix_fields on our where clause (t5a>t3a).
(re)fixing t5a, we attempt name resolution, search the fields context for the table containing the
field t3a. During the 1st execution, we "saved" the TABLE_LIST pointing to "table3" in item->cached_table,
so we search this table reference, finding our field.
During the first execution, after resolving the field t3a we need to mark as dependent, all the selects
between where the object is used and where the object is resolved. Prior to optimization, this is
select #7 (used) and select #4 (resolved).
During optimization in the 1st execution, selects # 1, 3, 4 & 5 are all collapsed into a semijoin
Our table list pointer has a select_lex from select #1
as we are fixing an outer reference, we now mark all the selects from where t3a is used (select #7) to where it is found (select #1)
as dependent in mark_select_range_as_dependent().
We start with select #7 and mark the containing item's used_tables_cache with OUTER_REF_TABLE_BIT and iterate outward.
The next most outwards using this->context.outer_select() is select #6. This is marked as above.
The next most outwards using this->context.outer_select() is select #4. This is marked as above.
The next most outwards using this->context.outer_select() is select #3.
this is a merged derived table dt, it has been merged into select #2, master_unit()->item is null
there is no containing item for the unit, so we crash trying to follow a null pointer.
The simplest fix for this is to encapsulate context->select_lex and use accessor functions that skip merged selects.