diff options
-rw-r--r-- | src/backend/optimizer/plan/setrefs.c | 27 | ||||
-rw-r--r-- | src/backend/optimizer/prep/prepunion.c | 1 | ||||
-rw-r--r-- | src/test/regress/expected/union.out | 18 | ||||
-rw-r--r-- | src/test/regress/sql/union.sql | 3 |
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) |