From 55c747b7f86c261d6eefdda5991e92807537f1bf Mon Sep 17 00:00:00 2001
From: TatsuyaKawata <kawatatatsuya0913@gmail.com>
Date: Sun, 28 Jun 2026 02:35:17 +0900
Subject: [PATCH v2] Change wait_time column of pg_stat_lock to double
 precision

Other statistics views (pg_stat_io, pg_stat_database, etc.) use double
precision for all measured-time columns.  Align pg_stat_lock with that
convention by changing wait_time from bigint to double precision.

To preserve the sub-millisecond remainder that the previous bigint
version discarded, accumulate the wait time internally in microseconds
(still as PgStat_Counter / int64) and convert to a millisecond double
only at display time.
---
 doc/src/sgml/monitoring.sgml             | 2 +-
 src/backend/storage/lmgr/proc.c          | 9 +++++----
 src/backend/utils/activity/pgstat_lock.c | 4 ++--
 src/backend/utils/adt/pgstatfuncs.c      | 2 +-
 src/include/catalog/catversion.h         | 2 +-
 src/include/catalog/pg_proc.dat          | 2 +-
 src/include/pgstat.h                     | 4 ++--
 7 files changed, 13 insertions(+), 12 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 08d5b824552..6dcf05eb702 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3359,7 +3359,7 @@ description | Waiting for a newly initialized WAL file to reach durable storage
      <row>
       <entry role="catalog_table_entry">
        <para role="column_definition">
-        <structfield>wait_time</structfield> <type>bigint</type>
+        <structfield>wait_time</structfield> <type>double precision</type>
        </para>
        <para>
         Total time spent waiting for locks of this type, in milliseconds.
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 6fa9de33e1c..cd69ffe2c31 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -1608,12 +1608,13 @@ ProcSleep(LOCALLOCK *locallock)
 			TimestampDifference(get_timeout_start_time(DEADLOCK_TIMEOUT),
 								GetCurrentTimestamp(),
 								&secs, &usecs);
-			msecs = secs * 1000 + usecs / 1000;
-			usecs = usecs % 1000;
-
 			/* Increment the lock statistics counters if done waiting. */
 			if (myWaitStatus == PROC_WAIT_STATUS_OK)
-				pgstat_count_lock_waits(locallock->tag.lock.locktag_type, msecs);
+				pgstat_count_lock_waits(locallock->tag.lock.locktag_type,
+										secs * 1000000 + usecs);
+
+			msecs = secs * 1000 + usecs / 1000;
+			usecs = usecs % 1000;
 
 			if (log_lock_waits)
 			{
diff --git a/src/backend/utils/activity/pgstat_lock.c b/src/backend/utils/activity/pgstat_lock.c
index aec64f8fb4b..455c455db8c 100644
--- a/src/backend/utils/activity/pgstat_lock.c
+++ b/src/backend/utils/activity/pgstat_lock.c
@@ -140,11 +140,11 @@ pgstat_count_lock_fastpath_exceeded(uint8 locktag_type)
  * like lock acquisitions.
  */
 void
-pgstat_count_lock_waits(uint8 locktag_type, long msecs)
+pgstat_count_lock_waits(uint8 locktag_type, long usecs)
 {
 	Assert(locktag_type <= LOCKTAG_LAST_TYPE);
 	PendingLockStats.stats[locktag_type].waits++;
-	PendingLockStats.stats[locktag_type].wait_time += (PgStat_Counter) msecs;
+	PendingLockStats.stats[locktag_type].wait_time += (PgStat_Counter) usecs;
 	have_lockstats = true;
 	pgstat_report_fixed = true;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 6f9c9c72de5..349b1e80ea7 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1761,7 +1761,7 @@ pg_stat_get_lock(PG_FUNCTION_ARGS)
 
 		values[i++] = CStringGetTextDatum(locktypename);
 		values[i++] = Int64GetDatum(lck_stats->waits);
-		values[i++] = Int64GetDatum(lck_stats->wait_time);
+		values[i++] = Float8GetDatum((double) lck_stats->wait_time / 1000.0);
 		values[i++] = Int64GetDatum(lck_stats->fastpath_exceeded);
 		values[i] = TimestampTzGetDatum(lock_stats->stat_reset_timestamp);
 
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 2fe3be9ada5..d2d626372bd 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -57,6 +57,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	202606251
+#define CATALOG_VERSION_NO	202606281
 
 #endif
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 384ba908d35..69dd052a479 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6064,7 +6064,7 @@
 { oid => '6509', descr => 'statistics: per lock type statistics',
   proname => 'pg_stat_get_lock', prorows => '10', proretset => 't',
   provolatile => 'v', proparallel => 'r', prorettype => 'record',
-  proargtypes => '', proallargtypes => '{text,int8,int8,int8,timestamptz}',
+  proargtypes => '', proallargtypes => '{text,int8,float8,int8,timestamptz}',
   proargmodes => '{o,o,o,o,o}',
   proargnames => '{locktype,waits,wait_time,fastpath_exceeded,stats_reset}',
   prosrc => 'pg_stat_get_lock' },
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index dfa2e837638..54e95f2c051 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -349,7 +349,7 @@ typedef struct PgStat_IO
 typedef struct PgStat_LockEntry
 {
 	PgStat_Counter waits;
-	PgStat_Counter wait_time;	/* time in milliseconds */
+	PgStat_Counter wait_time;	/* time in microseconds */
 	PgStat_Counter fastpath_exceeded;
 } PgStat_LockEntry;
 
@@ -638,7 +638,7 @@ extern bool pgstat_tracks_io_op(BackendType bktype, IOObject io_object,
 
 extern void pgstat_lock_flush(bool nowait);
 extern void pgstat_count_lock_fastpath_exceeded(uint8 locktag_type);
-extern void pgstat_count_lock_waits(uint8 locktag_type, long msecs);
+extern void pgstat_count_lock_waits(uint8 locktag_type, long usecs);
 extern PgStat_Lock *pgstat_fetch_stat_lock(void);
 
 /*
-- 
2.34.1

