1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

MDEV-25202: JSON_TABLE: Early table reference leads to unexpected result set

(Also fixes MDEV-25254).
Re-work Name Resolution for the argument of JSON_TABLE(json_doc, ....)
function. The json_doc argument can refer to other tables, but it can
only refer to the tables that precede[*] the JSON_TABLE(...) call.

[*] - For queries with RIGHT JOINs, the "preceding" is determined after
the query is normalized by converting RIGHT JOIN into left one.

The implementation is as follows:
- Table function arguments use their own Name_resolution_context.

- The Name_resolution_context now has a bitmap of tables that should be
  ignored when searching for a field.

- get_disallowed_table_deps() walks the TABLE_LIST::nested_join tree
  and computes a bitmap of tables that do not "precede" the given
  JSON_TABLE(...) invocation  (according the above definition of
  "preceding").
This commit is contained in:
Sergei Petrunia
2021-04-05 14:15:05 +03:00
committed by Alexey Botchkov
parent 13390a70e2
commit 84cf9c2e11
16 changed files with 398 additions and 39 deletions

View File

@ -6319,6 +6319,8 @@ Field *find_field_in_table_sef(TABLE *table, const char *name)
first_table list of tables to be searched for item
last_table end of the list of tables to search for item. If NULL
then search to the end of the list 'first_table'.
ignored_tables Bitmap of tables that should be ignored. Do not try
to find the field in those.
ref if 'item' is resolved to a view field, ref is set to
point to the found view field
report_error Degree of error reporting:
@ -6346,6 +6348,7 @@ Field *find_field_in_table_sef(TABLE *table, const char *name)
Field *
find_field_in_tables(THD *thd, Item_ident *item,
TABLE_LIST *first_table, TABLE_LIST *last_table,
table_map ignored_tables,
Item **ref, find_item_error_report_type report_error,
bool check_privileges, bool register_tree_change)
{
@ -6462,15 +6465,15 @@ find_field_in_tables(THD *thd, Item_ident *item,
db= name_buff;
}
if (first_table && first_table->select_lex &&
first_table->select_lex->end_lateral_table)
last_table= first_table->select_lex->end_lateral_table;
else if (last_table)
if (last_table)
last_table= last_table->next_name_resolution_table;
for (; cur_table != last_table ;
cur_table= cur_table->next_name_resolution_table)
{
if (cur_table->table && (cur_table->table->map & ignored_tables))
continue;
Field *cur_field= find_field_in_table_ref(thd, cur_table, name, length,
item->name.str, db, table_name, ref,
(thd->lex->sql_command ==