1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-20 05:03:10 +03:00

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
This commit is contained in:
Jeff Davis
2025-03-25 11:16:06 -07:00
parent 2a420f7995
commit 650ab8aaf1
11 changed files with 579 additions and 289 deletions

View File

@ -30364,14 +30364,15 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
<structname>mytable</structname>:
<programlisting>
SELECT pg_restore_relation_stats(
'relation', 'mytable'::regclass,
'schemaname', 'myschema',
'relname', 'mytable',
'relpages', 173::integer,
'reltuples', 10000::real);
</programlisting>
</para>
<para>
The argument <literal>relation</literal> with a value of type
<type>regclass</type> is required, and specifies the table. Other
The arguments <literal>schemaname</literal> and
<literal>relname</literal> are required, and specify the table. Other
arguments are the names and values of statistics corresponding to
certain columns in <link
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
<indexterm>
<primary>pg_clear_relation_stats</primary>
</indexterm>
<function>pg_clear_relation_stats</function> ( <parameter>relation</parameter> <type>regclass</type> )
<function>pg_clear_relation_stats</function> ( <parameter>schemaname</parameter> <type>text</type>, <parameter>relname</parameter> <type>text</type> )
<returnvalue>void</returnvalue>
</para>
<para>
@ -30457,22 +30458,23 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
<structname>mytable</structname>:
<programlisting>
SELECT pg_restore_attribute_stats(
'relation', 'mytable'::regclass,
'attname', 'col1'::name,
'schemaname', 'myschema',
'relname', 'mytable',
'attname', 'col1',
'inherited', false,
'avg_width', 125::integer,
'null_frac', 0.5::real);
</programlisting>
</para>
<para>
The required arguments are <literal>relation</literal> with a value
of type <type>regclass</type>, which specifies the table; either
<literal>attname</literal> with a value of type <type>name</type> or
<literal>attnum</literal> with a value of type <type>smallint</type>,
which specifies the column; and <literal>inherited</literal>, which
specifies whether the statistics include values from child tables.
Other arguments are the names and values of statistics corresponding
to columns in <link
The required arguments are <literal>schemaname</literal> and
<literal>relname</literal> with a value of type <type>text</type>
which specify the table; either <literal>attname</literal> with a
value of type <type>text</type> or <literal>attnum</literal> with a
value of type <type>smallint</type>, which specifies the column; and
<literal>inherited</literal>, which specifies whether the statistics
include values from child tables. Other arguments are the names and
values of statistics corresponding to columns in <link
linkend="view-pg-stats"><structname>pg_stats</structname></link>.
</para>
<para>
@ -30502,8 +30504,9 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
<primary>pg_clear_attribute_stats</primary>
</indexterm>
<function>pg_clear_attribute_stats</function> (
<parameter>relation</parameter> <type>regclass</type>,
<parameter>attname</parameter> <type>name</type>,
<parameter>schemaname</parameter> <type>text</type>,
<parameter>relname</parameter> <type>text</type>,
<parameter>attname</parameter> <type>text</type>,
<parameter>inherited</parameter> <type>boolean</type> )
<returnvalue>void</returnvalue>
</para>

View File

