summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
authorSergei Golubchik <serg@mariadb.org>2017-02-10 17:01:45 +0100
committerSergei Golubchik <serg@mariadb.org>2017-02-10 17:01:45 +0100
commit2195bb4e416232ab807ff67eecf03b1223bf6bff (patch)
tree4555af02df68cb0f26d454b1cf65086b62542875 /sql/item.cc
parent3ae038b732ce503fb839e9095355e05f5c6866f9 (diff)
parentbc4686f0f4d17dc57dd727c9f5390caa3022bdca (diff)
downloadmariadb-git-2195bb4e416232ab807ff67eecf03b1223bf6bff.tar.gz
Merge branch '10.1' into 10.2
Diffstat (limited to 'sql/item.cc')
-rw-r--r--sql/item.cc41
1 files changed, 40 insertions, 1 deletions
diff --git a/sql/item.cc b/sql/item.cc
index 369b2df2675..4ce0b318ed0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1189,7 +1189,8 @@ Item *Item_cache::safe_charset_converter(THD *thd, CHARSET_INFO *tocs)
if (conv == example)
return this;
Item_cache *cache;
- if (!conv || !(cache= new (thd->mem_root) Item_cache_str(thd, conv)))
+ if (!conv || conv->fix_fields(thd, (Item **) NULL) ||
+ !(cache= new (thd->mem_root) Item_cache_str(thd, conv)))
return NULL; // Safe conversion is not possible, or OEM
cache->setup(thd, conv);
cache->fixed= false; // Make Item::fix_fields() happy
@@ -2885,6 +2886,44 @@ void Item_field::fix_after_pullout(st_select_lex *new_parent, Item **ref)
depended_from= NULL;
if (context)
{
+ bool need_change= false;
+ /*
+ Suppose there are nested selects:
+
+ select_id=1
+ select_id=2
+ select_id=3 <----+
+ select_id=4 -+
+ select_id=5 --+
+
+ Suppose, pullout operation has moved anything that had select_id=4 or 5
+ in to select_id=3.
+
+ If this Item_field had a name resolution context pointing into select_lex
+ with id=4 or id=5, it needs a new name resolution context.
+
+ However, it could also be that this object is a part of outer reference:
+ Item_ref(Item_field(field in select with select_id=1))).
+ - The Item_ref object has a context with select_id=5, and so needs a new
+ name resolution context.
+ - The Item_field object has a context with select_id=1, and doesn't need
+ a new name resolution context.
+
+ So, the following loop walks from Item_field's current context upwards.
+ If we find that the select we've been pulled out to is up there, we
+ create the new name resolution context. Otherwise, we don't.
+ */
+ for (Name_resolution_context *ct= context; ct; ct= ct->outer_context)
+ {
+ if (new_parent == ct->select_lex)
+ {
+ need_change= true;
+ break;
+ }
+ }
+ if (!need_change)
+ return;
+
Name_resolution_context *ctx= new Name_resolution_context();
if (context->select_lex == new_parent)
{