From 6db4afe85564972e3914b8e88b547d08af37e132 Mon Sep 17 00:00:00 2001
From: Shinya Kato <shinya11.kato@gmail.com>
Date: Thu, 11 Jun 2026 16:23:39 +0900
Subject: [PATCH v1 5/5] Count local_temporary_table in
 pg_stat_deprecated_features

---
 doc/src/sgml/monitoring.sgml                  | 10 ++++++++
 src/backend/parser/gram.y                     | 14 +++++++++--
 .../activity/pgstat_deprecated_features.c     |  1 +
 src/include/catalog/pg_proc.dat               |  2 +-
 src/include/pgstat.h                          |  1 +
 src/test/regress/expected/stats.out           | 23 ++++++++++++++++++-
 src/test/regress/sql/stats.sql                | 11 +++++++++
 7 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 5b556075006..f30e7bc9364 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -3511,6 +3511,16 @@ description | Waiting for a newly initialized WAL file to reach durable storage
      </listitem>
     </varlistentry>
 
+    <varlistentry>
+     <term><literal>local_temporary_table</literal></term>
+     <listitem>
+      <para>
+       Use of the deprecated <literal>LOCAL</literal> keyword in temporary
+       table creation.
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry>
      <term><literal>md5_password_auth</literal></term>
      <listitem>
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index a0325cd8d1e..402cc16c828 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -3923,8 +3923,16 @@ CreateStmt:	CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')'
  */
 OptTemp:	TEMPORARY					{ $$ = RELPERSISTENCE_TEMP; }
 			| TEMP						{ $$ = RELPERSISTENCE_TEMP; }
-			| LOCAL TEMPORARY			{ $$ = RELPERSISTENCE_TEMP; }
-			| LOCAL TEMP				{ $$ = RELPERSISTENCE_TEMP; }
+			| LOCAL TEMPORARY
+				{
+					pgstat_count_deprecated_feature(PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE);
+					$$ = RELPERSISTENCE_TEMP;
+				}
+			| LOCAL TEMP
+				{
+					pgstat_count_deprecated_feature(PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE);
+					$$ = RELPERSISTENCE_TEMP;
+				}
 			| GLOBAL TEMPORARY
 				{
 					pgstat_count_deprecated_feature(PGSTAT_DEPRECATED_FEATURE_GLOBAL_TEMPORARY_TABLE);
@@ -13965,11 +13973,13 @@ OptTempTableName:
 				}
 			| LOCAL TEMPORARY opt_table qualified_name
 				{
+					pgstat_count_deprecated_feature(PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE);
 					$$ = $4;
 					$$->relpersistence = RELPERSISTENCE_TEMP;
 				}
 			| LOCAL TEMP opt_table qualified_name
 				{
+					pgstat_count_deprecated_feature(PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE);
 					$$ = $4;
 					$$->relpersistence = RELPERSISTENCE_TEMP;
 				}
