Generate pg_stat_get_* functions with Macros

Started by Drouvot, Bertrandabout 3 years ago22 messages
#1Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
1 attachment(s)

Hi hackers,

Please find attached a patch proposal to $SUBJECT.

The idea has been proposed by Andres in [1]/messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com and can be seen as preparatory work for [1]/messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com.

The patch introduces 2 new Macros, PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR and PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR.

For some functions (namely pg_stat_get_ins_since_vacuum(), pg_stat_get_dead_tuples(), pg_stat_get_mod_since_analyze(),
pg_stat_get_live_tuples(), pg_stat_get_last_autovacuum_time(), pg_stat_get_autovacuum_count(), pg_stat_get_last_vacuum_time(),
pg_stat_get_last_autoanalyze_time(), pg_stat_get_autoanalyze_count() and pg_stat_get_last_analyze_time()), I had to choose between renaming the function and the counter.

I took the later option to avoid changing the linked views, tests....

This patch is also a step forward to "cleaning" the metrics/fields/functions naming (means having them match).

[1]: /messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com

Looking forward to your feedback,

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

Attachments:

v1-0001-PGSTAT_DEFINE_REL_FIELD_ACCESSOR.patchtext/plain; charset=UTF-8; name=v1-0001-PGSTAT_DEFINE_REL_FIELD_ACCESSOR.patchDownload
diff --git a/src/backend/access/heap/README.HOT b/src/backend/access/heap/README.HOT
index 68c6709aa8..6fd1767f70 100644
--- a/src/backend/access/heap/README.HOT
+++ b/src/backend/access/heap/README.HOT
@@ -271,7 +271,7 @@ physical tuple by eliminating an intermediate heap-only tuple or
 replacing a physical root tuple by a redirect pointer, a decrement in
 the table's number of dead tuples is reported to pgstats, which may
 postpone autovacuuming.  Note that we do not count replacing a root tuple
-by a DEAD line pointer as decrementing n_dead_tuples; we still want
+by a DEAD line pointer as decrementing dead_tuples; we still want
 autovacuum to run to clean up the index entries and DEAD item.
 
 This area probably needs further work ...
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 601834d4b4..0746d80224 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3081,9 +3081,9 @@ relation_needs_vacanalyze(Oid relid,
 	if (PointerIsValid(tabentry) && AutoVacuumingActive())
 	{
 		reltuples = classForm->reltuples;
-		vactuples = tabentry->n_dead_tuples;
-		instuples = tabentry->inserts_since_vacuum;
-		anltuples = tabentry->changes_since_analyze;
+		vactuples = tabentry->dead_tuples;
+		instuples = tabentry->ins_since_vacuum;
+		anltuples = tabentry->mod_since_analyze;
 
 		/* If the table hasn't yet been vacuumed, take reltuples as zero */
 		if (reltuples < 0)
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f92e16e7af..a9c05153d9 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -231,8 +231,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
 	 * It is quite possible that a non-aggressive VACUUM ended up skipping
@@ -244,16 +244,16 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	 * autovacuum.  An anti-wraparound autovacuum will catch any persistent
 	 * stragglers.
 	 */
-	tabentry->inserts_since_vacuum = 0;
+	tabentry->ins_since_vacuum = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_vacuum_timestamp = ts;
-		tabentry->autovac_vacuum_count++;
+		tabentry->last_autovacuum_time = ts;
+		tabentry->autovacuum_count++;
 	}
 	else
 	{
-		tabentry->vacuum_timestamp = ts;
+		tabentry->last_vacuum_time = ts;
 		tabentry->vacuum_count++;
 	}
 
@@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
  * Report that the table was just analyzed.
  *
  * Caller must provide new live- and dead-tuples estimates, as well as a
- * flag indicating whether to reset the changes_since_analyze counter.
+ * flag indicating whether to reset the mod_since_analyze counter.
  */
 void
 pgstat_report_analyze(Relation rel,
@@ -318,25 +318,25 @@ pgstat_report_analyze(Relation rel,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
-	 * If commanded, reset changes_since_analyze to zero.  This forgets any
+	 * If commanded, reset mod_since_analyze to zero.  This forgets any
 	 * changes that were committed while the ANALYZE was in progress, but we
 	 * have no good way to estimate how many of those there were.
 	 */
 	if (resetcounter)
-		tabentry->changes_since_analyze = 0;
+		tabentry->mod_since_analyze = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_analyze_timestamp = GetCurrentTimestamp();
-		tabentry->autovac_analyze_count++;
+		tabentry->last_autoanalyze_time = GetCurrentTimestamp();
+		tabentry->autoanalyze_count++;
 	}
 	else
 	{
-		tabentry->analyze_timestamp = GetCurrentTimestamp();
+		tabentry->last_analyze_time = GetCurrentTimestamp();
 		tabentry->analyze_count++;
 	}
 
@@ -798,22 +798,22 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	 */
 	if (lstats->t_counts.t_truncdropped)
 	{
-		tabentry->n_live_tuples = 0;
-		tabentry->n_dead_tuples = 0;
-		tabentry->inserts_since_vacuum = 0;
+		tabentry->live_tuples = 0;
+		tabentry->dead_tuples = 0;
+		tabentry->ins_since_vacuum = 0;
 	}
 
-	tabentry->n_live_tuples += lstats->t_counts.t_delta_live_tuples;
-	tabentry->n_dead_tuples += lstats->t_counts.t_delta_dead_tuples;
-	tabentry->changes_since_analyze += lstats->t_counts.t_changed_tuples;
-	tabentry->inserts_since_vacuum += lstats->t_counts.t_tuples_inserted;
+	tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples;
+	tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples;
+	tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples;
+	tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted;
 	tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched;
 	tabentry->blocks_hit += lstats->t_counts.t_blocks_hit;
 
-	/* Clamp n_live_tuples in case of negative delta_live_tuples */
-	tabentry->n_live_tuples = Max(tabentry->n_live_tuples, 0);
-	/* Likewise for n_dead_tuples */
-	tabentry->n_dead_tuples = Max(tabentry->n_dead_tuples, 0);
+	/* Clamp live_tuples in case of negative delta_live_tuples */
+	tabentry->live_tuples = Max(tabentry->live_tuples, 0);
+	/* Likewise for dead_tuples */
+	tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
 
 	pgstat_unlock_entry(entry_ref);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..b79e6a2133 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,363 +36,106 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-Datum
-pg_stat_get_numscans(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->numscans);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_lastscan(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->lastscan;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-
-Datum
-pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_returned);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_inserted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_deleted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_hot_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_live_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_dead_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->changes_since_analyze);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_ins_since_vacuum(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->inserts_since_vacuum);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_hit);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->analyze_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_analyze_count);
-
-	PG_RETURN_INT64(result);
-}
+#define PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(function_name_prefix, stat_name) \
+Datum \
+CppConcat(function_name_prefix,stat_name)(PG_FUNCTION_ARGS) \
+{ \
+	Oid			relid = PG_GETARG_OID(0); \
+	int64		result; \
+	PgStat_StatTabEntry *tabentry; \
+	\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
+		result = 0; \
+	else \
+		result = (int64) (tabentry->stat_name); \
+	\
+	PG_RETURN_INT64(result); \
+} \
+
+#define PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(function_name_prefix, stat_name) \
+Datum \
+CppConcat(function_name_prefix,stat_name)(PG_FUNCTION_ARGS) \
+{ \
+	Oid			relid = PG_GETARG_OID(0); \
+	TimestampTz result; \
+	PgStat_StatTabEntry *tabentry; \
+	\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
+		result = 0; \
+	else \
+		result = tabentry->stat_name; \
+	\
+	if (result == 0) \
+		PG_RETURN_NULL(); \
+	else \
+		PG_RETURN_TIMESTAMPTZ(result); \
+} \
+
+/* pg_stat_get_numscans */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, numscans);
+
+/* pg_stat_get_tuples_returned */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_returned);
+
+/* pg_stat_get_tuples_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_fetched);
+
+/* pg_stat_get_tuples_inserted */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_inserted);
+
+/* pg_stat_get_tuples_updated */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_updated);
+
+/* pg_stat_get_tuples_deleted */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_deleted);
+
+/* pg_stat_get_tuples_hot_updated */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_hot_updated);
+
+/* pg_stat_get_live_tuples */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, live_tuples);
+
+/* pg_stat_get_dead_tuples */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, dead_tuples);
+
+/* pg_stat_get_mod_since_analyze */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, mod_since_analyze);
+
+/* pg_stat_get_ins_since_vacuum */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, ins_since_vacuum);
+
+/* pg_stat_get_blocks_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, blocks_fetched);
+
+/* pg_stat_get_blocks_hit */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, blocks_hit);
+
+/* pg_stat_get_vacuum_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, vacuum_count);
+
+/* pg_stat_get_autovacuum_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, autovacuum_count);
+
+/* pg_stat_get_analyze_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, analyze_count);
+
+/* pg_stat_get_autoanalyze_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, autoanalyze_count);
+
+/* pg_stat_get_lastscan */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(pg_stat_get_, lastscan);
+
+/* pg_stat_get_last_vacuum_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(pg_stat_get_, last_vacuum_time);
+
+/* pg_stat_get_last_autovacuum_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(pg_stat_get_, last_autovacuum_time);
+
+/* pg_stat_get_last_analyze_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(pg_stat_get_, last_analyze_time);
+
+/* pg_stat_get_last_autoanalyze_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(pg_stat_get_, last_autoanalyze_time);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9e2ce6f011..bc6349727b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -364,22 +364,22 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter tuples_deleted;
 	PgStat_Counter tuples_hot_updated;
 
-	PgStat_Counter n_live_tuples;
-	PgStat_Counter n_dead_tuples;
-	PgStat_Counter changes_since_analyze;
-	PgStat_Counter inserts_since_vacuum;
+	PgStat_Counter live_tuples;
+	PgStat_Counter dead_tuples;
+	PgStat_Counter mod_since_analyze;
+	PgStat_Counter ins_since_vacuum;
 
 	PgStat_Counter blocks_fetched;
 	PgStat_Counter blocks_hit;
 
-	TimestampTz vacuum_timestamp;	/* user initiated vacuum */
+	TimestampTz last_vacuum_time;	/* user initiated vacuum */
 	PgStat_Counter vacuum_count;
-	TimestampTz autovac_vacuum_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_vacuum_count;
-	TimestampTz analyze_timestamp;	/* user initiated */
+	TimestampTz last_autovacuum_time;	/* autovacuum initiated */
+	PgStat_Counter autovacuum_count;
+	TimestampTz last_analyze_time;	/* user initiated */
 	PgStat_Counter analyze_count;
-	TimestampTz autovac_analyze_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_analyze_count;
+	TimestampTz last_autoanalyze_time;	/* autovacuum initiated */
+	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
 typedef struct PgStat_WalStats