@ -36,7 +36,8 @@
enum attribute_stats_argnum
{
ATTRELATION_ARG = 0,
ATTRELSCHEMA_ARG = 0,
ATTRELNAME_ARG,
ATTNAME_ARG,
ATTNUM_ARG,
INHERITED_ARG,
@ -58,8 +59,9 @@ enum attribute_stats_argnum
static struct StatsArgInfo attarginfo[] =
{
[ATTRELATION_ARG] = {"relation", REGCLASSOID},
[ATTNAME_ARG] = {"attname", NAMEOID},
[ATTRELSCHEMA_ARG] = {"schemaname", TEXTOID},
[ATTRELNAME_ARG] = {"relname", TEXTOID},
[ATTNAME_ARG] = {"attname", TEXTOID},
[ATTNUM_ARG] = {"attnum", INT2OID},
[INHERITED_ARG] = {"inherited", BOOLOID},
[NULL_FRAC_ARG] = {"null_frac", FLOAT4OID},
@ -80,7 +82,8 @@ static struct StatsArgInfo attarginfo[] =
enum clear_attribute_stats_argnum
{
C_ATTRELATION_ARG = 0,
C_ATTRELSCHEMA_ARG = 0,
C_ATTRELNAME_ARG,
C_ATTNAME_ARG,
C_INHERITED_ARG,
C_NUM_ATTRIBUTE_STATS_ARGS
@ -88,8 +91,9 @@ enum clear_attribute_stats_argnum
static struct StatsArgInfo cleararginfo[] =
{
[C_ATTRELATION_ARG] = {"relation", REGCLASSOID},
[C_ATTNAME_ARG] = {"attname", NAMEOID},
[C_ATTRELSCHEMA_ARG] = {"relation", TEXTOID},
[C_ATTRELNAME_ARG] = {"relation", TEXTOID},
[C_ATTNAME_ARG] = {"attname", TEXTOID},
[C_INHERITED_ARG] = {"inherited", BOOLOID},
[C_NUM_ATTRIBUTE_STATS_ARGS] = {0}
};
@ -133,6 +137,8 @@ static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
static bool
attribute_statistics_update(FunctionCallInfo fcinfo)
{
char *nspname;
char *relname;
Oid reloid;
char *attname;
AttrNumber attnum;
@ -170,8 +176,13 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
bool result = true;
stats_check_required_arg(fcinfo, attarginfo, ATTRELATION_ARG);
reloid = PG_GETARG_OID(ATTRELATION_ARG);
stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG);
stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG);
nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELSCHEMA_ARG));
relname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELNAME_ARG));
reloid = stats_lookup_relid(nspname, relname);
if (RecoveryInProgress())
ereport(ERROR,
@ -185,21 +196,18 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
/* user can specify either attname or attnum, but not both */
if (!PG_ARGISNULL(ATTNAME_ARG))
{
Name attnamename;
if (!PG_ARGISNULL(ATTNUM_ARG))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot specify both attname and attnum")));
attnamename = PG_GETARG_NAME(ATTNAME_ARG);
attname = NameStr(*attnamename);
attname = TextDatumGetCString(PG_GETARG_DATUM(ATTNAME_ARG));
attnum = get_attnum(reloid, attname);
/* note that this test covers attisdropped cases too: */
if (attnum == InvalidAttrNumber)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
attname, get_rel_name(reloid))));
attname, relname)));
}
else if (!PG_ARGISNULL(ATTNUM_ARG))
{
@ -211,7 +219,7 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column %d of relation \"%s\" does not exist",
attnum, get_rel_name(reloid))));
attnum, relname)));
}
else
{
@ -900,13 +908,22 @@ init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
Datum
pg_clear_attribute_stats(PG_FUNCTION_ARGS)
{
char *nspname;
char *relname;
Oid reloid;
Name attname;
char *attname;
AttrNumber attnum;
bool inherited;
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELATION_ARG);
reloid = PG_GETARG_OID(C_ATTRELATION_ARG);
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELSCHEMA_ARG);
stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELNAME_ARG);
stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG);
stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG);
nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELSCHEMA_ARG));
relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELNAME_ARG));
reloid = stats_lookup_relid(nspname, relname);
if (RecoveryInProgress())
ereport(ERROR,
@ -916,23 +933,21 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
stats_lock_check_privileges(reloid);
stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG);
attname = PG_GETARG_NAME(C_ATTNAME_ARG);
attnum = get_attnum(reloid, NameStr(*attname));
attname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTNAME_ARG));
attnum = get_attnum(reloid, attname);
if (attnum < 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot clear statistics on system column \"%s\"",
NameStr(*attname))));
attname)));
if (attnum == InvalidAttrNumber)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
NameStr(*attname), get_rel_name(reloid))));
attname, get_rel_name(reloid))));
stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG);
inherited = PG_GETARG_BOOL(C_INHERITED_ARG);
delete_pg_statistic(reloid, attnum, inherited);

View File

