Details
Description
PoC:
SELECT ( ( ( WITH x AS ( WITH x AS ( SELECT x FROM ( SELECT * FROM ( SELECT 'x' ) x ) x WHERE ( SELECT x * x ORDER BY ( SELECT 1 GROUP BY 1 IN ( SELECT x ) ) ) ) SELECT x FROM x WHERE x ) SELECT * FROM x ) ) ) ; |
docker log:
mariadbd(my_print_stacktrace+0x32)[0x556678eaa7c2]
|
mariadbd(handle_fatal_signal+0x488)[0x556678983cf8]
|
/lib/x86_64-linux-gnu/libc.so.6(+0x42520)[0x7f8dd27eb520]
|
mariadbd(_ZN10Item_field15fix_outer_fieldEP3THDPP5FieldPP4Item+0x31b)[0x5566789ae8ab]
|
mariadbd(_ZN10Item_field10fix_fieldsEP3THDPP4Item+0x415)[0x5566789af675]
|
mariadbd(_ZN20Item_direct_view_ref10fix_fieldsEP3THDPP4Item+0x11b)[0x5566789b04ab]
|
mariadbd(_ZN9Item_func10fix_fieldsEP3THDPP4Item+0x8c)[0x5566789f4fec]
|
mariadbd(_ZN9Item_cond10fix_fieldsEP3THDPP4Item+0x139)[0x5566789ce5c9]
|
mariadbd(_ZN4JOIN14optimize_innerEv+0x69b)[0x55667878fb5b]
|
mariadbd(_ZN4JOIN8optimizeEv+0xda)[0x556678790e2a]
|
mariadbd(+0x7ec60c)[0x5566786ca60c]
|
mariadbd(_Z27mysql_handle_single_derivedP3LEXP10TABLE_LISTj+0x95)[0x5566786c9e35]
|
mariadbd(_ZN4JOIN14optimize_innerEv+0xb27)[0x55667878ffe7]
|
mariadbd(_ZN4JOIN8optimizeEv+0xda)[0x556678790e2a]
|
mariadbd(_ZN13st_select_lex31optimize_unflattened_subqueriesEb+0x115)[0x5566786eaa55]
|
mariadbd(_ZN4JOIN28optimize_constant_subqueriesEv+0x35)[0x556678889d55]
|
mariadbd(_ZN4JOIN14optimize_innerEv+0x503)[0x55667878f9c3]
|
mariadbd(_ZN4JOIN8optimizeEv+0xda)[0x556678790e2a]
|
mariadbd(_Z12mysql_selectP3THDP10TABLE_LISTR4ListI4ItemEPS4_jP8st_orderS9_S7_S9_yP13select_resultP18st_select_lex_unitP13st_select_lex+0xd1)[0x556678790f21]
|
mariadbd(_Z13handle_selectP3THDP3LEXP13select_resulty+0x154)[0x556678791774]
|
mariadbd(+0x826f55)[0x556678704f55]
|
mariadbd(_Z21mysql_execute_commandP3THDb+0x419e)[0x556678713f0e]
|
mariadbd(_Z11mysql_parseP3THDPcjP12Parser_state+0x1e7)[0x556678715237]
|
mariadbd(_Z16dispatch_command19enum_server_commandP3THDPcjb+0x14bd)[0x556678717a1d]
|
mariadbd(_Z10do_commandP3THDb+0x138)[0x556678719818]
|
mariadbd(_Z24do_handle_one_connectionP7CONNECTb+0x3bf)[0x5566788413af]
|
mariadbd(handle_one_connection+0x5d)[0x5566788416fd]
|
mariadbd(+0xcd1906)[0x556678baf906]
|
/lib/x86_64-linux-gnu/libc.so.6(+0x94b43)[0x7f8dd283db43]
|
/lib/x86_64-linux-gnu/libc.so.6(clone+0x44)[0x7f8dd28cebb4]
|
|
Trying to get some variables.
|
Some pointers may be invalid and cause the dump to abort.
|
Query (0x7f8d700130d8): SELECT ( ( ( WITH x AS ( WITH x AS ( SELECT x FROM ( SELECT * FROM ( SELECT 'x' ) x ) x WHERE ( SELECT x * x ORDER BY ( SELECT 1 GROUP BY 1 IN ( SELECT x ) ) ) ) SELECT x FROM x WHERE x ) SELECT * FROM x ) ) )
|
|
Connection ID (thread ID): 4
|
Status: NOT_KILLED
|
|
Optimizer switch: index_merge=on,index_merge_union=on,index_merge_sort_union=on,index_merge_intersection=on,index_merge_sort_intersection=off,engine_condition_pushdown=off,index_condition_pushdown=on,derived_merge=on,derived_with_keys=on,firstmatch=on,loosescan=on,materialization=on,in_to_exists=on,semijoin=on,partial_match_rowid_merge=on,partial_match_table_scan=on,subquery_cache=on,mrr=off,mrr_cost_based=off,mrr_sort_keys=off,outer_join_with_cache=on,semijoin_with_cache=on,join_cache_incremental=on,join_cache_hashed=on,join_cache_bka=on,optimize_join_buffer_size=on,table_elimination=on,extended_keys=on,exists_to_in=on,orderby_uses_equalities=on,condition_pushdown_for_derived=on,split_materialized=on,condition_pushdown_for_subquery=on,rowid_filter=on,condition_pushdown_from_having=on,not_null_range_scan=off,hash_join_cardinality=on
|
Attachments
Issue Links
- relates to
-
MDEV-29300 Assertion `*ref && (*ref)->fixed()' failed in Item_field::fix_outer_field on SELECT
-
- Confirmed
-
-
MDEV-36374 Item_subselect::used_tables_cache assertion check.
-
- Open
-
Let's investigate why we have a problem when fixing dt2.x from the expression dt2.x >=1 pushed into the derived table dt. This dt2.x is a full copy of dt2.x from the item list of the select that we get after having merged dt1. Due to this merge this occurrence of dt2.x is wrapped into an Item_direct_view_ref reference item. Another occurrence of
dt2.x appears after the merge in (SELECT dt1.x). It's also wrapped into an Item_direct_view_ref reference item. Bear in mind that both wrapper reference item points to the same dt2.x in the translation table created for dt1. We see that by the time when the first item Item_direct_view_ref(dt2.x) is used to create a copy of it to replace dt1.x from the expression dt1.x>= 1 to be pushed into dt the context structure of dt2.x from the translation table is already incorrect. Let's check when the pointer to this structure is changed. It's changed in the function:
bool Item_ident::remove_dependence_processor(void * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
if (get_depended_from() == (st_select_lex *) arg)
depended_from= 0;
context= &((st_select_lex *) arg)->context;
DBUG_RETURN(0);
}
when we execute the following code:
/*
it is single select without tables => possible optimization
remove the dependence mark since the item is moved to upper
select and is not outer anymore.
*/
where_item->walk(&Item::remove_dependence_processor, 0,
select_lex->outer_select());
Here we have:
(gdb) p dbug_print_select(select_lex)
$8 = 0x555557b87600 <dbug_item_print_buf> "select dt2.x"
(gdb) p dbug_print_item(where_item)
$9 = 0x555557b87600 <dbug_item_print_buf> "dt2.x"
(gdb) p where_item->type()
$10 = Item::REF_ITEM
(gdb) p ((Item_ref*)where_item)->ref_type()
$11 = Item_ref::VIEW_REF
(gdb) p ((Item_direct_view_ref*)where_item)->view->alias
$12 = {str = 0x7fff74019b30 "dt1", length = 3}
(gdb) p (*(((Item_direct_view_ref*)where_item)->ref))->type()
$14 = Item::FIELD_ITEM
(gdb) p dbug_print_item(*(((Item_direct_view_ref*)where_item)->ref))
$15 = 0x555557b87600 <dbug_item_print_buf> "dt2.x"
We see that the statement:
context= &((st_select_lex *) arg)->context;
effectively sets the new context of the occurrence dt2.x in the select list. After this change we have the context with:
(gdb) p dbug_print_select(((st_select_lex *) arg)->context.select_lex)
$38 = 0x555557b87600 <dbug_item_print_buf> "select t2.a from t2 where 1 in (subquery#6) and t2.a < 2"
gdb) p ((st_select_lex *) arg)->context.first_name_resolution_table->alias
$39 = {str = 0x7fff7801a8e0 "t2", length = 2}
dt2.x cannot be resolved a a field of t2.
The context of Item_direct_view_ref wrapper around dt2.x is also changed and in the same way.
Note that only the occurrence of dt2.x in the IN predicate is an outer reference. And
get_depended_from() != NULL only for this occurrence.
The following implementation of Item_ident::remove_dependence_processor could fix this problem:
bool Item_ident::remove_dependence_processor(void * arg)
{
DBUG_ENTER("Item_ident::remove_dependence_processor");
if (get_depended_from() == (st_select_lex *) arg)
{
depended_from= 0;
context= &((st_select_lex *) arg)->context;
}
DBUG_RETURN(0);
}
And indeed with this change we have:
MariaDB [test]> SELECT dt.x
-> FROM
-> (
-> SELECT dt1.x
-> FROM
-> (
-> SELECT dt2.x
-> FROM
-> (
-> SELECT t1.x FROM t1 WHERE t1.x < 2 GROUP BY t1.x
-> ) dt2
-> ) dt1
-> WHERE (SELECT t2.a FROM t2 WHERE (1 IN (SELECT dt1.x)) AND t2.a < 2) != 0
-> GROUP BY dt1.x
-> ) dt
-> WHERE dt.x>=1;
+------+
| x |
+------+
| 1 |
+------+
and all tests from the main test suite pass, and with --ps-protocol and --view-protocol as well.
Yet the query itself returns the empty set when executed in prepared mode.
MariaDB [test]> PREPARE stmt FROM "
"> SELECT dt.x
"> FROM
"> (
"> SELECT dt1.x
"> FROM
"> (
"> SELECT dt2.x
"> FROM
"> (
"> SELECT t1.x FROM t1 WHERE t1.x < 2 GROUP BY t1.x
"> ) dt2
"> ) dt1
"> WHERE (SELECT t2.a FROM t2 WHERE (1 IN (SELECT dt1.x)) AND t2.a < 2) != 0
"> GROUP BY dt1.x
"> ) dt
"> WHERE dt.x>=1;
"> ";
Query OK, 0 rows affected (0.002 sec)
Statement prepared
MariaDB [test]> EXECUTE stmt;
Empty set ( 0.003 sec)