Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd32d146

Browse files
committed
Add functions pg_restore_relation_stats(), pg_restore_attribute_stats().
Similar to the pg_set_*_stats() functions, except with a variadicsignature that's designed to be more future-proof. Additionally, mostproblems are reported as WARNINGs rather than ERRORs, allowing moststats to be restored even if some cannot.These functions are intended to be called from pg_dump to avoid theneed to run ANALYZE after an upgrade.Author: Corey HuinkerDiscussion:https://postgr.es/m/CADkLM=eErgzn7ECDpwFcptJKOk9SxZEk5Pot4d94eVTZsvj3gw@mail.gmail.com
1 parent534d0ea commitd32d146

File tree

9 files changed

+1891
-92
lines changed

9 files changed

+1891
-92
lines changed

‎doc/src/sgml/func.sgml

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30267,6 +30267,55 @@ DETAIL: Make sure pg_wal_replay_wait() isn't called within a transaction with a
3026730267
</entry>
3026830268
</row>
3026930269

30270+
<row>
30271+
<entry role="func_table_entry"><para role="func_signature">
30272+
<indexterm>
30273+
<primary>pg_restore_relation_stats</primary>
30274+
</indexterm>
30275+
<function>pg_restore_relation_stats</function> (
30276+
<literal>VARIADIC</literal> <parameter>kwargs</parameter> <type>"any"</type> )
30277+
<returnvalue>boolean</returnvalue>
30278+
</para>
30279+
<para>
30280+
Similar to <function>pg_set_relation_stats()</function>, but intended
30281+
for bulk restore of relation statistics. The tracked statistics may
30282+
change from version to version, so the primary purpose of this
30283+
function is to maintain a consistent function signature to avoid
30284+
errors when restoring statistics from previous versions.
30285+
</para>
30286+
<para>
30287+
Arguments are passed as pairs of <replaceable>argname</replaceable>
30288+
and <replaceable>argvalue</replaceable>, where
30289+
<replaceable>argname</replaceable> corresponds to a named argument in
30290+
<function>pg_set_relation_stats()</function> and
30291+
<replaceable>argvalue</replaceable> is of the corresponding type.
30292+
</para>
30293+
<para>
30294+
Additionally, this function supports argument name
30295+
<literal>version</literal> of type <type>integer</type>, which
30296+
specifies the version from which the statistics originated, improving
30297+
intepretation of older statistics.
30298+
</para>
30299+
<para>
30300+
For example, to set the <structname>relpages</structname> and
30301+
<structname>reltuples</structname> of the table
30302+
<structname>mytable</structname>:
30303+
<programlisting>
30304+
SELECT pg_restore_relation_stats(
30305+
'relation', 'mytable'::regclass,
30306+
'relpages', 173::integer,
30307+
'reltuples', 10000::float4);
30308+
</programlisting>
30309+
</para>
30310+
<para>
30311+
Minor errors are reported as a <literal>WARNING</literal> and
30312+
ignored, and remaining statistics will still be restored. If all
30313+
specified statistics are successfully restored, return
30314+
<literal>true</literal>, otherwise <literal>false</literal>.
30315+
</para>
30316+
</entry>
30317+
</row>
30318+
3027030319
<row>
3027130320
<entry role="func_table_entry">
3027230321
<para role="func_signature">
@@ -30338,6 +30387,57 @@ DETAIL: Make sure pg_wal_replay_wait() isn't called within a transaction with a
3033830387
</entry>
3033930388
</row>
3034030389