@ -19,9 +19,12 @@
#include "access/heapam.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "statistics/stat_utils.h"
#include "utils/builtins.h"
#include "utils/fmgroids.h"
#include "utils/fmgrprotos.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
@ -32,7 +35,8 @@
enum relation_stats_argnum
{
RELATION_ARG = 0,
RELSCHEMA_ARG = 0,
RELNAME_ARG,
RELPAGES_ARG,
RELTUPLES_ARG,
RELALLVISIBLE_ARG,
@ -42,7 +46,8 @@ enum relation_stats_argnum
static struct StatsArgInfo relarginfo[] =
{
[RELATION_ARG] = {"relation", REGCLASSOID},
[RELSCHEMA_ARG] = {"schemaname", TEXTOID},
[RELNAME_ARG] = {"relname", TEXTOID},
[RELPAGES_ARG] = {"relpages", INT4OID},
[RELTUPLES_ARG] = {"reltuples", FLOAT4OID},
[RELALLVISIBLE_ARG] = {"relallvisible", INT4OID},
@ -59,6 +64,8 @@ static bool
relation_statistics_update(FunctionCallInfo fcinfo)
{
bool result = true;
char *nspname;
char *relname;
Oid reloid;
Relation crel;
BlockNumber relpages = 0;
@ -76,6 +83,22 @@ relation_statistics_update(FunctionCallInfo fcinfo)
bool nulls[4] = {0};
int nreplaces = 0;
stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG);
stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG);
nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
relname = TextDatumGetCString(PG_GETARG_DATUM(RELNAME_ARG));
reloid = stats_lookup_relid(nspname, relname);
if (RecoveryInProgress())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
errhint("Statistics cannot be modified during recovery.")));
stats_lock_check_privileges(reloid);
if (!PG_ARGISNULL(RELPAGES_ARG))
{
relpages = PG_GETARG_UINT32(RELPAGES_ARG);
@ -108,17 +131,6 @@ relation_statistics_update(FunctionCallInfo fcinfo)
update_relallfrozen = true;
}
stats_check_required_arg(fcinfo, relarginfo, RELATION_ARG);
reloid = PG_GETARG_OID(RELATION_ARG);
if (RecoveryInProgress())
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
errhint("Statistics cannot be modified during recovery.")));
stats_lock_check_privileges(reloid);
/*
* Take RowExclusiveLock on pg_class, consistent with
* vac_update_relstats().
@ -187,20 +199,22 @@ relation_statistics_update(FunctionCallInfo fcinfo)
Datum
pg_clear_relation_stats(PG_FUNCTION_ARGS)
{
LOCAL_FCINFO(newfcinfo, 5);
LOCAL_FCINFO(newfcinfo, 6);
InitFunctionCallInfoData(*newfcinfo, NULL, 5, InvalidOid, NULL, NULL);
InitFunctionCallInfoData(*newfcinfo, NULL, 6, InvalidOid, NULL, NULL);
newfcinfo->args[0].value = PG_GETARG_OID(0);
newfcinfo->args[0].value = PG_GETARG_DATUM(0);
newfcinfo->args[0].isnull = PG_ARGISNULL(0);
newfcinfo->args[1].value = UInt32GetDatum(0);
newfcinfo->args[1].isnull = false;
newfcinfo->args[2].value = Float4GetDatum(-1.0);
newfcinfo->args[1].value = PG_GETARG_DATUM(1);
newfcinfo->args[1].isnull = PG_ARGISNULL(1);
newfcinfo->args[2].value = UInt32GetDatum(0);
newfcinfo->args[2].isnull = false;
newfcinfo->args[3].value = UInt32GetDatum(0);
newfcinfo->args[3].value = Float4GetDatum(-1.0);
newfcinfo->args[3].isnull = false;
newfcinfo->args[4].value = UInt32GetDatum(0);
newfcinfo->args[4].isnull = false;
newfcinfo->args[5].value = UInt32GetDatum(0);
newfcinfo->args[5].isnull = false;
relation_statistics_update(newfcinfo);
PG_RETURN_VOID();

View File

@ -18,6 +18,7 @@
#include "access/relation.h"
#include "catalog/index.h"
#include "catalog/namespace.h"
#include "catalog/pg_database.h"
#include "funcapi.h"
#include "miscadmin.h"
@ -213,6 +214,27 @@ stats_lock_check_privileges(Oid reloid)
relation_close(table, NoLock);
}
/*
* Lookup relation oid from schema and relation name.
*/
Oid
stats_lookup_relid(const char *nspname, const char *relname)
{
Oid nspoid;
Oid reloid;
nspoid = LookupExplicitNamespace(nspname, false);
reloid = get_relname_relid(relname, nspoid);
if (!OidIsValid(reloid))
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_TABLE),
errmsg("relation \"%s.%s\" does not exist",
nspname, relname)));
return reloid;
}
/*
* Find the argument number for the given argument name, returning -1 if not
* found.

View File

@ -10498,7 +10498,6 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
PQExpBuffer out;
DumpId *deps = NULL;
int ndeps = 0;
char *qualified_name;
int i_attname;
int i_inherited;
int i_null_frac;
@ -10563,15 +10562,16 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
out = createPQExpBuffer();
qualified_name = pg_strdup(fmtQualifiedDumpable(rsinfo));
/* restore relation stats */
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_relation_stats(\n");
appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
fout->remoteVersion);
appendPQExpBufferStr(out, "\t'relation', ");
appendStringLiteralAH(out, qualified_name, fout);
appendPQExpBufferStr(out, "::regclass,\n");
appendPQExpBufferStr(out, "\t'schemaname', ");
appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout);
appendPQExpBufferStr(out, ",\n");
appendPQExpBufferStr(out, "\t'relname', ");
appendStringLiteralAH(out, rsinfo->dobj.name, fout);
appendPQExpBufferStr(out, ",\n");
appendPQExpBuffer(out, "\t'relpages', '%d'::integer,\n", rsinfo->relpages);
appendPQExpBuffer(out, "\t'reltuples', '%s'::real,\n", rsinfo->reltuples);
appendPQExpBuffer(out, "\t'relallvisible', '%d'::integer\n);\n",
@ -10610,9 +10610,10 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
appendPQExpBufferStr(out, "SELECT * FROM pg_catalog.pg_restore_attribute_stats(\n");
appendPQExpBuffer(out, "\t'version', '%u'::integer,\n",
fout->remoteVersion);
appendPQExpBufferStr(out, "\t'relation', ");
appendStringLiteralAH(out, qualified_name, fout);
appendPQExpBufferStr(out, "::regclass");
appendPQExpBufferStr(out, "\t'schemaname', ");
appendStringLiteralAH(out, rsinfo->dobj.namespace->dobj.name, fout);
appendPQExpBufferStr(out, ",\n\t'relname', ");
appendStringLiteralAH(out, rsinfo->dobj.name, fout);
if (PQgetisnull(res, rownum, i_attname))
pg_fatal("attname cannot be NULL");
@ -10624,7 +10625,10 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
* their attnames are not necessarily stable across dump/reload.
*/
if (rsinfo->nindAttNames == 0)
appendNamedArgument(out, fout, "attname", "name", attname);
{
appendPQExpBuffer(out, ",\n\t'attname', ");
appendStringLiteralAH(out, attname, fout);
}
else
{
bool found = false;
@ -10704,7 +10708,6 @@ dumpRelationStats(Archive *fout, const RelStatsInfo *rsinfo)
.deps = deps,
.nDeps = ndeps));
free(qualified_name);
destroyPQExpBuffer(out);
destroyPQExpBuffer(query);
}

View File

