summaryrefslogtreecommitdiff
path: root/sql/sql_union.cc
diff options
context:
space:
mode:
authorSreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com>2017-05-24 08:50:05 +0530
committerSreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com>2017-05-24 08:50:05 +0530
commitc34f2e518a141ac117eaa4d08ca283d4440752b6 (patch)
treee814ff51c3b2e7bdb5874f3d51cdb8838ba07430 /sql/sql_union.cc
parentba15ff2aaaa208c90fdb996c880af28d2b5a0353 (diff)
downloadmariadb-git-c34f2e518a141ac117eaa4d08ca283d4440752b6.tar.gz
Bug #24595639: INCORRECT BEHAVIOR IN QUERY WITH UNION AND
GROUP BY Issue 1: -------- This problem occurs in the following conditions: 1) A UNION is present in the subquery of select list and handles multiple columns. 2) Query has a GROUP BY. A temporary table is created to handle the UNION. Item_field objects are based on the expressions of the result of the UNION (ie. the fake_select_lex). While checking validity of the columns in the GROUP BY list, the columns of the temporary table are checked in Item_ident::local_column. But the Item_field objects created for the temporary table don't have information like the Name_resolution_context that they belong to or whether they are dependent on an outer query. Since these members are null, incorrect behavior is caused. This can happen when such Item objects are cached to apply the IN-to-EXISTS transform for Item_row. Solution to Issue 1: -------------------- Context information of the first select in the UNION will be assigned to the new Item_field objects. Issue 2: -------- This problem occurs in the following conditions: 1) A UNION is present in the subquery of select list. 2) A column in the UNION's first SELECT refers to a table in the outer-query making it a dependent union. 3) GROUP BY column refers to the outer-referencing column. While resolving the select list with an outer-reference, an Item_outer_ref object is created to handle the outer-query's GROUP BY list. The Item_outer_ref object replaces the Item_field object in the item tree. Item_outer_ref::fix_fields will be called only while fixing the inner references of the outer query. Before resolving the outer-query, an Item_type_holder object needs to be created to handle the UNION. But as explained above, the Item_outer_ref object has not been fixed yet. Having a fixed Item object is a pre-condition for creating an Item_type_holder. Solution to Issue 2: -------------------- Use the reference (real_item()) of an Item_outer_ref object instead of the object itself while creating an Item_type_holder.
Diffstat (limited to 'sql/sql_union.cc')
-rw-r--r--sql/sql_union.cc15
1 files changed, 14 insertions, 1 deletions
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index d230b903d2c..ca6870dab9c 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2014, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -282,6 +282,19 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
Item *item_tmp;
while ((item_tmp= it++))
{
+ /*
+ If the outer query has a GROUP BY clause, an outer reference to this
+ query block may have been wrapped in a Item_outer_ref, which has not
+ been fixed yet. An Item_type_holder must be created based on a fixed
+ Item, so use the inner Item instead.
+ */
+ DBUG_ASSERT(item_tmp->fixed ||
+ (item_tmp->type() == Item::REF_ITEM &&
+ ((Item_ref *)(item_tmp))->ref_type() ==
+ Item_ref::OUTER_REF));
+ if (!item_tmp->fixed)
+ item_tmp= item_tmp->real_item();
+
/* Error's in 'new' will be detected after loop */
types.push_back(new Item_type_holder(thd_arg, item_tmp));
}