Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/utils/activity/pgstat_index.c
Line
Count
Source
1
/* -------------------------------------------------------------------------
2
 *
3
 * pgstat_index.c
4
 *    Implementation of index statistics.
5
 *
6
 * This file contains the implementation of index statistics.
7
 *
8
 * Copyright (c) 2001-2026, PostgreSQL Global Development Group
9
 *
10
 * IDENTIFICATION
11
 *    src/backend/utils/activity/pgstat_index.c
12
 * -------------------------------------------------------------------------
13
 */
14
15
#include "postgres.h"
16
17
#include "access/xact.h"
18
#include "catalog/catalog.h"
19
#include "utils/memutils.h"
20
#include "utils/pgstat_internal.h"
21
#include "utils/rel.h"
22
#include "utils/timestamp.h"
23
24
25
/*
26
 * Flush out pending stats for an index entry.
27
 *
28
 * If nowait is true and the lock could not be immediately acquired, returns
29
 * false without flushing the entry.  Otherwise returns true.
30
 *
31
 * Some of the stats are copied to the corresponding pending database stats
32
 * entry when successfully flushing.
33
 */
34
bool
35
pgstat_index_flush_cb(PgStat_EntryRef *entry_ref, bool nowait)
36
0
{
37
0
  Oid     dboid;
38
0
  PgStat_TableStatus *lstats; /* pending stats entry */
39
0
  PgStatShared_Index *shidxstats;
40
0
  PgStat_StatIdxEntry *idxentry;  /* index entry of shared stats */
41
0
  PgStat_StatDBEntry *dbentry;  /* pending database entry */
42
43
0
  dboid = entry_ref->shared_entry->key.dboid;
44
0
  lstats = (PgStat_TableStatus *) entry_ref->pending;
45
0
  shidxstats = (PgStatShared_Index *) entry_ref->shared_stats;
46
47
  /*
48
   * Ignore entries that didn't accumulate any actual counts, such as
49
   * indexes that were opened by the planner but not used.
50
   */
51
0
  if (pg_memory_is_all_zeros(&lstats->counts,
52
0
                 sizeof(struct PgStat_TableCounts)))
53
0
    return true;
54
55
0
  if (!pgstat_lock_entry(entry_ref, nowait))
56
0
    return false;
57
58
  /* Add the values to the shared entry. */
59
0
  idxentry = &shidxstats->stats;
60
61
0
  idxentry->numscans += lstats->counts.numscans;
62
0
  if (lstats->counts.numscans)
63
0
  {
64
0
    TimestampTz t = GetCurrentTransactionStopTimestamp();
65
66
0
    if (t > idxentry->lastscan)
67
0
      idxentry->lastscan = t;
68
0
  }
69
0
  idxentry->tuples_returned += lstats->counts.tuples_returned;
70
0
  idxentry->tuples_fetched += lstats->counts.tuples_fetched;
71
0
  idxentry->blocks_fetched += lstats->counts.blocks_fetched;
72
0
  idxentry->blocks_hit += lstats->counts.blocks_hit;
73
74
0
  pgstat_unlock_entry(entry_ref);
75
76
  /* The entry was successfully flushed, add the same to database stats */
77
0
  dbentry = pgstat_prep_database_pending(dboid);
78
0
  dbentry->tuples_returned += lstats->counts.tuples_returned;
79
0
  dbentry->tuples_fetched += lstats->counts.tuples_fetched;
80
0
  dbentry->blocks_fetched += lstats->counts.blocks_fetched;
81
0
  dbentry->blocks_hit += lstats->counts.blocks_hit;
82
83
0
  return true;
84
0
}
85
86
/*
87
 * Callback to delete pending index stats.
88
 */
89
void
90
pgstat_index_delete_pending_cb(PgStat_EntryRef *entry_ref)
91
0
{
92
0
  PgStat_TableStatus *pending = (PgStat_TableStatus *) entry_ref->pending;
93
94
0
  if (pending->relation)
95
0
    pgstat_unlink_relation(pending->relation);
96
0
}
97
98
/*
99
 * Callback to reset the timestamp on an index stats entry.
100
 */
101
void
102
pgstat_index_reset_timestamp_cb(PgStatShared_Common *header, TimestampTz ts)
103
0
{
104
0
  ((PgStatShared_Index *) header)->stats.stat_reset_time = ts;
105
0
}
106
107
/*
108
 * Support function for the SQL-callable pgstat* functions. Returns
109
 * the collected statistics for one index or NULL. NULL doesn't mean
110
 * that the index doesn't exist, just that there are no statistics, so the
111
 * caller is better off to report ZERO instead.
112
 */
113
PgStat_StatIdxEntry *
114
pgstat_fetch_stat_idxentry(Oid relid)
115
0
{
116
0
  return pgstat_fetch_stat_idxentry_ext(IsSharedRelation(relid), relid, NULL);
117
0
}
118
119
/*
120
 * More efficient version of pgstat_fetch_stat_idxentry(), allowing to specify
121
 * whether the to-be-accessed index is a shared relation or not.  This version
122
 * also returns whether the caller can pfree() the result if desired.
123
 */
124
PgStat_StatIdxEntry *
125
pgstat_fetch_stat_idxentry_ext(bool shared, Oid reloid, bool *may_free)
126
0
{
127
0
  Oid     dboid = (shared ? InvalidOid : MyDatabaseId);
128
129
0
  return (PgStat_StatIdxEntry *)
130
0
    pgstat_fetch_entry(PGSTAT_KIND_INDEX, dboid, reloid, may_free);
131
0
}