Commit f8bf2a01 authored by Dmitry Shulga's avatar Dmitry Shulga

MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning...

MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning in case it is executed in PS (prepared statement) mode

The EXPLAIN EXTENDED statement run as a prepared statement can produce extra
warning comparing with a case when EXPLAIN EXTENDED statement is run as
a regular statement. For example, the following test case
  CREATE TABLE t1 (c int);
  CREATE TABLE t2 (d int);
  EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1;

produces the extra warning
  "Field or reference 'c' of SELECT #2 was resolved in SELECT #1"
in case the above mentioned "EXPLAIN EXTENDED" statement is executed
in PS mode, that is by submitting the following statements:
   PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1";
   EXECUTE stmt;

The reason of the extra warning emittion is in a way items
are handled (being fixed) during execution of the JOIN::prepare() method.
The method Item_field::fix_fields() calls the find_field_in_tables()
function in case a field hasn't been associated yet with the item.
Implementation of the find_field_in_tables() function first checks whether
a table containing the required field was already opened and cached.
It is done by checking the data member item->cached_table. This data member
is set on handling the PRERARE FROM statement and checked on executing
the EXECUTE statement. If the data member item->cached_table is set
the find_field_in_tables() function invoked and the
mark_select_range_as_dependent() function called if the field
is an outer referencee. The mark_select_range_as_dependent() function
calls the mark_as_dependent() function that finally invokes
the push_warning_printf() function that produces extra warning.

