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
This commit is contained in:
parent
48e1291342
commit
5b7bfc3972
@ -32,7 +32,8 @@ static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait);
|
|||||||
static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode, Oid userid);
|
static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode, Oid userid);
|
||||||
static void RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid,
|
static void RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid,
|
||||||
Oid oldrelid, void *arg);
|
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
|
* LOCK TABLE
|
||||||
@ -195,12 +196,12 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
|
|||||||
strcmp(rte->eref->aliasname, "new") == 0))
|
strcmp(rte->eref->aliasname, "new") == 0))
|
||||||
continue;
|
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))
|
if (list_member_oid(context->ancestor_views, relid))
|
||||||
ereport(ERROR,
|
continue;
|
||||||
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
|
|
||||||
errmsg("infinite recursion detected in rules for relation \"%s\"",
|
|
||||||
get_rel_name(relid))));
|
|
||||||
|
|
||||||
/* Check permissions with the view owner's privilege. */
|
/* Check permissions with the view owner's privilege. */
|
||||||
aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner);
|
aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner);
|
||||||
@ -218,7 +219,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
|
|||||||
get_rel_name(relid))));
|
get_rel_name(relid))));
|
||||||
|
|
||||||
if (rte->relkind == RELKIND_VIEW)
|
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)
|
else if (rte->inh)
|
||||||
LockTableRecurse(relid, context->lockmode, context->nowait);
|
LockTableRecurse(relid, context->lockmode, context->nowait);
|
||||||
}
|
}
|
||||||
@ -235,13 +237,14 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
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;
|
LockViewRecurse_context context;
|
||||||
|
|
||||||
Relation view;
|
Relation view;
|
||||||
Query *viewquery;
|
Query *viewquery;
|
||||||
|
|
||||||
|
/* caller has already locked the view */
|
||||||
view = table_open(reloid, NoLock);
|
view = table_open(reloid, NoLock);
|
||||||
viewquery = get_view_query(view);
|
viewquery = get_view_query(view);
|
||||||
|
|
||||||
|
@ -124,16 +124,14 @@ select relname from pg_locks l, pg_class c
|
|||||||
(2 rows)
|
(2 rows)
|
||||||
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- detecting infinite recursions in view definitions
|
-- Verify that we cope with infinite recursion in view definitions.
|
||||||
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
|
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
|
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
|
||||||
ERROR: infinite recursion detected in rules for relation "lock_view2"
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
CREATE VIEW lock_view7 AS SELECT * from lock_view2;
|
CREATE VIEW lock_view7 AS SELECT * from lock_view2;
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
LOCK TABLE lock_view7 IN EXCLUSIVE MODE;
|
LOCK TABLE lock_view7 IN EXCLUSIVE MODE;
|
||||||
ERROR: infinite recursion detected in rules for relation "lock_view2"
|
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- Verify that we can lock a table with inheritance children.
|
-- Verify that we can lock a table with inheritance children.
|
||||||
CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1);
|
CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1);
|
||||||
|
@ -87,7 +87,7 @@ select relname from pg_locks l, pg_class c
|
|||||||
where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
|
where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
|
||||||
order by relname;
|
order by relname;
|
||||||
ROLLBACK;
|
ROLLBACK;
|
||||||
-- detecting infinite recursions in view definitions
|
-- Verify that we cope with infinite recursion in view definitions.
|
||||||
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
|
CREATE OR REPLACE VIEW lock_view2 AS SELECT * from lock_view3;
|
||||||
BEGIN TRANSACTION;
|
BEGIN TRANSACTION;
|
||||||
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
|
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user