Skip to content

Commit 650ab8a

Browse files
committed
Stats: use schemaname/relname instead of regclass.
For import and export, use schemaname/relname rather than regclass. This is more natural during export, fits with the other arguments better, and it gives better control over error handling in case we need to downgrade more errors to warnings. Also, use text for the argument types for schemaname, relname, and attname so that casts to "name" are not required. Author: Corey Huinker <corey.huinker@gmail.com> Discussion: https://postgr.es/m/CADkLM=ceOSsx_=oe73QQ-BxUFR2Cwqum7-UP_fPe22DBY0NerA@mail.gmail.com
1 parent 2a420f7 commit 650ab8a

File tree

11 files changed

+579
-289
lines changed

11 files changed

+579
-289
lines changed

doc/src/sgml/func.sgml

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30364,14 +30364,15 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
3036430364
<structname>mytable</structname>:
3036530365
<programlisting>
3036630366
SELECT pg_restore_relation_stats(
30367-
'relation', 'mytable'::regclass,
30368-
'relpages', 173::integer,
30369-
'reltuples', 10000::real);
30367+
'schemaname', 'myschema',
30368+
'relname', 'mytable',
30369+
'relpages', 173::integer,
30370+
'reltuples', 10000::real);
3037030371
</programlisting>
3037130372
</para>
3037230373
<para>
30373-
The argument <literal>relation</literal> with a value of type
30374-
<type>regclass</type> is required, and specifies the table. Other
30374+
The arguments <literal>schemaname</literal> and
30375+
<literal>relname</literal> are required, and specify the table. Other
3037530376
arguments are the names and values of statistics corresponding to
3037630377
certain columns in <link
3037730378
linkend="catalog-pg-class"><structname>pg_class</structname></link>.
@@ -30408,7 +30409,7 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
3040830409
<indexterm>
3040930410
<primary>pg_clear_relation_stats</primary>
3041030411
</indexterm>
30411-
<function>pg_clear_relation_stats</function> ( <parameter>relation</parameter> <type>regclass</type> )
30412+
<function>pg_clear_relation_stats</function> ( <parameter>schemaname</parameter> <type>text</type>, <parameter>relname</parameter> <type>text</type> )
3041230413
<returnvalue>void</returnvalue>
3041330414
</para>
3041430415
<para>
@@ -30457,22 +30458,23 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
3045730458
<structname>mytable</structname>:
3045830459
<programlisting>
3045930460
SELECT pg_restore_attribute_stats(
30460-
'relation', 'mytable'::regclass,
30461-
'attname', 'col1'::name,
30462-
'inherited', false,
30463-
'avg_width', 125::integer,
30464-
'null_frac', 0.5::real);
30461+
'schemaname', 'myschema',
30462+
'relname', 'mytable',
30463+
'attname', 'col1',
30464+
'inherited', false,
30465+
'avg_width', 125::integer,
30466+
'null_frac', 0.5::real);
3046530467
</programlisting>
3046630468
</para>
3046730469
<para>
30468-
The required arguments are <literal>relation</literal> with a value
30469-
of type <type>regclass</type>, which specifies the table; either
30470-
<literal>attname</literal> with a value of type <type>name</type> or
30471-
<literal>attnum</literal> with a value of type <type>smallint</type>,
30472-
which specifies the column; and <literal>inherited</literal>, which
30473-
specifies whether the statistics include values from child tables.
30474-
Other arguments are the names and values of statistics corresponding
30475-
to columns in <link
30470+
The required arguments are <literal>schemaname</literal> and
30471+
<literal>relname</literal> with a value of type <type>text</type>
30472+
which specify the table; either <literal>attname</literal> with a
30473+
value of type <type>text</type> or <literal>attnum</literal> with a
30474+
value of type <type>smallint</type>, which specifies the column; and
30475+
<literal>inherited</literal>, which specifies whether the statistics
30476+
include values from child tables. Other arguments are the names and
30477+
values of statistics corresponding to columns in <link
3047630478
linkend="view-pg-stats"><structname>pg_stats</structname></link>.
3047730479
</para>
3047830480
<para>
@@ -30502,8 +30504,9 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
3050230504
<primary>pg_clear_attribute_stats</primary>
3050330505
</indexterm>
3050430506
<function>pg_clear_attribute_stats</function> (
30505-
<parameter>relation</parameter> <type>regclass</type>,
30506-
<parameter>attname</parameter> <type>name</type>,
30507+
<parameter>schemaname</parameter> <type>text</type>,
30508+
<parameter>relname</parameter> <type>text</type>,
30509+
<parameter>attname</parameter> <type>text</type>,
3050730510
<parameter>inherited</parameter> <type>boolean</type> )
3050830511
<returnvalue>void</returnvalue>
3050930512
</para>