30390+
<row>
30391+
<entry role="func_table_entry"><para role="func_signature">
30392+
<indexterm>
30393+
<primary>pg_restore_attribute_stats</primary>
30394+
</indexterm>
30395+
<function>pg_restore_attribute_stats</function> (
30396+
<literal>VARIADIC</literal> <parameter>kwargs</parameter> <type>"any"</type> )
30397+
<returnvalue>boolean</returnvalue>
30398+
</para>
30399+
<para>
30400+
Similar to <function>pg_set_attribute_stats()</function>, but
30401+
intended for bulk restore of attribute statistics. The tracked
30402+
statistics may change from version to version, so the primary purpose
30403+
of this function is to maintain a consistent function signature to
30404+
avoid errors when restoring statistics from previous versions.
30405+
</para>
30406+
<para>
30407+
Arguments are passed as pairs of <replaceable>argname</replaceable>
30408+
and <replaceable>argvalue</replaceable>, where
30409+
<replaceable>argname</replaceable> corresponds to a named argument in
30410+
<function>pg_set_attribute_stats()</function> and
30411+
<replaceable>argvalue</replaceable> is of the corresponding type.
30412+
</para>
30413+
<para>
30414+
Additionally, this function supports argument name
30415+
<literal>version</literal> of type <type>integer</type>, which
30416+
specifies the version from which the statistics originated, improving
30417+
intepretation of older statistics.
30418+
</para>
30419+
<para>
30420+
For example, to set the <structname>avg_width</structname> and
30421+
<structname>null_frac</structname> for the attribute
30422+
<structname>col1</structname> of the table
30423+
<structname>mytable</structname>:
30424+
<programlisting>
30425+
SELECT pg_restore_attribute_stats(
30426+
'relation', 'mytable'::regclass,
30427+
'attname', 'col1'::name,
30428+
'inherited', false,
30429+
'avg_width', 125::integer,
30430+
'null_frac', 0.5::real);
30431+
</programlisting>
30432+
</para>
30433+
<para>
30434+
Minor errors are reported as a <literal>WARNING</literal> and
30435+
ignored, and remaining statistics will still be restored. If all
30436+
specified statistics are successfully restored, return
30437+
<literal>true</literal>, otherwise <literal>false</literal>.
30438+
</para>
30439+
</entry>
30440+
</row>
3034130441
</tbody>
3034230442
</tgroup>
3034330443
</table>

‎src/backend/statistics/attribute_stats.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -877,3 +877,22 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
877877
delete_pg_statistic(reloid,attnum,inherited);
878878
PG_RETURN_VOID();
879879
}
880+
881+
Datum
882+
pg_restore_attribute_stats(PG_FUNCTION_ARGS)
883+
{
884+
LOCAL_FCINFO(positional_fcinfo,NUM_ATTRIBUTE_STATS_ARGS);
885+
boolresult= true;
886+
887+
InitFunctionCallInfoData(*positional_fcinfo,NULL,NUM_ATTRIBUTE_STATS_ARGS,
888+
InvalidOid,NULL,NULL);
889+
890+
if (!stats_fill_fcinfo_from_arg_pairs(fcinfo,positional_fcinfo,
891+
attarginfo,WARNING))
892+
result= false;
893+
894+
if (!attribute_statistics_update(positional_fcinfo,WARNING))
895+
result= false;
896+
897+
PG_RETURN_BOOL(result);
898+
}

‎src/backend/statistics/relation_stats.c

Lines changed: 36 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,7 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
6767
boolnulls[3]= {0};
6868
intncols=0;
6969
TupleDesctupdesc;
70-
HeapTuplenewtup;
71-
70+
boolresult= true;
7271

7372
stats_check_required_arg(fcinfo,relarginfo,RELATION_ARG);
7473
reloid=PG_GETARG_OID(RELATION_ARG);
@@ -109,11 +108,9 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
109108
ereport(elevel,
110109
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
111110
errmsg("relpages cannot be < -1")));
112-
table_close(crel,RowExclusiveLock);
113-
return false;
111+
result= false;
114112
}
115-
116-
if (relpages!=pgcform->relpages)
113+
elseif (relpages!=pgcform->relpages)
117114
{
118115
replaces[ncols]=Anum_pg_class_relpages;
119116
values[ncols]=Int32GetDatum(relpages);
@@ -130,16 +127,15 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
130127
ereport(elevel,
131128
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
132129
errmsg("reltuples cannot be < -1.0")));
133-
table_close(crel,RowExclusiveLock);
134-
return false;
130+
result= false;
135131
}
136-
137-
if (reltuples!=pgcform->reltuples)
132+
elseif (reltuples!=pgcform->reltuples)
138133
{
139134
replaces[ncols]=Anum_pg_class_reltuples;
140135
values[ncols]=Float4GetDatum(reltuples);
141136
ncols++;
142137
}
138+
143139
}
144140

