Skip to content

Commit 5b7bfc3

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 48e1291 commit 5b7bfc3

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);
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
@@ -195,12 +196,12 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
195196
strcmp(rte->eref->aliasname, "new") == 0))
196197
continue;
197198

198-
/* Check infinite recursion in the view definition. */
199+
/*
200+
* We might be dealing with a self-referential view. If so, we
201+
* can just stop recursing, since we already locked it.
202+
*/
199203
if (list_member_oid(context->ancestor_views, relid))
200-
ereport(ERROR,
201-
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
202-
errmsg("infinite recursion detected in rules for relation \"%s\"",
203-
get_rel_name(relid))));
204+
continue;
204205

205206
/* Check permissions with the view owner's privilege. */
206207
aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner);
@@ -218,7 +219,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
218219
get_rel_name(relid))));
219220

220221
if (rte->relkind == RELKIND_VIEW)
221-
LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views);
222+
LockViewRecurse(relid, context->lockmode, context->nowait,
223+
context->ancestor_views);
222224
else if (rte->inh)
223225
LockTableRecurse(relid, context->lockmode, context->nowait);
224226
}
@@ -235,13 +237,14 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
235237
}
236238

237239
static void
238-
LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, List *ancestor_views)
240+
LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait,
241+
List *ancestor_views)
239242
{
240243
LockViewRecurse_context context;
241-
242244
Relation view;
243245
Query *viewquery;
244246

247+
/* caller has already locked the view */
245248
view = table_open(reloid, NoLock);
246249
viewquery = get_view_query(view);
247250

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)