From 0b86ade1c2f3dcd2407e535baad1654e65252316 Mon Sep 17 00:00:00 2001
From: Tatsuo Ishii <ishii@postgresql.org>
Date: Thu, 11 Mar 2004 01:47:41 +0000
Subject: [PATCH] Add NOWAIT option to LOCK command

---
 doc/src/sgml/ref/lock.sgml       | 10 ++++++----
 src/backend/access/heap/heapam.c | 29 ++++++++++++++++++++++++++++-
 src/backend/commands/lockcmds.c  |  4 ++--
 src/backend/nodes/copyfuncs.c    |  3 ++-
 src/backend/nodes/equalfuncs.c   |  3 ++-
 src/backend/parser/gram.y        | 13 ++++++++++---
 src/backend/parser/keywords.c    |  3 ++-
 src/include/access/heapam.h      |  3 ++-
 src/include/nodes/parsenodes.h   |  3 ++-
 9 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml
index e78ee548fc5..a2c2a78a7aa 100644
--- a/doc/src/sgml/ref/lock.sgml
+++ b/doc/src/sgml/ref/lock.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.40 2003/12/14 00:05:29 neilc Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/lock.sgml,v 1.41 2004/03/11 01:47:35 ishii Exp $
 PostgreSQL documentation
 -->
 
@@ -20,7 +20,7 @@ PostgreSQL documentation
 
  <refsynopsisdiv>
 <synopsis>
-LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ]
+LOCK [ TABLE ] <replaceable class="PARAMETER">name</replaceable> [, ...] [ IN <replaceable class="PARAMETER">lockmode</replaceable> MODE ] [ NOWAIT ]
 
 where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
 
@@ -34,8 +34,10 @@ where <replaceable class="PARAMETER">lockmode</replaceable> is one of:
 
   <para>
    <command>LOCK TABLE</command> obtains a table-level lock, waiting if
-   necessary for any conflicting locks to be released.  Once obtained,
-   the lock is held for the remainder of the current transaction.
+   necessary for any conflicting locks to be released.
+   If <literal>NOWAIT</literal> is given, <command>LOCK TABLE</command>
+   does not wait for acquiring lock, and throws an error instead.
+   Once obtained, the lock is held for the remainder of the current transaction.
    (There is no <command>UNLOCK TABLE</command> command; locks are always
    released at transaction end.)
   </para>
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index d98e3fd16c2..902f0621377 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.162 2004/01/16 20:51:30 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.163 2004/03/11 01:47:35 ishii Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -464,6 +464,33 @@ relation_open(Oid relationId, LOCKMODE lockmode)
 	return r;
 }
 
+Relation
+conditional_relation_open(Oid relationId, LOCKMODE lockmode, bool nowait)
+{
+	Relation	r;
+
+	Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
+	/* The relcache does all the real work... */
+	r = RelationIdGetRelation(relationId);
+
+	if (!RelationIsValid(r))
+		elog(ERROR, "could not open relation with OID %u", relationId);
+
+	if (lockmode != NoLock)
+	{
+		if (nowait)
+		{
+			if (!ConditionalLockRelation(r, lockmode))
+				elog(ERROR, "could not aquire relation lock");
+		}
+		else
+			LockRelation(r, lockmode);
+	}
+
+	return r;
+}
+
 /* ----------------
  *		relation_openrv - open any relation specified by a RangeVar
  *
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index 4634593ada5..58bee42f8fe 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.8 2003/11/29 19:51:47 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/lockcmds.c,v 1.9 2004/03/11 01:47:35 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +59,7 @@ LockTableCommand(LockStmt *lockstmt)
 			aclcheck_error(aclresult, ACL_KIND_CLASS,
 						   get_rel_name(reloid));
 
-		rel = relation_open(reloid, lockstmt->mode);
+		rel = conditional_relation_open(reloid, lockstmt->mode, lockstmt->nowait);
 
 		/* Currently, we only allow plain tables to be locked */
 		if (rel->rd_rel->relkind != RELKIND_RELATION)
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 39f454fd3c9..c1c4ddfed8b 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.277 2004/01/14 23:01:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.278 2004/03/11 01:47:35 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2316,6 +2316,7 @@ _copyLockStmt(LockStmt *from)
 
 	COPY_NODE_FIELD(relations);
 	COPY_SCALAR_FIELD(mode);