#2Nathan Bossart
nathandbossart@gmail.com
In reply to: Drouvot, Bertrand (#1)
Re: Generate pg_stat_get_* functions with Macros

Overall, this change looks straightforward, and it saves a couple hundred
lines.

On Tue, Nov 22, 2022 at 08:09:22AM +0100, Drouvot, Bertrand wrote:

+/* pg_stat_get_numscans */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, numscans);
+
+/* pg_stat_get_tuples_returned */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_returned);
+
+/* pg_stat_get_tuples_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_fetched);

Can we hard-code the prefix in the macro? It looks like all of these use
the same one.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

#3Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Nathan Bossart (#2)
1 attachment(s)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/3/22 1:51 AM, Nathan Bossart wrote:

Overall, this change looks straightforward, and it saves a couple hundred
lines.

Thanks for looking at it!

On Tue, Nov 22, 2022 at 08:09:22AM +0100, Drouvot, Bertrand wrote:

+/* pg_stat_get_numscans */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, numscans);
+
+/* pg_stat_get_tuples_returned */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_returned);
+
+/* pg_stat_get_tuples_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(pg_stat_get_, tuples_fetched);

Can we hard-code the prefix in the macro? It looks like all of these use
the same one.

Good point! Done in V2 attached.

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

Attachments:

v2-0001-PGSTAT_DEFINE_REL_FIELD_ACCESSOR.patchtext/plain; charset=UTF-8; name=v2-0001-PGSTAT_DEFINE_REL_FIELD_ACCESSOR.patchDownload
diff --git a/src/backend/access/heap/README.HOT b/src/backend/access/heap/README.HOT
index 68c6709aa8..6fd1767f70 100644
--- a/src/backend/access/heap/README.HOT
+++ b/src/backend/access/heap/README.HOT
@@ -271,7 +271,7 @@ physical tuple by eliminating an intermediate heap-only tuple or
 replacing a physical root tuple by a redirect pointer, a decrement in
 the table's number of dead tuples is reported to pgstats, which may
 postpone autovacuuming.  Note that we do not count replacing a root tuple
-by a DEAD line pointer as decrementing n_dead_tuples; we still want
+by a DEAD line pointer as decrementing dead_tuples; we still want
 autovacuum to run to clean up the index entries and DEAD item.
 
 This area probably needs further work ...
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 601834d4b4..0746d80224 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3081,9 +3081,9 @@ relation_needs_vacanalyze(Oid relid,
 	if (PointerIsValid(tabentry) && AutoVacuumingActive())
 	{
 		reltuples = classForm->reltuples;
-		vactuples = tabentry->n_dead_tuples;
-		instuples = tabentry->inserts_since_vacuum;
-		anltuples = tabentry->changes_since_analyze;
+		vactuples = tabentry->dead_tuples;
+		instuples = tabentry->ins_since_vacuum;
+		anltuples = tabentry->mod_since_analyze;
 
 		/* If the table hasn't yet been vacuumed, take reltuples as zero */
 		if (reltuples < 0)
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f92e16e7af..a9c05153d9 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -231,8 +231,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
 	 * It is quite possible that a non-aggressive VACUUM ended up skipping
@@ -244,16 +244,16 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	 * autovacuum.  An anti-wraparound autovacuum will catch any persistent
 	 * stragglers.
 	 */
-	tabentry->inserts_since_vacuum = 0;
+	tabentry->ins_since_vacuum = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_vacuum_timestamp = ts;
-		tabentry->autovac_vacuum_count++;
+		tabentry->last_autovacuum_time = ts;
+		tabentry->autovacuum_count++;
 	}
 	else
 	{
-		tabentry->vacuum_timestamp = ts;
+		tabentry->last_vacuum_time = ts;
 		tabentry->vacuum_count++;
 	}
 
@@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
  * Report that the table was just analyzed.
  *
  * Caller must provide new live- and dead-tuples estimates, as well as a
- * flag indicating whether to reset the changes_since_analyze counter.
+ * flag indicating whether to reset the mod_since_analyze counter.
  */
 void
 pgstat_report_analyze(Relation rel,
@@ -318,25 +318,25 @@ pgstat_report_analyze(Relation rel,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
-	 * If commanded, reset changes_since_analyze to zero.  This forgets any
+	 * If commanded, reset mod_since_analyze to zero.  This forgets any
 	 * changes that were committed while the ANALYZE was in progress, but we
 	 * have no good way to estimate how many of those there were.
 	 */
 	if (resetcounter)
-		tabentry->changes_since_analyze = 0;
+		tabentry->mod_since_analyze = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_analyze_timestamp = GetCurrentTimestamp();
-		tabentry->autovac_analyze_count++;
+		tabentry->last_autoanalyze_time = GetCurrentTimestamp();
+		tabentry->autoanalyze_count++;
 	}
 	else
 	{
-		tabentry->analyze_timestamp = GetCurrentTimestamp();
+		tabentry->last_analyze_time = GetCurrentTimestamp();
 		tabentry->analyze_count++;
 	}
 
@@ -798,22 +798,22 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	 */
 	if (lstats->t_counts.t_truncdropped)
 	{
-		tabentry->n_live_tuples = 0;
-		tabentry->n_dead_tuples = 0;
-		tabentry->inserts_since_vacuum = 0;
+		tabentry->live_tuples = 0;
+		tabentry->dead_tuples = 0;
+		tabentry->ins_since_vacuum = 0;
 	}
 
-	tabentry->n_live_tuples += lstats->t_counts.t_delta_live_tuples;
-	tabentry->n_dead_tuples += lstats->t_counts.t_delta_dead_tuples;
-	tabentry->changes_since_analyze += lstats->t_counts.t_changed_tuples;
-	tabentry->inserts_since_vacuum += lstats->t_counts.t_tuples_inserted;
+	tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples;
+	tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples;
+	tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples;
+	tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted;
 	tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched;
 	tabentry->blocks_hit += lstats->t_counts.t_blocks_hit;
 
-	/* Clamp n_live_tuples in case of negative delta_live_tuples */
-	tabentry->n_live_tuples = Max(tabentry->n_live_tuples, 0);
-	/* Likewise for n_dead_tuples */
-	tabentry->n_dead_tuples = Max(tabentry->n_dead_tuples, 0);
+	/* Clamp live_tuples in case of negative delta_live_tuples */
+	tabentry->live_tuples = Max(tabentry->live_tuples, 0);
+	/* Likewise for dead_tuples */
+	tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
 
 	pgstat_unlock_entry(entry_ref);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..38dc2d58fa 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,363 +36,106 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-Datum
-pg_stat_get_numscans(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->numscans);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_lastscan(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->lastscan;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-
-Datum
-pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_returned);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_inserted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_deleted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_hot_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_live_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_dead_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->changes_since_analyze);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_ins_since_vacuum(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->inserts_since_vacuum);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_hit);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->analyze_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_analyze_count);
-
-	PG_RETURN_INT64(result);
-}
+#define PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(stat_name) \
+Datum \
+CppConcat(pg_stat_get_,stat_name)(PG_FUNCTION_ARGS) \
+{ \
+	Oid			relid = PG_GETARG_OID(0); \
+	int64		result; \
+	PgStat_StatTabEntry *tabentry; \
+	\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
+		result = 0; \
+	else \
+		result = (int64) (tabentry->stat_name); \
+	\
+	PG_RETURN_INT64(result); \
+} \
+
+#define PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(stat_name) \
+Datum \
+CppConcat(pg_stat_get_,stat_name)(PG_FUNCTION_ARGS) \
+{ \
+	Oid			relid = PG_GETARG_OID(0); \
+	TimestampTz result; \
+	PgStat_StatTabEntry *tabentry; \
+	\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) \
+		result = 0; \
+	else \
+		result = tabentry->stat_name; \
+	\
+	if (result == 0) \
+		PG_RETURN_NULL(); \
+	else \
+		PG_RETURN_TIMESTAMPTZ(result); \
+} \
+
+/* pg_stat_get_numscans */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(numscans);
+
+/* pg_stat_get_tuples_returned */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_returned);
+
+/* pg_stat_get_tuples_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_fetched);
+
+/* pg_stat_get_tuples_inserted */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_inserted);
+
+/* pg_stat_get_tuples_updated */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_updated);
+
+/* pg_stat_get_tuples_deleted */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_deleted);
+
+/* pg_stat_get_tuples_hot_updated */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(tuples_hot_updated);
+
+/* pg_stat_get_live_tuples */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(live_tuples);
+
+/* pg_stat_get_dead_tuples */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(dead_tuples);
+
+/* pg_stat_get_mod_since_analyze */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(mod_since_analyze);
+
+/* pg_stat_get_ins_since_vacuum */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(ins_since_vacuum);
+
+/* pg_stat_get_blocks_fetched */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(blocks_fetched);
+
+/* pg_stat_get_blocks_hit */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(blocks_hit);
+
+/* pg_stat_get_vacuum_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(vacuum_count);
+
+/* pg_stat_get_autovacuum_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(autovacuum_count);
+
+/* pg_stat_get_analyze_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(analyze_count);
+
+/* pg_stat_get_autoanalyze_count */
+PGSTAT_DEFINE_REL_INT64_FIELD_ACCESSOR(autoanalyze_count);
+
+/* pg_stat_get_lastscan */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(lastscan);
+
+/* pg_stat_get_last_vacuum_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(last_vacuum_time);
+
+/* pg_stat_get_last_autovacuum_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(last_autovacuum_time);
+
+/* pg_stat_get_last_analyze_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(last_analyze_time);
+
+/* pg_stat_get_last_autoanalyze_time */
+PGSTAT_DEFINE_REL_TSTZ_FIELD_ACCESSOR(last_autoanalyze_time);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9e2ce6f011..bc6349727b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -364,22 +364,22 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter tuples_deleted;
 	PgStat_Counter tuples_hot_updated;
 
-	PgStat_Counter n_live_tuples;
-	PgStat_Counter n_dead_tuples;
-	PgStat_Counter changes_since_analyze;
-	PgStat_Counter inserts_since_vacuum;
+	PgStat_Counter live_tuples;
+	PgStat_Counter dead_tuples;
+	PgStat_Counter mod_since_analyze;
+	PgStat_Counter ins_since_vacuum;
 
 	PgStat_Counter blocks_fetched;
 	PgStat_Counter blocks_hit;
 
-	TimestampTz vacuum_timestamp;	/* user initiated vacuum */
+	TimestampTz last_vacuum_time;	/* user initiated vacuum */
 	PgStat_Counter vacuum_count;
-	TimestampTz autovac_vacuum_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_vacuum_count;
-	TimestampTz analyze_timestamp;	/* user initiated */
+	TimestampTz last_autovacuum_time;	/* autovacuum initiated */
+	PgStat_Counter autovacuum_count;
+	TimestampTz last_analyze_time;	/* user initiated */
 	PgStat_Counter analyze_count;
-	TimestampTz autovac_analyze_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_analyze_count;
+	TimestampTz last_autoanalyze_time;	/* autovacuum initiated */
+	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
 typedef struct PgStat_WalStats
