Skip to content

Commit 7dc18c6

Browse files
committed
Don't throw an error for LOCK TABLE on a self-referential view.
LOCK TABLE has complained about "infinite recursion" when applied to a self-referential view, ever since we made it recurse into views in v11. However, that breaks pg_dump's new assumption that it's okay to lock every relation. There doesn't seem to be any good reason to throw an error: if we just abandon the recursion, we've still satisfied the requirement of locking every referenced relation. Per bug #16703 from Andrew Bille (via Alexander Lakhin). Discussion: https://postgr.es/m/16703-e348f58aab3cf6cc@postgresql.org
1 parent 205f958 commit 7dc18c6

File tree

3 files changed

+14
-13
lines changed

3 files changed

+14
-13
lines changed

src/backend/commands/lockcmds.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid use
3232
static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode, Oid userid);
3333
static void RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid,
3434
Oid oldrelid, void *arg);
35-
static void LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, List *ancestor_views);
35+
static void LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait,
36+
List *ancestor_views);
3637

3738
/*
3839
* LOCK TABLE
@@ -216,12 +217,12 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
216217
(!strcmp(rte->eref->aliasname, "old") || !strcmp(rte->eref->aliasname, "new")))
217218
continue;
218219

219-
/* Check infinite recursion in the view definition. */
220+
/*
221+
* We might be dealing with a self-referential view. If so, we
222+
* can just stop recursing, since we already locked it.
223+
*/
220224
if (list_member_oid(context->ancestor_views, relid))
221-
ereport(ERROR,
222-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
223-
errmsg("infinite recursion detected in rules for relation \"%s\"",
224-
get_rel_name(relid))));
225+
continue;
225226

226227
/* Check permissions with the view owner's privilege. */
227228
aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner);
@@ -239,7 +240,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
239240
get_rel_name(relid))));
240241

241242
if (rte->relkind == RELKIND_VIEW)
242-
LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views);
243+
LockViewRecurse(relid, context->lockmode, context->nowait,
244+
context->ancestor_views);
243245
else if (rte->inh)
244246
LockTableRecurse(relid, context->lockmode, context->nowait, context->viewowner);
245247
}
@@ -256,13 +258,14 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
256258
}
257259

258260
static void
259-
LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, List *ancestor_views)
261+
LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait,
262+
List *ancestor_views)
260263
{
261264
LockViewRecurse_context context;
262-
263265
Relation view;
264266
Query *viewquery;
265267

268+
/* caller has already locked the view */
266269
view = heap_open(reloid, NoLock);
267270
viewquery = get_view_query(view);
268271

src/test/regress/expected/lock.out

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,16 +124,14 @@ select relname from pg_locks l, pg_class c
124124
(2 rows)
125125

126126
ROLLBACK;
127-
-- detecting infinite recursions in view definitions
127+
-- Verify that we cope with infinite recursion in view definitions.
128128
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
129129
BEGIN TRANSACTION;
130130
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
131-
ERROR: infinite recursion detected in rules for relation "lock_view2"
132131
ROLLBACK;
133132
CREATE VIEW lock_view7 AS SELECT * from lock_view2;
134133
BEGIN TRANSACTION;
135134
LOCK TABLE lock_view7 IN EXCLUSIVE MODE;
136-
ERROR: infinite recursion detected in rules for relation "lock_view2"
137135
ROLLBACK;
138136
-- Verify that we can lock a table with inheritance children.
139137
CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1);

src/test/regress/sql/lock.sql

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ select relname from pg_locks l, pg_class c
8787
where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
8888
order by relname;
8989
ROLLBACK;
90-
-- detecting infinite recursions in view definitions
90+
-- Verify that we cope with infinite recursion in view definitions.
9191
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
9292
BEGIN TRANSACTION;
9393
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;

0 commit comments

Comments
 (0)