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);
 
 
 /*

Reply via email to