nbtree: fix read page recheck typo.
[pgsql.git] / src / backend / statistics / relation_stats.c
blob26f15061e895ed5cf67918fd83b41ca82c439d24
1 /*-------------------------------------------------------------------------
2 * relation_stats.c
4 * PostgreSQL relation statistics manipulation
6 * Code supporting the direct import of relation statistics, similar to
7 * what is done by the ANALYZE command.
9 * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
10 * Portions Copyright (c) 1994, Regents of the University of California
12 * IDENTIFICATION
13 * src/backend/statistics/relation_stats.c
15 *-------------------------------------------------------------------------
18 #include "postgres.h"
20 #include "access/heapam.h"
21 #include "catalog/indexing.h"
22 #include "statistics/stat_utils.h"
23 #include "utils/fmgrprotos.h"
24 #include "utils/syscache.h"
26 #define DEFAULT_RELPAGES Int32GetDatum(0)
27 #define DEFAULT_RELTUPLES Float4GetDatum(-1.0)
28 #define DEFAULT_RELALLVISIBLE Int32GetDatum(0)
31 * Positional argument numbers, names, and types for
32 * relation_statistics_update().
35 enum relation_stats_argnum
37 RELATION_ARG = 0,
38 RELPAGES_ARG,
39 RELTUPLES_ARG,
40 RELALLVISIBLE_ARG,
41 NUM_RELATION_STATS_ARGS
44 static struct StatsArgInfo relarginfo[] =
46 [RELATION_ARG] = {"relation", REGCLASSOID},
47 [RELPAGES_ARG] = {"relpages", INT4OID},
48 [RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
49 [RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
50 [NUM_RELATION_STATS_ARGS] = {0}
53 static bool relation_statistics_update(FunctionCallInfo fcinfo, int elevel);
56 * Internal function for modifying statistics for a relation.
58 static bool
59 relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
61 Oid reloid;
62 Relation crel;
63 HeapTuple ctup;
64 Form_pg_class pgcform;
65 int replaces[3] = {0};
66 Datum values[3] = {0};
67 bool nulls[3] = {0};
68 int ncols = 0;
69 TupleDesc tupdesc;
70 HeapTuple newtup;
73 stats_check_required_arg(fcinfo, relarginfo, RELATION_ARG);
74 reloid = PG_GETARG_OID(RELATION_ARG);
76 stats_lock_check_privileges(reloid);
79 * Take RowExclusiveLock on pg_class, consistent with
80 * vac_update_relstats().
82 crel = table_open(RelationRelationId, RowExclusiveLock);
84 tupdesc = RelationGetDescr(crel);
85 ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid));
86 if (!HeapTupleIsValid(ctup))
88 ereport(elevel,
89 (errcode(ERRCODE_OBJECT_IN_USE),
90 errmsg("pg_class entry for relid %u not found", reloid)));
91 table_close(crel, RowExclusiveLock);
92 return false;
95 pgcform = (Form_pg_class) GETSTRUCT(ctup);
97 /* relpages */
98 if (!PG_ARGISNULL(RELPAGES_ARG))
100 int32 relpages = PG_GETARG_INT32(RELPAGES_ARG);
102 if (relpages < 0)
104 ereport(elevel,
105 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
106 errmsg("relpages cannot be < 0")));
107 table_close(crel, RowExclusiveLock);
108 return false;
111 if (relpages != pgcform->relpages)
113 replaces[ncols] = Anum_pg_class_relpages;
114 values[ncols] = Int32GetDatum(relpages);
115 ncols++;
119 if (!PG_ARGISNULL(RELTUPLES_ARG))
121 float reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG);
123 if (reltuples < -1.0)
125 ereport(elevel,
126 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
127 errmsg("reltuples cannot be < -1.0")));
128 table_close(crel, RowExclusiveLock);
129 return false;
132 if (reltuples != pgcform->reltuples)
134 replaces[ncols] = Anum_pg_class_reltuples;
135 values[ncols] = Float4GetDatum(reltuples);
136 ncols++;
140 if (!PG_ARGISNULL(RELALLVISIBLE_ARG))
142 int32 relallvisible = PG_GETARG_INT32(RELALLVISIBLE_ARG);
144 if (relallvisible < 0)
146 ereport(elevel,
147 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
148 errmsg("relallvisible cannot be < 0")));
149 table_close(crel, RowExclusiveLock);
150 return false;
153 if (relallvisible != pgcform->relallvisible)
155 replaces[ncols] = Anum_pg_class_relallvisible;
156 values[ncols] = Int32GetDatum(relallvisible);
157 ncols++;
161 /* only update pg_class if there is a meaningful change */
162 if (ncols == 0)
164 table_close(crel, RowExclusiveLock);
165 return false;
168 newtup = heap_modify_tuple_by_cols(ctup, tupdesc, ncols, replaces, values,
169 nulls);
171 CatalogTupleUpdate(crel, &newtup->t_self, newtup);
172 heap_freetuple(newtup);
174 /* release the lock, consistent with vac_update_relstats() */
175 table_close(crel, RowExclusiveLock);
177 return true;
181 * Set statistics for a given pg_class entry.
183 Datum
184 pg_set_relation_stats(PG_FUNCTION_ARGS)
186 PG_RETURN_BOOL(relation_statistics_update(fcinfo, ERROR));
190 * Clear statistics for a given pg_class entry; that is, set back to initial
191 * stats for a newly-created table.
193 Datum
194 pg_clear_relation_stats(PG_FUNCTION_ARGS)
196 LOCAL_FCINFO(newfcinfo, 4);
198 InitFunctionCallInfoData(*newfcinfo, NULL, 4, InvalidOid, NULL, NULL);
200 newfcinfo->args[0].value = PG_GETARG_OID(0);
201 newfcinfo->args[0].isnull = PG_ARGISNULL(0);
202 newfcinfo->args[1].value = DEFAULT_RELPAGES;
203 newfcinfo->args[1].isnull = false;
204 newfcinfo->args[2].value = DEFAULT_RELTUPLES;
205 newfcinfo->args[2].isnull = false;
206 newfcinfo->args[3].value = DEFAULT_RELALLVISIBLE;
207 newfcinfo->args[3].isnull = false;
209 PG_RETURN_BOOL(relation_statistics_update(newfcinfo, ERROR));