mirror of
				https://github.com/postgres/postgres.git
				synced 2025-11-04 00:02:52 -05:00 
			
		
		
		
	Allow to lock views.
Now all tables used in view definitions can be recursively locked by a LOCK command. Author: Yugo Nagata Reviewed by Robert Haas, Thomas Munro and me. Discussion: https://postgr.es/m/20171011183629.eb2817b3.nagata%40sraoss.co.jp
This commit is contained in:
		
							parent
							
								
									fb60478011
								
							
						
					
					
						commit
						34c20de4d0
					
				@ -45,6 +45,11 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
 | 
			
		||||
   end.)
 | 
			
		||||
  </para>
 | 
			
		||||
 | 
			
		||||
  <para>
 | 
			
		||||
   When a view is specified to be locked, all relations appearing in the view
 | 
			
		||||
   definition query are also locked recursively with the same lock mode. 
 | 
			
		||||
  </para>
 | 
			
		||||
 | 
			
		||||
  <para>
 | 
			
		||||
   When acquiring locks automatically for commands that reference
 | 
			
		||||
   tables, <productname>PostgreSQL</productname> always uses the least
 | 
			
		||||
 | 
			
		||||
@ -23,11 +23,15 @@
 | 
			
		||||
#include "utils/acl.h"
 | 
			
		||||
#include "utils/lsyscache.h"
 | 
			
		||||
#include "utils/syscache.h"
 | 
			
		||||
#include "rewrite/rewriteHandler.h"
 | 
			
		||||
#include "access/heapam.h"
 | 
			
		||||
#include "nodes/nodeFuncs.h"
 | 
			
		||||
 | 
			
		||||
static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait);
 | 
			
		||||
static AclResult LockTableAclCheck(Oid relid, LOCKMODE lockmode);
 | 
			
		||||
static void LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid);
 | 
			
		||||
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, Oid root_reloid, LOCKMODE lockmode, bool nowait);
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * LOCK TABLE
 | 
			
		||||
@ -62,8 +66,10 @@ LockTableCommand(LockStmt *lockstmt)
 | 
			
		||||
										  RangeVarCallbackForLockTable,
 | 
			
		||||
										  (void *) &lockstmt->mode);
 | 
			
		||||
 | 
			
		||||
		if (recurse)
 | 
			
		||||
			LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait);
 | 
			
		||||
		if (get_rel_relkind(reloid) == RELKIND_VIEW)
 | 
			
		||||
			LockViewRecurse(reloid, reloid, lockstmt->mode, lockstmt->nowait);
 | 
			
		||||
		else if (recurse)
 | 
			
		||||
			LockTableRecurse(reloid, lockstmt->mode, lockstmt->nowait, GetUserId());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -86,15 +92,17 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 | 
			
		||||
		return;					/* woops, concurrently dropped; no permissions
 | 
			
		||||
								 * check */
 | 
			
		||||
 | 
			
		||||
	/* Currently, we only allow plain tables to be locked */
 | 
			
		||||
	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE)
 | 
			
		||||
 | 
			
		||||
	/* Currently, we only allow plain tables or views to be locked */
 | 
			
		||||
	if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
 | 
			
		||||
		relkind != RELKIND_VIEW)
 | 
			
		||||
		ereport(ERROR,
 | 
			
		||||
				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
 | 
			
		||||
				 errmsg("\"%s\" is not a table",
 | 
			
		||||
				 errmsg("\"%s\" is not a table or a view",
 | 
			
		||||
						rv->relname)));
 | 
			
		||||
 | 
			
		||||
	/* Check permissions. */
 | 
			
		||||
	aclresult = LockTableAclCheck(relid, lockmode);
 | 
			
		||||
	aclresult = LockTableAclCheck(relid, lockmode, GetUserId());
 | 
			
		||||
	if (aclresult != ACLCHECK_OK)
 | 
			
		||||
		aclcheck_error(aclresult, get_relkind_objtype(get_rel_relkind(relid)), rv->relname);
 | 
			
		||||
}
 | 
			
		||||
@ -107,7 +115,7 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 | 
			
		||||
 * multiply-inheriting children more than once, but that's no problem.
 | 
			
		||||
 */
 | 
			
		||||
static void
 | 
			
		||||
LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait)
 | 
			
		||||
LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait, Oid userid)
 | 
			
		||||
{
 | 
			
		||||
	List	   *children;
 | 
			
		||||
	ListCell   *lc;
 | 
			
		||||
@ -120,7 +128,7 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait)
 | 
			
		||||
		AclResult	aclresult;
 | 
			
		||||
 | 
			
		||||
		/* Check permissions before acquiring the lock. */
 | 
			
		||||
		aclresult = LockTableAclCheck(childreloid, lockmode);
 | 
			
		||||
		aclresult = LockTableAclCheck(childreloid, lockmode, userid);
 | 
			
		||||
		if (aclresult != ACLCHECK_OK)
 | 
			
		||||
		{
 | 
			
		||||
			char	   *relname = get_rel_name(childreloid);
 | 
			
		||||
@ -157,15 +165,120 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait)
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		LockTableRecurse(childreloid, lockmode, nowait);
 | 
			
		||||
		LockTableRecurse(childreloid, lockmode, nowait, userid);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Apply LOCK TABLE recursively over a view
 | 
			
		||||
 *
 | 
			
		||||
 * All tables and views appearing in the view definition query are locked
 | 
			
		||||
 * recursively with the same lock mode.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
typedef struct
 | 
			
		||||
{
 | 
			
		||||
	Oid root_reloid;
 | 
			
		||||
	LOCKMODE lockmode;
 | 
			
		||||
	bool nowait;
 | 
			
		||||
	Oid viewowner;
 | 
			
		||||
	Oid viewoid;
 | 
			
		||||
} LockViewRecurse_context;
 | 
			
		||||
 | 
			
		||||
static bool
 | 
			
		||||
LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 | 
			
		||||
{
 | 
			
		||||
	if (node == NULL)
 | 
			
		||||
		return false;
 | 
			
		||||
 | 
			
		||||
	if (IsA(node, Query))
 | 
			
		||||
	{
 | 
			
		||||
		Query		*query = (Query *) node;
 | 
			
		||||
		ListCell	*rtable;
 | 
			
		||||
 | 
			
		||||
		foreach(rtable, query->rtable)
 | 
			
		||||
		{
 | 
			
		||||
			RangeTblEntry	*rte = lfirst(rtable);
 | 
			
		||||
			AclResult		 aclresult;
 | 
			
		||||
 | 
			
		||||
			Oid relid = rte->relid;
 | 
			
		||||
			char relkind = rte->relkind;
 | 
			
		||||
			char *relname = get_rel_name(relid);
 | 
			
		||||
 | 
			
		||||
			/* The OLD and NEW placeholder entries in the view's rtable are skipped. */
 | 
			
		||||
			if (relid == context->viewoid &&
 | 
			
		||||
				(!strcmp(rte->eref->aliasname, "old") || !strcmp(rte->eref->aliasname, "new")))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			/* Currently, we only allow plain tables or views to be locked. */
 | 
			
		||||
			if (relkind != RELKIND_RELATION && relkind != RELKIND_PARTITIONED_TABLE &&
 | 
			
		||||
				relkind != RELKIND_VIEW)
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			/* Check infinite recursion in the view definition. */
 | 
			
		||||
			if (relid == context->root_reloid)
 | 
			
		||||
				ereport(ERROR,
 | 
			
		||||
						(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
 | 
			
		||||
						errmsg("infinite recursion detected in rules for relation \"%s\"",
 | 
			
		||||
								get_rel_name(context->root_reloid))));
 | 
			
		||||
 | 
			
		||||
			/* Check permissions with the view owner's privilege. */
 | 
			
		||||
			aclresult = LockTableAclCheck(relid, context->lockmode, context->viewowner);
 | 
			
		||||
			if (aclresult != ACLCHECK_OK)
 | 
			
		||||
				aclcheck_error(aclresult, get_relkind_objtype(relkind), relname);
 | 
			
		||||
 | 
			
		||||
			/* We have enough rights to lock the relation; do so. */
 | 
			
		||||
			if (!context->nowait)
 | 
			
		||||
				LockRelationOid(relid, context->lockmode);
 | 
			
		||||
			else if (!ConditionalLockRelationOid(relid, context->lockmode))
 | 
			
		||||
				ereport(ERROR,
 | 
			
		||||
						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
 | 
			
		||||
						errmsg("could not obtain lock on relation \"%s\"",
 | 
			
		||||
								relname)));
 | 
			
		||||
 | 
			
		||||
			if (relkind == RELKIND_VIEW)
 | 
			
		||||
				LockViewRecurse(relid, context->root_reloid, context->lockmode, context->nowait);
 | 
			
		||||
			else if (rte->inh)
 | 
			
		||||
				LockTableRecurse(relid, context->lockmode, context->nowait, context->viewowner);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return query_tree_walker(query,
 | 
			
		||||
								 LockViewRecurse_walker,
 | 
			
		||||
								 context,
 | 
			
		||||
								 QTW_IGNORE_JOINALIASES);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return expression_tree_walker(node,
 | 
			
		||||
								  LockViewRecurse_walker,
 | 
			
		||||
								  context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void
 | 
			
		||||
LockViewRecurse(Oid reloid, Oid root_reloid, LOCKMODE lockmode, bool nowait)
 | 
			
		||||
{
 | 
			
		||||
	LockViewRecurse_context context;
 | 
			
		||||
 | 
			
		||||
	Relation		 view;
 | 
			
		||||
	Query			*viewquery;
 | 
			
		||||
 | 
			
		||||
	view = heap_open(reloid, NoLock);
 | 
			
		||||
	viewquery = get_view_query(view);
 | 
			
		||||
	heap_close(view, NoLock);
 | 
			
		||||
 | 
			
		||||
	context.root_reloid = root_reloid;
 | 
			
		||||
	context.lockmode = lockmode;
 | 
			
		||||
	context.nowait = nowait;
 | 
			
		||||
	context.viewowner = view->rd_rel->relowner;
 | 
			
		||||
	context.viewoid = reloid;
 | 
			
		||||
 | 
			
		||||
	LockViewRecurse_walker((Node *) viewquery, &context);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Check whether the current user is permitted to lock this relation.
 | 
			
		||||
 */
 | 
			
		||||
static AclResult
 | 
			
		||||
LockTableAclCheck(Oid reloid, LOCKMODE lockmode)
 | 
			
		||||
LockTableAclCheck(Oid reloid, LOCKMODE lockmode, Oid userid)
 | 
			
		||||
{
 | 
			
		||||
	AclResult	aclresult;
 | 
			
		||||
	AclMode		aclmask;
 | 
			
		||||
@ -178,7 +291,7 @@ LockTableAclCheck(Oid reloid, LOCKMODE lockmode)
 | 
			
		||||
	else
 | 
			
		||||
		aclmask = ACL_UPDATE | ACL_DELETE | ACL_TRUNCATE;
 | 
			
		||||
 | 
			
		||||
	aclresult = pg_class_aclcheck(reloid, GetUserId(), aclmask);
 | 
			
		||||
	aclresult = pg_class_aclcheck(reloid, userid, aclmask);
 | 
			
		||||
 | 
			
		||||
	return aclresult;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -5,7 +5,13 @@
 | 
			
		||||
CREATE SCHEMA lock_schema1;
 | 
			
		||||
SET search_path = lock_schema1;
 | 
			
		||||
CREATE TABLE lock_tbl1 (a BIGINT);
 | 
			
		||||
CREATE VIEW lock_view1 AS SELECT 1;
 | 
			
		||||
CREATE TABLE lock_tbl1a (a BIGINT);
 | 
			
		||||
CREATE VIEW lock_view1 AS SELECT * FROM lock_tbl1;
 | 
			
		||||
CREATE VIEW lock_view2(a,b) AS SELECT * FROM lock_tbl1, lock_tbl1a;
 | 
			
		||||
CREATE VIEW lock_view3 AS SELECT * from lock_view2;
 | 
			
		||||
CREATE VIEW lock_view4 AS SELECT (select a from lock_tbl1a limit 1) from lock_tbl1;
 | 
			
		||||
CREATE VIEW lock_view5 AS SELECT * from lock_tbl1 where a in (select * from lock_tbl1a);
 | 
			
		||||
CREATE VIEW lock_view6 AS SELECT * from (select * from lock_tbl1) sub;
 | 
			
		||||
CREATE ROLE regress_rol_lock1;
 | 
			
		||||
ALTER ROLE regress_rol_lock1 SET search_path = lock_schema1;
 | 
			
		||||
GRANT USAGE ON SCHEMA lock_schema1 TO regress_rol_lock1;
 | 
			
		||||
@ -30,8 +36,90 @@ LOCK TABLE lock_tbl1 IN SHARE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN SHARE ROW EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN ACCESS EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_view1 IN EXCLUSIVE MODE;   -- Will fail; can't lock a non-table
 | 
			
		||||
ERROR:  "lock_view1" is not a table
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
-- Verify that we can lock views.
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view1 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view1 and lock_tbl1 are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_view1
 | 
			
		||||
(2 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view1, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_tbl1a
 | 
			
		||||
 lock_view2
 | 
			
		||||
(3 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view3 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view3, lock_view2, lock_tbl1, and lock_tbl1a are locked recursively.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_tbl1a
 | 
			
		||||
 lock_view2
 | 
			
		||||
 lock_view3
 | 
			
		||||
(4 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view4 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view4, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_tbl1a
 | 
			
		||||
 lock_view4
 | 
			
		||||
(3 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view5 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view5, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_tbl1a
 | 
			
		||||
 lock_view5
 | 
			
		||||
(3 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view6 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view6 an lock_tbl1 are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
  relname   
 | 
			
		||||
------------
 | 
			
		||||
 lock_tbl1
 | 
			
		||||
 lock_view6
 | 
			
		||||
(2 rows)
 | 
			
		||||
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
-- Verify that we can lock a table with inheritance children.
 | 
			
		||||
CREATE TABLE lock_tbl2 (b BIGINT) INHERITS (lock_tbl1);
 | 
			
		||||
@ -54,10 +142,16 @@ RESET ROLE;
 | 
			
		||||
--
 | 
			
		||||
-- Clean up
 | 
			
		||||
--
 | 
			
		||||
DROP VIEW lock_view6;
 | 
			
		||||
DROP VIEW lock_view5;
 | 
			
		||||
DROP VIEW lock_view4;
 | 
			
		||||
DROP VIEW lock_view3;
 | 
			
		||||
DROP VIEW lock_view2;
 | 
			
		||||
DROP VIEW lock_view1;
 | 
			
		||||
DROP TABLE lock_tbl3;
 | 
			
		||||
DROP TABLE lock_tbl2;
 | 
			
		||||
DROP TABLE lock_tbl1;
 | 
			
		||||
DROP TABLE lock_tbl1a;
 | 
			
		||||
DROP SCHEMA lock_schema1 CASCADE;
 | 
			
		||||
DROP ROLE regress_rol_lock1;
 | 
			
		||||
-- atomic ops tests
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,13 @@
 | 
			
		||||
CREATE SCHEMA lock_schema1;
 | 
			
		||||
SET search_path = lock_schema1;
 | 
			
		||||
CREATE TABLE lock_tbl1 (a BIGINT);
 | 
			
		||||
CREATE VIEW lock_view1 AS SELECT 1;
 | 
			
		||||
CREATE TABLE lock_tbl1a (a BIGINT);
 | 
			
		||||
CREATE VIEW lock_view1 AS SELECT * FROM lock_tbl1;
 | 
			
		||||
CREATE VIEW lock_view2(a,b) AS SELECT * FROM lock_tbl1, lock_tbl1a;
 | 
			
		||||
CREATE VIEW lock_view3 AS SELECT * from lock_view2;
 | 
			
		||||
CREATE VIEW lock_view4 AS SELECT (select a from lock_tbl1a limit 1) from lock_tbl1;
 | 
			
		||||
CREATE VIEW lock_view5 AS SELECT * from lock_tbl1 where a in (select * from lock_tbl1a);
 | 
			
		||||
CREATE VIEW lock_view6 AS SELECT * from (select * from lock_tbl1) sub;
 | 
			
		||||
CREATE ROLE regress_rol_lock1;
 | 
			
		||||
ALTER ROLE regress_rol_lock1 SET search_path = lock_schema1;
 | 
			
		||||
GRANT USAGE ON SCHEMA lock_schema1 TO regress_rol_lock1;
 | 
			
		||||
@ -33,7 +39,50 @@ LOCK TABLE lock_tbl1 IN SHARE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN SHARE ROW EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_tbl1 IN ACCESS EXCLUSIVE MODE NOWAIT;
 | 
			
		||||
LOCK TABLE lock_view1 IN EXCLUSIVE MODE;   -- Will fail; can't lock a non-table
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
 | 
			
		||||
-- Verify that we can lock views.
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view1 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view1 and lock_tbl1 are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view2 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view1, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view3 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view3, lock_view2, lock_tbl1, and lock_tbl1a are locked recursively.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view4 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view4, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view5 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view5, lock_tbl1, and lock_tbl1a are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
BEGIN TRANSACTION;
 | 
			
		||||
LOCK TABLE lock_view6 IN EXCLUSIVE MODE;
 | 
			
		||||
-- lock_view6 an lock_tbl1 are locked.
 | 
			
		||||
select relname from pg_locks l, pg_class c
 | 
			
		||||
 where l.relation = c.oid and relname like '%lock_%' and mode = 'ExclusiveLock'
 | 
			
		||||
 order by relname;
 | 
			
		||||
ROLLBACK;
 | 
			
		||||
 | 
			
		||||
-- Verify that we can lock a table with inheritance children.
 | 
			
		||||
@ -58,10 +107,16 @@ RESET ROLE;
 | 
			
		||||
--
 | 
			
		||||
-- Clean up
 | 
			
		||||
--
 | 
			
		||||
DROP VIEW lock_view6;
 | 
			
		||||
DROP VIEW lock_view5;
 | 
			
		||||
DROP VIEW lock_view4;
 | 
			
		||||
DROP VIEW lock_view3;
 | 
			
		||||
DROP VIEW lock_view2;
 | 
			
		||||
DROP VIEW lock_view1;
 | 
			
		||||
DROP TABLE lock_tbl3;
 | 
			
		||||
DROP TABLE lock_tbl2;
 | 
			
		||||
DROP TABLE lock_tbl1;
 | 
			
		||||
DROP TABLE lock_tbl1a;
 | 
			
		||||
DROP SCHEMA lock_schema1 CASCADE;
 | 
			
		||||
DROP ROLE regress_rol_lock1;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user