diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-05 11:44:32 -0500 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2020-11-05 11:44:32 -0500 |
commit | 7dc18c619dac7ddf8af62b4d33e4bd33c7bfb067 (patch) | |
tree | 1989151dba91a1f3dc9c78a805bd26a986af1f4a /src/backend/commands/lockcmds.c | |
parent | 205f958406cc85f8f73e151906ecd281ff05d80a (diff) | |
download | postgresql-7dc18c619dac7ddf8af62b4d33e4bd33c7bfb067.tar.gz postgresql-7dc18c619dac7ddf8af62b4d33e4bd33c7bfb067.zip |
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
Diffstat (limited to 'src/backend/commands/lockcmds.c')
-rw-r--r-- | src/backend/commands/lockcmds.c | 21 |
1 files changed, 12 insertions, 9 deletions
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c index 1be3a0d1edb..dbd8cf47068 100644 --- a/src/backend/commands/lockcmds.c +++ b/src/backend/commands/lockcmds.c @@ -32,7 +32,8 @@ static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid use static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode, Oid userid); static void RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid, void *arg); -static void LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, List *ancestor_views); +static void LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, + List *ancestor_views); /* * LOCK TABLE @@ -216,12 +217,12 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context) (!strcmp(rte->eref->aliasname, "old") || !strcmp(rte->eref->aliasname, "new"))) continue; - /* Check infinite recursion in the view definition. */ + /* + * We might be dealing with a self-referential view. If so, we + * can just stop recursing, since we already locked it. + */ if (list_member_oid(context->ancestor_views, relid)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_OBJECT_DEFINITION), - errmsg("infinite recursion detected in rules for relation \"%s\"", - get_rel_name(relid)))); + continue; /* Check permissions with the view owner's privilege. */ aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner); @@ -239,7 +240,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context) get_rel_name(relid)))); if (rte->relkind == RELKIND_VIEW) - LockViewRecurse(relid, context->lockmode, context->nowait, context->ancestor_views); + LockViewRecurse(relid, context->lockmode, context->nowait, + context->ancestor_views); else if (rte->inh) LockTableRecurse(relid, context->lockmode, context->nowait, context->viewowner); } @@ -256,13 +258,14 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context) } static void -LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, List *ancestor_views) +LockViewRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, + List *ancestor_views) { LockViewRecurse_context context; - Relation view; Query *viewquery; + /* caller has already locked the view */ view = heap_open(reloid, NoLock); viewquery = get_view_query(view); |