Hi hackers,
Please find attached a patch proposal for $SUBJECT.
The idea has been raised in [1] by Andres: it would allow to simplify even more
the work done to
generate pg_stat_get_xact*() functions with Macros.
Indeed, with the reconciliation done in find_tabstat_entry() then all the
pg_stat_get_xact*() functions
(making use of find_tabstat_entry()) now "look the same" (should they take into
account live subtransactions or not).
Looking forward to your feedback,
Regards
--
Bertrand Drouvot
PostgreSQL Contributors Team
RDS Open Source Databases
Amazon Web Services: https://aws.amazon.com
[1]:
https://www.postgresql.org/message-id/20230111225907.6el6c5j3hukizqxc%40awork3.anarazel.de
diff --git a/src/backend/utils/activity/pgstat.c
b/src/backend/utils/activity/pgstat.c
index 0fa5370bcd..a08a2c8e66 100644
--- a/src/backend/utils/activity/pgstat.c
+++ b/src/backend/utils/activity/pgstat.c
@@ -291,7 +291,7 @@ static const PgStat_KindInfo
pgstat_kind_infos[PGSTAT_NUM_KINDS] = {
.shared_size = sizeof(PgStatShared_Function),
.shared_data_off = offsetof(PgStatShared_Function, stats),
.shared_data_len = sizeof(((PgStatShared_Function *) 0)->stats),
- .pending_size = sizeof(PgStat_BackendFunctionEntry),
+ .pending_size = sizeof(PgStat_FunctionCounts),
.flush_pending_cb = pgstat_function_flush_cb,
},
diff --git a/src/backend/utils/activity/pgstat_function.c
b/src/backend/utils/activity/pgstat_function.c
index 6139a27fee..0fdcefb783 100644
--- a/src/backend/utils/activity/pgstat_function.c
+++ b/src/backend/utils/activity/pgstat_function.c
@@ -73,7 +73,7 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo,
PgStat_FunctionCallUsage
*fcu)
{
PgStat_EntryRef *entry_ref;
- PgStat_BackendFunctionEntry *pending;
+ PgStat_FunctionCounts *pending;
bool created_entry;
if (pgstat_track_functions <= fcinfo->flinfo->fn_stats)
@@ -121,10 +121,10 @@ pgstat_init_function_usage(FunctionCallInfo fcinfo,
pending = entry_ref->pending;
- fcu->fs = &pending->f_counts;
+ fcu->fs = pending;
/* save stats for this function, later used to compensate for recursion
*/
- fcu->save_f_total_time = pending->f_counts.f_total_time;
+ fcu->save_f_total_time = pending->f_total_time;
/* save current backend-wide total time */
fcu->save_total = total_func_time;
@@ -192,10 +192,10 @@ pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
bool finalize)
bool
pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
{
- PgStat_BackendFunctionEntry *localent;
+ PgStat_FunctionCounts *localent;
PgStatShared_Function *shfuncent;
- localent = (PgStat_BackendFunctionEntry *) entry_ref->pending;
+ localent = (PgStat_FunctionCounts *) entry_ref->pending;
shfuncent = (PgStatShared_Function *) entry_ref->shared_stats;
/* localent always has non-zero content */
@@ -203,11 +203,11 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool
nowait)
if (!pgstat_lock_entry(entry_ref, nowait))
return false;
- shfuncent->stats.f_numcalls += localent->f_counts.f_numcalls;
+ shfuncent->stats.f_numcalls += localent->f_numcalls;
shfuncent->stats.f_total_time +=
- INSTR_TIME_GET_MICROSEC(localent->f_counts.f_total_time);
+ INSTR_TIME_GET_MICROSEC(localent->f_total_time);
shfuncent->stats.f_self_time +=
- INSTR_TIME_GET_MICROSEC(localent->f_counts.f_self_time);
+ INSTR_TIME_GET_MICROSEC(localent->f_self_time);
pgstat_unlock_entry(entry_ref);
@@ -215,11 +215,11 @@ pgstat_function_flush_cb(PgStat_EntryRef *entry_ref, bool
nowait)
}
/*
- * find any existing PgStat_BackendFunctionEntry entry for specified function
+ * find any existing PgStat_FunctionCounts entry for specified function
*
* If no entry, return NULL, don't create a new one
*/
-PgStat_BackendFunctionEntry *
+PgStat_FunctionCounts *
find_funcstat_entry(Oid func_id)
{
PgStat_EntryRef *entry_ref;
diff --git a/src/backend/utils/activity/pgstat_relation.c
b/src/backend/utils/activity/pgstat_relation.c
index 2e20b93c20..b33965c581 100644
--- a/src/backend/utils/activity/pgstat_relation.c
+++ b/src/backend/utils/activity/pgstat_relation.c
@@ -466,14 +466,30 @@ PgStat_TableStatus *
find_tabstat_entry(Oid rel_id)
{
PgStat_EntryRef *entry_ref;
+ PgStat_TableStatus *tablestatus = NULL;
entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION,
MyDatabaseId, rel_id);
if (!entry_ref)
entry_ref = pgstat_fetch_pending_entry(PGSTAT_KIND_RELATION,
InvalidOid, rel_id);
if (entry_ref)
- return entry_ref->pending;
- return NULL;
+ {
+ PgStat_TableStatus *tabentry = (PgStat_TableStatus *)
entry_ref->pending;
+ PgStat_TableXactStatus *trans;
+
+ tablestatus = palloc(sizeof(PgStat_TableStatus));
+ memcpy(tablestatus, tabentry, sizeof(PgStat_TableStatus));
+
+ /* live subtransactions' counts aren't in t_counts yet */
+ for (trans = tabentry->trans; trans != NULL; trans =
trans->upper)
+ {
+ tablestatus->t_counts.t_tuples_inserted +=
trans->tuples_inserted;
+ tablestatus->t_counts.t_tuples_updated +=
trans->tuples_updated;
+ tablestatus->t_counts.t_tuples_deleted +=
trans->tuples_deleted;
+ }
+ }
+
+ return tablestatus;
}
/*
diff --git a/src/backend/utils/adt/pgstatfuncs.c
b/src/backend/utils/adt/pgstatfuncs.c
index 6737493402..40a6fbf871 100644
--- a/src/backend/utils/adt/pgstatfuncs.c
+++ b/src/backend/utils/adt/pgstatfuncs.c
@@ -1366,7 +1366,10 @@ pg_stat_get_xact_numscans(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_numscans);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1381,7 +1384,10 @@ pg_stat_get_xact_tuples_returned(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_tuples_returned);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1396,7 +1402,10 @@ pg_stat_get_xact_tuples_fetched(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_tuples_fetched);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1407,16 +1416,13 @@ pg_stat_get_xact_tuples_inserted(PG_FUNCTION_ARGS)
Oid relid = PG_GETARG_OID(0);
int64 result;
PgStat_TableStatus *tabentry;
- PgStat_TableXactStatus *trans;
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
{
- result = tabentry->t_counts.t_tuples_inserted;
- /* live subtransactions' counts aren't in t_tuples_inserted yet
*/
- for (trans = tabentry->trans; trans != NULL; trans =
trans->upper)
- result += trans->tuples_inserted;
+ result = (int64) (tabentry->t_counts.t_tuples_inserted);
+ pfree(tabentry);
}
PG_RETURN_INT64(result);
@@ -1428,16 +1434,13 @@ pg_stat_get_xact_tuples_updated(PG_FUNCTION_ARGS)
Oid relid = PG_GETARG_OID(0);
int64 result;
PgStat_TableStatus *tabentry;
- PgStat_TableXactStatus *trans;
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
{
- result = tabentry->t_counts.t_tuples_updated;
- /* live subtransactions' counts aren't in t_tuples_updated yet
*/
- for (trans = tabentry->trans; trans != NULL; trans =
trans->upper)
- result += trans->tuples_updated;
+ result = (int64) (tabentry->t_counts.t_tuples_updated);
+ pfree(tabentry);
}
PG_RETURN_INT64(result);
@@ -1449,16 +1452,13 @@ pg_stat_get_xact_tuples_deleted(PG_FUNCTION_ARGS)
Oid relid = PG_GETARG_OID(0);
int64 result;
PgStat_TableStatus *tabentry;
- PgStat_TableXactStatus *trans;
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
{
- result = tabentry->t_counts.t_tuples_deleted;
- /* live subtransactions' counts aren't in t_tuples_deleted yet
*/
- for (trans = tabentry->trans; trans != NULL; trans =
trans->upper)
- result += trans->tuples_deleted;
+ result = (int64) (tabentry->t_counts.t_tuples_deleted);
+ pfree(tabentry);
}
PG_RETURN_INT64(result);
@@ -1474,7 +1474,10 @@ pg_stat_get_xact_tuples_hot_updated(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_tuples_hot_updated);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1489,7 +1492,10 @@ pg_stat_get_xact_blocks_fetched(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_blocks_fetched);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1504,7 +1510,10 @@ pg_stat_get_xact_blocks_hit(PG_FUNCTION_ARGS)
if ((tabentry = find_tabstat_entry(relid)) == NULL)
result = 0;
else
+ {
result = (int64) (tabentry->t_counts.t_blocks_hit);
+ pfree(tabentry);
+ }
PG_RETURN_INT64(result);
}
@@ -1513,33 +1522,33 @@ Datum
pg_stat_get_xact_function_calls(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
- PgStat_BackendFunctionEntry *funcentry;
+ PgStat_FunctionCounts *funcentry;
if ((funcentry = find_funcstat_entry(funcid)) == NULL)
PG_RETURN_NULL();
- PG_RETURN_INT64(funcentry->f_counts.f_numcalls);
+ PG_RETURN_INT64(funcentry->f_numcalls);
}
Datum
pg_stat_get_xact_function_total_time(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
- PgStat_BackendFunctionEntry *funcentry;
+ PgStat_FunctionCounts *funcentry;
if ((funcentry = find_funcstat_entry(funcid)) == NULL)
PG_RETURN_NULL();
-
PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_total_time));
+ PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_total_time));
}
Datum
pg_stat_get_xact_function_self_time(PG_FUNCTION_ARGS)
{
Oid funcid = PG_GETARG_OID(0);
- PgStat_BackendFunctionEntry *funcentry;
+ PgStat_FunctionCounts *funcentry;
if ((funcentry = find_funcstat_entry(funcid)) == NULL)
PG_RETURN_NULL();
-
PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_counts.f_self_time));
+ PG_RETURN_FLOAT8(INSTR_TIME_GET_MILLISEC(funcentry->f_self_time));
}
diff --git a/src/include/pgstat.h b/src/include/pgstat.h
index 5e3326a3b9..b94ae7f70d 100644
--- a/src/include/pgstat.h
+++ b/src/include/pgstat.h
@@ -110,15 +110,6 @@ typedef struct PgStat_FunctionCounts
instr_time f_self_time;
} PgStat_FunctionCounts;
-/* ----------
- * PgStat_BackendFunctionEntry Non-flushed function stats.
- * ----------
- */
-typedef struct PgStat_BackendFunctionEntry
-{
- PgStat_FunctionCounts f_counts;
-} PgStat_BackendFunctionEntry;
-
/*
* Working state needed to accumulate per-function-call timing statistics.
*/
@@ -491,7 +482,7 @@ extern void
pgstat_end_function_usage(PgStat_FunctionCallUsage *fcu,
bool
finalize);
extern PgStat_StatFuncEntry *pgstat_fetch_stat_funcentry(Oid func_id);
-extern PgStat_BackendFunctionEntry *find_funcstat_entry(Oid func_id);
+extern PgStat_FunctionCounts *find_funcstat_entry(Oid func_id);
/*