src/backend/statistics/attribute_stats.c

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@
3636

3737
enum attribute_stats_argnum
3838
{
39-
ATTRELATION_ARG = 0,
39+
ATTRELSCHEMA_ARG = 0,
40+
ATTRELNAME_ARG,
4041
ATTNAME_ARG,
4142
ATTNUM_ARG,
4243
INHERITED_ARG,
@@ -58,8 +59,9 @@ enum attribute_stats_argnum
5859

5960
static struct StatsArgInfo attarginfo[] =
6061
{
61-
[ATTRELATION_ARG] = {"relation", REGCLASSOID},
62-
[ATTNAME_ARG] = {"attname", NAMEOID},
62+
[ATTRELSCHEMA_ARG] = {"schemaname", TEXTOID},
63+
[ATTRELNAME_ARG] = {"relname", TEXTOID},
64+
[ATTNAME_ARG] = {"attname", TEXTOID},
6365
[ATTNUM_ARG] = {"attnum", INT2OID},
6466
[INHERITED_ARG] = {"inherited", BOOLOID},
6567
[NULL_FRAC_ARG] = {"null_frac", FLOAT4OID},
@@ -80,16 +82,18 @@ static struct StatsArgInfo attarginfo[] =
8082

8183
enum clear_attribute_stats_argnum
8284
{
83-
C_ATTRELATION_ARG = 0,
85+
C_ATTRELSCHEMA_ARG = 0,
86+
C_ATTRELNAME_ARG,
8487
C_ATTNAME_ARG,
8588
C_INHERITED_ARG,
8689
C_NUM_ATTRIBUTE_STATS_ARGS
8790
};
8891

8992
static struct StatsArgInfo cleararginfo[] =
9093
{
91-
[C_ATTRELATION_ARG] = {"relation", REGCLASSOID},
92-
[C_ATTNAME_ARG] = {"attname", NAMEOID},
94+
[C_ATTRELSCHEMA_ARG] = {"relation", TEXTOID},
95+
[C_ATTRELNAME_ARG] = {"relation", TEXTOID},
96+
[C_ATTNAME_ARG] = {"attname", TEXTOID},
9397
[C_INHERITED_ARG] = {"inherited", BOOLOID},
9498
[C_NUM_ATTRIBUTE_STATS_ARGS] = {0}
9599
};
@@ -133,6 +137,8 @@ static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
133137
static bool
134138
attribute_statistics_update(FunctionCallInfo fcinfo)
135139
{
140+
char *nspname;
141+
char *relname;
136142
Oid reloid;
137143
char *attname;
138144
AttrNumber attnum;
@@ -170,8 +176,13 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
170176

171177
bool result = true;
172178

173-
stats_check_required_arg(fcinfo, attarginfo, ATTRELATION_ARG);
174-
reloid = PG_GETARG_OID(ATTRELATION_ARG);
179+
stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG);
180+
stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG);
181+
182+
nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELSCHEMA_ARG));
183+
relname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELNAME_ARG));
184+
185+
reloid = stats_lookup_relid(nspname, relname);
175186