#4Nathan Bossart
nathandbossart@gmail.com
In reply to: Drouvot, Bertrand (#3)
1 attachment(s)
Re: Generate pg_stat_get_* functions with Macros

On Sat, Dec 03, 2022 at 10:31:19AM +0100, Drouvot, Bertrand wrote:

On 12/3/22 1:51 AM, Nathan Bossart wrote:

Can we hard-code the prefix in the macro? It looks like all of these use
the same one.

Good point! Done in V2 attached.

Thanks. I editorialized a bit in the attached v3. I'm not sure that my
proposed names for the macros are actually an improvement. WDYT?

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

Attachments:

v3-0001-generate-some-pg_stat_get_-functions-with-macros.patchtext/x-diff; charset=us-asciiDownload
From 88ee4410b27709efe06f233a1cee29a8932936bd Mon Sep 17 00:00:00 2001
From: Nathan Bossart <nathandbossart@gmail.com>
Date: Sat, 3 Dec 2022 12:07:37 -0800
Subject: [PATCH v3 1/1] generate some pg_stat_get_* functions with macros

---
 src/backend/access/heap/README.HOT           |   2 +-
 src/backend/postmaster/autovacuum.c          |   6 +-
 src/backend/utils/activity/pgstat_relation.c |  50 +-
 src/backend/utils/adt/pgstatfuncs.c          | 457 ++++---------------
 src/include/pgstat.h                         |  20 +-
 5 files changed, 139 insertions(+), 396 deletions(-)

diff --git a/src/backend/access/heap/README.HOT b/src/backend/access/heap/README.HOT
index 68c6709aa8..6fd1767f70 100644
--- a/src/backend/access/heap/README.HOT
+++ b/src/backend/access/heap/README.HOT
@@ -271,7 +271,7 @@ physical tuple by eliminating an intermediate heap-only tuple or
 replacing a physical root tuple by a redirect pointer, a decrement in
 the table's number of dead tuples is reported to pgstats, which may
 postpone autovacuuming.  Note that we do not count replacing a root tuple
-by a DEAD line pointer as decrementing n_dead_tuples; we still want
+by a DEAD line pointer as decrementing dead_tuples; we still want
 autovacuum to run to clean up the index entries and DEAD item.
 
 This area probably needs further work ...
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 601834d4b4..0746d80224 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3081,9 +3081,9 @@ relation_needs_vacanalyze(Oid relid,
 	if (PointerIsValid(tabentry) && AutoVacuumingActive())
 	{
 		reltuples = classForm->reltuples;
-		vactuples = tabentry->n_dead_tuples;
-		instuples = tabentry->inserts_since_vacuum;
-		anltuples = tabentry->changes_since_analyze;
+		vactuples = tabentry->dead_tuples;
+		instuples = tabentry->ins_since_vacuum;
+		anltuples = tabentry->mod_since_analyze;
 
 		/* If the table hasn't yet been vacuumed, take reltuples as zero */
 		if (reltuples < 0)
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f92e16e7af..a9c05153d9 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -231,8 +231,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
 	 * It is quite possible that a non-aggressive VACUUM ended up skipping
@@ -244,16 +244,16 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	 * autovacuum.  An anti-wraparound autovacuum will catch any persistent
 	 * stragglers.
 	 */
-	tabentry->inserts_since_vacuum = 0;
+	tabentry->ins_since_vacuum = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_vacuum_timestamp = ts;
-		tabentry->autovac_vacuum_count++;
+		tabentry->last_autovacuum_time = ts;
+		tabentry->autovacuum_count++;
 	}
 	else
 	{
-		tabentry->vacuum_timestamp = ts;
+		tabentry->last_vacuum_time = ts;
 		tabentry->vacuum_count++;
 	}
 
@@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
  * Report that the table was just analyzed.
  *
  * Caller must provide new live- and dead-tuples estimates, as well as a
- * flag indicating whether to reset the changes_since_analyze counter.
+ * flag indicating whether to reset the mod_since_analyze counter.
  */
 void
 pgstat_report_analyze(Relation rel,
@@ -318,25 +318,25 @@ pgstat_report_analyze(Relation rel,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
-	 * If commanded, reset changes_since_analyze to zero.  This forgets any
+	 * If commanded, reset mod_since_analyze to zero.  This forgets any
 	 * changes that were committed while the ANALYZE was in progress, but we
 	 * have no good way to estimate how many of those there were.
 	 */
 	if (resetcounter)
-		tabentry->changes_since_analyze = 0;
+		tabentry->mod_since_analyze = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_analyze_timestamp = GetCurrentTimestamp();
-		tabentry->autovac_analyze_count++;
+		tabentry->last_autoanalyze_time = GetCurrentTimestamp();
+		tabentry->autoanalyze_count++;
 	}
 	else
 	{
-		tabentry->analyze_timestamp = GetCurrentTimestamp();
+		tabentry->last_analyze_time = GetCurrentTimestamp();
 		tabentry->analyze_count++;
 	}
 
@@ -798,22 +798,22 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	 */
 	if (lstats->t_counts.t_truncdropped)
 	{
-		tabentry->n_live_tuples = 0;
-		tabentry->n_dead_tuples = 0;
-		tabentry->inserts_since_vacuum = 0;
+		tabentry->live_tuples = 0;
+		tabentry->dead_tuples = 0;
+		tabentry->ins_since_vacuum = 0;
 	}
 
-	tabentry->n_live_tuples += lstats->t_counts.t_delta_live_tuples;
-	tabentry->n_dead_tuples += lstats->t_counts.t_delta_dead_tuples;
-	tabentry->changes_since_analyze += lstats->t_counts.t_changed_tuples;
-	tabentry->inserts_since_vacuum += lstats->t_counts.t_tuples_inserted;
+	tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples;
+	tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples;
+	tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples;
+	tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted;
 	tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched;
 	tabentry->blocks_hit += lstats->t_counts.t_blocks_hit;
 
-	/* Clamp n_live_tuples in case of negative delta_live_tuples */
-	tabentry->n_live_tuples = Max(tabentry->n_live_tuples, 0);
-	/* Likewise for n_dead_tuples */
-	tabentry->n_dead_tuples = Max(tabentry->n_dead_tuples, 0);
+	/* Clamp live_tuples in case of negative delta_live_tuples */
+	tabentry->live_tuples = Max(tabentry->live_tuples, 0);
+	/* Likewise for dead_tuples */
+	tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
 
 	pgstat_unlock_entry(entry_ref);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..97397c074f 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,363 +36,106 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-Datum
-pg_stat_get_numscans(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->numscans);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_lastscan(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->lastscan;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-
-Datum
-pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_returned);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_inserted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_deleted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_hot_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_live_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_dead_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->changes_since_analyze);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_ins_since_vacuum(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->inserts_since_vacuum);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_hit);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->analyze_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_analyze_count);
-
-	PG_RETURN_INT64(result);
-}
+#define PG_STAT_GET_TABENTRY_INT64(stat)						\
+Datum															\
+CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
+{																\
+	Oid			relid = PG_GETARG_OID(0);						\
+	int64		result;											\
+	PgStat_StatTabEntry *tabentry;								\
+																\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = (int64) (tabentry->stat);						\
+																\
+	PG_RETURN_INT64(result);									\
+}																\
+
+/* pg_stat_get_analyze_count */
+PG_STAT_GET_TABENTRY_INT64(analyze_count);
+
+/* pg_stat_get_autoanalyze_count */
+PG_STAT_GET_TABENTRY_INT64(autoanalyze_count);
+
+/* pg_stat_get_autovacuum_count */
+PG_STAT_GET_TABENTRY_INT64(autovacuum_count);
+
+/* pg_stat_get_blocks_fetched */
+PG_STAT_GET_TABENTRY_INT64(blocks_fetched);
+
+/* pg_stat_get_blocks_hit */
+PG_STAT_GET_TABENTRY_INT64(blocks_hit);
+
+/* pg_stat_get_dead_tuples */
+PG_STAT_GET_TABENTRY_INT64(dead_tuples);
+
+/* pg_stat_get_ins_since_vacuum */
+PG_STAT_GET_TABENTRY_INT64(ins_since_vacuum);
+
+/* pg_stat_get_live_tuples */
+PG_STAT_GET_TABENTRY_INT64(live_tuples);
+
+/* pg_stat_get_mods_since_analyze */
+PG_STAT_GET_TABENTRY_INT64(mod_since_analyze);
+
+/* pg_stat_get_numscans */
+PG_STAT_GET_TABENTRY_INT64(numscans);
+
+/* pg_stat_get_tuples_deleted */
+PG_STAT_GET_TABENTRY_INT64(tuples_deleted);
+
+/* pg_stat_get_tuples_fetched */
+PG_STAT_GET_TABENTRY_INT64(tuples_fetched);
+
+/* pg_stat_get_tuples_hot_updated */
+PG_STAT_GET_TABENTRY_INT64(tuples_hot_updated);
+
+/* pg_stat_get_tuples_inserted */
+PG_STAT_GET_TABENTRY_INT64(tuples_inserted);
+
+/* pg_stat_get_tuples_returned */
+PG_STAT_GET_TABENTRY_INT64(tuples_returned);
+
+/* pg_stat_get_tuples_updated */
+PG_STAT_GET_TABENTRY_INT64(tuples_updated);
+
+/* pg_stat_get_vacuum_count */
+PG_STAT_GET_TABENTRY_INT64(vacuum_count);
+
+#define PG_STAT_GET_TABENTRY_TIMESTAMPTZ(stat)					\
+Datum															\
+CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
+{																\
+	Oid			relid = PG_GETARG_OID(0);						\
+	TimestampTz result;											\
+	PgStat_StatTabEntry *tabentry;								\
+																\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = tabentry->stat;								\
+																\
+	if (result == 0)											\
+		PG_RETURN_NULL();										\
+	else														\
+		PG_RETURN_TIMESTAMPTZ(result);							\
+}																\
+
+/* pg_stat_get_last_analyze_time */
+PG_STAT_GET_TABENTRY_TIMESTAMPTZ(last_analyze_time);
+
+/* pg_stat_get_last_autoanalyze_time */
+PG_STAT_GET_TABENTRY_TIMESTAMPTZ(last_autoanalyze_time);
+
+/* pg_stat_get_last_autovacuum_time */
+PG_STAT_GET_TABENTRY_TIMESTAMPTZ(last_autovacuum_time);
+
+/* pg_stat_get_last_vacuum_time */
+PG_STAT_GET_TABENTRY_TIMESTAMPTZ(last_vacuum_time);
+
+/* pg_stat_get_lastscan */
+PG_STAT_GET_TABENTRY_TIMESTAMPTZ(lastscan);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9e2ce6f011..bc6349727b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -364,22 +364,22 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter tuples_deleted;
 	PgStat_Counter tuples_hot_updated;
 
-	PgStat_Counter n_live_tuples;
-	PgStat_Counter n_dead_tuples;
-	PgStat_Counter changes_since_analyze;
-	PgStat_Counter inserts_since_vacuum;
+	PgStat_Counter live_tuples;
+	PgStat_Counter dead_tuples;
+	PgStat_Counter mod_since_analyze;
+	PgStat_Counter ins_since_vacuum;
 
 	PgStat_Counter blocks_fetched;
 	PgStat_Counter blocks_hit;
 
-	TimestampTz vacuum_timestamp;	/* user initiated vacuum */
+	TimestampTz last_vacuum_time;	/* user initiated vacuum */
 	PgStat_Counter vacuum_count;
-	TimestampTz autovac_vacuum_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_vacuum_count;
-	TimestampTz analyze_timestamp;	/* user initiated */
+	TimestampTz last_autovacuum_time;	/* autovacuum initiated */
+	PgStat_Counter autovacuum_count;
+	TimestampTz last_analyze_time;	/* user initiated */
 	PgStat_Counter analyze_count;
-	TimestampTz autovac_analyze_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_analyze_count;
+	TimestampTz last_autoanalyze_time;	/* autovacuum initiated */
+	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
 typedef struct PgStat_WalStats
-- 
2.25.1

#5Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Nathan Bossart (#4)
1 attachment(s)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/3/22 9:16 PM, Nathan Bossart wrote:

On Sat, Dec 03, 2022 at 10:31:19AM +0100, Drouvot, Bertrand wrote:

On 12/3/22 1:51 AM, Nathan Bossart wrote:

Can we hard-code the prefix in the macro? It looks like all of these use
the same one.

Good point! Done in V2 attached.

Thanks. I editorialized a bit in the attached v3. I'm not sure that my
proposed names for the macros are actually an improvement. WDYT?

Thanks! I do prefer the macros definition ordering that you're proposing (that makes pgstatfuncs.c "easier" to read).

As far the names, I think it's better to replace "TAB" with "REL" (like in v4 attached): the reason is that those macros will be used in [1]/messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com for both tables and indexes stats (and so we'd have to replace "TAB" with "REL" in [1]/messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com).
Having "REL" already in place reduces the changes that will be needed in [1]/messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com.

[1]: /messages/by-id/f572abe7-a1bb-e13b-48c7-2ca150546822@gmail.com

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

Attachments:

v4-0001-generate-some-pg_stat_get_-functions-with-macros.patchtext/plain; charset=UTF-8; name=v4-0001-generate-some-pg_stat_get_-functions-with-macros.patchDownload
diff --git a/src/backend/access/heap/README.HOT b/src/backend/access/heap/README.HOT
index 68c6709aa8..6fd1767f70 100644
--- a/src/backend/access/heap/README.HOT
+++ b/src/backend/access/heap/README.HOT
@@ -271,7 +271,7 @@ physical tuple by eliminating an intermediate heap-only tuple or
 replacing a physical root tuple by a redirect pointer, a decrement in
 the table's number of dead tuples is reported to pgstats, which may
 postpone autovacuuming.  Note that we do not count replacing a root tuple
