Commit 4a10dd02 authored by Sergei Petrunia's avatar Sergei Petrunia Committed by Alexey Botchkov

MDEV-25380: JSON_TABLE: Assertion `join->best_read < double(1.797...) fails

The query used a subquery of this form:

SELECT ...
WHERE
   EXISTS( SELECT ...
           FROM JSON_TABLE(outer_ref, ..) as JT
           WHERE trivial_correlation_cond)

EXISTS-to-IN conversion code was unable to see that the subquery will
still be correlated after the trivial_correlation is removed, which
eventually caused a crash due to inability to construct a query plan.

Fixed by making Item_subselect::walk() also walk arguments of Table
Functions.
parent eb2550ee
...@@ -734,5 +734,21 @@ Shirt blue 20 ...@@ -734,5 +734,21 @@ Shirt blue 20
Shirt white 20 Shirt white 20
drop table t1; drop table t1;
# #
# MDEV-25380: JSON_TABLE: Assertion `join->best_read < double(1.797...) fails
#
CREATE TABLE t1 (a INT, b TEXT);
INSERT INTO t1 VALUES (1,'{}'),(2,'[]');
explain
SELECT *
FROM t1
WHERE
EXISTS(SELECT *
FROM JSON_TABLE(b, '$' COLUMNS(o FOR ORDINALITY)) AS jt
WHERE jt.o = t1.a);
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 ALL NULL NULL NULL NULL 2
1 PRIMARY jt ALL NULL NULL NULL NULL 40 Table function: json_table; Using where; FirstMatch(t1)
drop table t1;
#
# End of 10.6 tests # End of 10.6 tests
# #
...@@ -627,6 +627,23 @@ select t.item_name, jt.* from (select t1.item_name, concat(concat(concat("{\"col ...@@ -627,6 +627,23 @@ select t.item_name, jt.* from (select t1.item_name, concat(concat(concat("{\"col
drop table t1; drop table t1;
--echo #
--echo # MDEV-25380: JSON_TABLE: Assertion `join->best_read < double(1.797...) fails
--echo #
CREATE TABLE t1 (a INT, b TEXT);
INSERT INTO t1 VALUES (1,'{}'),(2,'[]');
explain
SELECT *
FROM t1
WHERE
EXISTS(SELECT *
FROM JSON_TABLE(b, '$' COLUMNS(o FOR ORDINALITY)) AS jt
WHERE jt.o = t1.a);
drop table t1;
--echo # --echo #
--echo # End of 10.6 tests --echo # End of 10.6 tests
--echo # --echo #
...@@ -719,6 +719,34 @@ bool Item_subselect::unknown_splocal_processor(void *argument) ...@@ -719,6 +719,34 @@ bool Item_subselect::unknown_splocal_processor(void *argument)
} }
static
int walk_table_functions_for_list(Item_processor processor,
bool walk_subquery, void *argument,
List<TABLE_LIST>& join_list)
{
List_iterator<TABLE_LIST> li(join_list);
int res;
while (TABLE_LIST *table= li++)
{
if (Table_function_json_table *tf= table->table_function)
{
if ((res= tf->walk_items(processor, walk_subquery, argument)))
{
return res;
}
}
if (table->nested_join)
{
if ((res= walk_table_functions_for_list(processor, walk_subquery,
argument,
table->nested_join->join_list)))
return res;
}
}
return 0;
}
bool Item_subselect::walk(Item_processor processor, bool walk_subquery, bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
void *argument) void *argument)
{ {
...@@ -751,6 +779,11 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery, ...@@ -751,6 +779,11 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
argument)) argument))
return 1; return 1;
/* TODO: why does this walk WHERE/HAVING but not ON expressions of outer joins? */ /* TODO: why does this walk WHERE/HAVING but not ON expressions of outer joins? */
/* Consider walking ON epxression in walk_table_functions_for_list */
if (walk_table_functions_for_list(processor, walk_subquery, argument,
*lex->join_list))
return 1;
while ((item=li++)) while ((item=li++))
{ {
......
...@@ -1341,6 +1341,12 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table, ...@@ -1341,6 +1341,12 @@ int Table_function_json_table::setup(THD *thd, TABLE_LIST *sql_table,
return FALSE; return FALSE;
} }
int Table_function_json_table::walk_items(Item_processor processor,
bool walk_subquery, void *argument)
{
return m_json->walk(processor, walk_subquery, argument);
}
void Table_function_json_table::get_estimates(ha_rows *out_rows, void Table_function_json_table::get_estimates(ha_rows *out_rows,
double *scan_time, double *scan_time,
double *startup_cost) double *startup_cost)
......
...@@ -200,6 +200,9 @@ class Table_function_json_table : public Sql_alloc ...@@ -200,6 +200,9 @@ class Table_function_json_table : public Sql_alloc
/*** Name resolution functions ***/ /*** Name resolution functions ***/
int setup(THD *thd, TABLE_LIST *sql_table, SELECT_LEX *s_lex); int setup(THD *thd, TABLE_LIST *sql_table, SELECT_LEX *s_lex);
int walk_items(Item_processor processor, bool walk_subquery,
void *argument);
/*** Functions for interaction with the Query Optimizer ***/ /*** Functions for interaction with the Query Optimizer ***/
void fix_after_pullout(TABLE_LIST *sql_table, void fix_after_pullout(TABLE_LIST *sql_table,
st_select_lex *new_parent, bool merge); st_select_lex *new_parent, bool merge);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment