aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_clause.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_clause.c')
-rw-r--r--src/backend/parser/parse_clause.c37
1 files changed, 31 insertions, 6 deletions
diff --git a/src/backend/parser/parse_clause.c b/src/backend/parser/parse_clause.c
index 38dc3ea0976..60521d13475 100644
--- a/src/backend/parser/parse_clause.c
+++ b/src/backend/parser/parse_clause.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.70 2000/10/07 00:58:17 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/parser/parse_clause.c,v 1.71 2000/11/08 22:09:58 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -88,6 +88,34 @@ makeRangeTable(ParseState *pstate, List *frmList)
}
/*
+ * lockTargetTable
+ * Find the target relation of INSERT/UPDATE/DELETE and acquire write
+ * lock on it. This must be done before building the range table,
+ * in case the target is also mentioned as a source relation --- we
+ * want to be sure to grab the write lock before any read lock.
+ *
+ * The ParseState's link to the target relcache entry is also set here.
+ */
+void
+lockTargetTable(ParseState *pstate, char *relname)
+{
+ /* Close old target; this could only happen for multi-action rules */
+ if (pstate->p_target_relation != NULL)
+ heap_close(pstate->p_target_relation, NoLock);
+ pstate->p_target_relation = NULL;
+ pstate->p_target_rangetblentry = NULL; /* setTargetTable will set this */
+
+ /*
+ * Open target rel and grab suitable lock (which we will hold till
+ * end of transaction).
+ *
+ * analyze.c will eventually do the corresponding heap_close(),
+ * but *not* release the lock.
+ */
+ pstate->p_target_relation = heap_openr(relname, RowExclusiveLock);
+}
+
+/*
* setTargetTable
* Add the target relation of INSERT/UPDATE/DELETE to the range table,
* and make the special links to it in the ParseState.
@@ -133,13 +161,10 @@ setTargetTable(ParseState *pstate, char *relname, bool inh, bool inJoinSet)
if (inJoinSet)
addRTEtoJoinList(pstate, rte);
- /* This could only happen for multi-action rules */
- if (pstate->p_target_relation != NULL)
- heap_close(pstate->p_target_relation, AccessShareLock);
+ /* lockTargetTable should have been called earlier */
+ Assert(pstate->p_target_relation != NULL);
pstate->p_target_rangetblentry = rte;
- pstate->p_target_relation = heap_open(rte->relid, AccessShareLock);
- /* will close relation later, see analyze.c */
}