-by a DEAD line pointer as decrementing n_dead_tuples; we still want
+by a DEAD line pointer as decrementing dead_tuples; we still want
 autovacuum to run to clean up the index entries and DEAD item.
 
 This area probably needs further work ...
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 601834d4b4..0746d80224 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -3081,9 +3081,9 @@ relation_needs_vacanalyze(Oid relid,
 	if (PointerIsValid(tabentry) && AutoVacuumingActive())
 	{
 		reltuples = classForm->reltuples;
-		vactuples = tabentry->n_dead_tuples;
-		instuples = tabentry->inserts_since_vacuum;
-		anltuples = tabentry->changes_since_analyze;
+		vactuples = tabentry->dead_tuples;
+		instuples = tabentry->ins_since_vacuum;
+		anltuples = tabentry->mod_since_analyze;
 
 		/* If the table hasn't yet been vacuumed, take reltuples as zero */
 		if (reltuples < 0)
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index f92e16e7af..a9c05153d9 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -231,8 +231,8 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
 	 * It is quite possible that a non-aggressive VACUUM ended up skipping
@@ -244,16 +244,16 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
 	 * autovacuum.  An anti-wraparound autovacuum will catch any persistent
 	 * stragglers.
 	 */
-	tabentry->inserts_since_vacuum = 0;
+	tabentry->ins_since_vacuum = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_vacuum_timestamp = ts;
-		tabentry->autovac_vacuum_count++;
+		tabentry->last_autovacuum_time = ts;
+		tabentry->autovacuum_count++;
 	}
 	else
 	{
-		tabentry->vacuum_timestamp = ts;
+		tabentry->last_vacuum_time = ts;
 		tabentry->vacuum_count++;
 	}
 
@@ -264,7 +264,7 @@ pgstat_report_vacuum(Oid tableoid, bool shared,
  * Report that the table was just analyzed.
  *
  * Caller must provide new live- and dead-tuples estimates, as well as a
- * flag indicating whether to reset the changes_since_analyze counter.
+ * flag indicating whether to reset the mod_since_analyze counter.
  */
 void
 pgstat_report_analyze(Relation rel,
@@ -318,25 +318,25 @@ pgstat_report_analyze(Relation rel,
 	shtabentry = (PgStatShared_Relation *) entry_ref->shared_stats;
 	tabentry = &shtabentry->stats;
 
-	tabentry->n_live_tuples = livetuples;
-	tabentry->n_dead_tuples = deadtuples;
+	tabentry->live_tuples = livetuples;
+	tabentry->dead_tuples = deadtuples;
 
 	/*
-	 * If commanded, reset changes_since_analyze to zero.  This forgets any
+	 * If commanded, reset mod_since_analyze to zero.  This forgets any
 	 * changes that were committed while the ANALYZE was in progress, but we
 	 * have no good way to estimate how many of those there were.
 	 */
 	if (resetcounter)
-		tabentry->changes_since_analyze = 0;
+		tabentry->mod_since_analyze = 0;
 
 	if (IsAutoVacuumWorkerProcess())
 	{
-		tabentry->autovac_analyze_timestamp = GetCurrentTimestamp();
-		tabentry->autovac_analyze_count++;
+		tabentry->last_autoanalyze_time = GetCurrentTimestamp();
+		tabentry->autoanalyze_count++;
 	}
 	else
 	{
-		tabentry->analyze_timestamp = GetCurrentTimestamp();
+		tabentry->last_analyze_time = GetCurrentTimestamp();
 		tabentry->analyze_count++;
 	}
 
@@ -798,22 +798,22 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 	 */
 	if (lstats->t_counts.t_truncdropped)
 	{
-		tabentry->n_live_tuples = 0;
-		tabentry->n_dead_tuples = 0;
-		tabentry->inserts_since_vacuum = 0;
+		tabentry->live_tuples = 0;
+		tabentry->dead_tuples = 0;
+		tabentry->ins_since_vacuum = 0;
 	}
 
-	tabentry->n_live_tuples += lstats->t_counts.t_delta_live_tuples;
-	tabentry->n_dead_tuples += lstats->t_counts.t_delta_dead_tuples;
-	tabentry->changes_since_analyze += lstats->t_counts.t_changed_tuples;
-	tabentry->inserts_since_vacuum += lstats->t_counts.t_tuples_inserted;
+	tabentry->live_tuples += lstats->t_counts.t_delta_live_tuples;
+	tabentry->dead_tuples += lstats->t_counts.t_delta_dead_tuples;
+	tabentry->mod_since_analyze += lstats->t_counts.t_changed_tuples;
+	tabentry->ins_since_vacuum += lstats->t_counts.t_tuples_inserted;
 	tabentry->blocks_fetched += lstats->t_counts.t_blocks_fetched;
 	tabentry->blocks_hit += lstats->t_counts.t_blocks_hit;
 
-	/* Clamp n_live_tuples in case of negative delta_live_tuples */
-	tabentry->n_live_tuples = Max(tabentry->n_live_tuples, 0);
-	/* Likewise for n_dead_tuples */
-	tabentry->n_dead_tuples = Max(tabentry->n_dead_tuples, 0);
+	/* Clamp live_tuples in case of negative delta_live_tuples */
+	tabentry->live_tuples = Max(tabentry->live_tuples, 0);
+	/* Likewise for dead_tuples */
+	tabentry->dead_tuples = Max(tabentry->dead_tuples, 0);
 
 	pgstat_unlock_entry(entry_ref);
 
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index ae3365d917..973979508d 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -36,363 +36,106 @@
 
 #define HAS_PGSTAT_PERMISSIONS(role)	 (has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS) || has_privs_of_role(GetUserId(), role))
 
-Datum
-pg_stat_get_numscans(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->numscans);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_lastscan(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->lastscan;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-
-Datum
-pg_stat_get_tuples_returned(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_returned);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_inserted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_deleted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->tuples_hot_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_live_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_live_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_dead_tuples(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->n_dead_tuples);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_mod_since_analyze(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->changes_since_analyze);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_ins_since_vacuum(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->inserts_since_vacuum);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_fetched);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_blocks_hit(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->blocks_hit);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_last_vacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autovacuum_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_vacuum_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_analyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_last_autoanalyze_time(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	TimestampTz result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = tabentry->autovac_analyze_timestamp;
-
-	if (result == 0)
-		PG_RETURN_NULL();
-	else
-		PG_RETURN_TIMESTAMPTZ(result);
-}
-
-Datum
-pg_stat_get_vacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autovacuum_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_vacuum_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_analyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->analyze_count);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_autoanalyze_count(PG_FUNCTION_ARGS)
-{
-	Oid			relid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatTabEntry *tabentry;
-
-	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (tabentry->autovac_analyze_count);
-
-	PG_RETURN_INT64(result);
-}
+#define PG_STAT_GET_RELENTRY_INT64(stat)						\
+Datum															\
+CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
+{																\
+	Oid			relid = PG_GETARG_OID(0);						\
+	int64		result;											\
+	PgStat_StatTabEntry *tabentry;								\
+																\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = (int64) (tabentry->stat);						\
+																\
+	PG_RETURN_INT64(result);									\
+}																\
+
+/* pg_stat_get_analyze_count */
+PG_STAT_GET_RELENTRY_INT64(analyze_count);
+
+/* pg_stat_get_autoanalyze_count */
+PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);
+
+/* pg_stat_get_autovacuum_count */
+PG_STAT_GET_RELENTRY_INT64(autovacuum_count);
+
+/* pg_stat_get_blocks_fetched */
+PG_STAT_GET_RELENTRY_INT64(blocks_fetched);
+
+/* pg_stat_get_blocks_hit */
+PG_STAT_GET_RELENTRY_INT64(blocks_hit);
+
+/* pg_stat_get_dead_tuples */
+PG_STAT_GET_RELENTRY_INT64(dead_tuples);
+
+/* pg_stat_get_ins_since_vacuum */
+PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum);
+
+/* pg_stat_get_live_tuples */
+PG_STAT_GET_RELENTRY_INT64(live_tuples);
+
+/* pg_stat_get_mods_since_analyze */
+PG_STAT_GET_RELENTRY_INT64(mod_since_analyze);
+
+/* pg_stat_get_numscans */
+PG_STAT_GET_RELENTRY_INT64(numscans);
+
+/* pg_stat_get_tuples_deleted */
+PG_STAT_GET_RELENTRY_INT64(tuples_deleted);
+
+/* pg_stat_get_tuples_fetched */
+PG_STAT_GET_RELENTRY_INT64(tuples_fetched);
+
+/* pg_stat_get_tuples_hot_updated */
+PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated);
+
+/* pg_stat_get_tuples_inserted */
+PG_STAT_GET_RELENTRY_INT64(tuples_inserted);
+
+/* pg_stat_get_tuples_returned */
+PG_STAT_GET_RELENTRY_INT64(tuples_returned);
+
+/* pg_stat_get_tuples_updated */
+PG_STAT_GET_RELENTRY_INT64(tuples_updated);
+
+/* pg_stat_get_vacuum_count */
+PG_STAT_GET_RELENTRY_INT64(vacuum_count);
+
+#define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat)					\
+Datum															\
+CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
+{																\
+	Oid			relid = PG_GETARG_OID(0);						\
+	TimestampTz result;											\
+	PgStat_StatTabEntry *tabentry;								\
+																\
+	if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = tabentry->stat;								\
+																\
+	if (result == 0)											\
+		PG_RETURN_NULL();										\
+	else														\
+		PG_RETURN_TIMESTAMPTZ(result);							\
+}																\
+
+/* pg_stat_get_last_analyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time);
+
+/* pg_stat_get_last_autoanalyze_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time);
+
+/* pg_stat_get_last_autovacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time);
+
+/* pg_stat_get_last_vacuum_time */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time);
+
+/* pg_stat_get_lastscan */
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan);
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 9e2ce6f011..bc6349727b 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -364,22 +364,22 @@ typedef struct PgStat_StatTabEntry
 	PgStat_Counter tuples_deleted;
 	PgStat_Counter tuples_hot_updated;
 
-	PgStat_Counter n_live_tuples;
-	PgStat_Counter n_dead_tuples;
-	PgStat_Counter changes_since_analyze;
-	PgStat_Counter inserts_since_vacuum;
+	PgStat_Counter live_tuples;
+	PgStat_Counter dead_tuples;
+	PgStat_Counter mod_since_analyze;
+	PgStat_Counter ins_since_vacuum;
 
 	PgStat_Counter blocks_fetched;
 	PgStat_Counter blocks_hit;
 
-	TimestampTz vacuum_timestamp;	/* user initiated vacuum */
+	TimestampTz last_vacuum_time;	/* user initiated vacuum */
 	PgStat_Counter vacuum_count;
-	TimestampTz autovac_vacuum_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_vacuum_count;
-	TimestampTz analyze_timestamp;	/* user initiated */
+	TimestampTz last_autovacuum_time;	/* autovacuum initiated */
+	PgStat_Counter autovacuum_count;
+	TimestampTz last_analyze_time;	/* user initiated */
 	PgStat_Counter analyze_count;
-	TimestampTz autovac_analyze_timestamp;	/* autovacuum initiated */
-	PgStat_Counter autovac_analyze_count;
+	TimestampTz last_autoanalyze_time;	/* autovacuum initiated */
+	PgStat_Counter autoanalyze_count;
 } PgStat_StatTabEntry;
 
 typedef struct PgStat_WalStats
#6Nathan Bossart
nathandbossart@gmail.com
In reply to: Drouvot, Bertrand (#5)
Re: Generate pg_stat_get_* functions with Macros

On Sun, Dec 04, 2022 at 06:07:37AM +0100, Drouvot, Bertrand wrote:

On 12/3/22 9:16 PM, Nathan Bossart wrote:

Thanks. I editorialized a bit in the attached v3. I'm not sure that my
proposed names for the macros are actually an improvement. WDYT?

Thanks! I do prefer the macros definition ordering that you're proposing (that makes pgstatfuncs.c "easier" to read).

As far the names, I think it's better to replace "TAB" with "REL" (like in v4 attached): the reason is that those macros will be used in [1] for both tables and indexes stats (and so we'd have to replace "TAB" with "REL" in [1]).
Having "REL" already in place reduces the changes that will be needed in [1].

Alright. I marked this as ready-for-committer.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