176187
if (RecoveryInProgress())
177188
ereport(ERROR,
@@ -185,21 +196,18 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
185196
/* user can specify either attname or attnum, but not both */
186197
if (!PG_ARGISNULL(ATTNAME_ARG))
187198
{
188-
Name attnamename;
189-
190199
if (!PG_ARGISNULL(ATTNUM_ARG))
191200
ereport(ERROR,
192201
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
193202
errmsg("cannot specify both attname and attnum")));
194-
attnamename = PG_GETARG_NAME(ATTNAME_ARG);
195-
attname = NameStr(*attnamename);
203+
attname = TextDatumGetCString(PG_GETARG_DATUM(ATTNAME_ARG));
196204
attnum = get_attnum(reloid, attname);
197205
/* note that this test covers attisdropped cases too: */
198206
if (attnum == InvalidAttrNumber)
199207
ereport(ERROR,
200208
(errcode(ERRCODE_UNDEFINED_COLUMN),
201209
errmsg("column \"%s\" of relation \"%s\" does not exist",
202-
attname, get_rel_name(reloid))));
210+
attname, relname)));
203211
}
204212
else if (!PG_ARGISNULL(ATTNUM_ARG))
205213
{
@@ -211,7 +219,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
211219
ereport(ERROR,
212220
(errcode(ERRCODE_UNDEFINED_COLUMN),
213221
errmsg("column %d of relation \"%s\" does not exist",
214-
attnum, get_rel_name(reloid))));
222+
attnum, relname)));
215223
}
216224
else
217225
{
@@ -900,13 +908,22 @@ init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
900908
Datum
901909
pg_clear_attribute_stats(PG_FUNCTION_ARGS)
902910
{
911+
char *nspname;
912+
char *relname;
903913
Oid reloid;
904-
Name attname;
914+
char *attname;
905915
AttrNumber attnum;
906916
bool inherited;
907917

908-
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELATION_ARG);
909-
reloid = PG_GETARG_OID(C_ATTRELATION_ARG);
918+
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELSCHEMA_ARG);
919+
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELNAME_ARG);
920+
stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG);
921+
stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG);
922+
923+
nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELSCHEMA_ARG));
924+
relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELNAME_ARG));
925+
926+
reloid = stats_lookup_relid(nspname, relname);
910927

911928
if (RecoveryInProgress())
912929
ereport(ERROR,
@@ -916,23 +933,21 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
916933

917934
stats_lock_check_privileges(reloid);
918935

919-
stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG);
920-
attname = PG_GETARG_NAME(C_ATTNAME_ARG);
921-
attnum = get_attnum(reloid, NameStr(*attname));
936+
attname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTNAME_ARG));
937+
attnum = get_attnum(reloid, attname);
922938

923939
if (attnum < 0)
924940
ereport(ERROR,
925941
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
926942
errmsg("cannot clear statistics on system column \"%s\"",
927-
NameStr(*attname))));
943+
attname)));
928944

929945
if (attnum == InvalidAttrNumber)
930946
ereport(ERROR,
931947
(errcode(ERRCODE_UNDEFINED_COLUMN),
932948
errmsg("column \"%s\" of relation \"%s\" does not exist",
933-
NameStr(*attname), get_rel_name(reloid))));
949+
attname, get_rel_name(reloid))));
934950

935-
stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG);
936951
inherited = PG_GETARG_BOOL(C_INHERITED_ARG);
937952

938953
delete_pg_statistic(reloid, attnum, inherited);

src/backend/statistics/relation_stats.c

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919

2020
#include "access/heapam.h"
2121
#include "catalog/indexing.h"
22+
#include "catalog/namespace.h"
2223
#include "statistics/stat_utils.h"
24+
#include "utils/builtins.h"
2325
#include "utils/fmgroids.h"
2426
#include "utils/fmgrprotos.h"
27+
#include "utils/lsyscache.h"
2528
#include "utils/syscache.h"
2629

2730

@@ -32,7 +35,8 @@
3235

3336
enum relation_stats_argnum
3437
{
35-
RELATION_ARG = 0,
38+
RELSCHEMA_ARG = 0,
39+
RELNAME_ARG,
3640
RELPAGES_ARG,
3741
RELTUPLES_ARG,
3842
RELALLVISIBLE_ARG,
@@ -42,7 +46,8 @@ enum relation_stats_argnum
4246

4347
static struct StatsArgInfo relarginfo[] =
4448
{
45-
[RELATION_ARG] = {"relation", REGCLASSOID},
49+
[RELSCHEMA_ARG] = {"schemaname", TEXTOID},
50+
[RELNAME_ARG] = {"relname", TEXTOID},
4651
[RELPAGES_ARG] = {"relpages", INT4OID},
4752
[RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
4853
[RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
@@ -59,6 +64,8 @@ static bool
5964
relation_statistics_update(FunctionCallInfo fcinfo)
6065
{
6166
bool result = true;
67+
char *nspname;
68+
char *relname;
6269
Oid reloid;
6370
Relation crel;
6471
BlockNumber relpages = 0;
@@ -76,6 +83,22 @@ relation_statistics_update(FunctionCallInfo fcinfo)
7683
bool nulls[4] = {0};
7784
int nreplaces = 0;
7885

86+
stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG);
87+
stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG);
88+
89+
nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
90+
relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
91+
92+
reloid = stats_lookup_relid(nspname, relname);
93+
94+
if (RecoveryInProgress())
95+
ereport(ERROR,
96+
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
97+
errmsg("recovery is in progress"),
98+
errhint("Statistics cannot be modified during recovery.")));
99+
100+
stats_lock_check_privileges(reloid);
101+
79102
if (!PG_ARGISNULL(RELPAGES_ARG))
80103
{
81104
relpages = PG_GETARG_UINT32(RELPAGES_ARG);
@@ -108,17 +131,6 @@ relation_statistics_update(FunctionCallInfo fcinfo)
108131
update_relallfrozen = true;
109132
}
110133

111-
stats_check_required_arg(fcinfo, relarginfo, RELATION_ARG);
112-
reloid = PG_GETARG_OID(RELATION_ARG);
113-
114-
if (RecoveryInProgress())
115-
ereport(ERROR,
116-
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
117-
errmsg("recovery is in progress"),
118-
errhint("Statistics cannot be modified during recovery.")));
119-
120-
stats_lock_check_privileges(reloid);
121-
122134
/*
123135
* Take RowExclusiveLock on pg_class, consistent with
124136
* vac_update_relstats().
@@ -187,20 +199,22 @@ relation_statistics_update(FunctionCallInfo fcinfo)
187199
Datum
188200
pg_clear_relation_stats(PG_FUNCTION_ARGS)
189201
{
190-
LOCAL_FCINFO(newfcinfo, 5);
202+
LOCAL_FCINFO(newfcinfo, 6);
191203

192-
InitFunctionCallInfoData(*newfcinfo, NULL, 5, InvalidOid, NULL, NULL);
204+
InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL);
193205

194-
newfcinfo->args[0].value = PG_GETARG_OID(0);
206+
newfcinfo->args[0].value = PG_GETARG_DATUM(0);
195207
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);
208+
newfcinfo->args[1].value = PG_GETARG_DATUM(1);
209+
newfcinfo->args[1].isnull = PG_ARGISNULL(1);
210+
newfcinfo->args[2].value = UInt32GetDatum(0);
199211
newfcinfo->args[2].isnull = false;
200-
newfcinfo->args[3].value = UInt32GetDatum(0);
212+
newfcinfo->args[3].value = Float4GetDatum(-1.0);
201213
newfcinfo->args[3].isnull = false;
202214
newfcinfo->args[4].value = UInt32GetDatum(0);
203215
newfcinfo->args[4].isnull = false;
216+
newfcinfo->args[5].value = UInt32GetDatum(0);
217+
newfcinfo->args[5].isnull = false;
204218

205219
relation_statistics_update(newfcinfo);
206220
PG_RETURN_VOID();

src/backend/statistics/stat_utils.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include "access/relation.h"
2020
#include "catalog/index.h"
21+
#include "catalog/namespace.h"
2122
#include "catalog/pg_database.h"
2223
#include "funcapi.h"
2324
#include "miscadmin.h"
@@ -213,6 +214,27 @@ stats_lock_check_privileges(Oid reloid)
213214
relation_close(table, NoLock);
214215
}
215216

217+
/*
218+
* Lookup relation oid from schema and relation name.
219+
*/
220+
Oid
221+
stats_lookup_relid(const char *nspname, const char *relname)
222+
{
223+
Oid nspoid;
224+
Oid reloid;
225+
226+
nspoid = LookupExplicitNamespace(nspname, false);
227+
reloid = get_relname_relid(relname, nspoid);
228+
if (!OidIsValid(reloid))
229+
ereport(ERROR,
230+
(errcode(ERRCODE_UNDEFINED_TABLE),
231+
errmsg("relation \"%s.%s\" does not exist",
232+
nspname, relname)));
233+
234+
return reloid;
235+
}
236+
237+
216238
/*
217239
* Find the argument number for the given argument name, returning -1 if not
218240
* found.

0 commit comments

Comments
 (0)