+	COPY_SCALAR_FIELD(nowait);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 7951fad039c..b23002ff947 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.215 2004/01/14 23:01:55 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.216 2004/03/11 01:47:35 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1252,6 +1252,7 @@ _equalLockStmt(LockStmt *a, LockStmt *b)
 {
 	COMPARE_NODE_FIELD(relations);
 	COMPARE_SCALAR_FIELD(mode);
+	COMPARE_SCALAR_FIELD(nowait);
 
 	return true;
 }
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 20db7fc6213..9fd2e5b5795 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.447 2004/03/09 05:05:41 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.448 2004/03/11 01:47:37 ishii Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -169,6 +169,7 @@ static void doNegateFloat(Value *v);
 %type <ival>	opt_lock lock_type cast_context
 %type <boolean>	opt_force opt_or_replace transaction_access_mode
 				opt_grant_grant_option opt_revoke_grant_option
+				opt_nowait
 
 %type <boolean>	like_including_defaults
 
@@ -375,7 +376,7 @@ static void doNegateFloat(Value *v);
 	MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
 
 	NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NOCREATEDB
-	NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NULL_P
+	NOCREATEUSER NONE NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P
 	NULLIF NUMERIC
 
 	OBJECT_P OF OFF OFFSET OIDS OLD ON ONLY OPERATOR OPTION OR
@@ -4347,12 +4348,13 @@ DeleteStmt: DELETE_P FROM relation_expr where_clause
 				}
 		;
 
-LockStmt:	LOCK_P opt_table qualified_name_list opt_lock
+LockStmt:	LOCK_P opt_table qualified_name_list opt_lock opt_nowait
 				{
 					LockStmt *n = makeNode(LockStmt);
 
 					n->relations = $3;
 					n->mode = $4;
+					n->nowait = $5;
 					$$ = (Node *)n;
 				}
 		;
@@ -4371,6 +4373,10 @@ lock_type:	ACCESS SHARE					{ $$ = AccessShareLock; }
 			| ACCESS EXCLUSIVE				{ $$ = AccessExclusiveLock; }
 		;
 
+opt_nowait:	NOWAIT 			{ $$ = TRUE; }
+			| /*EMPTY*/						{ $$ = FALSE; }
+		;
+
 
 /*****************************************************************************
  *
@@ -7683,6 +7689,7 @@ reserved_keyword:
 			| LOCALTIMESTAMP
 			| NEW
 			| NOT
+			| NOWAIT
 			| NULL_P
 			| OFF
 			| OFFSET
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 24430a9cc60..54ac767126f 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.146 2004/03/09 05:05:41 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.147 2004/03/11 01:47:40 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -213,6 +213,7 @@ static const ScanKeyword ScanKeywords[] = {
 	{"nothing", NOTHING},
 	{"notify", NOTIFY},
 	{"notnull", NOTNULL},
+	{"nowait", NOWAIT},
 	{"null", NULL_P},
 	{"nullif", NULLIF},
 	{"numeric", NUMERIC},
diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h
index 1b7e19fe073..c6579ea2462 100644
--- a/src/include/access/heapam.h
+++ b/src/include/access/heapam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.86 2003/11/29 22:40:55 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/access/heapam.h,v 1.87 2004/03/11 01:47:41 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -129,6 +129,7 @@ extern Datum heap_getsysattr(HeapTuple tup, int attnum, bool *isnull);
 /* heapam.c */
 
 extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation conditional_relation_open(Oid relationId, LOCKMODE lockmode, bool nowait);
 extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
 extern Relation relation_openr(const char *sysRelationName, LOCKMODE lockmode);
 extern void relation_close(Relation relation, LOCKMODE lockmode);
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 01ff239a444..ab505939bc3 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.253 2004/01/14 23:01:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.254 2004/03/11 01:47:41 ishii Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1619,6 +1619,7 @@ typedef struct LockStmt
 	NodeTag		type;
 	List	   *relations;		/* relations to lock */
 	int			mode;			/* lock mode */
+	bool		nowait;		/* no wait mode */
 } LockStmt;
 
 /* ----------------------
-- 
GitLab