@@ -38,6 +38,7 @@ enum attribute_stats_argnum
38
38
{
39
39
ATTRELATION_ARG = 0 ,
40
40
ATTNAME_ARG ,
41
+ ATTNUM_ARG ,
41
42
INHERITED_ARG ,
42
43
NULL_FRAC_ARG ,
43
44
AVG_WIDTH_ARG ,
@@ -59,6 +60,7 @@ static struct StatsArgInfo attarginfo[] =
59
60
{
60
61
[ATTRELATION_ARG ] = {"relation" , REGCLASSOID },
61
62
[ATTNAME_ARG ] = {"attname" , NAMEOID },
63
+ [ATTNUM_ARG ] = {"attnum" , INT2OID },
62
64
[INHERITED_ARG ] = {"inherited" , BOOLOID },
63
65
[NULL_FRAC_ARG ] = {"null_frac" , FLOAT4OID },
64
66
[AVG_WIDTH_ARG ] = {"avg_width" , INT4OID },
@@ -76,6 +78,22 @@ static struct StatsArgInfo attarginfo[] =
76
78
[NUM_ATTRIBUTE_STATS_ARGS ] = {0 }
77
79
};
78
80
81
+ enum clear_attribute_stats_argnum
82
+ {
83
+ C_ATTRELATION_ARG = 0 ,
84
+ C_ATTNAME_ARG ,
85
+ C_INHERITED_ARG ,
86
+ C_NUM_ATTRIBUTE_STATS_ARGS
87
+ };
88
+
89
+ static struct StatsArgInfo cleararginfo [] =
90
+ {
91
+ [C_ATTRELATION_ARG ] = {"relation" , REGCLASSOID },
92
+ [C_ATTNAME_ARG ] = {"attname" , NAMEOID },
93
+ [C_INHERITED_ARG ] = {"inherited" , BOOLOID },
94
+ [C_NUM_ATTRIBUTE_STATS_ARGS ] = {0 }
95
+ };
96
+
79
97
static bool attribute_statistics_update (FunctionCallInfo fcinfo );
80
98
static Node * get_attr_expr (Relation rel , int attnum );
81
99
static void get_attr_stat_type (Oid reloid , AttrNumber attnum ,
@@ -116,9 +134,9 @@ static bool
116
134
attribute_statistics_update (FunctionCallInfo fcinfo )
117
135
{
118
136
Oid reloid ;
119
- Name attname ;
120
- bool inherited ;
137
+ char * attname ;
121
138
AttrNumber attnum ;
139
+ bool inherited ;
122
140
123
141
Relation starel ;
124
142
HeapTuple statup ;
@@ -164,21 +182,51 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
164
182
/* lock before looking up attribute */
165
183
stats_lock_check_privileges (reloid );
166
184
167
- stats_check_required_arg (fcinfo , attarginfo , ATTNAME_ARG );
168
- attname = PG_GETARG_NAME (ATTNAME_ARG );
169
- attnum = get_attnum (reloid , NameStr (* attname ));
185
+ /* user can specify either attname or attnum, but not both */
186
+ if (!PG_ARGISNULL (ATTNAME_ARG ))
187
+ {
188
+ Name attnamename ;
189
+
190
+ if (!PG_ARGISNULL (ATTNUM_ARG ))
191
+ ereport (ERROR ,
192
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
193
+ errmsg ("cannot specify both attname and attnum" )));
194
+ attnamename = PG_GETARG_NAME (ATTNAME_ARG );
195
+ attname = NameStr (* attnamename );
196
+ attnum = get_attnum (reloid , attname );
197
+ /* note that this test covers attisdropped cases too: */
198
+ if (attnum == InvalidAttrNumber )
199
+ ereport (ERROR ,
200
+ (errcode (ERRCODE_UNDEFINED_COLUMN ),
201
+ errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
202
+ attname , get_rel_name (reloid ))));
203
+ }
204
+ else if (!PG_ARGISNULL (ATTNUM_ARG ))
205
+ {
206
+ attnum = PG_GETARG_INT16 (ATTNUM_ARG );
207
+ attname = get_attname (reloid , attnum , true);
208
+ /* annoyingly, get_attname doesn't check attisdropped */
209
+ if (attname == NULL ||
210
+ !SearchSysCacheExistsAttName (reloid , attname ))
211
+ ereport (ERROR ,
212
+ (errcode (ERRCODE_UNDEFINED_COLUMN ),
213
+ errmsg ("column %d of relation \"%s\" does not exist" ,
214
+ attnum , get_rel_name (reloid ))));
215
+ }
216
+ else
217
+ {
218
+ ereport (ERROR ,
219
+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
220
+ errmsg ("must specify either attname or attnum" )));
221
+ attname = NULL ; /* keep compiler quiet */
222
+ attnum = 0 ;
223
+ }
170
224
171
225
if (attnum < 0 )
172
226
ereport (ERROR ,
173
227
(errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
174
228
errmsg ("cannot modify statistics on system column \"%s\"" ,
175
- NameStr (* attname ))));
176
-
177
- if (attnum == InvalidAttrNumber )
178
- ereport (ERROR ,
179
- (errcode (ERRCODE_UNDEFINED_COLUMN ),
180
- errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
181
- NameStr (* attname ), get_rel_name (reloid ))));
229
+ attname )));
182
230
183
231
stats_check_required_arg (fcinfo , attarginfo , INHERITED_ARG );
184
232
inherited = PG_GETARG_BOOL (INHERITED_ARG );
@@ -241,7 +289,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
241
289
& elemtypid , & elem_eq_opr ))
242
290
{
243
291
ereport (WARNING ,
244
- (errmsg ("unable to determine element type of attribute \"%s\"" , NameStr ( * attname ) ),
292
+ (errmsg ("unable to determine element type of attribute \"%s\"" , attname ),
245
293
errdetail ("Cannot set STATISTIC_KIND_MCELEM or STATISTIC_KIND_DECHIST." )));
246
294
elemtypid = InvalidOid ;
247
295
elem_eq_opr = InvalidOid ;
@@ -257,7 +305,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
257
305
{
258
306
ereport (WARNING ,
259
307
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
260
- errmsg ("could not determine less-than operator for attribute \"%s\"" , NameStr ( * attname ) ),
308
+ errmsg ("could not determine less-than operator for attribute \"%s\"" , attname ),
261
309
errdetail ("Cannot set STATISTIC_KIND_HISTOGRAM or STATISTIC_KIND_CORRELATION." )));
262
310
263
311
do_histogram = false;
@@ -271,7 +319,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
271
319
{
272
320
ereport (WARNING ,
273
321
(errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
274
- errmsg ("attribute \"%s\" is not a range type" , NameStr ( * attname ) ),
322
+ errmsg ("attribute \"%s\" is not a range type" , attname ),
275
323
errdetail ("Cannot set STATISTIC_KIND_RANGE_LENGTH_HISTOGRAM or STATISTIC_KIND_BOUNDS_HISTOGRAM." )));
276
324
277
325
do_bounds_histogram = false;
@@ -857,8 +905,8 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
857
905
AttrNumber attnum ;
858
906
bool inherited ;
859
907
860
- stats_check_required_arg (fcinfo , attarginfo , ATTRELATION_ARG );
861
- reloid = PG_GETARG_OID (ATTRELATION_ARG );
908
+ stats_check_required_arg (fcinfo , cleararginfo , C_ATTRELATION_ARG );
909
+ reloid = PG_GETARG_OID (C_ATTRELATION_ARG );
862
910
863
911
if (RecoveryInProgress ())
864
912
ereport (ERROR ,
@@ -868,8 +916,8 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
868
916
869
917
stats_lock_check_privileges (reloid );
870
918
871
- stats_check_required_arg (fcinfo , attarginfo , ATTNAME_ARG );
872
- attname = PG_GETARG_NAME (ATTNAME_ARG );
919
+ stats_check_required_arg (fcinfo , cleararginfo , C_ATTNAME_ARG );
920
+ attname = PG_GETARG_NAME (C_ATTNAME_ARG );
873
921
attnum = get_attnum (reloid , NameStr (* attname ));
874
922
875
923
if (attnum < 0 )
@@ -884,13 +932,39 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
884
932
errmsg ("column \"%s\" of relation \"%s\" does not exist" ,
885
933
NameStr (* attname ), get_rel_name (reloid ))));
886
934
887
- stats_check_required_arg (fcinfo , attarginfo , INHERITED_ARG );
888
- inherited = PG_GETARG_BOOL (INHERITED_ARG );
935
+ stats_check_required_arg (fcinfo , cleararginfo , C_INHERITED_ARG );
936
+ inherited = PG_GETARG_BOOL (C_INHERITED_ARG );
889
937
890
938
delete_pg_statistic (reloid , attnum , inherited );
891
939
PG_RETURN_VOID ();
892
940
}
893
941
942
+ /*
943
+ * Import statistics for a given relation attribute.
944
+ *
945
+ * Inserts or replaces a row in pg_statistic for the given relation and
946
+ * attribute name or number. It takes input parameters that correspond to
947
+ * columns in the view pg_stats.
948
+ *
949
+ * Parameters are given in a pseudo named-attribute style: they must be
950
+ * pairs of parameter names (as text) and values (of appropriate types).
951
+ * We do that, rather than using regular named-parameter notation, so
952
+ * that we can add or change parameters without fear of breaking
953
+ * carelessly-written calls.
954
+ *
955
+ * Parameters null_frac, avg_width, and n_distinct all correspond to NOT NULL
956
+ * columns in pg_statistic. The remaining parameters all belong to a specific
957
+ * stakind. Some stakinds require multiple parameters, which must be specified
958
+ * together (or neither specified).
959
+ *
960
+ * Parameters are only superficially validated. Omitting a parameter or
961
+ * passing NULL leaves the statistic unchanged.
962
+ *
963
+ * Parameters corresponding to ANYARRAY columns are instead passed in as text
964
+ * values, which is a valid input string for an array of the type or element
965
+ * type of the attribute. Any error generated by the array_in() function will
966
+ * in turn fail the function.
967
+ */
894
968
Datum
895
969
pg_restore_attribute_stats (PG_FUNCTION_ARGS )
896
970
{
0 commit comments