Simplify IsIndexUsableForReplicaIdentityFull()
[pgsql.git] / src / backend / statistics / relation_stats.c
blobe619d5cf5b19aa96e6ddd2cfdeef7d180fe8d217
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 bool result = true;
72 stats_check_required_arg(fcinfo, relarginfo, RELATION_ARG);
73 reloid = PG_GETARG_OID(RELATION_ARG);
75 if (RecoveryInProgress())
76 ereport(ERROR,
77 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
78 errmsg("recovery is in progress"),
79 errhint("Statistics cannot be modified during recovery.")));
81 stats_lock_check_privileges(reloid);
84 * Take RowExclusiveLock on pg_class, consistent with
85 * vac_update_relstats().
87 crel = table_open(RelationRelationId, RowExclusiveLock);
89 tupdesc = RelationGetDescr(crel);
90 ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid));
91 if (!HeapTupleIsValid(ctup))
93 ereport(elevel,
94 (errcode(ERRCODE_OBJECT_IN_USE),
95 errmsg("pg_class entry for relid %u not found", reloid)));
96 table_close(crel, RowExclusiveLock);
97 return false;
100 pgcform = (Form_pg_class) GETSTRUCT(ctup);
102 /* relpages */
103 if (!PG_ARGISNULL(RELPAGES_ARG))
105 int32 relpages = PG_GETARG_INT32(RELPAGES_ARG);
108 * Partitioned tables may have relpages=-1. Note: for relations with
109 * no storage, relpages=-1 is not used consistently, but must be
110 * supported here.
112 if (relpages < -1)
114 ereport(elevel,
115 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
116 errmsg("relpages cannot be < -1")));
117 result = false;
119 else if (relpages != pgcform->relpages)
121 replaces[ncols] = Anum_pg_class_relpages;
122 values[ncols] = Int32GetDatum(relpages);
123 ncols++;
127 if (!PG_ARGISNULL(RELTUPLES_ARG))
129 float reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG);
131 if (reltuples < -1.0)
133 ereport(elevel,
134 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
135 errmsg("reltuples cannot be < -1.0")));
136 result = false;
138 else if (reltuples != pgcform->reltuples)
140 replaces[ncols] = Anum_pg_class_reltuples;
141 values[ncols] = Float4GetDatum(reltuples);
142 ncols++;
147 if (!PG_ARGISNULL(RELALLVISIBLE_ARG))
149 int32 relallvisible = PG_GETARG_INT32(RELALLVISIBLE_ARG);
151 if (relallvisible < 0)
153 ereport(elevel,
154 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
155 errmsg("relallvisible cannot be < 0")));
156 result = false;
158 else if (relallvisible != pgcform->relallvisible)
160 replaces[ncols] = Anum_pg_class_relallvisible;
161 values[ncols] = Int32GetDatum(relallvisible);
162 ncols++;
166 /* only update pg_class if there is a meaningful change */
167 if (ncols > 0)
169 HeapTuple newtup;
171 newtup = heap_modify_tuple_by_cols(ctup, tupdesc, ncols, replaces, values,
172 nulls);
173 CatalogTupleUpdate(crel, &newtup->t_self, newtup);
174 heap_freetuple(newtup);
177 /* release the lock, consistent with vac_update_relstats() */
178 table_close(crel, RowExclusiveLock);
180 CommandCounterIncrement();
182 return result;
186 * Set statistics for a given pg_class entry.
188 Datum
189 pg_set_relation_stats(PG_FUNCTION_ARGS)
191 relation_statistics_update(fcinfo, ERROR);
192 PG_RETURN_VOID();
196 * Clear statistics for a given pg_class entry; that is, set back to initial
197 * stats for a newly-created table.
199 Datum
200 pg_clear_relation_stats(PG_FUNCTION_ARGS)
202 LOCAL_FCINFO(newfcinfo, 4);
204 InitFunctionCallInfoData(*newfcinfo, NULL, 4, InvalidOid, NULL, NULL);
206 newfcinfo->args[0].value = PG_GETARG_OID(0);
207 newfcinfo->args[0].isnull = PG_ARGISNULL(0);
208 newfcinfo->args[1].value = DEFAULT_RELPAGES;
209 newfcinfo->args[1].isnull = false;
210 newfcinfo->args[2].value = DEFAULT_RELTUPLES;
211 newfcinfo->args[2].isnull = false;
212 newfcinfo->args[3].value = DEFAULT_RELALLVISIBLE;
213 newfcinfo->args[3].isnull = false;
215 relation_statistics_update(newfcinfo, ERROR);
216 PG_RETURN_VOID();
219 Datum
220 pg_restore_relation_stats(PG_FUNCTION_ARGS)
222 LOCAL_FCINFO(positional_fcinfo, NUM_RELATION_STATS_ARGS);
223 bool result = true;
225 InitFunctionCallInfoData(*positional_fcinfo, NULL,
226 NUM_RELATION_STATS_ARGS,
227 InvalidOid, NULL, NULL);
229 if (!stats_fill_fcinfo_from_arg_pairs(fcinfo, positional_fcinfo,
230 relarginfo, WARNING))
231 result = false;
233 if (!relation_statistics_update(positional_fcinfo, WARNING))
234 result = false;
236 PG_RETURN_BOOL(result);