diff --git a/src/backend/utils/activity/pgstat_deprecated_features.c b/src/backend/utils/activity/pgstat_deprecated_features.c
index fadffc1d19d..a9b18711825 100644
--- a/src/backend/utils/activity/pgstat_deprecated_features.c
+++ b/src/backend/utils/activity/pgstat_deprecated_features.c
@@ -28,6 +28,7 @@
  */
 static const char *const pgstat_deprecated_feature_names[] = {
 	[PGSTAT_DEPRECATED_FEATURE_GLOBAL_TEMPORARY_TABLE] = "global_temporary_table",
+	[PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE] = "local_temporary_table",
 	[PGSTAT_DEPRECATED_FEATURE_MD5_PASSWORD_AUTH] = "md5_password_auth",
 	[PGSTAT_DEPRECATED_FEATURE_MD5_PASSWORD_SET] = "md5_password_set",
 };
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 6d11271d095..ebc4105b1c8 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -6070,7 +6070,7 @@
   prosrc => 'pg_stat_get_lock' },
 
 { oid => '8987', descr => 'statistics: deprecated feature usage',
-  proname => 'pg_stat_get_deprecated_features', prorows => '3',
+  proname => 'pg_stat_get_deprecated_features', prorows => '4',
   proretset => 't', provolatile => 'v', proparallel => 'r',
   prorettype => 'record', proargtypes => '',
   proallargtypes => '{text,int8,timestamptz,timestamptz}',
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 90bc163cc00..a19a12564b6 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -277,6 +277,7 @@ typedef struct PgStat_CheckpointerStats
 typedef enum PgStat_DeprecatedFeature
 {
 	PGSTAT_DEPRECATED_FEATURE_GLOBAL_TEMPORARY_TABLE,
+	PGSTAT_DEPRECATED_FEATURE_LOCAL_TEMPORARY_TABLE,
 	PGSTAT_DEPRECATED_FEATURE_MD5_PASSWORD_AUTH,
 	PGSTAT_DEPRECATED_FEATURE_MD5_PASSWORD_SET,
 } PgStat_DeprecatedFeature;
diff --git a/src/test/regress/expected/stats.out b/src/test/regress/expected/stats.out
index 50e5e18ef0b..eee3563f4ad 100644
--- a/src/test/regress/expected/stats.out
+++ b/src/test/regress/expected/stats.out
@@ -1101,6 +1101,26 @@ SELECT usage_count = :deprecated_global_temp_count + 1 AS incremented,
  t           | t
 (1 row)
 
+-- Creating a temporary table with the deprecated LOCAL keyword must be
+-- counted, even though it is accepted silently.
+SELECT usage_count AS deprecated_local_temp_count
+  FROM pg_stat_deprecated_features WHERE name = 'local_temporary_table' \gset
+CREATE LOCAL TEMPORARY TABLE stats_local_temp (a int);
+DROP TABLE stats_local_temp;
+SELECT pg_stat_force_next_flush();
+ pg_stat_force_next_flush 
+--------------------------
+ 
+(1 row)
+
+SELECT usage_count = :deprecated_local_temp_count + 1 AS incremented,
+       last_used IS NOT NULL AS has_last_used
+  FROM pg_stat_deprecated_features WHERE name = 'local_temporary_table';
+ incremented | has_last_used 
+-------------+---------------
+ t           | t
+(1 row)
+
 -- Setting an MD5-encrypted password must be counted even when
 -- md5_password_warnings is disabled.
 SET md5_password_warnings = off;
@@ -1170,9 +1190,10 @@ SELECT name FROM pg_stat_deprecated_features ORDER BY name COLLATE "C";
           name          
 ------------------------
  global_temporary_table
+ local_temporary_table
  md5_password_auth
  md5_password_set
-(3 rows)
+(4 rows)
 
 -- Test that reset_shared with deprecated_features specified as the stats type works
 SELECT max(stats_reset) AS deprecated_features_reset_ts FROM pg_stat_deprecated_features \gset
diff --git a/src/test/regress/sql/stats.sql b/src/test/regress/sql/stats.sql
index 24e196212af..9be3c4873cc 100644
--- a/src/test/regress/sql/stats.sql
+++ b/src/test/regress/sql/stats.sql
@@ -511,6 +511,17 @@ SELECT usage_count = :deprecated_global_temp_count + 1 AS incremented,
        last_used IS NOT NULL AS has_last_used
   FROM pg_stat_deprecated_features WHERE name = 'global_temporary_table';
 
+-- Creating a temporary table with the deprecated LOCAL keyword must be
+-- counted, even though it is accepted silently.
+SELECT usage_count AS deprecated_local_temp_count
+  FROM pg_stat_deprecated_features WHERE name = 'local_temporary_table' \gset
+CREATE LOCAL TEMPORARY TABLE stats_local_temp (a int);
+DROP TABLE stats_local_temp;
+SELECT pg_stat_force_next_flush();
+SELECT usage_count = :deprecated_local_temp_count + 1 AS incremented,
+       last_used IS NOT NULL AS has_last_used
+  FROM pg_stat_deprecated_features WHERE name = 'local_temporary_table';
+
 -- Setting an MD5-encrypted password must be counted even when
 -- md5_password_warnings is disabled.
 SET md5_password_warnings = off;
-- 
2.47.3