#7Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Nathan Bossart (#6)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/4/22 6:32 PM, Nathan Bossart wrote:

On Sun, Dec 04, 2022 at 06:07:37AM +0100, Drouvot, Bertrand wrote:

On 12/3/22 9:16 PM, Nathan Bossart wrote:

Thanks. I editorialized a bit in the attached v3. I'm not sure that my
proposed names for the macros are actually an improvement. WDYT?

Thanks! I do prefer the macros definition ordering that you're proposing (that makes pgstatfuncs.c "easier" to read).

As far the names, I think it's better to replace "TAB" with "REL" (like in v4 attached): the reason is that those macros will be used in [1] for both tables and indexes stats (and so we'd have to replace "TAB" with "REL" in [1]).
Having "REL" already in place reduces the changes that will be needed in [1].

Alright. I marked this as ready-for-committer.

Thanks!

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#8Michael Paquier
michael@paquier.xyz
In reply to: Drouvot, Bertrand (#7)
Re: Generate pg_stat_get_* functions with Macros

On Mon, Dec 05, 2022 at 08:27:15AM +0100, Drouvot, Bertrand wrote:

On 12/4/22 6:32 PM, Nathan Bossart wrote:

Alright. I marked this as ready-for-committer.

Thanks!

Well, that's kind of nice:
5 files changed, 139 insertions(+), 396 deletions(-)
And I like removing code, so..

In the same area, I am counting a total of 21 (?) pgstat routines for
databases that rely on pgstat_fetch_stat_dbentry() while returning an
int64. This would lead to more cleanup.
--
Michael

#9Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Michael Paquier (#8)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/5/22 8:44 AM, Michael Paquier wrote:

On Mon, Dec 05, 2022 at 08:27:15AM +0100, Drouvot, Bertrand wrote:

On 12/4/22 6:32 PM, Nathan Bossart wrote:

Alright. I marked this as ready-for-committer.

Thanks!

Well, that's kind of nice:
5 files changed, 139 insertions(+), 396 deletions(-)
And I like removing code, so..

Thanks for looking at it!

In the same area, I am counting a total of 21 (?) pgstat routines for
databases that rely on pgstat_fetch_stat_dbentry() while returning an
int64. This would lead to more cleanup.
--

Yeah, good point, thanks!

I'll look at the "databases" ones but I think in a separate patch. The reason is that the current one is preparatory work for [1]https://commitfest.postgresql.org/41/3984/.
Means, once the current patch is committed, working on [1]https://commitfest.postgresql.org/41/3984/ and "cleaning" the databases one could be done in parallel. Sounds good to you?

[1]: https://commitfest.postgresql.org/41/3984/

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#10Michael Paquier
michael@paquier.xyz
In reply to: Drouvot, Bertrand (#9)
Re: Generate pg_stat_get_* functions with Macros

On Mon, Dec 05, 2022 at 09:11:43AM +0100, Drouvot, Bertrand wrote:

Means, once the current patch is committed, working on [1] and
"cleaning" the databases one could be done in parallel. Sounds good
to you?

Doing that in a separate patch is fine by me.
--
Michael

#11Michael Paquier
michael@paquier.xyz
In reply to: Michael Paquier (#10)
1 attachment(s)
Re: Generate pg_stat_get_* functions with Macros

On Mon, Dec 05, 2022 at 05:16:56PM +0900, Michael Paquier wrote:

Doing that in a separate patch is fine by me.

I have applied the patch for the tab entries, then could not resist
poking at the parts for the db entries. This leads to more reduction
than the other one actually, as of:
4 files changed, 169 insertions(+), 447 deletions(-)

Like the previous one, the functions have the same names and the field
names are updated to fit in the picture. Thoughts?
--
Michael

Attachments:

0001-Generate-stat-functions-for-db-entries.patchtext/x-diff; charset=us-asciiDownload
From 485219765dd359b759b6eece295f4b92b59e0803 Mon Sep 17 00:00:00 2001
From: Michael Paquier <michael@paquier.xyz>
Date: Tue, 6 Dec 2022 11:41:26 +0900
Subject: [PATCH] Generate stat functions for db entries

---
 src/include/pgstat.h                         |  54 +--
 src/backend/utils/activity/pgstat_database.c |  94 ++--
 src/backend/utils/activity/pgstat_relation.c |  14 +-
 src/backend/utils/adt/pgstatfuncs.c          | 454 ++++---------------
 4 files changed, 169 insertions(+), 447 deletions(-)

diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index bc6349727b..a3df8d27c3 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -278,35 +278,35 @@ typedef struct PgStat_CheckpointerStats
 
 typedef struct PgStat_StatDBEntry
 {
-	PgStat_Counter n_xact_commit;
-	PgStat_Counter n_xact_rollback;
-	PgStat_Counter n_blocks_fetched;
-	PgStat_Counter n_blocks_hit;
-	PgStat_Counter n_tuples_returned;
-	PgStat_Counter n_tuples_fetched;
-	PgStat_Counter n_tuples_inserted;
-	PgStat_Counter n_tuples_updated;
-	PgStat_Counter n_tuples_deleted;
+	PgStat_Counter xact_commit;
+	PgStat_Counter xact_rollback;
+	PgStat_Counter blocks_fetched;
+	PgStat_Counter blocks_hit;
+	PgStat_Counter tuples_returned;
+	PgStat_Counter tuples_fetched;
+	PgStat_Counter tuples_inserted;
+	PgStat_Counter tuples_updated;
+	PgStat_Counter tuples_deleted;
 	TimestampTz last_autovac_time;
-	PgStat_Counter n_conflict_tablespace;
-	PgStat_Counter n_conflict_lock;
-	PgStat_Counter n_conflict_snapshot;
-	PgStat_Counter n_conflict_bufferpin;
-	PgStat_Counter n_conflict_startup_deadlock;
-	PgStat_Counter n_temp_files;
-	PgStat_Counter n_temp_bytes;
-	PgStat_Counter n_deadlocks;
-	PgStat_Counter n_checksum_failures;
+	PgStat_Counter conflict_tablespace;
+	PgStat_Counter conflict_lock;
+	PgStat_Counter conflict_snapshot;
+	PgStat_Counter conflict_bufferpin;
+	PgStat_Counter conflict_startup_deadlock;
+	PgStat_Counter temp_files;
+	PgStat_Counter temp_bytes;
+	PgStat_Counter deadlocks;
+	PgStat_Counter checksum_failures;
 	TimestampTz last_checksum_failure;
-	PgStat_Counter n_block_read_time;	/* times in microseconds */
-	PgStat_Counter n_block_write_time;
-	PgStat_Counter n_sessions;
-	PgStat_Counter total_session_time;
-	PgStat_Counter total_active_time;
-	PgStat_Counter total_idle_in_xact_time;
-	PgStat_Counter n_sessions_abandoned;
-	PgStat_Counter n_sessions_fatal;
-	PgStat_Counter n_sessions_killed;
+	PgStat_Counter blk_read_time;	/* times in microseconds */
+	PgStat_Counter blk_write_time;
+	PgStat_Counter sessions;
+	PgStat_Counter session_time;
+	PgStat_Counter active_time;
+	PgStat_Counter idle_in_transaction_time;
+	PgStat_Counter sessions_abandoned;
+	PgStat_Counter sessions_fatal;
+	PgStat_Counter sessions_killed;
 
 	TimestampTz stat_reset_timestamp;
 } PgStat_StatDBEntry;
diff --git a/src/backend/utils/activity/pgstat_database.c b/src/backend/utils/activity/pgstat_database.c
index d9275611f0..290086fc22 100644
--- a/src/backend/utils/activity/pgstat_database.c
+++ b/src/backend/utils/activity/pgstat_database.c
@@ -98,19 +98,19 @@ pgstat_report_recovery_conflict(int reason)
 			 */
 			break;
 		case PROCSIG_RECOVERY_CONFLICT_TABLESPACE:
-			dbentry->n_conflict_tablespace++;
+			dbentry->conflict_tablespace++;
 			break;
 		case PROCSIG_RECOVERY_CONFLICT_LOCK:
-			dbentry->n_conflict_lock++;
+			dbentry->conflict_lock++;
 			break;
 		case PROCSIG_RECOVERY_CONFLICT_SNAPSHOT:
-			dbentry->n_conflict_snapshot++;
+			dbentry->conflict_snapshot++;
 			break;
 		case PROCSIG_RECOVERY_CONFLICT_BUFFERPIN:
-			dbentry->n_conflict_bufferpin++;
+			dbentry->conflict_bufferpin++;
 			break;
 		case PROCSIG_RECOVERY_CONFLICT_STARTUP_DEADLOCK:
-			dbentry->n_conflict_startup_deadlock++;
+			dbentry->conflict_startup_deadlock++;
 			break;
 	}
 }
@@ -127,7 +127,7 @@ pgstat_report_deadlock(void)
 		return;
 
 	dbent = pgstat_prep_database_pending(MyDatabaseId);
-	dbent->n_deadlocks++;
+	dbent->deadlocks++;
 }
 
 /*
@@ -150,7 +150,7 @@ pgstat_report_checksum_failures_in_db(Oid dboid, int failurecount)
 		pgstat_get_entry_ref_locked(PGSTAT_KIND_DATABASE, dboid, InvalidOid, false);
 
 	sharedent = (PgStatShared_Database *) entry_ref->shared_stats;
-	sharedent->stats.n_checksum_failures += failurecount;
+	sharedent->stats.checksum_failures += failurecount;
 	sharedent->stats.last_checksum_failure = GetCurrentTimestamp();
 
 	pgstat_unlock_entry(entry_ref);
@@ -177,8 +177,8 @@ pgstat_report_tempfile(size_t filesize)
 		return;
 
 	dbent = pgstat_prep_database_pending(MyDatabaseId);
-	dbent->n_temp_bytes += filesize;
-	dbent->n_temp_files++;
+	dbent->temp_bytes += filesize;
+	dbent->temp_files++;
 }
 
 /*
@@ -195,7 +195,7 @@ pgstat_report_connect(Oid dboid)
 	pgLastSessionReportTime = MyStartTimestamp;
 
 	dbentry = pgstat_prep_database_pending(MyDatabaseId);
-	dbentry->n_sessions++;
+	dbentry->sessions++;
 }
 
 /*
@@ -218,13 +218,13 @@ pgstat_report_disconnect(Oid dboid)
 			/* we don't collect these */
 			break;
 		case DISCONNECT_CLIENT_EOF:
-			dbentry->n_sessions_abandoned++;
+			dbentry->sessions_abandoned++;
 			break;
 		case DISCONNECT_FATAL:
-			dbentry->n_sessions_fatal++;
+			dbentry->sessions_fatal++;
 			break;
 		case DISCONNECT_KILLED:
-			dbentry->n_sessions_killed++;
+			dbentry->sessions_killed++;
 			break;
 	}
 }
@@ -274,10 +274,10 @@ pgstat_update_dbstats(TimestampTz ts)
 	 * Accumulate xact commit/rollback and I/O timings to stats entry of the
 	 * current database.
 	 */
-	dbentry->n_xact_commit += pgStatXactCommit;
-	dbentry->n_xact_rollback += pgStatXactRollback;
-	dbentry->n_block_read_time += pgStatBlockReadTime;
-	dbentry->n_block_write_time += pgStatBlockWriteTime;
+	dbentry->xact_commit += pgStatXactCommit;
+	dbentry->xact_rollback += pgStatXactRollback;
+	dbentry->blk_read_time += pgStatBlockReadTime;
+	dbentry->blk_write_time += pgStatBlockWriteTime;
 
 	if (pgstat_should_report_connstat())
 	{
@@ -290,9 +290,9 @@ pgstat_update_dbstats(TimestampTz ts)
 		 */
 		TimestampDifference(pgLastSessionReportTime, ts, &secs, &usecs);
 		pgLastSessionReportTime = ts;
-		dbentry->total_session_time += (PgStat_Counter) secs * 1000000 + usecs;
-		dbentry->total_active_time += pgStatActiveTime;
-		dbentry->total_idle_in_xact_time += pgStatTransactionIdleTime;
+		dbentry->session_time += (PgStat_Counter) secs * 1000000 + usecs;
+		dbentry->active_time += pgStatActiveTime;
+		dbentry->idle_in_transaction_time += pgStatTransactionIdleTime;
 	}
 
 	pgStatXactCommit = 0;