@ -4741,14 +4741,16 @@ my %tests = (
regexp => qr/^
\QSELECT * FROM pg_catalog.pg_restore_relation_stats(\E\s+
'version',\s'\d+'::integer,\s+
'relation',\s'dump_test.dup_test_post_data_ix'::regclass,\s+
'schemaname',\s'dump_test',\s+
'relname',\s'dup_test_post_data_ix',\s+
'relpages',\s'\d+'::integer,\s+
'reltuples',\s'\d+'::real,\s+
'relallvisible',\s'\d+'::integer\s+
\);\s+
\QSELECT * FROM pg_catalog.pg_restore_attribute_stats(\E\s+
'version',\s'\d+'::integer,\s+
'relation',\s'dump_test.dup_test_post_data_ix'::regclass,\s+
'schemaname',\s'dump_test',\s+
'relname',\s'dup_test_post_data_ix',\s+
'attnum',\s'2'::smallint,\s+
'inherited',\s'f'::boolean,\s+
'null_frac',\s'0'::real,\s+

View File

@ -57,6 +57,6 @@
*/
/* yyyymmddN */
#define CATALOG_VERSION_NO 202503241
#define CATALOG_VERSION_NO 202503251
#endif

View File

@ -12453,8 +12453,8 @@
descr => 'clear statistics on relation',
proname => 'pg_clear_relation_stats', provolatile => 'v', proisstrict => 'f',
proparallel => 'u', prorettype => 'void',
proargtypes => 'regclass',
proargnames => '{relation}',
proargtypes => 'text text',
proargnames => '{schemaname,relname}',
prosrc => 'pg_clear_relation_stats' },
{ oid => '8461',
descr => 'restore statistics on attribute',
@ -12469,8 +12469,8 @@
descr => 'clear statistics on attribute',
proname => 'pg_clear_attribute_stats', provolatile => 'v', proisstrict => 'f',
proparallel => 'u', prorettype => 'void',
proargtypes => 'regclass name bool',
proargnames => '{relation,attname,inherited}',
proargtypes => 'text text text bool',
proargnames => '{schemaname,relname,attname,inherited}',
prosrc => 'pg_clear_attribute_stats' },
# GiST stratnum implementations

View File

@ -32,6 +32,8 @@ extern bool stats_check_arg_pair(FunctionCallInfo fcinfo,
extern void stats_lock_check_privileges(Oid reloid);
extern Oid stats_lookup_relid(const char *nspname, const char *relname);
extern bool stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
FunctionCallInfo positional_fcinfo,
struct StatsArgInfo *arginfo);

View File

@ -14,7 +14,8 @@ CREATE TABLE stats_import.test(
) WITH (autovacuum_enabled = false);
SELECT
pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', 18::integer,
'reltuples', 21::real,
'relallvisible', 24::integer,
@ -36,7 +37,7 @@ ORDER BY relname;
test | 18 | 21 | 24 | 27
(1 row)
SELECT pg_clear_relation_stats('stats_import.test'::regclass);
SELECT pg_clear_relation_stats('stats_import', 'test');
pg_clear_relation_stats
-------------------------
@ -45,33 +46,49 @@ SELECT pg_clear_relation_stats('stats_import.test'::regclass);
--
-- relstats tests
--
--- error: relation is wrong type
-- error: schemaname missing
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 0::oid,
'relname', 'test',
'relpages', 17::integer);
WARNING: argument "relation" has type "oid", expected type "regclass"
ERROR: "relation" cannot be NULL
ERROR: "schemaname" cannot be NULL
-- error: relname missing
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relpages', 17::integer);
ERROR: "relname" cannot be NULL
--- error: schemaname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 3.6::float,
'relname', 'test',
'relpages', 17::integer);
WARNING: argument "schemaname" has type "double precision", expected type "text"
ERROR: "schemaname" cannot be NULL
--- error: relname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 0::oid,
'relpages', 17::integer);
WARNING: argument "relname" has type "oid", expected type "text"
ERROR: "relname" cannot be NULL
-- error: relation not found
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 0::oid::regclass,
'schemaname', 'stats_import',
'relname', 'nope',
'relpages', 17::integer);
ERROR: could not open relation with OID 0
ERROR: relation "stats_import.nope" does not exist
-- error: odd number of variadic arguments cannot be pairs
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible');
ERROR: variadic arguments must be name/value pairs
HINT: Provide an even number of variadic arguments that can be divided into pairs.
-- error: argument name is NULL
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
NULL, '17'::integer);
ERROR: name at variadic position 3 is NULL
-- error: argument name is not a text type
SELECT pg_restore_relation_stats(
'relation', '0'::oid::regclass,
17, '17'::integer);
ERROR: name at variadic position 3 has type "integer", expected type "text"
ERROR: name at variadic position 5 is NULL
-- starting stats
SELECT relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
@ -84,7 +101,8 @@ WHERE oid = 'stats_import.test_i'::regclass;
-- regular indexes have special case locking rules
BEGIN;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.test_i'::regclass,
'schemaname', 'stats_import',
'relname', 'test_i',
'relpages', 18::integer);
pg_restore_relation_stats
---------------------------
@ -132,7 +150,8 @@ WHERE oid = 'stats_import.part_parent'::regclass;
--
BEGIN;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.part_parent_i'::regclass,
'schemaname', 'stats_import',
'relname', 'part_parent_i',
'relpages', 2::integer);
pg_restore_relation_stats
---------------------------
@ -166,7 +185,8 @@ WHERE oid = 'stats_import.part_parent_i'::regclass;
-- ok: set all relstats, with version, no bounds checking
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'version', 150000::integer,
'relpages', '-17'::integer,
'reltuples', 400::real,
@ -187,7 +207,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just relpages, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', '16'::integer);
pg_restore_relation_stats
---------------------------
@ -204,7 +225,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just reltuples, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'reltuples', '500'::real);
pg_restore_relation_stats
---------------------------
@ -221,7 +243,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just relallvisible, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible', 5::integer);
pg_restore_relation_stats
---------------------------
@ -238,7 +261,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: just relallfrozen
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'version', 150000::integer,
'relallfrozen', 3::integer);
pg_restore_relation_stats
@ -256,7 +280,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- warn: bad relpages type, rest updated
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', 'nope'::text,
'reltuples', 400.0::real,
'relallvisible', 4::integer,
@ -277,7 +302,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- unrecognized argument name, rest ok
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', '171'::integer,
'nope', 10::integer);
WARNING: unrecognized argument name: "nope"
@ -295,8 +321,7 @@ WHERE oid = 'stats_import.test'::regclass;
(1 row)
-- ok: clear stats
SELECT pg_catalog.pg_clear_relation_stats(
relation => 'stats_import.test'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'test');
pg_clear_relation_stats
-------------------------
@ -313,50 +338,71 @@ WHERE oid = 'stats_import.test'::regclass;
-- invalid relkinds for statistics
CREATE SEQUENCE stats_import.testseq;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.testseq'::regclass);
'schemaname', 'stats_import',
'relname', 'testseq');
ERROR: cannot modify statistics for relation "testseq"
DETAIL: This operation is not supported for sequences.
SELECT pg_catalog.pg_clear_relation_stats(
'stats_import.testseq'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testseq');
ERROR: cannot modify statistics for relation "testseq"
DETAIL: This operation is not supported for sequences.
CREATE VIEW stats_import.testview AS SELECT * FROM stats_import.test;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.testview'::regclass);
ERROR: cannot modify statistics for relation "testview"
DETAIL: This operation is not supported for views.
SELECT pg_catalog.pg_clear_relation_stats(
'stats_import.testview'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testview');
ERROR: cannot modify statistics for relation "testview"
DETAIL: This operation is not supported for views.
--
-- attribute stats
--
-- error: object does not exist
-- error: schemaname missing
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', '0'::oid::regclass,
'attname', 'id'::name,
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: could not open relation with OID 0
-- error: relation null
ERROR: "schemaname" cannot be NULL
-- error: schema does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', NULL::oid::regclass,
'attname', 'id'::name,
'schemaname', 'nope',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: "relation" cannot be NULL
ERROR: schema "nope" does not exist
-- error: relname missing
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: "relname" cannot be NULL
-- error: relname does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'nope',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: relation "stats_import.nope" does not exist
-- error: relname null
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', NULL,
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: "relname" cannot be NULL
-- error: NULL attname
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', NULL::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', NULL,
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: must specify either attname or attnum
-- error: attname doesn't exist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'nope'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'nope',
'inherited', false::boolean,
'null_frac', 0.1::real,
'avg_width', 2::integer,
@ -364,36 +410,41 @@ SELECT pg_catalog.pg_restore_attribute_stats(
ERROR: column "nope" of relation "test" does not exist
-- error: both attname and attnum
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: cannot specify both attname and attnum
-- error: neither attname nor attnum
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: must specify either attname or attnum
-- error: attribute is system column
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'xmin'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'xmin',
'inherited', false::boolean,
'null_frac', 0.1::real);
ERROR: cannot modify statistics on system column "xmin"
-- error: inherited null
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', NULL::boolean,
'null_frac', 0.1::real);
ERROR: "inherited" cannot be NULL
-- ok: just the fixed values, with version, no stakinds
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'version', 150000::integer,
'null_frac', 0.2::real,
@ -421,7 +472,8 @@ AND attname = 'id';
-- for any stat-having relation.
--
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.4::real);
@ -443,8 +495,9 @@ AND attname = 'id';
-- warn: unrecognized argument name, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.2::real,
'nope', 0.5::real);
@ -467,8 +520,9 @@ AND attname = 'id';
-- warn: mcv / mcf null mismatch part 1, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.21::real,
'most_common_freqs', '{0.1,0.2,0.3}'::real[]
@ -492,8 +546,9 @@ AND attname = 'id';
-- warn: mcv / mcf null mismatch part 2, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.21::real,
'most_common_vals', '{1,2,3}'::text
@ -517,8 +572,9 @@ AND attname = 'id';
-- warn: mcf type mismatch, mcv-pair fails, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.22::real,
'most_common_vals', '{2,1,3}'::text,
@ -544,8 +600,9 @@ AND attname = 'id';
-- warn: mcv cast failure, mcv-pair fails, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.23::real,
'most_common_vals', '{2,four,3}'::text,
@ -570,8 +627,9 @@ AND attname = 'id';
-- ok: mcv+mcf
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'most_common_vals', '{2,1,3}'::text,
'most_common_freqs', '{0.3,0.25,0.05}'::real[]
@ -594,8 +652,9 @@ AND attname = 'id';
-- warn: NULL in histogram array, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.24::real,
'histogram_bounds', '{1,NULL,3,4}'::text
@ -619,8 +678,9 @@ AND attname = 'id';
-- ok: histogram_bounds
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'histogram_bounds', '{1,2,3,4}'::text
);
@ -642,8 +702,9 @@ AND attname = 'id';
-- warn: elem_count_histogram null element, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.25::real,
'elem_count_histogram', '{1,1,NULL,1,1,1,1,1}'::real[]
@ -667,8 +728,9 @@ AND attname = 'tags';
-- ok: elem_count_histogram
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.26::real,
'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}'::real[]
@ -691,8 +753,9 @@ AND attname = 'tags';
-- warn: range stats on a scalar type, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.27::real,
'range_empty_frac', 0.5::real,
@ -718,8 +781,9 @@ AND attname = 'id';
-- warn: range_empty_frac range_length_hist null mismatch, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.28::real,
'range_length_histogram', '{399,499,Infinity}'::text
@ -743,8 +807,9 @@ AND attname = 'arange';
-- warn: range_empty_frac range_length_hist null mismatch part 2, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.29::real,
'range_empty_frac', 0.5::real
@ -768,8 +833,9 @@ AND attname = 'arange';
-- ok: range_empty_frac + range_length_hist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'range_empty_frac', 0.5::real,
'range_length_histogram', '{399,499,Infinity}'::text
@ -792,8 +858,9 @@ AND attname = 'arange';
-- warn: range bounds histogram on scalar, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.31::real,
'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text
@ -818,8 +885,9 @@ AND attname = 'id';
-- ok: range_bounds_histogram
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text
);
@ -841,8 +909,9 @@ AND attname = 'arange';
-- warn: cannot set most_common_elems for range type, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.32::real,
'most_common_elems', '{3,1}'::text,
@ -868,8 +937,9 @@ AND attname = 'arange';
-- warn: scalars can't have mcelem, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.33::real,
'most_common_elems', '{1,3}'::text,
@ -895,8 +965,9 @@ AND attname = 'id';
-- warn: mcelem / mcelem mismatch, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.34::real,
'most_common_elems', '{one,two}'::text
@ -920,8 +991,9 @@ AND attname = 'tags';
-- warn: mcelem / mcelem null mismatch part 2, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.35::real,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3}'::real[]
@ -945,8 +1017,9 @@ AND attname = 'tags';
-- ok: mcelem
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'most_common_elems', '{one,three}'::text,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[]
@ -969,8 +1042,9 @@ AND attname = 'tags';
-- warn: scalars can't have elem_count_histogram, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.36::real,
'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1}'::real[]
@ -1022,8 +1096,9 @@ SELECT s.schemaname, s.tablename, s.attname, s.inherited, r.*
FROM pg_catalog.pg_stats AS s
CROSS JOIN LATERAL
pg_catalog.pg_restore_attribute_stats(
'relation', ('stats_import.' || s.tablename || '_clone')::regclass,
'attname', s.attname,
'schemaname', 'stats_import',
'relname', s.tablename::text || '_clone',
'attname', s.attname::text,
'inherited', s.inherited,
'version', 150000,
'null_frac', s.null_frac,
@ -1200,9 +1275,10 @@ AND attname = 'arange';
(1 row)
SELECT pg_catalog.pg_clear_attribute_stats(
relation => 'stats_import.test'::regclass,
attname => 'arange'::name,
inherited => false::boolean);
schemaname => 'stats_import',
relname => 'test',
attname => 'arange',
inherited => false);
pg_clear_attribute_stats
--------------------------
@ -1219,6 +1295,53 @@ AND attname = 'arange';
0
(1 row)
-- temp tables
CREATE TEMP TABLE stats_temp(i int);
SELECT pg_restore_relation_stats(
'schemaname', 'pg_temp',
'relname', 'stats_temp',
'relpages', '-19'::integer,
'reltuples', 401::real,
'relallvisible', 5::integer,
'relallfrozen', 3::integer);
pg_restore_relation_stats
---------------------------
t
(1 row)
SELECT relname, relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
WHERE oid = 'pg_temp.stats_temp'::regclass
ORDER BY relname;
relname | relpages | reltuples | relallvisible | relallfrozen
------------+----------+-----------+---------------+--------------
stats_temp | -19 | 401 | 5 | 3
(1 row)
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'pg_temp',
'relname', 'stats_temp',
'attname', 'i',
'inherited', false::boolean,
'null_frac', 0.0123::real
);
pg_restore_attribute_stats
----------------------------
t
(1 row)
SELECT tablename, null_frac
FROM pg_stats
WHERE schemaname like 'pg_temp%'
AND tablename = 'stats_temp'
AND inherited = false
AND attname = 'i';
tablename | null_frac
------------+-----------
stats_temp | 0.0123
(1 row)
DROP TABLE stats_temp;
DROP SCHEMA stats_import CASCADE;
NOTICE: drop cascades to 6 other objects
DETAIL: drop cascades to type stats_import.complex_type

