diff options
author | Sreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com> | 2017-05-24 08:50:05 +0530 |
---|---|---|
committer | Sreeharsha Ramanavarapu <sreeharsha.ramanavarapu@oracle.com> | 2017-05-24 08:50:05 +0530 |
commit | c34f2e518a141ac117eaa4d08ca283d4440752b6 (patch) | |
tree | e814ff51c3b2e7bdb5874f3d51cdb8838ba07430 /sql/sql_union.cc | |
parent | ba15ff2aaaa208c90fdb996c880af28d2b5a0353 (diff) | |
download | mariadb-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.cc | 15 |
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)); } |