summaryrefslogtreecommitdiff
path: root/sql/item.cc
diff options
context:
space:
mode:
authorVicențiu Ciorbaru <vicentiu@mariadb.org>2017-01-16 03:18:14 +0200
committerVicențiu Ciorbaru <vicentiu@mariadb.org>2017-01-16 03:18:14 +0200
commit8e15768731c52b6bbb29d7bfe27bdd71c025a3a3 (patch)
tree3148e77619dba81f92ab25d604079b46689e58b8 /sql/item.cc
parentebb8c9fb26f86cff8c0d81bd2415f415cef952bb (diff)
parent66744f4540c464413055a79111c34449e8381618 (diff)
downloadmariadb-git-8e15768731c52b6bbb29d7bfe27bdd71c025a3a3.tar.gz
Merge branch '10.0' into 10.1
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 015f5591c5d..2e7bc8e20c0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1133,7 +1133,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(current_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
@@ -2679,6 +2680,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)
{