@@ -370,44 +370,44 @@ pgstat_database_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 #define PGSTAT_ACCUM_DBCOUNT(item)		\
 	(sharedent)->stats.item += (pendingent)->item
 
-	PGSTAT_ACCUM_DBCOUNT(n_xact_commit);
-	PGSTAT_ACCUM_DBCOUNT(n_xact_rollback);
-	PGSTAT_ACCUM_DBCOUNT(n_blocks_fetched);
-	PGSTAT_ACCUM_DBCOUNT(n_blocks_hit);
+	PGSTAT_ACCUM_DBCOUNT(xact_commit);
+	PGSTAT_ACCUM_DBCOUNT(xact_rollback);
+	PGSTAT_ACCUM_DBCOUNT(blocks_fetched);
+	PGSTAT_ACCUM_DBCOUNT(blocks_hit);
 
-	PGSTAT_ACCUM_DBCOUNT(n_tuples_returned);
-	PGSTAT_ACCUM_DBCOUNT(n_tuples_fetched);
-	PGSTAT_ACCUM_DBCOUNT(n_tuples_inserted);
-	PGSTAT_ACCUM_DBCOUNT(n_tuples_updated);
-	PGSTAT_ACCUM_DBCOUNT(n_tuples_deleted);
+	PGSTAT_ACCUM_DBCOUNT(tuples_returned);
+	PGSTAT_ACCUM_DBCOUNT(tuples_fetched);
+	PGSTAT_ACCUM_DBCOUNT(tuples_inserted);
+	PGSTAT_ACCUM_DBCOUNT(tuples_updated);
+	PGSTAT_ACCUM_DBCOUNT(tuples_deleted);
 
 	/* last_autovac_time is reported immediately */
 	Assert(pendingent->last_autovac_time == 0);
 
-	PGSTAT_ACCUM_DBCOUNT(n_conflict_tablespace);
-	PGSTAT_ACCUM_DBCOUNT(n_conflict_lock);
-	PGSTAT_ACCUM_DBCOUNT(n_conflict_snapshot);
-	PGSTAT_ACCUM_DBCOUNT(n_conflict_bufferpin);
-	PGSTAT_ACCUM_DBCOUNT(n_conflict_startup_deadlock);
+	PGSTAT_ACCUM_DBCOUNT(conflict_tablespace);
+	PGSTAT_ACCUM_DBCOUNT(conflict_lock);
+	PGSTAT_ACCUM_DBCOUNT(conflict_snapshot);
+	PGSTAT_ACCUM_DBCOUNT(conflict_bufferpin);
+	PGSTAT_ACCUM_DBCOUNT(conflict_startup_deadlock);
 
-	PGSTAT_ACCUM_DBCOUNT(n_temp_bytes);
-	PGSTAT_ACCUM_DBCOUNT(n_temp_files);
-	PGSTAT_ACCUM_DBCOUNT(n_deadlocks);
+	PGSTAT_ACCUM_DBCOUNT(temp_bytes);
+	PGSTAT_ACCUM_DBCOUNT(temp_files);
+	PGSTAT_ACCUM_DBCOUNT(deadlocks);
 
 	/* checksum failures are reported immediately */
-	Assert(pendingent->n_checksum_failures == 0);
+	Assert(pendingent->checksum_failures == 0);
 	Assert(pendingent->last_checksum_failure == 0);
 
-	PGSTAT_ACCUM_DBCOUNT(n_block_read_time);
-	PGSTAT_ACCUM_DBCOUNT(n_block_write_time);
+	PGSTAT_ACCUM_DBCOUNT(blk_read_time);
+	PGSTAT_ACCUM_DBCOUNT(blk_write_time);
 
-	PGSTAT_ACCUM_DBCOUNT(n_sessions);
-	PGSTAT_ACCUM_DBCOUNT(total_session_time);
-	PGSTAT_ACCUM_DBCOUNT(total_active_time);
-	PGSTAT_ACCUM_DBCOUNT(total_idle_in_xact_time);
-	PGSTAT_ACCUM_DBCOUNT(n_sessions_abandoned);
-	PGSTAT_ACCUM_DBCOUNT(n_sessions_fatal);
-	PGSTAT_ACCUM_DBCOUNT(n_sessions_killed);
+	PGSTAT_ACCUM_DBCOUNT(sessions);
+	PGSTAT_ACCUM_DBCOUNT(session_time);
+	PGSTAT_ACCUM_DBCOUNT(active_time);
+	PGSTAT_ACCUM_DBCOUNT(idle_in_transaction_time);
+	PGSTAT_ACCUM_DBCOUNT(sessions_abandoned);
+	PGSTAT_ACCUM_DBCOUNT(sessions_fatal);
+	PGSTAT_ACCUM_DBCOUNT(sessions_killed);
 #undef PGSTAT_ACCUM_DBCOUNT
 
 	pgstat_unlock_entry(entry_ref);
diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c
index a9c05153d9..f9788c30ae 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -819,13 +819,13 @@ pgstat_relation_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
 
 	/* The entry was successfully flushed, add the same to database stats */
 	dbentry = pgstat_prep_database_pending(dboid);
-	dbentry->n_tuples_returned += lstats->t_counts.t_tuples_returned;
-	dbentry->n_tuples_fetched += lstats->t_counts.t_tuples_fetched;
-	dbentry->n_tuples_inserted += lstats->t_counts.t_tuples_inserted;
-	dbentry->n_tuples_updated += lstats->t_counts.t_tuples_updated;
-	dbentry->n_tuples_deleted += lstats->t_counts.t_tuples_deleted;
-	dbentry->n_blocks_fetched += lstats->t_counts.t_blocks_fetched;
-	dbentry->n_blocks_hit += lstats->t_counts.t_blocks_hit;
+	dbentry->tuples_returned += lstats->t_counts.t_tuples_returned;
+	dbentry->tuples_fetched += lstats->t_counts.t_tuples_fetched;
+	dbentry->tuples_inserted += lstats->t_counts.t_tuples_inserted;
+	dbentry->tuples_updated += lstats->t_counts.t_tuples_updated;
+	dbentry->tuples_deleted += lstats->t_counts.t_tuples_deleted;
+	dbentry->blocks_fetched += lstats->t_counts.t_blocks_fetched;
+	dbentry->blocks_hit += lstats->t_counts.t_blocks_hit;
 
 	return true;
 }
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 973979508d..e6dd168a05 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -938,148 +938,85 @@ pg_stat_get_db_numbackends(PG_FUNCTION_ARGS)
 }
 
 
-Datum
-pg_stat_get_db_xact_commit(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+#define PG_STAT_GET_DBENTRY_INT64(stat)							\
+Datum															\
+CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)				\
+{																\
+	Oid			dbid = PG_GETARG_OID(0);						\
+	int64		result;											\
+	PgStat_StatDBEntry *dbentry;								\
+																\
+	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = (int64) (dbentry->stat);						\
+																\
+	PG_RETURN_INT64(result);									\
+}																\
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_xact_commit);
+/* pg_stat_get_db_xact_commit */
+PG_STAT_GET_DBENTRY_INT64(xact_commit);
 
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_xact_rollback */
+PG_STAT_GET_DBENTRY_INT64(xact_rollback);
 
+/* pg_stat_get_db_blocks_fetched */
+PG_STAT_GET_DBENTRY_INT64(blocks_fetched);
 
-Datum
-pg_stat_get_db_xact_rollback(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_blocks_hit */
+PG_STAT_GET_DBENTRY_INT64(blocks_hit);
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_xact_rollback);
+/* pg_stat_get_db_tuples_returned */
+PG_STAT_GET_DBENTRY_INT64(tuples_returned);
 
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_tuples_fetched */
+PG_STAT_GET_DBENTRY_INT64(tuples_fetched);
 
+/* pg_stat_get_db_tuples_inserted */
+PG_STAT_GET_DBENTRY_INT64(tuples_inserted);
 
-Datum
-pg_stat_get_db_blocks_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_tuples_updated */
+PG_STAT_GET_DBENTRY_INT64(tuples_updated);
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_blocks_fetched);
+/* pg_stat_get_db_tuples_deleted */
+PG_STAT_GET_DBENTRY_INT64(tuples_deleted);
 
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_temp_files */
+PG_STAT_GET_DBENTRY_INT64(temp_files);
 
+/* pg_stat_get_db_temp_bytes */
+PG_STAT_GET_DBENTRY_INT64(temp_bytes);
 
-Datum
-pg_stat_get_db_blocks_hit(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_conflict_tablespace */
+PG_STAT_GET_DBENTRY_INT64(conflict_tablespace);
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_blocks_hit);
+/* pg_stat_get_db_conflict_lock */
+PG_STAT_GET_DBENTRY_INT64(conflict_lock);
 
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_conflict_snapshot */
+PG_STAT_GET_DBENTRY_INT64(conflict_snapshot);
 
+/* pg_stat_get_db_conflict_bufferpin */
+PG_STAT_GET_DBENTRY_INT64(conflict_bufferpin);
 
-Datum
-pg_stat_get_db_tuples_returned(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_conflict_startup_deadlock */
+PG_STAT_GET_DBENTRY_INT64(conflict_startup_deadlock);
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_tuples_returned);
+/* pg_stat_get_db_deadlocks */
+PG_STAT_GET_DBENTRY_INT64(deadlocks);
 
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_sessions */
+PG_STAT_GET_DBENTRY_INT64(sessions);
 
+/* pg_stat_get_db_sessions_abandoned */
+PG_STAT_GET_DBENTRY_INT64(sessions_abandoned);
 
-Datum
-pg_stat_get_db_tuples_fetched(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_sessions_fatal */
+PG_STAT_GET_DBENTRY_INT64(sessions_fatal);
 
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_tuples_fetched);
+/* pg_stat_get_db_sessions_killed */
+PG_STAT_GET_DBENTRY_INT64(sessions_killed);
 
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_db_tuples_inserted(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_tuples_inserted);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_db_tuples_updated(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_tuples_updated);
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_db_tuples_deleted(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_tuples_deleted);
-
-	PG_RETURN_INT64(result);
-}
 
 Datum
 pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
@@ -1099,111 +1036,6 @@ pg_stat_get_db_stat_reset_time(PG_FUNCTION_ARGS)
 		PG_RETURN_TIMESTAMPTZ(result);
 }
 
-Datum
-pg_stat_get_db_temp_files(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = dbentry->n_temp_files;
-
-	PG_RETURN_INT64(result);
-}
-
-
-Datum
-pg_stat_get_db_temp_bytes(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = dbentry->n_temp_bytes;
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_conflict_tablespace(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_conflict_tablespace);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_conflict_lock(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_conflict_lock);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_conflict_snapshot(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_conflict_snapshot);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_conflict_bufferpin(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_conflict_bufferpin);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_conflict_startup_deadlock(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_conflict_startup_deadlock);
-
-	PG_RETURN_INT64(result);
-}
 
 Datum
 pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
@@ -1215,26 +1047,11 @@ pg_stat_get_db_conflict_all(PG_FUNCTION_ARGS)
 	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (dbentry->n_conflict_tablespace +
-						  dbentry->n_conflict_lock +
-						  dbentry->n_conflict_snapshot +
-						  dbentry->n_conflict_bufferpin +
-						  dbentry->n_conflict_startup_deadlock);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_deadlocks(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = (int64) (dbentry->n_deadlocks);
+		result = (int64) (dbentry->conflict_tablespace +
+						  dbentry->conflict_lock +
+						  dbentry->conflict_snapshot +
+						  dbentry->conflict_bufferpin +
+						  dbentry->conflict_startup_deadlock);
 
 	PG_RETURN_INT64(result);
 }
@@ -1252,7 +1069,7 @@ pg_stat_get_db_checksum_failures(PG_FUNCTION_ARGS)
 	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
 		result = 0;
 	else
