aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c47
1 files changed, 21 insertions, 26 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 0dda5bc27cd..71281f0e2fd 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -1356,14 +1356,18 @@ transformFKConstraints(ParseState *pstate, CreateStmtContext *cxt,
* a predicate expression. There are several code paths that create indexes
* without bothering to call this, because they know they don't have any
* such expressions to deal with.
+ *
+ * To avoid race conditions, it's important that this function rely only on
+ * the passed-in relid (and not on stmt->relation) to determine the target
+ * relation.
*/
IndexStmt *
-transformIndexStmt(IndexStmt *stmt, const char *queryString)
+transformIndexStmt(Oid relid, IndexStmt *stmt, const char *queryString)
{
- Relation rel;
ParseState *pstate;
RangeTblEntry *rte;
ListCell *l;
+ Relation rel;
/*
* We must not scribble on the passed-in IndexStmt, so copy it. (This is
@@ -1371,25 +1375,17 @@ transformIndexStmt(IndexStmt *stmt, const char *queryString)
*/
stmt = (IndexStmt *) copyObject(stmt);
- /*
- * Open the parent table with appropriate locking. We must do this
- * because addRangeTableEntry() would acquire only AccessShareLock,
- * leaving DefineIndex() needing to do a lock upgrade with consequent risk
- * of deadlock. Make sure this stays in sync with the type of lock
- * DefineIndex() wants.
- */
- rel = heap_openrv(stmt->relation,
- (stmt->concurrent ? ShareUpdateExclusiveLock : ShareLock));
-
/* Set up pstate */
pstate = make_parsestate(NULL);
pstate->p_sourcetext = queryString;
/*
* Put the parent table into the rtable so that the expressions can refer
- * to its fields without qualification.
+ * to its fields without qualification. Caller is responsible for locking
+ * relation, but we still need to open it.
*/
- rte = addRangeTableEntry(pstate, stmt->relation, NULL, false, true);
+ rel = relation_open(relid, NoLock);
+ rte = addRangeTableEntryForRelation(pstate, rel, NULL, false, true);
/* no to join list, yes to namespaces */
addRTEtoQuery(pstate, rte, false, true, true);
@@ -1431,7 +1427,7 @@ transformIndexStmt(IndexStmt *stmt, const char *queryString)
free_parsestate(pstate);
- /* Close relation, but keep the lock */
+ /* Close relation */
heap_close(rel, NoLock);
return stmt;
@@ -1722,9 +1718,14 @@ transformRuleStmt(RuleStmt *stmt, const char *queryString,
* Returns a List of utility commands to be done in sequence. One of these
* will be the transformed AlterTableStmt, but there may be additional actions
* to be done before and after the actual AlterTable() call.
+ *
+ * To avoid race conditions, it's important that this function rely only on
+ * the passed-in relid (and not on stmt->relation) to determine the target
+ * relation.
*/
List *
-transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
+transformAlterTableStmt(Oid relid, AlterTableStmt *stmt,
+ const char *queryString)
{
Relation rel;
ParseState *pstate;
@@ -1743,14 +1744,8 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
*/
stmt = (AlterTableStmt *) copyObject(stmt);
- /*
- * Acquire exclusive lock on the target relation, which will be held until
- * end of transaction. This ensures any decisions we make here based on
- * the state of the relation will still be good at execution. We must get
- * exclusive lock now because execution will; taking a lower grade lock
- * now and trying to upgrade later risks deadlock.
- */
- rel = relation_openrv(stmt->relation, AccessExclusiveLock);
+ /* Caller is responsible for locking the relation */
+ rel = relation_open(relid, NoLock);
/* Set up pstate */
pstate = make_parsestate(NULL);
@@ -1866,7 +1861,7 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
Assert(IsA(idxstmt, IndexStmt));
newcmd = makeNode(AlterTableCmd);
newcmd->subtype = AT_AddIndex;
- newcmd->def = (Node *) transformIndexStmt((IndexStmt *) idxstmt,
+ newcmd->def = (Node *) transformIndexStmt(relid, (IndexStmt *) idxstmt,
queryString);
newcmds = lappend(newcmds, newcmd);
}
@@ -1888,7 +1883,7 @@ transformAlterTableStmt(AlterTableStmt *stmt, const char *queryString)
newcmds = lappend(newcmds, newcmd);
}
- /* Close rel but keep lock */
+ /* Close rel */
relation_close(rel, NoLock);
/*