summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/optimizer/plan/setrefs.c27
-rw-r--r--src/backend/optimizer/prep/prepunion.c1
-rw-r--r--src/test/regress/expected/union.out18
-rw-r--r--src/test/regress/sql/union.sql3
4 files changed, 36 insertions, 13 deletions
diff --git a/src/backend/optimizer/plan/setrefs.c b/src/backend/optimizer/plan/setrefs.c
index 6950eff2c5b..ccdc9bc264a 100644
--- a/src/backend/optimizer/plan/setrefs.c
+++ b/src/backend/optimizer/plan/setrefs.c
@@ -1034,16 +1034,35 @@ set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
* expected to occur here, it seems safer to special-case
* it here and keep the assertions that ROWID_VARs
* shouldn't be seen by fix_scan_expr.
+ *
+ * We also must handle the case where set operations have
+ * been short-circuited resulting in a dummy Result node.
+ * prepunion.c uses varno==0 for the set op targetlist.
+ * See generate_setop_tlist() and generate_setop_tlist().
+ * Here we rewrite these to use varno==1, which is the
+ * varno of the first set-op child. Without this, EXPLAIN
+ * will have trouble displaying targetlists of dummy set
+ * operations.
*/
foreach(l, splan->plan.targetlist)
{
TargetEntry *tle = (TargetEntry *) lfirst(l);
Var *var = (Var *) tle->expr;
- if (var && IsA(var, Var) && var->varno == ROWID_VAR)
- tle->expr = (Expr *) makeNullConst(var->vartype,
- var->vartypmod,
- var->varcollid);
+ if (var && IsA(var, Var))
+ {
+ if (var->varno == ROWID_VAR)
+ tle->expr = (Expr *) makeNullConst(var->vartype,
+ var->vartypmod,
+ var->varcollid);
+ else if (var->varno == 0)
+ tle->expr = (Expr *) makeVar(1,
+ var->varattno,
+ var->vartype,
+ var->vartypmod,
+ var->varcollid,
+ var->varlevelsup);
+ }
}
splan->plan.targetlist =
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 547dbd53540..da9431108a2 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -826,7 +826,6 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root,
/* If all UNION children were dummy rels, make the resulting rel dummy */
if (cheapest_pathlist == NIL)
{
- result_rel->reltarget = create_pathtarget(root, list_nth(tlist_list, 0));
mark_dummy_rel(result_rel);
return result_rel;
diff --git a/src/test/regress/expected/union.out b/src/test/regress/expected/union.out
index 7c089e0d598..15931beea3a 100644
--- a/src/test/regress/expected/union.out
+++ b/src/test/regress/expected/union.out
@@ -1258,14 +1258,18 @@ SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1 WHERE 1=2
UNION
-SELECT ten FROM tenk1 WHERE 1=2;
- QUERY PLAN
---------------------------------
- Result
+SELECT ten FROM tenk1 WHERE 1=2
+ORDER BY 1;
+ QUERY PLAN
+--------------------------------------
+ Sort
Output: unnamed_subquery.two
- Replaces: Aggregate
- One-Time Filter: false
-(4 rows)
+ Sort Key: unnamed_subquery.two
+ -> Result
+ Output: unnamed_subquery.two
+ Replaces: Aggregate
+ One-Time Filter: false
+(7 rows)
-- Test constraint exclusion of UNION ALL subqueries
explain (costs off)
diff --git a/src/test/regress/sql/union.sql b/src/test/regress/sql/union.sql
index 56bd20e741c..e252316f69b 100644
--- a/src/test/regress/sql/union.sql
+++ b/src/test/regress/sql/union.sql
@@ -484,7 +484,8 @@ SELECT two FROM tenk1 WHERE 1=2
UNION
SELECT four FROM tenk1 WHERE 1=2
UNION
-SELECT ten FROM tenk1 WHERE 1=2;
+SELECT ten FROM tenk1 WHERE 1=2
+ORDER BY 1;
-- Test constraint exclusion of UNION ALL subqueries
explain (costs off)