View File

@ -17,7 +17,8 @@ CREATE TABLE stats_import.test(
SELECT
pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', 18::integer,
'reltuples', 21::real,
'relallvisible', 24::integer,
@ -32,37 +33,52 @@ FROM pg_class
WHERE oid = 'stats_import.test'::regclass
ORDER BY relname;
SELECT pg_clear_relation_stats('stats_import.test'::regclass);
SELECT pg_clear_relation_stats('stats_import', 'test');
--
-- relstats tests
--
--- error: relation is wrong type
-- error: schemaname missing
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 0::oid,
'relname', 'test',
'relpages', 17::integer);
-- error: relname missing
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relpages', 17::integer);
--- error: schemaname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 3.6::float,
'relname', 'test',
'relpages', 17::integer);
--- error: relname is wrong type
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 0::oid,
'relpages', 17::integer);
-- error: relation not found
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 0::oid::regclass,
'schemaname', 'stats_import',
'relname', 'nope',
'relpages', 17::integer);
-- error: odd number of variadic arguments cannot be pairs
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible');
-- error: argument name is NULL
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
NULL, '17'::integer);
-- error: argument name is not a text type
SELECT pg_restore_relation_stats(
'relation', '0'::oid::regclass,
17, '17'::integer);
-- starting stats
SELECT relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
@ -71,7 +87,8 @@ WHERE oid = 'stats_import.test_i'::regclass;
-- regular indexes have special case locking rules
BEGIN;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.test_i'::regclass,
'schemaname', 'stats_import',
'relname', 'test_i',
'relpages', 18::integer);
SELECT mode FROM pg_locks
@ -108,7 +125,8 @@ WHERE oid = 'stats_import.part_parent'::regclass;
BEGIN;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.part_parent_i'::regclass,
'schemaname', 'stats_import',
'relname', 'part_parent_i',
'relpages', 2::integer);
SELECT mode FROM pg_locks
@ -127,7 +145,8 @@ WHERE oid = 'stats_import.part_parent_i'::regclass;
-- ok: set all relstats, with version, no bounds checking
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'version', 150000::integer,
'relpages', '-17'::integer,
'reltuples', 400::real,
@ -140,7 +159,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just relpages, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', '16'::integer);
SELECT relpages, reltuples, relallvisible, relallfrozen
@ -149,7 +169,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just reltuples, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'reltuples', '500'::real);
SELECT relpages, reltuples, relallvisible, relallfrozen
@ -158,7 +179,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: set just relallvisible, rest stay same
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible', 5::integer);
SELECT relpages, reltuples, relallvisible, relallfrozen
@ -167,7 +189,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- ok: just relallfrozen
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'version', 150000::integer,
'relallfrozen', 3::integer);
@ -177,7 +200,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- warn: bad relpages type, rest updated
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', 'nope'::text,
'reltuples', 400.0::real,
'relallvisible', 4::integer,
@ -189,7 +213,8 @@ WHERE oid = 'stats_import.test'::regclass;
-- unrecognized argument name, rest ok
SELECT pg_restore_relation_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'relpages', '171'::integer,
'nope', 10::integer);
@ -198,8 +223,7 @@ FROM pg_class
WHERE oid = 'stats_import.test'::regclass;
-- ok: clear stats
SELECT pg_catalog.pg_clear_relation_stats(
relation => 'stats_import.test'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'test');
SELECT relpages, reltuples, relallvisible
FROM pg_class
@ -209,48 +233,70 @@ WHERE oid = 'stats_import.test'::regclass;
CREATE SEQUENCE stats_import.testseq;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.testseq'::regclass);
'schemaname', 'stats_import',
'relname', 'testseq');
SELECT pg_catalog.pg_clear_relation_stats(
'stats_import.testseq'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testseq');
CREATE VIEW stats_import.testview AS SELECT * FROM stats_import.test;
SELECT pg_catalog.pg_restore_relation_stats(
'relation', 'stats_import.testview'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(
'stats_import.testview'::regclass);
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testview');
--
-- attribute stats
--
-- error: object does not exist
-- error: schemaname missing
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', '0'::oid::regclass,
'attname', 'id'::name,
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: relation null
-- error: schema does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', NULL::oid::regclass,
'attname', 'id'::name,
'schemaname', 'nope',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: relname missing
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: relname does not exist
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'nope',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: relname null
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', NULL,
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: NULL attname
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', NULL::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', NULL,
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: attname doesn't exist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'nope'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'nope',
'inherited', false::boolean,
'null_frac', 0.1::real,
'avg_width', 2::integer,
@ -258,36 +304,41 @@ SELECT pg_catalog.pg_restore_attribute_stats(
-- error: both attname and attnum
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: neither attname nor attnum
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: attribute is system column
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'xmin'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'xmin',
'inherited', false::boolean,
'null_frac', 0.1::real);
-- error: inherited null
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', NULL::boolean,
'null_frac', 0.1::real);
-- ok: just the fixed values, with version, no stakinds
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'version', 150000::integer,
'null_frac', 0.2::real,
@ -307,7 +358,8 @@ AND attname = 'id';
-- for any stat-having relation.
--
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'schemaname', 'stats_import',
'relname', 'test',
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.4::real);
@ -321,8 +373,9 @@ AND attname = 'id';
-- warn: unrecognized argument name, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.2::real,
'nope', 0.5::real);
@ -336,8 +389,9 @@ AND attname = 'id';
-- warn: mcv / mcf null mismatch part 1, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.21::real,
'most_common_freqs', '{0.1,0.2,0.3}'::real[]
@ -352,8 +406,9 @@ AND attname = 'id';
-- warn: mcv / mcf null mismatch part 2, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.21::real,
'most_common_vals', '{1,2,3}'::text
@ -368,8 +423,9 @@ AND attname = 'id';
-- warn: mcf type mismatch, mcv-pair fails, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.22::real,
'most_common_vals', '{2,1,3}'::text,
@ -385,8 +441,9 @@ AND attname = 'id';
-- warn: mcv cast failure, mcv-pair fails, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.23::real,
'most_common_vals', '{2,four,3}'::text,
@ -402,8 +459,9 @@ AND attname = 'id';
-- ok: mcv+mcf
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'most_common_vals', '{2,1,3}'::text,
'most_common_freqs', '{0.3,0.25,0.05}'::real[]
@ -418,8 +476,9 @@ AND attname = 'id';
-- warn: NULL in histogram array, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.24::real,
'histogram_bounds', '{1,NULL,3,4}'::text
@ -434,8 +493,9 @@ AND attname = 'id';
-- ok: histogram_bounds
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'histogram_bounds', '{1,2,3,4}'::text
);
@ -449,8 +509,9 @@ AND attname = 'id';
-- warn: elem_count_histogram null element, rest get set
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.25::real,
'elem_count_histogram', '{1,1,NULL,1,1,1,1,1}'::real[]
@ -465,8 +526,9 @@ AND attname = 'tags';
-- ok: elem_count_histogram
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.26::real,
'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}'::real[]
@ -481,8 +543,9 @@ AND attname = 'tags';
-- warn: range stats on a scalar type, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.27::real,
'range_empty_frac', 0.5::real,
@ -498,8 +561,9 @@ AND attname = 'id';
-- warn: range_empty_frac range_length_hist null mismatch, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.28::real,
'range_length_histogram', '{399,499,Infinity}'::text
@ -514,8 +578,9 @@ AND attname = 'arange';
-- warn: range_empty_frac range_length_hist null mismatch part 2, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.29::real,
'range_empty_frac', 0.5::real
@ -530,8 +595,9 @@ AND attname = 'arange';
-- ok: range_empty_frac + range_length_hist
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'range_empty_frac', 0.5::real,
'range_length_histogram', '{399,499,Infinity}'::text
@ -546,8 +612,9 @@ AND attname = 'arange';
-- warn: range bounds histogram on scalar, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.31::real,
'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text
@ -562,8 +629,9 @@ AND attname = 'id';
-- ok: range_bounds_histogram
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'range_bounds_histogram', '{"[-1,1)","[0,4)","[1,4)","[1,100)"}'::text
);
@ -577,8 +645,9 @@ AND attname = 'arange';
-- warn: cannot set most_common_elems for range type, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'arange'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'arange',
'inherited', false::boolean,
'null_frac', 0.32::real,
'most_common_elems', '{3,1}'::text,
@ -594,8 +663,9 @@ AND attname = 'arange';
-- warn: scalars can't have mcelem, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.33::real,
'most_common_elems', '{1,3}'::text,
@ -611,8 +681,9 @@ AND attname = 'id';
-- warn: mcelem / mcelem mismatch, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.34::real,
'most_common_elems', '{one,two}'::text
@ -627,8 +698,9 @@ AND attname = 'tags';
-- warn: mcelem / mcelem null mismatch part 2, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'null_frac', 0.35::real,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3}'::real[]
@ -643,8 +715,9 @@ AND attname = 'tags';
-- ok: mcelem
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'tags'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'tags',
'inherited', false::boolean,
'most_common_elems', '{one,three}'::text,
'most_common_elem_freqs', '{0.3,0.2,0.2,0.3,0.0}'::real[]
@ -659,8 +732,9 @@ AND attname = 'tags';
-- warn: scalars can't have elem_count_histogram, rest ok
SELECT pg_catalog.pg_restore_attribute_stats(
'relation', 'stats_import.test'::regclass,
'attname', 'id'::name,
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.36::real,
'elem_count_histogram', '{1,1,1,1,1,1,1,1,1,1}'::real[]
@ -707,8 +781,9 @@ SELECT s.schemaname, s.tablename, s.attname, s.inherited, r.*
FROM pg_catalog.pg_stats AS s
CROSS JOIN LATERAL
pg_catalog.pg_restore_attribute_stats(
'relation', ('stats_import.' || s.tablename || '_clone')::regclass,
'attname', s.attname,
'schemaname', 'stats_import',
'relname', s.tablename::text || '_clone',
'attname', s.attname::text,
'inherited', s.inherited,
'version', 150000,
'null_frac', s.null_frac,
@ -853,9 +928,10 @@ AND inherited = false
AND attname = 'arange';
SELECT pg_catalog.pg_clear_attribute_stats(
relation => 'stats_import.test'::regclass,
attname => 'arange'::name,
inherited => false::boolean);
schemaname => 'stats_import',
relname => 'test',
attname => 'arange',
inherited => false);
SELECT COUNT(*)
FROM pg_stats
@ -864,4 +940,34 @@ AND tablename = 'test'
AND inherited = false
AND attname = 'arange';
-- temp tables
CREATE TEMP TABLE stats_temp(i int);
SELECT pg_restore_relation_stats(
'schemaname', 'pg_temp',
'relname', 'stats_temp',
'relpages', '-19'::integer,
'reltuples', 401::real,
'relallvisible', 5::integer,
'relallfrozen', 3::integer);
SELECT relname, relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
WHERE oid = 'pg_temp.stats_temp'::regclass
ORDER BY relname;
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'pg_temp',
'relname', 'stats_temp',
'attname', 'i',
'inherited', false::boolean,
'null_frac', 0.0123::real
);
SELECT tablename, null_frac
FROM pg_stats
WHERE schemaname like 'pg_temp%'
AND tablename = 'stats_temp'
AND inherited = false
AND attname = 'i';
DROP TABLE stats_temp;
DROP SCHEMA stats_import CASCADE;