@@ -235,16 +235,24 @@ static bool have_relation_stats = false;
235235static bool have_function_stats = false;
236236
237237/*
238- * Tuple insertion/deletion counts for an open transaction can't be propagated
239- * into PgStat_TableStatus counters until we know if it is going to commit
240- * or abort. Hence, we keep these counts in per-subxact structs that live
241- * in TopTransactionContext. This data structure is designed on the assumption
242- * that subxacts won't usually modify very many tables.
238+ * Some stats changes are transactional. To maintain those, a stack of
239+ * PgStat_SubXactStatus entries is maintained, which contain data pertaining
240+ * to the current transaction and its active subtransactions.
243241 */
244242typedef struct PgStat_SubXactStatus
245243{
246244int nest_level ;/* subtransaction nest level */
245+
247246struct PgStat_SubXactStatus * prev ;/* higher-level subxact if any */
247+
248+ /*
249+ * Tuple insertion/deletion counts for an open transaction can't be
250+ * propagated into PgStat_TableStatus counters until we know if it is
251+ * going to commit or abort. Hence, we keep these counts in per-subxact
252+ * structs that live in TopTransactionContext. This data structure is
253+ * designed on the assumption that subxacts won't usually modify very many
254+ * tables.
255+ */
248256PgStat_TableXactStatus * first ;/* head of list for this subxact */
249257}PgStat_SubXactStatus ;
250258
@@ -2305,10 +2313,11 @@ find_tabstat_entry(Oid rel_id)
23052313}
23062314
23072315/*
2308- * get_tabstat_stack_level - add a new (sub)transaction stack entry if needed
2316+ * Ensure (sub)transaction stack entry for the given nest_level exists, adding
2317+ * it if needed.
23092318 */
23102319static PgStat_SubXactStatus *
2311- get_tabstat_stack_level (int nest_level )
2320+ pgstat_xact_stack_level_get (int nest_level )
23122321{
23132322PgStat_SubXactStatus * xact_state ;
23142323
@@ -2339,7 +2348,7 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
23392348 * If this is the first rel to be modified at the current nest level, we
23402349 * first have to push a transaction stack entry.
23412350 */
2342- xact_state = get_tabstat_stack_level (nest_level );
2351+ xact_state = pgstat_xact_stack_level_get (nest_level );
23432352
23442353/* Now make a per-table stack entry */
23452354trans = (PgStat_TableXactStatus * )
@@ -2353,6 +2362,19 @@ add_tabstat_xact_level(PgStat_TableStatus *pgstat_info, int nest_level)
23532362pgstat_info -> trans = trans ;
23542363}
23552364
2365+ /*
2366+ * Add a new (sub)transaction record if needed.
2367+ */
2368+ static void
2369+ ensure_tabstat_xact_level (PgStat_TableStatus * pgstat_info )
2370+ {
2371+ int nest_level = GetCurrentTransactionNestLevel ();
2372+
2373+ if (pgstat_info -> trans == NULL ||
2374+ pgstat_info -> trans -> nest_level != nest_level )
2375+ add_tabstat_xact_level (pgstat_info ,nest_level );
2376+ }
2377+
23562378/*
23572379 * pgstat_count_heap_insert - count a tuple insertion of n tuples
23582380 */
@@ -2362,13 +2384,8 @@ pgstat_count_heap_insert(Relation rel, PgStat_Counter n)
23622384if (pgstat_relation_should_count (rel ))
23632385{
23642386PgStat_TableStatus * pgstat_info = rel -> pgstat_info ;
2365- int nest_level = GetCurrentTransactionNestLevel ();
2366-
2367- /* We have to log the effect at the proper transactional level */
2368- if (pgstat_info -> trans == NULL ||
2369- pgstat_info -> trans -> nest_level != nest_level )
2370- add_tabstat_xact_level (pgstat_info ,nest_level );
23712387
2388+ ensure_tabstat_xact_level (pgstat_info );
23722389pgstat_info -> trans -> tuples_inserted += n ;
23732390}
23742391}
@@ -2382,13 +2399,8 @@ pgstat_count_heap_update(Relation rel, bool hot)
23822399if (pgstat_relation_should_count (rel ))
23832400{
23842401PgStat_TableStatus * pgstat_info = rel -> pgstat_info ;
2385- int nest_level = GetCurrentTransactionNestLevel ();
2386-
2387- /* We have to log the effect at the proper transactional level */
2388- if (pgstat_info -> trans == NULL ||
2389- pgstat_info -> trans -> nest_level != nest_level )
2390- add_tabstat_xact_level (pgstat_info ,nest_level );
23912402
2403+ ensure_tabstat_xact_level (pgstat_info );
23922404pgstat_info -> trans -> tuples_updated ++ ;
23932405
23942406/* t_tuples_hot_updated is nontransactional, so just advance it */
@@ -2406,13 +2418,8 @@ pgstat_count_heap_delete(Relation rel)
24062418if (pgstat_relation_should_count (rel ))
24072419{
24082420PgStat_TableStatus * pgstat_info = rel -> pgstat_info ;
2409- int nest_level = GetCurrentTransactionNestLevel ();
2410-
2411- /* We have to log the effect at the proper transactional level */
2412- if (pgstat_info -> trans == NULL ||
2413- pgstat_info -> trans -> nest_level != nest_level )
2414- add_tabstat_xact_level (pgstat_info ,nest_level );
24152421
2422+ ensure_tabstat_xact_level (pgstat_info );
24162423pgstat_info -> trans -> tuples_deleted ++ ;
24172424}
24182425}
@@ -2463,13 +2470,8 @@ pgstat_count_truncate(Relation rel)
24632470if (pgstat_relation_should_count (rel ))
24642471{
24652472PgStat_TableStatus * pgstat_info = rel -> pgstat_info ;
2466- int nest_level = GetCurrentTransactionNestLevel ();
2467-
2468- /* We have to log the effect at the proper transactional level */
2469- if (pgstat_info -> trans == NULL ||
2470- pgstat_info -> trans -> nest_level != nest_level )
2471- add_tabstat_xact_level (pgstat_info ,nest_level );
24722473
2474+ ensure_tabstat_xact_level (pgstat_info );
24732475pgstat_truncdrop_save_counters (pgstat_info -> trans , false);
24742476pgstat_info -> trans -> tuples_inserted = 0 ;
24752477pgstat_info -> trans -> tuples_updated = 0 ;
@@ -2656,7 +2658,7 @@ AtEOSubXact_PgStat_Relations(PgStat_SubXactStatus *xact_state, bool isCommit, in
26562658 */
26572659PgStat_SubXactStatus * upper_xact_state ;
26582660
2659- upper_xact_state = get_tabstat_stack_level (nestDepth - 1 );
2661+ upper_xact_state = pgstat_xact_stack_level_get (nestDepth - 1 );
26602662trans -> next = upper_xact_state -> first ;
26612663upper_xact_state -> first = trans ;
26622664trans -> nest_level = nestDepth - 1 ;