aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer/util
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2011-11-08 21:14:21 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2011-11-08 21:14:21 -0500
commit57664ed25e5dea117158a2e663c29e60b3546e1c (patch)
treefa7d1fb4b6fae1fa81452ac7bb1f58042b26c9c9 /src/backend/optimizer/util
parent3b8161723c645853021b57330dd2ea0484ec6131 (diff)
downloadpostgresql-57664ed25e5dea117158a2e663c29e60b3546e1c.tar.gz
postgresql-57664ed25e5dea117158a2e663c29e60b3546e1c.zip
Wrap appendrel member outputs in PlaceHolderVars in additional cases.
Add PlaceHolderVar wrappers as needed to make UNION ALL sub-select output expressions appear non-constant and distinct from each other. This makes the world safe for add_child_rel_equivalences to do what it does. Before, it was possible for that function to add identical expressions to different EquivalenceClasses, which logically should imply merging such ECs, which would be wrong; or to improperly add a constant to an EquivalenceClass, drastically changing its behavior. Per report from Teodor Sigaev. The only currently known consequence of this bug is "MergeAppend child's targetlist doesn't match MergeAppend" planner failures in 9.1 and later. I am suspicious that there may be other failure modes that could affect older release branches; but in the absence of any hard evidence, I'll refrain from back-patching further than 9.1.
Diffstat (limited to 'src/backend/optimizer/util')
-rw-r--r--src/backend/optimizer/util/placeholder.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/src/backend/optimizer/util/placeholder.c b/src/backend/optimizer/util/placeholder.c
index 8b65245b510..3ae5154684d 100644
--- a/src/backend/optimizer/util/placeholder.c
+++ b/src/backend/optimizer/util/placeholder.c
@@ -104,28 +104,41 @@ find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv,
}
/*
- * find_placeholders_in_jointree
- * Search the jointree for PlaceHolderVars, and build PlaceHolderInfos
+ * find_placeholders_in_query
+ * Search the query for PlaceHolderVars, and build PlaceHolderInfos
*
- * We don't need to look at the targetlist because build_base_rel_tlists()
- * will already have made entries for any PHVs in the tlist.
+ * We need to examine the jointree, but not the targetlist, because
+ * build_base_rel_tlists() will already have made entries for any PHVs
+ * in the targetlist.
+ *
+ * We also need to search for PHVs in AppendRelInfo translated_vars
+ * lists. In most cases, translated_vars entries aren't directly referenced
+ * elsewhere, but we need to create PlaceHolderInfo entries for them to
+ * support set_rel_width() calculations for the appendrel child relations.
*/
void
-find_placeholders_in_jointree(PlannerInfo *root)
+find_placeholders_in_query(PlannerInfo *root)
{
/* We need do nothing if the query contains no PlaceHolderVars */
if (root->glob->lastPHId != 0)
{
- /* Start recursion at top of jointree */
+ /* Recursively search the jointree */
Assert(root->parse->jointree != NULL &&
IsA(root->parse->jointree, FromExpr));
(void) find_placeholders_recurse(root, (Node *) root->parse->jointree);
+
+ /*
+ * Also search the append_rel_list for translated vars that are PHVs.
+ * Barring finding them elsewhere in the query, they do not need any
+ * ph_may_need bits, only to be present in the PlaceHolderInfo list.
+ */
+ mark_placeholders_in_expr(root, (Node *) root->append_rel_list, NULL);
}
}
/*
* find_placeholders_recurse
- * One recursion level of find_placeholders_in_jointree.
+ * One recursion level of jointree search for find_placeholders_in_query.
*
* jtnode is the current jointree node to examine.
*