To fix the issue, calling of push_warning_printf() is elimited in case
it was run indirectly in result of hanlding already opened table from
the Item_field::fix_fields() method.
parent e95cdc45
...@@ -5419,5 +5419,42 @@ id select_type table type possible_keys key key_len ref rows Extra ...@@ -5419,5 +5419,42 @@ id select_type table type possible_keys key key_len ref rows Extra
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
# #
# MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning
# in case it is executed in PS (prepared statement) mode
#
CREATE TABLE t1 (c int);
CREATE TABLE t2 (d int);
# EXPLAIN EXTENDED in regular way (not PS mode)
EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1`
SHOW WARNINGS;
Level Code Message
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1`
# Now run the same EXPLAIN EXTENDED in PS mode. Number of warnings
# and their content must be the same as in case running the statement
# in regular way
PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1";
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
EXECUTE stmt;
id select_type table type possible_keys key key_len ref rows filtered Extra
1 PRIMARY t1 system NULL NULL NULL NULL 0 0.00 const row not found
2 SUBQUERY NULL NULL NULL NULL NULL NULL NULL NULL Impossible WHERE noticed after reading const tables
Warnings:
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1`
SHOW WARNINGS;
Level Code Message
Note 1276 Field or reference 'test.t1.c' of SELECT #2 was resolved in SELECT #1
Note 1003 select (select 1 from `test`.`t2` where 0) AS `(SELECT 1 FROM t2 WHERE d = c)` from `test`.`t1`
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
#
# End of 10.2 tests # End of 10.2 tests
# #
...@@ -4926,6 +4926,26 @@ EXECUTE stmt; ...@@ -4926,6 +4926,26 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt; DEALLOCATE PREPARE stmt;
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning
--echo # in case it is executed in PS (prepared statement) mode
--echo #
CREATE TABLE t1 (c int);
CREATE TABLE t2 (d int);
--echo # EXPLAIN EXTENDED in regular way (not PS mode)
EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1;
SHOW WARNINGS;
--echo # Now run the same EXPLAIN EXTENDED in PS mode. Number of warnings
--echo # and their content must be the same as in case running the statement
--echo # in regular way
PREPARE stmt FROM "EXPLAIN EXTENDED SELECT (SELECT 1 FROM t2 WHERE d = c) FROM t1";
EXECUTE stmt;
SHOW WARNINGS;
DEALLOCATE PREPARE stmt;
DROP TABLE t1, t2;
--echo # --echo #
--echo # End of 10.2 tests --echo # End of 10.2 tests
--echo # --echo #
...@@ -4668,11 +4668,14 @@ bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) ...@@ -4668,11 +4668,14 @@ bool Item_ref_null_helper::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
@param resolved_item item which was resolved in outer SELECT(for warning) @param resolved_item item which was resolved in outer SELECT(for warning)
@param mark_item item which should be marked (can be differ in case of @param mark_item item which should be marked (can be differ in case of
substitution) substitution)
@param suppress_warning_output flag specifying whether to suppress output of
a warning message
*/ */
static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
Item_ident *resolved_item, Item_ident *resolved_item,
Item_ident *mark_item) Item_ident *mark_item,
bool suppress_warning_output)
{ {
DBUG_ENTER("mark_as_dependent"); DBUG_ENTER("mark_as_dependent");
...@@ -4685,7 +4688,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, ...@@ -4685,7 +4688,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
if (current->mark_as_dependent(thd, last, if (current->mark_as_dependent(thd, last,
/** resolved_item psergey-thu **/ mark_item)) /** resolved_item psergey-thu **/ mark_item))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (thd->lex->describe & DESCRIBE_EXTENDED) if ((thd->lex->describe & DESCRIBE_EXTENDED) && !suppress_warning_output)
{ {
const char *db_name= (resolved_item->db_name ? const char *db_name= (resolved_item->db_name ?
resolved_item->db_name : ""); resolved_item->db_name : "");
...@@ -4714,6 +4717,8 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, ...@@ -4714,6 +4717,8 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
@param found_item Item which was found during resolving (if resolved @param found_item Item which was found during resolving (if resolved
identifier belongs to VIEW) identifier belongs to VIEW)
@param resolved_item Identifier which was resolved @param resolved_item Identifier which was resolved
@param suppress_warning_output flag specifying whether to suppress output of
a warning message
@note @note
We have to mark all items between current_sel (including) and We have to mark all items between current_sel (including) and
...@@ -4727,7 +4732,8 @@ void mark_select_range_as_dependent(THD *thd, ...@@ -4727,7 +4732,8 @@ void mark_select_range_as_dependent(THD *thd,
SELECT_LEX *last_select, SELECT_LEX *last_select,
SELECT_LEX *current_sel, SELECT_LEX *current_sel,
Field *found_field, Item *found_item, Field *found_field, Item *found_item,
Item_ident *resolved_item) Item_ident *resolved_item,
bool suppress_warning_output)
{ {
/* /*
Go from current SELECT to SELECT where field was resolved (it Go from current SELECT to SELECT where field was resolved (it
...@@ -4762,7 +4768,7 @@ void mark_select_range_as_dependent(THD *thd, ...@@ -4762,7 +4768,7 @@ void mark_select_range_as_dependent(THD *thd,
found_field->table->map; found_field->table->map;
prev_subselect_item->const_item_cache= 0; prev_subselect_item->const_item_cache= 0;
mark_as_dependent(thd, last_select, current_sel, resolved_item, mark_as_dependent(thd, last_select, current_sel, resolved_item,
dependent); dependent, suppress_warning_output);
} }
} }
...@@ -5228,7 +5234,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ...@@ -5228,7 +5234,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
context->select_lex, this, context->select_lex, this,
((ref_type == REF_ITEM || ((ref_type == REF_ITEM ||
ref_type == FIELD_ITEM) ? ref_type == FIELD_ITEM) ?
(Item_ident*) (*reference) : 0)); (Item_ident*) (*reference) : 0), false);
return 0; return 0;
} }
} }
...@@ -5240,7 +5246,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ...@@ -5240,7 +5246,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
context->select_lex, this, context->select_lex, this,
((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ?
(Item_ident*) (*reference) : (Item_ident*) (*reference) :
0)); 0), false);
if (thd->lex->in_sum_func && if (thd->lex->in_sum_func &&
thd->lex->in_sum_func->nest_level >= select->nest_level) thd->lex->in_sum_func->nest_level >= select->nest_level)
{ {
...@@ -5354,7 +5360,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ...@@ -5354,7 +5360,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
set_max_sum_func_level(thd, select); set_max_sum_func_level(thd, select);
mark_as_dependent(thd, last_checked_context->select_lex, mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, rf, context->select_lex, rf,
rf); rf, false);
return 0; return 0;
} }
...@@ -5367,7 +5373,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) ...@@ -5367,7 +5373,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference)
set_max_sum_func_level(thd, select); set_max_sum_func_level(thd, select);
mark_as_dependent(thd, last_checked_context->select_lex, mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, context->select_lex,
this, (Item_ident*)*reference); this, (Item_ident*)*reference, false);
if (last_checked_context->select_lex->having_fix_field) if (last_checked_context->select_lex->having_fix_field)
{ {
Item_ref *rf; Item_ref *rf;
...@@ -7401,7 +7407,7 @@ class Dependency_marker: public Field_enumerator ...@@ -7401,7 +7407,7 @@ class Dependency_marker: public Field_enumerator
if (tbl->table == item->field->table) if (tbl->table == item->field->table)
{ {
if (sel != current_select) if (sel != current_select)
mark_as_dependent(thd, sel, current_select, item, item); mark_as_dependent(thd, sel, current_select, item, item, false);
return; return;
} }
} }
...@@ -7596,7 +7602,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -7596,7 +7602,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
((refer_type == REF_ITEM || ((refer_type == REF_ITEM ||
refer_type == FIELD_ITEM) ? refer_type == FIELD_ITEM) ?
(Item_ident*) (*reference) : (Item_ident*) (*reference) :
0)); 0), false);
/* /*
view reference found, we substituted it instead of this view reference found, we substituted it instead of this
Item, so can quit Item, so can quit
...@@ -7646,7 +7652,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -7646,7 +7652,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
goto error; goto error;
thd->change_item_tree(reference, fld); thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex, mark_as_dependent(thd, last_checked_context->select_lex,
current_sel, fld, fld); current_sel, fld, fld, false);
/* /*
A reference is resolved to a nest level that's outer or the same as A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of the nest level of the enclosing set function : adjust the value of
...@@ -7669,7 +7675,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ...@@ -7669,7 +7675,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
/* Should be checked in resolve_ref_in_select_and_group(). */ /* Should be checked in resolve_ref_in_select_and_group(). */
DBUG_ASSERT(*ref && (*ref)->fixed); DBUG_ASSERT(*ref && (*ref)->fixed);
mark_as_dependent(thd, last_checked_context->select_lex, mark_as_dependent(thd, last_checked_context->select_lex,
context->select_lex, this, this); context->select_lex, this, this, false);
/* /*
A reference is resolved to a nest level that's outer or the same as A reference is resolved to a nest level that's outer or the same as
the nest level of the enclosing set function : adjust the value of the nest level of the enclosing set function : adjust the value of
......
...@@ -6088,7 +6088,8 @@ void mark_select_range_as_dependent(THD *thd, ...@@ -6088,7 +6088,8 @@ void mark_select_range_as_dependent(THD *thd,
st_select_lex *last_select, st_select_lex *last_select,
st_select_lex *current_sel, st_select_lex *current_sel,
Field *found_field, Item *found_item, Field *found_field, Item *found_item,
Item_ident *resolved_item); Item_ident *resolved_item,
bool suppress_warning_output);
extern Cached_item *new_Cached_item(THD *thd, Item *item, extern Cached_item *new_Cached_item(THD *thd, Item *item,
bool pass_through_ref); bool pass_through_ref);
......
...@@ -283,7 +283,8 @@ class Item_subselect :public Item_result_field, ...@@ -283,7 +283,8 @@ class Item_subselect :public Item_result_field,
friend bool Item_ref::fix_fields(THD *, Item **); friend bool Item_ref::fix_fields(THD *, Item **);
friend void mark_select_range_as_dependent(THD*, friend void mark_select_range_as_dependent(THD*,
st_select_lex*, st_select_lex*, st_select_lex*, st_select_lex*,
Field*, Item*, Item_ident*); Field*, Item*, Item_ident*,
bool);
friend bool convert_join_subqueries_to_semijoins(JOIN *join); friend bool convert_join_subqueries_to_semijoins(JOIN *join);
}; };
......
...@@ -6046,7 +6046,7 @@ find_field_in_tables(THD *thd, Item_ident *item, ...@@ -6046,7 +6046,7 @@ find_field_in_tables(THD *thd, Item_ident *item,
if (!all_merged && current_sel != last_select) if (!all_merged && current_sel != last_select)
{ {
mark_select_range_as_dependent(thd, last_select, current_sel, mark_select_range_as_dependent(thd, last_select, current_sel,
found, *ref, item); found, *ref, item, true);
} }
} }
return found; return found;
......
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