1 /*-------------------------------------------------------------------------
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
13 * src/backend/statistics/relation_stats.c
15 *-------------------------------------------------------------------------
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
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.
59 relation_statistics_update(FunctionCallInfo fcinfo
, int elevel
)
64 Form_pg_class pgcform
;
65 int replaces
[3] = {0};
66 Datum values
[3] = {0};
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
))
89 (errcode(ERRCODE_OBJECT_IN_USE
),
90 errmsg("pg_class entry for relid %u not found", reloid
)));
91 table_close(crel
, RowExclusiveLock
);
95 pgcform
= (Form_pg_class
) GETSTRUCT(ctup
);
98 if (!PG_ARGISNULL(RELPAGES_ARG
))
100 int32 relpages
= PG_GETARG_INT32(RELPAGES_ARG
);
105 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
106 errmsg("relpages cannot be < 0")));
107 table_close(crel
, RowExclusiveLock
);
111 if (relpages
!= pgcform
->relpages
)
113 replaces
[ncols
] = Anum_pg_class_relpages
;
114 values
[ncols
] = Int32GetDatum(relpages
);
119 if (!PG_ARGISNULL(RELTUPLES_ARG
))
121 float reltuples
= PG_GETARG_FLOAT4(RELTUPLES_ARG
);
123 if (reltuples
< -1.0)
126 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
127 errmsg("reltuples cannot be < -1.0")));
128 table_close(crel
, RowExclusiveLock
);
132 if (reltuples
!= pgcform
->reltuples
)
134 replaces
[ncols
] = Anum_pg_class_reltuples
;
135 values
[ncols
] = Float4GetDatum(reltuples
);
140 if (!PG_ARGISNULL(RELALLVISIBLE_ARG
))
142 int32 relallvisible
= PG_GETARG_INT32(RELALLVISIBLE_ARG
);
144 if (relallvisible
< 0)
147 (errcode(ERRCODE_INVALID_PARAMETER_VALUE
),
148 errmsg("relallvisible cannot be < 0")));
149 table_close(crel
, RowExclusiveLock
);
153 if (relallvisible
!= pgcform
->relallvisible
)
155 replaces
[ncols
] = Anum_pg_class_relallvisible
;
156 values
[ncols
] = Int32GetDatum(relallvisible
);
161 /* only update pg_class if there is a meaningful change */
164 table_close(crel
, RowExclusiveLock
);
168 newtup
= heap_modify_tuple_by_cols(ctup
, tupdesc
, ncols
, replaces
, values
,
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
);
181 * Set statistics for a given pg_class entry.
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.
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
));