aboutsummaryrefslogtreecommitdiff
path: root/src/backend/rewrite/rewriteHandler.c
diff options
context:
space:
mode:
authorStephen Frost <sfrost@snowman.net>2015-12-21 10:34:20 -0500
committerStephen Frost <sfrost@snowman.net>2015-12-21 10:34:20 -0500
commit496943ec2b6de0f22cd9e18f673e13635b5972ef (patch)
treecace174a6042ba44850e98beb69f33d61fde5c50 /src/backend/rewrite/rewriteHandler.c
parent0c28e767c612c9e90ae8ab188cf9b21114a34ddc (diff)
downloadpostgresql-496943ec2b6de0f22cd9e18f673e13635b5972ef.tar.gz
postgresql-496943ec2b6de0f22cd9e18f673e13635b5972ef.zip
Make viewquery a copy in rewriteTargetView()
Rather than expect the Query returned by get_view_query() to be read-only and then copy bits and pieces of it out, simply copy the entire structure when we get it. This addresses an issue where AcquireRewriteLocks, which is called by acquireLocksOnSubLinks(), scribbles on the parsetree passed in, which was actually an entry in relcache, leading to segfaults with certain view definitions. This also future-proofs us a bit for anyone adding more code to this path. The acquireLocksOnSubLinks() was added in commit c3e0ddd40. Back-patch to 9.3 as that commit was.
Diffstat (limited to 'src/backend/rewrite/rewriteHandler.c')
-rw-r--r--src/backend/rewrite/rewriteHandler.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/src/backend/rewrite/rewriteHandler.c b/src/backend/rewrite/rewriteHandler.c
index 903cf59f9df..26c9e348d56 100644
--- a/src/backend/rewrite/rewriteHandler.c
+++ b/src/backend/rewrite/rewriteHandler.c
@@ -2026,6 +2026,9 @@ fireRules(Query *parsetree,
*
* Caller should have verified that the relation is a view, and therefore
* we should find an ON SELECT action.
+ *
+ * Note that the pointer returned is into the relcache and therefore must
+ * be treated as read-only to the caller and not modified or scribbled on.
*/
Query *
get_view_query(Relation view)
@@ -2613,9 +2616,16 @@ rewriteTargetView(Query *parsetree, Relation view)
List *view_targetlist;
ListCell *lc;
- /* The view must be updatable, else fail */
- viewquery = get_view_query(view);
+ /*
+ * Get the Query from the view's ON SELECT rule. We're going to munge the
+ * Query to change the view's base relation into the target relation,
+ * along with various other changes along the way, so we need to make a
+ * copy of it (get_view_query() returns a pointer into the relcache, so we
+ * have to treat it as read-only).
+ */
+ viewquery = copyObject(get_view_query(view));
+ /* The view must be updatable, else fail */
auto_update_detail =
view_query_is_auto_updatable(viewquery,
parsetree->commandType != CMD_DELETE);
@@ -2779,7 +2789,7 @@ rewriteTargetView(Query *parsetree, Relation view)
* outer query. Perhaps someday we should refactor things enough so that
* we can share code with the planner.)
*/
- new_rte = (RangeTblEntry *) copyObject(base_rte);
+ new_rte = (RangeTblEntry *) base_rte;
parsetree->rtable = lappend(parsetree->rtable, new_rte);
new_rt_index = list_length(parsetree->rtable);
@@ -2791,14 +2801,14 @@ rewriteTargetView(Query *parsetree, Relation view)
new_rte->inh = false;
/*
- * Make a copy of the view's targetlist, adjusting its Vars to reference
- * the new target RTE, ie make their varnos be new_rt_index instead of
- * base_rt_index. There can be no Vars for other rels in the tlist, so
- * this is sufficient to pull up the tlist expressions for use in the
- * outer query. The tlist will provide the replacement expressions used
- * by ReplaceVarsFromTargetList below.
+ * Adjust the view's targetlist Vars to reference the new target RTE, ie
+ * make their varnos be new_rt_index instead of base_rt_index. There can
+ * be no Vars for other rels in the tlist, so this is sufficient to pull
+ * up the tlist expressions for use in the outer query. The tlist will
+ * provide the replacement expressions used by ReplaceVarsFromTargetList
+ * below.
*/
- view_targetlist = copyObject(viewquery->targetList);
+ view_targetlist = viewquery->targetList;
ChangeVarNodes((Node *) view_targetlist,
base_rt_index,
@@ -2949,7 +2959,7 @@ rewriteTargetView(Query *parsetree, Relation view)
if (parsetree->commandType != CMD_INSERT &&
viewquery->jointree->quals != NULL)
{
- Node *viewqual = (Node *) copyObject(viewquery->jointree->quals);
+ Node *viewqual = (Node *) viewquery->jointree->quals;
ChangeVarNodes(viewqual, base_rt_index, new_rt_index, 0);
@@ -3028,7 +3038,7 @@ rewriteTargetView(Query *parsetree, Relation view)
if (viewquery->jointree->quals != NULL)
{
- wco->qual = (Node *) copyObject(viewquery->jointree->quals);
+ wco->qual = (Node *) viewquery->jointree->quals;
ChangeVarNodes(wco->qual, base_rt_index, new_rt_index, 0);
/*