aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2017-12-22 12:08:06 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2017-12-22 12:08:06 -0500
commitc4c2885cbb1803f772e58f6db4c8951d8cd672cd (patch)
treedbbee347118a299ec8c35e4276d4dca3fbb46b94 /src/backend
parent854823fa334cb826eed50da751801d0693b10173 (diff)
downloadpostgresql-c4c2885cbb1803f772e58f6db4c8951d8cd672cd.tar.gz
postgresql-c4c2885cbb1803f772e58f6db4c8951d8cd672cd.zip
Fix UNION/INTERSECT/EXCEPT over no columns.
Since 9.4, we've allowed the syntax "select union select" and variants of that. However, the planner wasn't expecting a no-column set operation and ended up treating the set operation as if it were UNION ALL. Turns out it's trivial to fix in v10 and later; we just need to be careful about not generating a Sort node with no sort keys. However, since a weird corner case like this is never going to be exercised by developers, we'd better have thorough regression tests if we want to consider it supported. Per report from Victor Yegorov. Discussion: https://postgr.es/m/CAGnEbojGJrRSOgJwNGM7JSJZpVAf8xXcVPbVrGdhbVEHZ-BUMw@mail.gmail.com
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/optimizer/plan/createplan.c1
-rw-r--r--src/backend/optimizer/prep/prepunion.c26
2 files changed, 10 insertions, 17 deletions
diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c
index 1a0d3a885f9..1a9fd829008 100644
--- a/src/backend/optimizer/plan/createplan.c
+++ b/src/backend/optimizer/plan/createplan.c
@@ -6326,7 +6326,6 @@ make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
* convert SortGroupClause list into arrays of attr indexes and equality
* operators, as wanted by executor
*/
- Assert(numCols > 0);
dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index a24e8acfa6c..f87849ea476 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -711,10 +711,6 @@ generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
/* Identify the grouping semantics */
groupList = generate_setop_grouplist(op, tlist);
- /* punt if nothing to group on (can this happen?) */
- if (groupList == NIL)
- return path;
-
/*
* Estimate number of distinct groups that we'll need hashtable entries
* for; this is the size of the left-hand input for EXCEPT, or the smaller
@@ -741,7 +737,7 @@ generate_nonunion_path(SetOperationStmt *op, PlannerInfo *root,
dNumGroups, dNumOutputRows,
(op->op == SETOP_INTERSECT) ? "INTERSECT" : "EXCEPT");
- if (!use_hash)
+ if (groupList && !use_hash)
path = (Path *) create_sort_path(root,
result_rel,
path,
@@ -864,10 +860,6 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
/* Identify the grouping semantics */
groupList = generate_setop_grouplist(op, tlist);
- /* punt if nothing to group on (can this happen?) */
- if (groupList == NIL)
- return path;
-
/*
* XXX for the moment, take the number of distinct groups as equal to the
* total input size, ie, the worst case. This is too conservative, but we
@@ -898,13 +890,15 @@ make_union_unique(SetOperationStmt *op, Path *path, List *tlist,
else
{
/* Sort and Unique */
- path = (Path *) create_sort_path(root,
- result_rel,
- path,
- make_pathkeys_for_sortclauses(root,
- groupList,
- tlist),
- -1.0);
+ if (groupList)
+ path = (Path *)
+ create_sort_path(root,
+ result_rel,
+ path,
+ make_pathkeys_for_sortclauses(root,
+ groupList,
+ tlist),
+ -1.0);
/* We have to manually jam the right tlist into the path; ick */
path->pathtarget = create_pathtarget(root, tlist);
path = (Path *) create_upper_unique_path(root,