提交 82fa6ef7 编写于 作者: S Shreedhar Hardikar 提交者: Shreedhar Hardikar

Project certain outrrefs in the targetlist of subqueries

In a previous ORCA version (3.311) we added code to fall back gracefully
when a subquery select list contains a single outer ref that is not part
of an expression, such as in

select * from foo where a is null or a = (select foo.b from bar)

This commit adds a fix that allows us to handle such queries in ORCA
by adding a project in the translator that will echo the outer ref
from within the subquery, and using that projected value in the
select list of the subquery. This ensures that we use a NULL value for
the scalar subquery in the expression for the outer ref when the
subquery returns no rows.

Also note that this is still skipped for grouping cols in the target
list. This was done to avoid regression for certain queries, such as:

select *
from A
where not exists (select sum(C.i)
                  from C
                  where C.i = A.i
                  group by a.i);

ORCA is currently unable to decorrelate sub-queries that contain project
nodes, So, a `SELECT 1` in the subquery would also cause this
regression. In the above query, the parser adds `a.i` to the target list
of the subquery, that would get an echo projection (as described above),
and thus would prevent decorelation by ORCA. For this reason, we decided
to maintain existing behavior until ORCA is able to handle projections
in subqueries better.

Also add ICG tests.
Co-authored-by: NHans Zeller <hzeller@pivotal.io>
Co-authored-by: NShreedhar Hardikar <shardikar@pivotal.io>
上级 24049865
......@@ -3626,7 +3626,15 @@ CTranslatorQueryToDXL::TranslateTargetListToDXLProject
BOOL is_grouping_col = CTranslatorUtils::IsGroupingColumn(target_entry, plgrpcl);
if (!is_groupby || (is_groupby && is_grouping_col))
{
CDXLNode *project_elem_dxlnode = TranslateExprToDXLProject(target_entry->expr, target_entry->resname);
// Insist projection for any outer refs to ensure any decorelation of a
// subquery results in a correct plan using the projected reference,
// instead of the outer ref directly.
// TODO: Remove is_grouping_col from this check once const projections in
// subqueries no longer prevent decorrelation
BOOL insist_proj = (IsA(target_entry->expr, Var) &&
((Var *) (target_entry->expr))->varlevelsup > 0 &&
!is_grouping_col);
CDXLNode *project_elem_dxlnode = TranslateExprToDXLProject(target_entry->expr, target_entry->resname, insist_proj /* insist_new_colids */);
ULONG colid = CDXLScalarProjElem::Cast(project_elem_dxlnode->GetOperator())->Id();
AddSortingGroupingColumn(target_entry, sort_grpref_to_colid_mapping, colid);
......@@ -3634,9 +3642,9 @@ CTranslatorQueryToDXL::TranslateTargetListToDXLProject
// add column to the list of output columns of the query
StoreAttnoColIdMapping(output_attno_to_colid_mapping, resno, colid);
if (!IsA(target_entry->expr, Var))
if (!IsA(target_entry->expr, Var) || insist_proj)
{
// only add computed columns to the project list
// only add computed columns to the project list or if it's an outerref
project_list_dxlnode->AddChild(project_elem_dxlnode);
}
else
......
......@@ -11873,7 +11873,7 @@ ERROR: Query requires a feature that has been disabled by a configuration setti
DETAIL: Could not devise a query plan for the given query.
HINT: Current settings: optimizer=off; optimizer_cte_inlining_bound=1000; optimizer_metadata_caching=on
reset optimizer_join_order;
-- test selecting an outer ref from a scalar subquery, this will fall back to planner
-- test selecting an outer ref from a scalar subquery
-- expect 0 rows
SELECT 1
FROM tcorr1
......@@ -11888,20 +11888,20 @@ WHERE tcorr1.a IS NULL OR
----------
(0 rows)
-- expect 1 row, subquery returns a row, falls back in ORCA
-- expect 1 row, subquery returns a row
select * from tcorr1 where b = (select tcorr1.b from tcorr2);
a | b
---+----
1 | 99
(1 row)
-- expect 0 rows, subquery returns no rows, falls back in ORCA
-- expect 0 rows, subquery returns no rows
select * from tcorr1 where b = (select tcorr1.b from tcorr2 where b=33);
a | b
---+---
(0 rows)
-- expect 1 row, subquery returns nothing, so a < 22 is true, falls back in ORCA
-- expect 1 row, subquery returns nothing, so a < 22 is true
select * from tcorr1 where a < coalesce((select tcorr1.a from tcorr2 where a = 11), 22);
a | b
---+----
......
......@@ -11930,7 +11930,7 @@ ERROR: Query requires a feature that has been disabled by a configuration setti
DETAIL: Could not devise a query plan for the given query.
HINT: Current settings: optimizer=on; optimizer_cte_inlining_bound=1000; optimizer_metadata_caching=on
reset optimizer_join_order;
-- test selecting an outer ref from a scalar subquery, this will fall back to planner
-- test selecting an outer ref from a scalar subquery
-- expect 0 rows
SELECT 1
FROM tcorr1
......@@ -11941,29 +11941,25 @@ WHERE tcorr1.a IS NULL OR
FROM tcorr2) al
WHERE 3 = tcorr1.a
);
INFO: GPORCA failed to produce a plan, falling back to planner
?column?
----------
(0 rows)
-- expect 1 row, subquery returns a row, falls back in ORCA
-- expect 1 row, subquery returns a row
select * from tcorr1 where b = (select tcorr1.b from tcorr2);
INFO: GPORCA failed to produce a plan, falling back to planner
a | b
---+----
1 | 99
(1 row)
-- expect 0 rows, subquery returns no rows, falls back in ORCA
-- expect 0 rows, subquery returns no rows
select * from tcorr1 where b = (select tcorr1.b from tcorr2 where b=33);
INFO: GPORCA failed to produce a plan, falling back to planner
a | b
---+---
(0 rows)
-- expect 1 row, subquery returns nothing, so a < 22 is true, falls back in ORCA
-- expect 1 row, subquery returns nothing, so a < 22 is true
select * from tcorr1 where a < coalesce((select tcorr1.a from tcorr2 where a = 11), 22);
INFO: GPORCA failed to produce a plan, falling back to planner
a | b
---+----
1 | 99
......
......@@ -2050,7 +2050,7 @@ where out.b in (select coalesce(tcorr2.a, 99)
reset optimizer_join_order;
-- test selecting an outer ref from a scalar subquery, this will fall back to planner
-- test selecting an outer ref from a scalar subquery
-- expect 0 rows
SELECT 1
FROM tcorr1
......@@ -2062,13 +2062,13 @@ WHERE tcorr1.a IS NULL OR
WHERE 3 = tcorr1.a
);
-- expect 1 row, subquery returns a row, falls back in ORCA
-- expect 1 row, subquery returns a row
select * from tcorr1 where b = (select tcorr1.b from tcorr2);
-- expect 0 rows, subquery returns no rows, falls back in ORCA
-- expect 0 rows, subquery returns no rows
select * from tcorr1 where b = (select tcorr1.b from tcorr2 where b=33);
-- expect 1 row, subquery returns nothing, so a < 22 is true, falls back in ORCA
-- expect 1 row, subquery returns nothing, so a < 22 is true
select * from tcorr1 where a < coalesce((select tcorr1.a from tcorr2 where a = 11), 22);
reset optimizer_trace_fallback;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册