From 7d94ac6e86670e11fdde20cdf8cebb008bbf8901 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Tue, 7 Jul 2020 18:45:39 -0400
Subject: [PATCH v3 1/2] accept any relkind in LOCK TABLE

---
 doc/src/sgml/ref/lock.sgml      | 15 +++++++++------
 src/backend/commands/lockcmds.c | 18 ++++--------------
 2 files changed, 13 insertions(+), 20 deletions(-)

diff --git a/doc/src/sgml/ref/lock.sgml b/doc/src/sgml/ref/lock.sgml
index 4cdfae2279..37881f25ac 100644
--- a/doc/src/sgml/ref/lock.sgml
+++ b/doc/src/sgml/ref/lock.sgml
@@ -16,7 +16,7 @@ PostgreSQL documentation
 
  <refnamediv>
   <refname>LOCK</refname>
-  <refpurpose>lock a table</refpurpose>
+  <refpurpose>lock a named relation (table, etc)</refpurpose>
  </refnamediv>
 
  <refsynopsisdiv>
@@ -34,7 +34,9 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
   <title>Description</title>
 
   <para>
-   <command>LOCK TABLE</command> obtains a table-level lock, waiting
+   <command>LOCK TABLE</command> obtains a table-level lock on a
+   relation (table, partitioned table, foreign table, view,
+   materialized view, index, composite type, sequence), waiting
    if necessary for any conflicting locks to be released.  If
    <literal>NOWAIT</literal> is specified, <command>LOCK
    TABLE</command> does not wait to acquire the desired lock: if it
@@ -115,17 +117,18 @@ LOCK [ TABLE ] [ ONLY ] <replaceable class="parameter">name</replaceable> [ * ]
     <term><replaceable class="parameter">name</replaceable></term>
     <listitem>
      <para>
-      The name (optionally schema-qualified) of an existing table to
-      lock. If <literal>ONLY</literal> is specified before the table name, only that
+      The name (optionally schema-qualified) of an existing relation to
+      lock. If <literal>ONLY</literal> is specified before a table name, only that
       table is locked. If <literal>ONLY</literal> is not specified, the table and all
       its descendant tables (if any) are locked.  Optionally, <literal>*</literal>
       can be specified after the table name to explicitly indicate that
-      descendant tables are included.
+      descendant tables are included.  When locking a view, all relations appearing
+      in the view definition are locked, regardless of <literal>ONLY</literal>.
      </para>
 
      <para>
       The command <literal>LOCK TABLE a, b;</literal> is equivalent to
-      <literal>LOCK TABLE a; LOCK TABLE b;</literal>. The tables are locked
+      <literal>LOCK TABLE a; LOCK TABLE b;</literal>. The relations are locked
       one-by-one in the order specified in the <command>LOCK
       TABLE</command> command.
      </para>
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index d8cafc42bb..215c1a2bd5 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -83,14 +83,6 @@ RangeVarCallbackForLockTable(const RangeVar *rv, Oid relid, Oid oldrelid,
 		return;					/* woops, concurrently dropped; no permissions
 								 * check */
 
-	/* 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 or view",
-						rv->relname)));
-
 	/*
 	 * Make note if a temporary relation has been accessed in this
 	 * transaction.
@@ -187,11 +179,14 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 		{
 			RangeTblEntry *rte = lfirst(rtable);
 			AclResult	aclresult;
-
 			Oid			relid = rte->relid;
 			char		relkind = rte->relkind;
 			char	   *relname = get_rel_name(relid);
 
+			/* ignore all non-relation RTEs */
+			if (rte->rtekind != RTE_RELATION)
+				continue;
+
 			/*
 			 * The OLD and NEW placeholder entries in the view's rtable are
 			 * skipped.
@@ -201,11 +196,6 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 				 strcmp(rte->eref->aliasname, "new") == 0))
 				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 (list_member_oid(context->ancestor_views, relid))
 				ereport(ERROR,
-- 
2.20.1

