diff options
author | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2021-04-12 19:28:10 +0700 |
---|---|---|
committer | Dmitry Shulga <dmitry.shulga@mariadb.com> | 2021-04-12 20:16:57 +0700 |
commit | f8bf2a0170b385bbba8f9f8dc97841f58229d39a (patch) | |
tree | bf500420882b3bd09ef240e7da88f21cd58201e4 /sql | |
parent | e95cdc451a969ab8186eabe76be19f578182e946 (diff) | |
download | mariadb-git-f8bf2a0170b385bbba8f9f8dc97841f58229d39a.tar.gz |
MDEV-25108: Running of the EXPLAIN EXTENDED statement produces extra warning in case it is executed in PS (prepared statement) modebb-10.2-MDEV-25108-2
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.
Diffstat (limited to 'sql')
-rw-r--r-- | sql/item.cc | 30 | ||||
-rw-r--r-- | sql/item.h | 3 | ||||
-rw-r--r-- | sql/item_subselect.h | 3 | ||||
-rw-r--r-- | sql/sql_base.cc | 2 |
4 files changed, 23 insertions, 15 deletions
diff --git a/sql/item.cc b/sql/item.cc index 45f40874ddb..55d135c660e 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -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 mark_item item which should be marked (can be differ in case of 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, Item_ident *resolved_item, - Item_ident *mark_item) + Item_ident *mark_item, + bool suppress_warning_output) { DBUG_ENTER("mark_as_dependent"); @@ -4685,7 +4688,7 @@ static bool mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current, if (current->mark_as_dependent(thd, last, /** resolved_item psergey-thu **/ mark_item)) 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 ? resolved_item->db_name : ""); @@ -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 identifier belongs to VIEW) @param resolved_item Identifier which was resolved + @param suppress_warning_output flag specifying whether to suppress output of + a warning message @note We have to mark all items between current_sel (including) and @@ -4727,7 +4732,8 @@ void mark_select_range_as_dependent(THD *thd, SELECT_LEX *last_select, SELECT_LEX *current_sel, 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 @@ -4762,7 +4768,7 @@ void mark_select_range_as_dependent(THD *thd, found_field->table->map; prev_subselect_item->const_item_cache= 0; 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) context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? - (Item_ident*) (*reference) : 0)); + (Item_ident*) (*reference) : 0), false); return 0; } } @@ -5240,7 +5246,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) context->select_lex, this, ((ref_type == REF_ITEM || ref_type == FIELD_ITEM) ? (Item_ident*) (*reference) : - 0)); + 0), false); if (thd->lex->in_sum_func && 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) set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, rf, - rf); + rf, false); return 0; } @@ -5367,7 +5373,7 @@ Item_field::fix_outer_field(THD *thd, Field **from_field, Item **reference) set_max_sum_func_level(thd, select); mark_as_dependent(thd, last_checked_context->select_lex, context->select_lex, - this, (Item_ident*)*reference); + this, (Item_ident*)*reference, false); if (last_checked_context->select_lex->having_fix_field) { Item_ref *rf; @@ -7401,7 +7407,7 @@ public: if (tbl->table == item->field->table) { if (sel != current_select) - mark_as_dependent(thd, sel, current_select, item, item); + mark_as_dependent(thd, sel, current_select, item, item, false); return; } } @@ -7596,7 +7602,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) ((refer_type == REF_ITEM || refer_type == FIELD_ITEM) ? (Item_ident*) (*reference) : - 0)); + 0), false); /* view reference found, we substituted it instead of this Item, so can quit @@ -7646,7 +7652,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference) goto error; thd->change_item_tree(reference, fld); 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 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) /* Should be checked in resolve_ref_in_select_and_group(). */ DBUG_ASSERT(*ref && (*ref)->fixed); 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 the nest level of the enclosing set function : adjust the value of diff --git a/sql/item.h b/sql/item.h index cb1e8519b27..b13336939f9 100644 --- a/sql/item.h +++ b/sql/item.h @@ -6088,7 +6088,8 @@ void mark_select_range_as_dependent(THD *thd, st_select_lex *last_select, st_select_lex *current_sel, 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, bool pass_through_ref); diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 130f90839e3..7b2078939f1 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -283,7 +283,8 @@ public: friend bool Item_ref::fix_fields(THD *, Item **); friend void mark_select_range_as_dependent(THD*, st_select_lex*, st_select_lex*, - Field*, Item*, Item_ident*); + Field*, Item*, Item_ident*, + bool); friend bool convert_join_subqueries_to_semijoins(JOIN *join); }; diff --git a/sql/sql_base.cc b/sql/sql_base.cc index b8d18abb50c..f10846acdd7 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -6046,7 +6046,7 @@ find_field_in_tables(THD *thd, Item_ident *item, if (!all_merged && current_sel != last_select) { mark_select_range_as_dependent(thd, last_select, current_sel, - found, *ref, item); + found, *ref, item, true); } } return found; |