-		result = (int64) (dbentry->n_checksum_failures);
+		result = (int64) (dbentry->checksum_failures);
 
 	PG_RETURN_INT64(result);
 }
@@ -1278,131 +1095,36 @@ pg_stat_get_db_checksum_last_failure(PG_FUNCTION_ARGS)
 		PG_RETURN_TIMESTAMPTZ(result);
 }
 
-Datum
-pg_stat_get_db_blk_read_time(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	double		result;
-	PgStat_StatDBEntry *dbentry;
+#define PG_STAT_GET_DBENTRY_FLOAT8(stat)						\
+Datum															\
+CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)				\
+{																\
+	Oid			dbid = PG_GETARG_OID(0);						\
+	double		result;											\
+	PgStat_StatDBEntry *dbentry;								\
+																\
+	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)	\
+		result = 0;												\
+	else														\
+		result = ((double) dbentry->stat) / 1000.0;				\
+																\
+	PG_RETURN_FLOAT8(result);									\
+}																\
 
-	/* convert counter from microsec to millisec for display */
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = ((double) dbentry->n_block_read_time) / 1000.0;
+/* pg_stat_get_db_blk_read_time */
+PG_STAT_GET_DBENTRY_FLOAT8(blk_read_time);
 
-	PG_RETURN_FLOAT8(result);
-}
+/* pg_stat_get_db_blk_write_time */
+PG_STAT_GET_DBENTRY_FLOAT8(blk_write_time);
 
-Datum
-pg_stat_get_db_blk_write_time(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	double		result;
-	PgStat_StatDBEntry *dbentry;
+/* pg_stat_get_db_session_time */
+PG_STAT_GET_DBENTRY_FLOAT8(session_time);
 
-	/* convert counter from microsec to millisec for display */
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)
-		result = 0;
-	else
-		result = ((double) dbentry->n_block_write_time) / 1000.0;
+/* pg_stat_get_db_active_time */
+PG_STAT_GET_DBENTRY_FLOAT8(active_time);
 
-	PG_RETURN_FLOAT8(result);
-}
-
-Datum
-pg_stat_get_db_session_time(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	double		result = 0.0;
-	PgStat_StatDBEntry *dbentry;
-
-	/* convert counter from microsec to millisec for display */
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = ((double) dbentry->total_session_time) / 1000.0;
-
-	PG_RETURN_FLOAT8(result);
-}
-
-Datum
-pg_stat_get_db_active_time(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	double		result = 0.0;
-	PgStat_StatDBEntry *dbentry;
-
-	/* convert counter from microsec to millisec for display */
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = ((double) dbentry->total_active_time) / 1000.0;
-
-	PG_RETURN_FLOAT8(result);
-}
-
-Datum
-pg_stat_get_db_idle_in_transaction_time(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	double		result = 0.0;
-	PgStat_StatDBEntry *dbentry;
-
-	/* convert counter from microsec to millisec for display */
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = ((double) dbentry->total_idle_in_xact_time) / 1000.0;
-
-	PG_RETURN_FLOAT8(result);
-}
-
-Datum
-pg_stat_get_db_sessions(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result = 0;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = (int64) (dbentry->n_sessions);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_sessions_abandoned(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result = 0;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = (int64) (dbentry->n_sessions_abandoned);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_sessions_fatal(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result = 0;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = (int64) (dbentry->n_sessions_fatal);
-
-	PG_RETURN_INT64(result);
-}
-
-Datum
-pg_stat_get_db_sessions_killed(PG_FUNCTION_ARGS)
-{
-	Oid			dbid = PG_GETARG_OID(0);
-	int64		result = 0;
-	PgStat_StatDBEntry *dbentry;
-
-	if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) != NULL)
-		result = (int64) (dbentry->n_sessions_killed);
-
-	PG_RETURN_INT64(result);
-}
+/* pg_stat_get_db_idle_in_transaction_time */
+PG_STAT_GET_DBENTRY_FLOAT8(idle_in_transaction_time);
 
 Datum
 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
-- 
2.38.1

#12Nathan Bossart
nathandbossart@gmail.com
In reply to: Michael Paquier (#11)
Re: Generate pg_stat_get_* functions with Macros

On Tue, Dec 06, 2022 at 11:45:10AM +0900, Michael Paquier wrote:

I have applied the patch for the tab entries, then could not resist
poking at the parts for the db entries. This leads to more reduction
than the other one actually, as of:
4 files changed, 169 insertions(+), 447 deletions(-)

Like the previous one, the functions have the same names and the field
names are updated to fit in the picture. Thoughts?

I might alphabetize the functions, but otherwise it looks good to me.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

#13Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Michael Paquier (#11)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/6/22 3:45 AM, Michael Paquier wrote:

On Mon, Dec 05, 2022 at 05:16:56PM +0900, Michael Paquier wrote:

Doing that in a separate patch is fine by me.

I have applied the patch for the tab entries, then could not resist
poking at the parts for the db entries. This leads to more reduction
than the other one actually, as of:
4 files changed, 169 insertions(+), 447 deletions(-)

Like the previous one, the functions have the same names and the field
names are updated to fit in the picture. Thoughts?

Thanks! For this one (the INT64 case) the fields renaming are not strictly mandatory as we could add the "n_" in the macro itself, something like:

+#define PG_STAT_GET_DBENTRY_INT64(stat)                                                        \
+Datum                                                                                                                  \
+CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)                              \
+{                                                                                                                              \
+       Oid                     dbid = PG_GETARG_OID(0);                                                \
+       int64           result;                                                                                 \
+       PgStat_StatDBEntry *dbentry;                                                            \
+                                                                                                                               \
+       if ((dbentry = pgstat_fetch_stat_dbentry(dbid)) == NULL)        \
+               result = 0;                                                                                             \
+       else                                                                                                            \
+               result = (int64) (dbentry->CppConcat(n_,stat)); \
+                                                                                                                               \
+       PG_RETURN_INT64(result);                                                                        \
+}

Fields renaming was mandatory in the previous ones as there was already a mix of with/without "n_" in the existing fields names.

That said, I think it's better to rename the fields as you did (to be "consistent" on the naming between relation/db stats), so the patch LGTM.

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#14Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Michael Paquier (#11)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/6/22 3:45 AM, Michael Paquier wrote:

On Mon, Dec 05, 2022 at 05:16:56PM +0900, Michael Paquier wrote:

Doing that in a separate patch is fine by me.

I have applied the patch for the tab entries,

Oops, I missed this part when reading the email the first time and just saw the patch has been committed.

So, thanks for having applied the patch!

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#15Bharath Rupireddy
bharath.rupireddyforpostgres@gmail.com
In reply to: Michael Paquier (#11)
Re: Generate pg_stat_get_* functions with Macros

On Tue, Dec 6, 2022 at 8:15 AM Michael Paquier <michael@paquier.xyz> wrote:

On Mon, Dec 05, 2022 at 05:16:56PM +0900, Michael Paquier wrote:

Doing that in a separate patch is fine by me.

I have applied the patch for the tab entries, then could not resist
poking at the parts for the db entries. This leads to more reduction
than the other one actually, as of:
4 files changed, 169 insertions(+), 447 deletions(-)

Like the previous one, the functions have the same names and the field
names are updated to fit in the picture. Thoughts?

Likewise, is there a plan to add function generation macros for
pg_stat_get_bgwriter, pg_stat_get_xact and so on?

--
Bharath Rupireddy
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com

#16Michael Paquier
michael@paquier.xyz
In reply to: Bharath Rupireddy (#15)
Re: Generate pg_stat_get_* functions with Macros

On Tue, Dec 06, 2022 at 12:23:55PM +0530, Bharath Rupireddy wrote:

Likewise, is there a plan to add function generation macros for
pg_stat_get_bgwriter, pg_stat_get_xact and so on?

Yes, I saw that and we could do it, but I did not get as much
enthusiastic in terms of code reduction.
--
Michael

#17Michael Paquier
michael@paquier.xyz
In reply to: Drouvot, Bertrand (#13)
Re: Generate pg_stat_get_* functions with Macros

On Tue, Dec 06, 2022 at 05:28:47AM +0100, Drouvot, Bertrand wrote:

Fields renaming was mandatory in the previous ones as there was
already a mix of with/without "n_" in the existing fields names.

That said, I think it's better to rename the fields as you did (to
be "consistent" on the naming between relation/db stats), so the
patch LGTM.

Yeah, PgStat_StatDBEntry is the last one using this style, so I have
kept my change with the variables renamed rather than painting more
CppConcat()s. The functions are still named the same as the original
ones.
--
Michael

#18Tom Lane
tgl@sss.pgh.pa.us
In reply to: Michael Paquier (#16)
Re: Generate pg_stat_get_* functions with Macros

This series of patches has caused buildfarm member wrasse to
start complaining about "empty declarations":

wrasse | 2022-12-09 21:08:33 | "/export/home/nm/farm/studio64v12_6/HEAD/pgsql.build/../pgsql/src/backend/utils/adt/pgstatfuncs.c", line 56: warning: syntax error: empty declaration
wrasse | 2022-12-09 21:08:33 | "/export/home/nm/farm/studio64v12_6/HEAD/pgsql.build/../pgsql/src/backend/utils/adt/pgstatfuncs.c", line 59: warning: syntax error: empty declaration
wrasse | 2022-12-09 21:08:33 | "/export/home/nm/farm/studio64v12_6/HEAD/pgsql.build/../pgsql/src/backend/utils/adt/pgstatfuncs.c", line 62: warning: syntax error: empty declaration

[ etc etc ]

Presumably it could be silenced by removing the semicolons after
the new macro calls:

/* pg_stat_get_analyze_count */
PG_STAT_GET_RELENTRY_INT64(analyze_count);

/* pg_stat_get_autoanalyze_count */
PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);

/* pg_stat_get_autovacuum_count */
PG_STAT_GET_RELENTRY_INT64(autovacuum_count);

I wondered if that would confuse pgindent, but a quick check
says no. (The blank lines in between may be helping.)

While I'm nitpicking, I think that the way you've set up the
macro definitions is a bit dangerous:

#define PG_STAT_GET_RELENTRY_INT64(stat) \
Datum \
CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS) \
{ \
... \
PG_RETURN_INT64(result); \
} \

The backslash after the last right brace means that the line
following that is part of the macro body. This does no harm as
long as said line is blank ... but I think it's a foot-gun
waiting to bite somebody, because visually you'd think the macro
ends with the brace. So I'd leave off that last backslash.

regards, tom lane

#19Michael Paquier
michael@paquier.xyz
In reply to: Tom Lane (#18)
Re: Generate pg_stat_get_* functions with Macros

On Fri, Dec 09, 2022 at 09:43:56PM -0500, Tom Lane wrote:

Presumably it could be silenced by removing the semicolons after
the new macro calls:

/* pg_stat_get_analyze_count */
PG_STAT_GET_RELENTRY_INT64(analyze_count);

/* pg_stat_get_autoanalyze_count */
PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);

/* pg_stat_get_autovacuum_count */
PG_STAT_GET_RELENTRY_INT64(autovacuum_count);

I wondered if that would confuse pgindent, but a quick check
says no. (The blank lines in between may be helping.)

Indeed. Will fix.

The backslash after the last right brace means that the line
following that is part of the macro body. This does no harm as
long as said line is blank ... but I think it's a foot-gun
waiting to bite somebody, because visually you'd think the macro
ends with the brace. So I'd leave off that last backslash.

Will address this one as well for all the macro definitions. Thanks!
--
Michael

#20Nathan Bossart
nathandbossart@gmail.com
In reply to: Tom Lane (#18)
1 attachment(s)
Re: Generate pg_stat_get_* functions with Macros

On Fri, Dec 09, 2022 at 09:43:56PM -0500, Tom Lane wrote:

Presumably it could be silenced by removing the semicolons after
the new macro calls:

The backslash after the last right brace means that the line
following that is part of the macro body. This does no harm as
long as said line is blank ... but I think it's a foot-gun
waiting to bite somebody, because visually you'd think the macro
ends with the brace. So I'd leave off that last backslash.

Indeed. Patch attached.

--
Nathan Bossart
Amazon Web Services: https://aws.amazon.com

Attachments:

fix_pgstat.patchtext/x-diff; charset=us-asciiDownload
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c
index 25a159b5e5..04a5a99002 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -50,58 +50,58 @@ CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
 		result = (int64) (tabentry->stat);						\
 																\
 	PG_RETURN_INT64(result);									\
-}																\
+}
 
 /* pg_stat_get_analyze_count */
