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-2024, 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"
22 #include "statistics/stat_utils.h"
23 #include "utils/fmgrprotos.h"
24 #include "utils/syscache.h"
25 
26 #define DEFAULT_RELPAGES Int32GetDatum(0)
27 #define DEFAULT_RELTUPLES Float4GetDatum(-1.0)
28 #define DEFAULT_RELALLVISIBLE Int32GetDatum(0)
29 
30 /*
31  * Positional argument numbers, names, and types for
32  * relation_statistics_update().
33  */
34 
36 {
42 };
43 
44 static struct StatsArgInfo relarginfo[] =
45 {
46  [RELATION_ARG] = {"relation", REGCLASSOID},
47  [RELPAGES_ARG] = {"relpages", INT4OID},
48  [RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
49  [RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
51 };
52 
53 static bool relation_statistics_update(FunctionCallInfo fcinfo, int elevel);
54 
55 /*
56  * Internal function for modifying statistics for a relation.
57  */
58 static bool
60 {
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;
71 
72 
74  reloid = PG_GETARG_OID(RELATION_ARG);
75 
77 
78  /*
79  * Take RowExclusiveLock on pg_class, consistent with
80  * vac_update_relstats().
81  */
82  crel = table_open(RelationRelationId, RowExclusiveLock);
83 
84  tupdesc = RelationGetDescr(crel);
85  ctup = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(reloid));
86  if (!HeapTupleIsValid(ctup))
87  {
88  ereport(elevel,
89  (errcode(ERRCODE_OBJECT_IN_USE),
90  errmsg("pg_class entry for relid %u not found", reloid)));
92  return false;
93  }
94 
95  pgcform = (Form_pg_class) GETSTRUCT(ctup);
96 
97  /* relpages */
99  {
100  int32 relpages = PG_GETARG_INT32(RELPAGES_ARG);
101 
102  /*
103  * Partitioned tables may have relpages=-1. Note: for relations with
104  * no storage, relpages=-1 is not used consistently, but must be
105  * supported here.
106  */
107  if (relpages < -1)
108  {
109  ereport(elevel,
110  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
111  errmsg("relpages cannot be < -1")));
113  return false;
114  }
115 
116  if (relpages != pgcform->relpages)
117  {
118  replaces[ncols] = Anum_pg_class_relpages;
119  values[ncols] = Int32GetDatum(relpages);
120  ncols++;
121  }
122  }
123 
125  {
126  float reltuples = PG_GETARG_FLOAT4(RELTUPLES_ARG);
127 
128  if (reltuples < -1.0)
129  {
130  ereport(elevel,
131  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
132  errmsg("reltuples cannot be < -1.0")));
134  return false;
135  }
136 
137  if (reltuples != pgcform->reltuples)
138  {
139  replaces[ncols] = Anum_pg_class_reltuples;
140  values[ncols] = Float4GetDatum(reltuples);
141  ncols++;
142  }
143  }
144 
146  {
147  int32 relallvisible = PG_GETARG_INT32(RELALLVISIBLE_ARG);
148 
149  if (relallvisible < 0)
150  {
151  ereport(elevel,
152  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
153  errmsg("relallvisible cannot be < 0")));
155  return false;
156  }
157 
158  if (relallvisible != pgcform->relallvisible)
159  {
160  replaces[ncols] = Anum_pg_class_relallvisible;
161  values[ncols] = Int32GetDatum(relallvisible);
162  ncols++;
163  }
164  }
165 
166  /* only update pg_class if there is a meaningful change */
167  if (ncols == 0)
168  {
170  return false;
171  }
172 
173  newtup = heap_modify_tuple_by_cols(ctup, tupdesc, ncols, replaces, values,
174  nulls);
175 
176  CatalogTupleUpdate(crel, &newtup->t_self, newtup);
177  heap_freetuple(newtup);
178 
179  /* release the lock, consistent with vac_update_relstats() */
181 
182  return true;
183 }
184 
185 /*
186  * Set statistics for a given pg_class entry.
187  */
188 Datum
190 {
192  PG_RETURN_VOID();
193 }
194 
195 /*
196  * Clear statistics for a given pg_class entry; that is, set back to initial
197  * stats for a newly-created table.
198  */
199 Datum
201 {
202  LOCAL_FCINFO(newfcinfo, 4);
203 
204  InitFunctionCallInfoData(*newfcinfo, NULL, 4, InvalidOid, NULL, NULL);
205 
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;
214 
215  relation_statistics_update(newfcinfo, ERROR);
216  PG_RETURN_VOID();
217 }
static Datum values[MAXATTR]
Definition: bootstrap.c:150
signed int int32
Definition: c.h:496
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ERROR
Definition: elog.h:39
#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 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_INT32(n)
Definition: fmgr.h:269
#define PG_GETARG_FLOAT4(n)
Definition: fmgr.h:281
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
HeapTuple heap_modify_tuple_by_cols(HeapTuple tuple, TupleDesc tupleDesc, int nCols, const int *replCols, const Datum *replValues, const bool *replIsnull)
Definition: heaptuple.c:1277
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1434
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
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:153
static Datum Float4GetDatum(float4 X)
Definition: postgres.h:475
uintptr_t Datum
Definition: postgres.h:64
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:212
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationGetDescr(relation)
Definition: rel.h:531
static struct StatsArgInfo relarginfo[]
relation_stats_argnum
@ RELALLVISIBLE_ARG
@ RELATION_ARG
@ RELPAGES_ARG
@ RELTUPLES_ARG
@ NUM_RELATION_STATS_ARGS
static bool relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
#define DEFAULT_RELTUPLES
#define DEFAULT_RELALLVISIBLE
#define DEFAULT_RELPAGES
Datum pg_set_relation_stats(PG_FUNCTION_ARGS)
Datum pg_clear_relation_stats(PG_FUNCTION_ARGS)
void stats_check_required_arg(FunctionCallInfo fcinfo, struct StatsArgInfo *arginfo, int argnum)
Definition: stat_utils.c:32
void stats_lock_check_privileges(Oid reloid)
Definition: stat_utils.c:126
ItemPointerData t_self
Definition: htup.h:65
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40