I wrote:
> My own thoughts were along the lines of "don't ever assign pathkeys to
> an AppendPath"; not sure if that's equivalent to your first idea.
Concretely, the attached fixes the given test case. There are other
calls to create_append_path in prepunion.c, and I think they may
all need to do likewise, but I didn't analyze them.
It'd be nominally cleaner to add a flag to create_append_path telling
it whether it's allowed to override the given pathkeys. I didn't do
that here because it seems like this is a localized problem that
should eventually be fixed inside prepunion.c, but there's room to
argue differently.
regards, tom lane
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index b136f12ff3b..c4e95f14dc5 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -862,6 +862,17 @@ generate_union_paths(SetOperationStmt *op, PlannerInfo *root,
apath = (Path *) create_append_path(root, result_rel, cheapest,
NIL, NULL, 0, false, -1);
+ /*
+ * Although we told create_append_path to assign NIL pathkeys to the
+ * AppendPath, it may have overridden that (if there's just one surviving
+ * child path, it will use that path's pathkeys). However, createplan.c
+ * will fail because the append relation's tlist contains varno-0 Vars
+ * (cf. generate_append_tlist), which won't match what is in the pathkeys.
+ * We need to fix that someday, but for now, just force the AppendPath's
+ * pathkeys back to NIL.
+ */
+ apath->pathkeys = NIL;
+
/*
* Initialize the result row estimate to the total input size. This is
* correct for UNION ALL; for the UNION case it is overwritten below with