145141
if (!PG_ARGISNULL(RELALLVISIBLE_ARG))
@@ -151,11 +147,9 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
151147
ereport(elevel,
152148
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
153149
errmsg("relallvisible cannot be < 0")));
154-
table_close(crel,RowExclusiveLock);
155-
return false;
150+
result= false;
156151
}
157-
158-
if (relallvisible!=pgcform->relallvisible)
152+
elseif (relallvisible!=pgcform->relallvisible)
159153
{
160154
replaces[ncols]=Anum_pg_class_relallvisible;
161155
values[ncols]=Int32GetDatum(relallvisible);
@@ -164,22 +158,20 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
164158
}
165159

166160
/* only update pg_class if there is a meaningful change */
167-
if (ncols==0)
161+
if (ncols>0)
168162
{
169-
table_close(crel,RowExclusiveLock);
170-
return false;
171-
}
172-
173-
newtup=heap_modify_tuple_by_cols(ctup,tupdesc,ncols,replaces,values,
174-
nulls);
163+
HeapTuplenewtup;
175164

176-
CatalogTupleUpdate(crel,&newtup->t_self,newtup);
177-
heap_freetuple(newtup);
165+
newtup=heap_modify_tuple_by_cols(ctup,tupdesc,ncols,replaces,values,
166+
nulls);
167+
CatalogTupleUpdate(crel,&newtup->t_self,newtup);
168+
heap_freetuple(newtup);
169+
}
178170

179171
/* release the lock, consistent with vac_update_relstats() */
180172
table_close(crel,RowExclusiveLock);
181173

182-
returntrue;
174+
returnresult;
183175
}
184176

