PostgreSQL Source Code git master
relation_stats.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 * relation_stats.c
3 *
4 * PostgreSQL relation statistics manipulation
5 *
6 * Code supporting the direct import of relation statistics, similar to
7 * what is done by the ANALYZE command.
8 *
9 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
11 *
12 * IDENTIFICATION
13 * src/backend/statistics/relation_stats.c
14 *
15 *-------------------------------------------------------------------------
16 */
17
18#include "postgres.h"
19
20#include "access/heapam.h"
21#include "catalog/indexing.h"
23#include "utils/fmgroids.h"
24#include "utils/fmgrprotos.h"
25#include "utils/syscache.h"
26
27
28/*
29 * Positional argument numbers, names, and types for
30 * relation_statistics_update().
31 */
32
34{
41};
42
43static struct StatsArgInfo relarginfo[] =
44{
45 [RELATION_ARG] = {"relation", REGCLASSOID},
46 [RELPAGES_ARG] = {"relpages", INT4OID},
47 [RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
48 [RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
49 [RELALLFROZEN_ARG] = {"relallfrozen", INT4OID},
51};
52
54
55/*
56 * Internal function for modifying statistics for a relation.
57 */
58static bool
60{
61 bool result = true;
62 Oid reloid;
63 Relation crel;
64 BlockNumber relpages = 0;
65 bool update_relpages = false;
66 float reltuples = 0;
67 bool update_reltuples = false;
68 BlockNumber relallvisible = 0;
69 bool update_relallvisible = false;
70 BlockNumber relallfrozen = 0;
71 bool update_relallfrozen = false;
72 HeapTuple ctup;
73 Form_pg_class pgcform;
74 int replaces[4] = {0};
75 Datum values[4] = {0};
76 bool nulls[4] = {0};
77 int nreplaces = 0;
78
80 {
82 update_relpages = true;
83 }
84
86 {
88 if (reltuples < -1.0)
89 {
91 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
92 errmsg("reltuples cannot be < -1.0")));
93 result = false;
94 }
95 else
96 update_reltuples = true;
97 }
98
100 {
101 relallvisible = PG_GETARG_UINT32(RELALLVISIBLE_ARG);
102 update_relallvisible = true;
103 }
104
106 {
107 relallfrozen = PG_GETARG_UINT32(RELALLFROZEN_ARG);
108 update_relallfrozen = true;
109 }
110
112 reloid = PG_GETARG_OID(RELATION_ARG);
113
114 if (RecoveryInProgress())
116 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
117 errmsg("recovery is in progress"),
118 errhint("Statistics cannot be modified during recovery.")));
119
121
122 /*
123 * Take RowExclusiveLock on pg_class, consistent with
124 * vac_update_relstats().
125 */
126 crel = table_open(RelationRelationId, RowExclusiveLock);
127
128 ctup = SearchSysCache1(RELOID, ObjectIdGetDatum(reloid));
129 if (!HeapTupleIsValid(ctup))
130 elog(ERROR, "pg_class entry for relid %u not found", reloid);
131
132 pgcform = (Form_pg_class) GETSTRUCT(ctup);
133
134 if (update_relpages && relpages != pgcform->relpages)
135 {
136 replaces[nreplaces] = Anum_pg_class_relpages;
137 values[nreplaces] = UInt32GetDatum(relpages);
138 nreplaces++;
139 }
140
141 if (update_reltuples && reltuples != pgcform->reltuples)
142 {
143 replaces[nreplaces] = Anum_pg_class_reltuples;
144 values[nreplaces] = Float4GetDatum(reltuples);
145 nreplaces++;
146 }
147
148 if (update_relallvisible && relallvisible != pgcform->relallvisible)
149 {
150 replaces[nreplaces] = Anum_pg_class_relallvisible;
151 values[nreplaces] = UInt32GetDatum(relallvisible);
152 nreplaces++;
153 }
154
155 if (update_relallfrozen && relallfrozen != pgcform->relallfrozen)
156 {
157 replaces[nreplaces] = Anum_pg_class_relallfrozen;
158 values[nreplaces] = UInt32GetDatum(relallfrozen);
159 nreplaces++;
160 }
161
162 if (nreplaces > 0)
163 {
164 TupleDesc tupdesc = RelationGetDescr(crel);
165 HeapTuple newtup;
166
167 newtup = heap_modify_tuple_by_cols(ctup, tupdesc, nreplaces,
168 replaces, values, nulls);
169 CatalogTupleUpdate(crel, &newtup->t_self, newtup);
170 heap_freetuple(newtup);
171 }
172
173 ReleaseSysCache(ctup);
174
175 /* release the lock, consistent with vac_update_relstats() */
177
179
180 return result;
181}
182
183/*
184 * Clear statistics for a given pg_class entry; that is, set back to initial
185 * stats for a newly-created table.
186 */
187Datum
189{
190 LOCAL_FCINFO(newfcinfo, 5);
191
192 InitFunctionCallInfoData(*newfcinfo, NULL, 5, InvalidOid, NULL, NULL);
193
194 newfcinfo->args[0].value = PG_GETARG_OID(0);
195 newfcinfo->args[0].isnull = PG_ARGISNULL(0);
196 newfcinfo->args[1].value = UInt32GetDatum(0);
197 newfcinfo->args[1].isnull = false;
198 newfcinfo->args[2].value = Float4GetDatum(-1.0);
199 newfcinfo->args[2].isnull = false;
200 newfcinfo->args[3].value = UInt32GetDatum(0);
201 newfcinfo->args[3].isnull = false;
202 newfcinfo->args[4].value = UInt32GetDatum(0);
203 newfcinfo->args[4].isnull = false;
204
207}
208
209Datum
211{
212 LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
213 bool result = true;
214
215 InitFunctionCallInfoData(*positional_fcinfo, NULL,
217 InvalidOid, NULL, NULL);
218
219 if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
220 relarginfo))
221 result = false;
222
223 if (!relation_statistics_update(positional_fcinfo))
224 result = false;
225
226 PG_RETURN_BOOL(result);
227}
uint32 BlockNumber
Definition: block.h:31
static Datum values[MAXATTR]
Definition: bootstrap.c:151
int errhint(const char *fmt,...)
Definition: elog.c:1317
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define WARNING
Definition: elog.h:36
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_RETURN_VOID()
Definition: fmgr.h:349
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_GETARG_UINT32(n)
Definition: fmgr.h:270
#define InitFunctionCallInfoData(Fcinfo, Flinfo, Nargs, Collation, Context, Resultinfo)
Definition: fmgr.h:150
#define PG_ARGISNULL(n)
Definition: fmgr.h:209
#define LOCAL_FCINFO(name, nargs)
Definition: fmgr.h:110
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
Definition: heaptuple.c:1278
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
#define RowExclusiveLock
Definition: lockdefs.h:38
FormData_pg_class * Form_pg_class
Definition: pg_class.h:156
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:480
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum UInt32GetDatum(uint32 X)
Definition: postgres.h:237
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationGetDescr(relation)
Definition: rel.h:539
static struct StatsArgInfo relarginfo[]
relation_stats_argnum
@ RELALLVISIBLE_ARG
@ RELATION_ARG
@ RELPAGES_ARG
@ RELALLFROZEN_ARG
@ RELTUPLES_ARG
@ NUM_RELATION_STATS_ARGS
Datum pg_restore_relation_stats(PG_FUNCTION_ARGS)
static bool relation_statistics_update(FunctionCallInfo fcinfo)
Datum pg_clear_relation_stats(PG_FUNCTION_ARGS)
bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo, FunctionCallInfo positional_fcinfo, struct StatsArgInfo *arginfo)
Definition: stat_utils.c:263
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition: stat_utils.c:36
void stats_lock_check_privileges(Oid reloid)
Definition: stat_utils.c:130
ItemPointerData t_self
Definition: htup.h:65
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:269
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:221
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void CommandCounterIncrement(void)
Definition: xact.c:1100
bool RecoveryInProgress(void)
Definition: xlog.c:6380