-PG_STAT_GET_RELENTRY_INT64(analyze_count);
+PG_STAT_GET_RELENTRY_INT64(analyze_count)
 
 /* pg_stat_get_autoanalyze_count */
-PG_STAT_GET_RELENTRY_INT64(autoanalyze_count);
+PG_STAT_GET_RELENTRY_INT64(autoanalyze_count)
 
 /* pg_stat_get_autovacuum_count */
-PG_STAT_GET_RELENTRY_INT64(autovacuum_count);
+PG_STAT_GET_RELENTRY_INT64(autovacuum_count)
 
 /* pg_stat_get_blocks_fetched */
-PG_STAT_GET_RELENTRY_INT64(blocks_fetched);
+PG_STAT_GET_RELENTRY_INT64(blocks_fetched)
 
 /* pg_stat_get_blocks_hit */
-PG_STAT_GET_RELENTRY_INT64(blocks_hit);
+PG_STAT_GET_RELENTRY_INT64(blocks_hit)
 
 /* pg_stat_get_dead_tuples */
-PG_STAT_GET_RELENTRY_INT64(dead_tuples);
+PG_STAT_GET_RELENTRY_INT64(dead_tuples)
 
 /* pg_stat_get_ins_since_vacuum */
-PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum);
+PG_STAT_GET_RELENTRY_INT64(ins_since_vacuum)
 
 /* pg_stat_get_live_tuples */
-PG_STAT_GET_RELENTRY_INT64(live_tuples);
+PG_STAT_GET_RELENTRY_INT64(live_tuples)
 
 /* pg_stat_get_mods_since_analyze */
-PG_STAT_GET_RELENTRY_INT64(mod_since_analyze);
+PG_STAT_GET_RELENTRY_INT64(mod_since_analyze)
 
 /* pg_stat_get_numscans */
-PG_STAT_GET_RELENTRY_INT64(numscans);
+PG_STAT_GET_RELENTRY_INT64(numscans)
 
 /* pg_stat_get_tuples_deleted */
-PG_STAT_GET_RELENTRY_INT64(tuples_deleted);
+PG_STAT_GET_RELENTRY_INT64(tuples_deleted)
 
 /* pg_stat_get_tuples_fetched */
-PG_STAT_GET_RELENTRY_INT64(tuples_fetched);
+PG_STAT_GET_RELENTRY_INT64(tuples_fetched)
 
 /* pg_stat_get_tuples_hot_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated);
+PG_STAT_GET_RELENTRY_INT64(tuples_hot_updated)
 
 /* pg_stat_get_tuples_inserted */
-PG_STAT_GET_RELENTRY_INT64(tuples_inserted);
+PG_STAT_GET_RELENTRY_INT64(tuples_inserted)
 
 /* pg_stat_get_tuples_returned */
-PG_STAT_GET_RELENTRY_INT64(tuples_returned);
+PG_STAT_GET_RELENTRY_INT64(tuples_returned)
 
 /* pg_stat_get_tuples_updated */
-PG_STAT_GET_RELENTRY_INT64(tuples_updated);
+PG_STAT_GET_RELENTRY_INT64(tuples_updated)
 
 /* pg_stat_get_vacuum_count */
-PG_STAT_GET_RELENTRY_INT64(vacuum_count);
+PG_STAT_GET_RELENTRY_INT64(vacuum_count)
 
 #define PG_STAT_GET_RELENTRY_TIMESTAMPTZ(stat)					\
 Datum															\
@@ -120,22 +120,22 @@ CppConcat(pg_stat_get_,stat)(PG_FUNCTION_ARGS)					\
 		PG_RETURN_NULL();										\
 	else														\
 		PG_RETURN_TIMESTAMPTZ(result);							\
-}																\
+}
 
 /* pg_stat_get_last_analyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time);
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_analyze_time)
 
 /* pg_stat_get_last_autoanalyze_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time);
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autoanalyze_time)
 
 /* pg_stat_get_last_autovacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time);
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_autovacuum_time)
 
 /* pg_stat_get_last_vacuum_time */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time);
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(last_vacuum_time)
 
 /* pg_stat_get_lastscan */
-PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan);
+PG_STAT_GET_RELENTRY_TIMESTAMPTZ(lastscan)
 
 Datum
 pg_stat_get_function_calls(PG_FUNCTION_ARGS)
@@ -952,70 +952,70 @@ CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)				\
 		result = (int64) (dbentry->stat);						\
 																\
 	PG_RETURN_INT64(result);									\
-}																\
+}
 
 /* pg_stat_get_db_blocks_fetched */
-PG_STAT_GET_DBENTRY_INT64(blocks_fetched);
+PG_STAT_GET_DBENTRY_INT64(blocks_fetched)
 
 /* pg_stat_get_db_blocks_hit */
-PG_STAT_GET_DBENTRY_INT64(blocks_hit);
+PG_STAT_GET_DBENTRY_INT64(blocks_hit)
 
 /* pg_stat_get_db_conflict_bufferpin */
-PG_STAT_GET_DBENTRY_INT64(conflict_bufferpin);
+PG_STAT_GET_DBENTRY_INT64(conflict_bufferpin)
 
 /* pg_stat_get_db_conflict_lock */
-PG_STAT_GET_DBENTRY_INT64(conflict_lock);
+PG_STAT_GET_DBENTRY_INT64(conflict_lock)
 
 /* pg_stat_get_db_conflict_snapshot */
-PG_STAT_GET_DBENTRY_INT64(conflict_snapshot);
+PG_STAT_GET_DBENTRY_INT64(conflict_snapshot)
 
 /* pg_stat_get_db_conflict_startup_deadlock */
-PG_STAT_GET_DBENTRY_INT64(conflict_startup_deadlock);
+PG_STAT_GET_DBENTRY_INT64(conflict_startup_deadlock)
 
 /* pg_stat_get_db_conflict_tablespace */
-PG_STAT_GET_DBENTRY_INT64(conflict_tablespace);
+PG_STAT_GET_DBENTRY_INT64(conflict_tablespace)
 
 /* pg_stat_get_db_deadlocks */
-PG_STAT_GET_DBENTRY_INT64(deadlocks);
+PG_STAT_GET_DBENTRY_INT64(deadlocks)
 
 /* pg_stat_get_db_sessions */
-PG_STAT_GET_DBENTRY_INT64(sessions);
+PG_STAT_GET_DBENTRY_INT64(sessions)
 
 /* pg_stat_get_db_sessions_abandoned */
-PG_STAT_GET_DBENTRY_INT64(sessions_abandoned);
+PG_STAT_GET_DBENTRY_INT64(sessions_abandoned)
 
 /* pg_stat_get_db_sessions_fatal */
-PG_STAT_GET_DBENTRY_INT64(sessions_fatal);
+PG_STAT_GET_DBENTRY_INT64(sessions_fatal)
 
 /* pg_stat_get_db_sessions_killed */
-PG_STAT_GET_DBENTRY_INT64(sessions_killed);
+PG_STAT_GET_DBENTRY_INT64(sessions_killed)
 
 /* pg_stat_get_db_temp_bytes */
-PG_STAT_GET_DBENTRY_INT64(temp_bytes);
+PG_STAT_GET_DBENTRY_INT64(temp_bytes)
 
 /* pg_stat_get_db_temp_files */
-PG_STAT_GET_DBENTRY_INT64(temp_files);
+PG_STAT_GET_DBENTRY_INT64(temp_files)
 
 /* pg_stat_get_db_tuples_deleted */
-PG_STAT_GET_DBENTRY_INT64(tuples_deleted);
+PG_STAT_GET_DBENTRY_INT64(tuples_deleted)
 
 /* pg_stat_get_db_tuples_fetched */
-PG_STAT_GET_DBENTRY_INT64(tuples_fetched);
+PG_STAT_GET_DBENTRY_INT64(tuples_fetched)
 
 /* pg_stat_get_db_tuples_inserted */
-PG_STAT_GET_DBENTRY_INT64(tuples_inserted);
+PG_STAT_GET_DBENTRY_INT64(tuples_inserted)
 
 /* pg_stat_get_db_tuples_returned */
-PG_STAT_GET_DBENTRY_INT64(tuples_returned);
+PG_STAT_GET_DBENTRY_INT64(tuples_returned)
 
 /* pg_stat_get_db_tuples_updated */
-PG_STAT_GET_DBENTRY_INT64(tuples_updated);
+PG_STAT_GET_DBENTRY_INT64(tuples_updated)
 
 /* pg_stat_get_db_xact_commit */
-PG_STAT_GET_DBENTRY_INT64(xact_commit);
+PG_STAT_GET_DBENTRY_INT64(xact_commit)
 
 /* pg_stat_get_db_xact_rollback */
-PG_STAT_GET_DBENTRY_INT64(xact_rollback);
+PG_STAT_GET_DBENTRY_INT64(xact_rollback)
 
 
 Datum
@@ -1109,22 +1109,22 @@ CppConcat(pg_stat_get_db_,stat)(PG_FUNCTION_ARGS)				\
 		result = ((double) dbentry->stat) / 1000.0;				\
 																\
 	PG_RETURN_FLOAT8(result);									\
-}																\
+}
 
 /* pg_stat_get_db_active_time */
-PG_STAT_GET_DBENTRY_FLOAT8(active_time);
+PG_STAT_GET_DBENTRY_FLOAT8(active_time)
 
 /* pg_stat_get_db_blk_read_time */
-PG_STAT_GET_DBENTRY_FLOAT8(blk_read_time);
+PG_STAT_GET_DBENTRY_FLOAT8(blk_read_time)
 
 /* pg_stat_get_db_blk_write_time */
-PG_STAT_GET_DBENTRY_FLOAT8(blk_write_time);
+PG_STAT_GET_DBENTRY_FLOAT8(blk_write_time)
 
 /* pg_stat_get_db_idle_in_transaction_time */
-PG_STAT_GET_DBENTRY_FLOAT8(idle_in_transaction_time);
+PG_STAT_GET_DBENTRY_FLOAT8(idle_in_transaction_time)
 
 /* pg_stat_get_db_session_time */
-PG_STAT_GET_DBENTRY_FLOAT8(session_time);
+PG_STAT_GET_DBENTRY_FLOAT8(session_time)
 
 Datum
 pg_stat_get_bgwriter_timed_checkpoints(PG_FUNCTION_ARGS)
#21Michael Paquier
michael@paquier.xyz
In reply to: Nathan Bossart (#20)
Re: Generate pg_stat_get_* functions with Macros

On Fri, Dec 09, 2022 at 07:55:45PM -0800, Nathan Bossart wrote:

Indeed. Patch attached.

Yep, thanks. I have exactly the same thing brewing in one of my
staging branches.
--
Michael

#22Drouvot, Bertrand
bertranddrouvot.pg@gmail.com
In reply to: Nathan Bossart (#20)
Re: Generate pg_stat_get_* functions with Macros

Hi,

On 12/10/22 4:55 AM, Nathan Bossart wrote:

On Fri, Dec 09, 2022 at 09:43:56PM -0500, Tom Lane wrote:

Presumably it could be silenced by removing the semicolons after
the new macro calls:

The backslash after the last right brace means that the line
following that is part of the macro body. This does no harm as
long as said line is blank ... but I think it's a foot-gun
waiting to bite somebody, because visually you'd think the macro
ends with the brace. So I'd leave off that last backslash.

Indeed. Patch attached.

Oh right. Thanks Tom for the explanations and Nathan/Michael for the fix.

Regards,

--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com