185177
/*
@@ -215,3 +207,23 @@ pg_clear_relation_stats(PG_FUNCTION_ARGS)
215207
relation_statistics_update(newfcinfo,ERROR);
216208
PG_RETURN_VOID();
217209
}
210+
211+
Datum
212+
pg_restore_relation_stats(PG_FUNCTION_ARGS)
213+
{
214+
LOCAL_FCINFO(positional_fcinfo,NUM_RELATION_STATS_ARGS);
215+
boolresult= true;
216+
217+
InitFunctionCallInfoData(*positional_fcinfo,NULL,
218+
NUM_RELATION_STATS_ARGS,
219+
InvalidOid,NULL,NULL);
220+
221+
if (!stats_fill_fcinfo_from_arg_pairs(fcinfo,positional_fcinfo,
222+
relarginfo,WARNING))
223+
result= false;
224+
225+
if (!relation_statistics_update(positional_fcinfo,WARNING))
226+
result= false;
227+
228+
PG_RETURN_BOOL(result);
229+
}

‎src/backend/statistics/stat_utils.c

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

1919
#include"access/relation.h"
2020
#include"catalog/pg_database.h"
21+
#include"funcapi.h"
2122
#include"miscadmin.h"
2223
#include"statistics/stat_utils.h"
2324
#include"utils/acl.h"
@@ -165,3 +166,128 @@ stats_lock_check_privileges(Oid reloid)
165166

166167
relation_close(rel,NoLock);
167168
}
169+
170+
/*
171+
* Find the argument number for the given argument name, returning -1 if not
172+
* found.
173+
*/
174+
staticint
175+
get_arg_by_name(constchar*argname,structStatsArgInfo*arginfo,intelevel)
176+
{
177+
intargnum;
178+
179+
for (argnum=0;arginfo[argnum].argname!=NULL;argnum++)
180+
if (pg_strcasecmp(argname,arginfo[argnum].argname)==0)
181+
returnargnum;
182+
183+
ereport(elevel,
184+
(errmsg("unrecognized argument name: \"%s\"",argname)));
185+
186+
return-1;
187+
}
188+
189+
/*
190+
* Ensure that a given argument matched the expected type.
191+
*/
192+
staticbool
193+
stats_check_arg_type(constchar*argname,Oidargtype,Oidexpectedtype,intelevel)
194+
{
195+
if (argtype!=expectedtype)
196+
{
197+
ereport(elevel,
198+
(errmsg("argument \"%s\" has type \"%s\", expected type \"%s\"",
199+
argname,format_type_be(argtype),
200+
format_type_be(expectedtype))));
201+
return false;
202+
}
203+
204+
return true;
205+
}
206+
207+
/*
208+
* Translate variadic argument pairs from 'pairs_fcinfo' into a
209+
* 'positional_fcinfo' appropriate for calling relation_statistics_update() or
210+
* attribute_statistics_update() with positional arguments.
211+
*
212+
* Caller should have already initialized positional_fcinfo with a size
213+
* appropriate for calling the intended positional function, and arginfo
214+
* should also match the intended positional function.
215+
*/
216+
bool
217+
stats_fill_fcinfo_from_arg_pairs(FunctionCallInfopairs_fcinfo,
218+
FunctionCallInfopositional_fcinfo,
219+
structStatsArgInfo*arginfo,
220+
intelevel)
221+
{
222+
Datum*args;
223+
bool*argnulls;
224+
Oid*types;
225+
intnargs;
226+
boolresult= true;
227+
228+
/* clear positional args */
229+
for (inti=0;arginfo[i].argname!=NULL;i++)
230+
{
231+
positional_fcinfo->args[i].value= (Datum)0;
232+
positional_fcinfo->args[i].isnull= true;
233+
}
234+
235+
nargs=extract_variadic_args(pairs_fcinfo,0, true,
236+
&args,&types,&argnulls);
237+
238+
if (nargs %2!=0)
239+
ereport(ERROR,
240+
errmsg("variadic arguments must be name/value pairs"),
241+
errhint("Provide an even number of variadic arguments that can be divided into pairs."));
242+
243+
/*
244+
* For each argument name/value pair, find corresponding positional
245+
* argument for the argument name, and assign the argument value to
246+
* postitional_fcinfo.
247+
*/
248+
for (inti=0;i<nargs;i+=2)
249+
{
250+
intargnum;
251+
char*argname;
252+
253+
if (argnulls[i])
254+
ereport(ERROR,
255+
(errmsg("name at variadic position %d is NULL",i+1)));
256+
257+
if (types[i]!=TEXTOID)
258+
ereport(ERROR,
259+
(errmsg("name at variadic position %d has type \"%s\", expected type \"%s\"",
260+
i+1,format_type_be(types[i]),
261+
format_type_be(TEXTOID))));
262+
263+
if (argnulls[i+1])
264+
continue;
265+
266+
argname=TextDatumGetCString(args[i]);
267+
268+
/*
269+
* The 'version' argument is a special case, not handled by arginfo
270+
* because it's not a valid positional argument.
271+
*
272+
* For now, 'version' is accepted but ignored. In the future it can be
273+
* used to interpret older statistics properly.
274+
*/
275+
if (pg_strcasecmp(argname,"version")==0)
276+
continue;
277+
278+
argnum=get_arg_by_name(argname,arginfo,elevel);
279+
280+
if (argnum<0|| !stats_check_arg_type(argname,types[i+1],
281+
arginfo[argnum].argtype,
282+
elevel))
283+
{
284+
result= false;
285+
continue;
286+
}
287+
288+
positional_fcinfo->args[argnum].value=args[i+1];
289+
positional_fcinfo->args[argnum].isnull= false;
290+
}
291+
292+
returnresult;
293+
}

‎src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,6 @@
5757
*/
5858

5959
/*yyyymmddN */
60-
#defineCATALOG_VERSION_NO202410241
60+
#defineCATALOG_VERSION_NO202410242
6161

6262
#endif

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp