From d09dddcac5a7947aab78925ccdaa1df9bd875685 Mon Sep 17 00:00:00 2001
From: ChangAo Chen <cca5507@qq.com>
Date: Thu, 14 May 2026 13:05:32 +0800
Subject: [PATCH v1] Make log_lock_failures support LOCK NOWAIT

---
 doc/src/sgml/config.sgml            |  9 +++++----
 src/backend/catalog/namespace.c     |  6 +++++-
 src/backend/commands/lockcmds.c     | 18 +++++++++++++++---
 src/backend/commands/repack.c       |  4 ++--
 src/backend/commands/tablecmds.c    |  2 +-
 src/backend/commands/vacuum.c       |  2 +-
 src/backend/postmaster/autovacuum.c |  2 +-
 src/backend/storage/lmgr/lmgr.c     |  4 ++--
 src/include/catalog/namespace.h     |  1 +
 src/include/storage/lmgr.h          |  2 +-
 10 files changed, 34 insertions(+), 16 deletions(-)

diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml
index 73cc0412330..f4cf888e813 100644
--- a/doc/src/sgml/config.sgml
+++ b/doc/src/sgml/config.sgml
@@ -8373,10 +8373,11 @@ log_line_prefix = '%m [%p] %q%u@%d/%a '
         Controls whether a detailed log message is produced
         when a lock acquisition fails.  This is useful for analyzing
         the causes of lock failures.  Currently, only lock failures
-        due to <literal>SELECT NOWAIT</literal> is supported.
-        The default is <literal>off</literal>.  Only superusers and
-        users with the appropriate <literal>SET</literal> privilege
-        can change this setting.
+        due to <literal>SELECT NOWAIT</literal> and
+        <literal>LOCK NOWAIT</literal> is supported.  The default is
+        <literal>off</literal>.  Only superusers and users with the
+        appropriate <literal>SET</literal> privilege can change this
+        setting.
        </para>
       </listitem>
      </varlistentry>
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 56b87d878e8..d7ddeec53ce 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -429,6 +429,9 @@ spcache_insert(const char *searchPath, Oid roleid)
  * If flags contains RVR_SKIP_LOCKED, return InvalidOid if we'd have to wait
  * for a lock.
  *
+ * If flags contains RVR_LOG_LOCK_FAILURE, log lock failure if we'd have
+ * to wait for a lock.
+ *
  * flags cannot contain both RVR_NOWAIT and RVR_SKIP_LOCKED.
  *
  * Note that if RVR_MISSING_OK and RVR_SKIP_LOCKED are both specified, a
@@ -591,7 +594,8 @@ RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode,
 			AcceptInvalidationMessages();
 		else if (!(flags & (RVR_NOWAIT | RVR_SKIP_LOCKED)))
 			LockRelationOid(relId, lockmode);
-		else if (!ConditionalLockRelationOid(relId, lockmode))
+		else if (!ConditionalLockRelationOid(relId, lockmode,
+											 (flags & RVR_LOG_LOCK_FAILURE)))
 		{
 			int			elevel = (flags & RVR_SKIP_LOCKED) ? DEBUG1 : ERROR;
 
diff --git a/src/backend/commands/lockcmds.c b/src/backend/commands/lockcmds.c
index f66b8f17b9b..0043dc96773 100644
--- a/src/backend/commands/lockcmds.c
+++ b/src/backend/commands/lockcmds.c
@@ -23,6 +23,7 @@
 #include "nodes/nodeFuncs.h"
 #include "rewrite/rewriteHandler.h"
 #include "storage/lmgr.h"
+#include "storage/lock.h"
 #include "utils/acl.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -50,9 +51,18 @@ LockTableCommand(LockStmt *lockstmt)
 		RangeVar   *rv = (RangeVar *) lfirst(p);
 		bool		recurse = rv->inh;
 		Oid			reloid;
+		uint32		flags = 0;
+
+		if (lockstmt->nowait)
+		{
+			flags |= RVR_NOWAIT;
+
+			if (log_lock_failures)
+				flags |= RVR_LOG_LOCK_FAILURE;
+		}
 
 		reloid = RangeVarGetRelidExtended(rv, lockstmt->mode,
-										  lockstmt->nowait ? RVR_NOWAIT : 0,
+										  flags,
 										  RangeVarCallbackForLockTable,
 										  &lockstmt->mode);
 
@@ -131,7 +141,8 @@ LockTableRecurse(Oid reloid, LOCKMODE lockmode, bool nowait)
 
 		if (!nowait)
 			LockRelationOid(childreloid, lockmode);
-		else if (!ConditionalLockRelationOid(childreloid, lockmode))
+		else if (!ConditionalLockRelationOid(childreloid, lockmode,
+											 log_lock_failures))
 		{
 			/* try to throw error by name; relation could be deleted... */
 			char	   *relname = get_rel_name(childreloid);
@@ -217,7 +228,8 @@ LockViewRecurse_walker(Node *node, LockViewRecurse_context *context)
 			/* We have enough rights to lock the relation; do so. */
 			if (!context->nowait)
 				LockRelationOid(relid, context->lockmode);
-			else if (!ConditionalLockRelationOid(relid, context->lockmode))
+			else if (!ConditionalLockRelationOid(relid, context->lockmode,
+												 log_lock_failures))
 				ereport(ERROR,
 						(errcode(ERRCODE_LOCK_NOT_AVAILABLE),
 						 errmsg("could not obtain lock on relation \"%s\"",
diff --git a/src/backend/commands/repack.c b/src/backend/commands/repack.c
index fae88d6bb83..136e7f15977 100644
--- a/src/backend/commands/repack.c
+++ b/src/backend/commands/repack.c
@@ -2129,7 +2129,7 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt)
 			 * disregard it.  Be sure to release this if we ultimately decide
 			 * not to process the table!
 			 */
-			if (!ConditionalLockRelationOid(index->indrelid, AccessShareLock))
+			if (!ConditionalLockRelationOid(index->indrelid, AccessShareLock, false))
 				continue;
 
 			/* Verify that the table still exists; skip if not */
@@ -2188,7 +2188,7 @@ get_tables_to_repack(RepackCommand cmd, bool usingindex, MemoryContext permcxt)
 			 * disregard the table.  Be sure to release this if we ultimately
 			 * decide not to process the table!
 			 */
-			if (!ConditionalLockRelationOid(class->oid, AccessShareLock))
+			if (!ConditionalLockRelationOid(class->oid, AccessShareLock, false))
 				continue;
 
 			/* Verify that the table still exists */
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 92b0f38c353..fd50a4c4f21 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -17373,7 +17373,7 @@ AlterTableMoveAll(AlterTableMoveAllStmt *stmt)
 						   NameStr(relForm->relname));
 
 		if (stmt->nowait &&
-			!ConditionalLockRelationOid(relOid, AccessExclusiveLock))
+			!ConditionalLockRelationOid(relOid, AccessExclusiveLock, false))
 			ereport(ERROR,
 					(errcode(ERRCODE_OBJECT_IN_USE),
 					 errmsg("aborting because lock on relation \"%s.%s\" is not available",
diff --git a/src/backend/commands/vacuum.c b/src/backend/commands/vacuum.c
index a4abb29cf64..7bd13421093 100644
--- a/src/backend/commands/vacuum.c
+++ b/src/backend/commands/vacuum.c
@@ -789,7 +789,7 @@ vacuum_open_relation(Oid relid, RangeVar *relation, uint32 options,
 	 */
 	if (!(options & VACOPT_SKIP_LOCKED))
 		rel = try_relation_open(relid, lmode);
-	else if (ConditionalLockRelationOid(relid, lmode))
+	else if (ConditionalLockRelationOid(relid, lmode, false))
 		rel = try_relation_open(relid, NoLock);
 	else
 	{
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index a5a8db2ff88..550c38d3ed7 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2220,7 +2220,7 @@ do_autovacuum(void)
 		 * somebody else is using (or dropping) the table, so it's not our
 		 * concern anymore.  Having the lock prevents race conditions below.
 		 */
-		if (!ConditionalLockRelationOid(relid, AccessExclusiveLock))
+		if (!ConditionalLockRelationOid(relid, AccessExclusiveLock, false))
 			continue;
 
 		/*
diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c
index 2ccf7237fee..29871105416 100644
--- a/src/backend/storage/lmgr/lmgr.c
+++ b/src/backend/storage/lmgr/lmgr.c
@@ -148,7 +148,7 @@ LockRelationOid(Oid relid, LOCKMODE lockmode)
  * LockXXX routines in this file, but they could easily be added if needed.
  */
 bool
-ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
+ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode, bool logLockFailure)
 {
 	LOCKTAG		tag;
 	LOCALLOCK  *locallock;
@@ -157,7 +157,7 @@ ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode)
 	SetLocktagRelationOid(&tag, relid);
 
 	res = LockAcquireExtended(&tag, lockmode, false, true, true, &locallock,
-							  false);
+							  logLockFailure);
 
 	if (res == LOCKACQUIRE_NOT_AVAIL)
 		return false;
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 9453a3e4932..cae2c2f53ec 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -90,6 +90,7 @@ typedef enum RVROption
 	RVR_MISSING_OK = 1 << 0,	/* don't error if relation doesn't exist */
 	RVR_NOWAIT = 1 << 1,		/* error if relation cannot be locked */
 	RVR_SKIP_LOCKED = 1 << 2,	/* skip if relation cannot be locked */
+	RVR_LOG_LOCK_FAILURE = 1 << 3,	/* log failure if relation cannot be locked */
 }			RVROption;
 
 typedef void (*RangeVarGetRelidCallback) (const RangeVar *relation, Oid relId,
diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h
index 2a985ce5e15..7a31a90e8c9 100644
--- a/src/include/storage/lmgr.h
+++ b/src/include/storage/lmgr.h
@@ -39,7 +39,7 @@ extern void RelationInitLockInfo(Relation relation);
 /* Lock a relation */
 extern void LockRelationOid(Oid relid, LOCKMODE lockmode);
 extern void LockRelationId(LockRelId *relid, LOCKMODE lockmode);
-extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode);
+extern bool ConditionalLockRelationOid(Oid relid, LOCKMODE lockmode, bool logLockFailure);
 extern void UnlockRelationId(LockRelId *relid, LOCKMODE lockmode);
 extern void UnlockRelationOid(Oid relid, LOCKMODE lockmode);
 
-- 
2.34.1

