v7-0002-Downgrade-as-man-pg_restore_-_stats-errors-to-war.patch
text/x-patch
Filename: v7-0002-Downgrade-as-man-pg_restore_-_stats-errors-to-war.patch
Type: text/x-patch
Part: 1
Message:
Re: Statistics Import and Export
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: format-patch
Series: patch v7-0002
Subject: Downgrade as man pg_restore_*_stats errors to warnings.
| File | + | − |
|---|---|---|
| src/backend/statistics/attribute_stats.c | 86 | 38 |
| src/backend/statistics/relation_stats.c | 7 | 3 |
| src/backend/statistics/stat_utils.c | 37 | 14 |
| src/include/statistics/stat_utils.h | 2 | 2 |
| src/test/regress/expected/stats_import.out | 127 | 36 |
| src/test/regress/sql/stats_import.sql | 18 | 18 |
From 4d8d76b78b87f53d0adbd6781a2a66beac5bc264 Mon Sep 17 00:00:00 2001
From: Corey Huinker <corey.huinker@gmail.com>
Date: Sat, 8 Mar 2025 00:52:41 -0500
Subject: [PATCH v7 2/2] Downgrade as man pg_restore_*_stats errors to
warnings.
We want to avoid errors that can potentially stop an otherwise
successful pg_upgrade or pg_restore operation. With that in mind, change
as many ERROR reports to WARNING + early termination with no data
updated.
---
src/include/statistics/stat_utils.h | 4 +-
src/backend/statistics/attribute_stats.c | 124 +++++++++++-----
src/backend/statistics/relation_stats.c | 10 +-
src/backend/statistics/stat_utils.c | 51 +++++--
src/test/regress/expected/stats_import.out | 163 ++++++++++++++++-----
src/test/regress/sql/stats_import.sql | 36 ++---
6 files changed, 277 insertions(+), 111 deletions(-)
diff --git a/src/include/statistics/stat_utils.h b/src/include/statistics/stat_utils.h
index cad042c8e4a..298cbae3436 100644
--- a/src/include/statistics/stat_utils.h
+++ b/src/include/statistics/stat_utils.h
@@ -21,7 +21,7 @@ struct StatsArgInfo
Oid argtype;
};
-extern void stats_check_required_arg(FunctionCallInfo fcinfo,
+extern bool stats_check_required_arg(FunctionCallInfo fcinfo,
struct StatsArgInfo *arginfo,
int argnum);
extern bool stats_check_arg_array(FunctionCallInfo fcinfo,
@@ -30,7 +30,7 @@ extern bool stats_check_arg_pair(FunctionCallInfo fcinfo,
struct StatsArgInfo *arginfo,
int argnum1, int argnum2);
-extern void stats_lock_check_privileges(Oid reloid);
+extern bool stats_lock_check_privileges(Oid reloid);
extern Oid stats_schema_check_privileges(const char *nspname);
diff --git a/src/backend/statistics/attribute_stats.c b/src/backend/statistics/attribute_stats.c
index f87db2d6102..4f9bc18f8c6 100644
--- a/src/backend/statistics/attribute_stats.c
+++ b/src/backend/statistics/attribute_stats.c
@@ -100,7 +100,7 @@ static struct StatsArgInfo cleararginfo[] =
static bool attribute_statistics_update(FunctionCallInfo fcinfo);
static Node *get_attr_expr(Relation rel, int attnum);
-static void get_attr_stat_type(Oid reloid, AttrNumber attnum,
+static bool get_attr_stat_type(Oid reloid, AttrNumber attnum,
Oid *atttypid, int32 *atttypmod,
char *atttyptype, Oid *atttypcoll,
Oid *eq_opr, Oid *lt_opr);
@@ -129,10 +129,12 @@ static void init_empty_stats_tuple(Oid reloid, int16 attnum, bool inherited,
* stored as an anyarray, and the representation of the array needs to store
* the correct element type, which must be derived from the attribute.
*
- * Major errors, such as the table not existing, the attribute not existing,
- * or a permissions failure are always reported at ERROR. Other errors, such
- * as a conversion failure on one statistic kind, are reported as a WARNING
- * and other statistic kinds may still be updated.
+ * This function is called during database upgrades and restorations, therefore
+ * it is imperative to avoid ERRORs that could potentially end the upgrade or
+ * restore unless. Major errors, such as the table not existing, the attribute
+ * not existing, or permissions failure are reported as WARNINGs with an end to
+ * the function, thus allowing the upgrade/restore to continue, but without the
+ * stats that can be regenereated once the database is online again.
*/
static bool
attribute_statistics_update(FunctionCallInfo fcinfo)
@@ -149,8 +151,8 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
HeapTuple statup;
Oid atttypid = InvalidOid;
- int32 atttypmod;
- char atttyptype;
+ int32 atttypmod = -1;
+ char atttyptype = TYPTYPE_PSEUDO; /* Not a great default, but there is no TYPTYPE_INVALID */
Oid atttypcoll = InvalidOid;
Oid eq_opr = InvalidOid;
Oid lt_opr = InvalidOid;
@@ -177,17 +179,19 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
bool result = true;
- stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG);
- stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG);
+ if (!stats_check_required_arg(fcinfo, attarginfo, ATTRELSCHEMA_ARG))
+ return false;
+ if (!stats_check_required_arg(fcinfo, attarginfo, ATTRELNAME_ARG))
+ return false;
nspname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELSCHEMA_ARG));
nspoid = stats_schema_check_privileges(nspname);
- if (nspoid == InvalidOid)
+ if (!OidIsValid(nspoid))
return false;
relname = TextDatumGetCString(PG_GETARG_DATUM(ATTRELNAME_ARG));
reloid = get_relname_relid(relname, nspoid);
- if (reloid == InvalidOid)
+ if (!OidIsValid(reloid))
{
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
@@ -196,29 +200,39 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
}
if (RecoveryInProgress())
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
errhint("Statistics cannot be modified during recovery.")));
+ return false;
+ }
/* lock before looking up attribute */
- stats_lock_check_privileges(reloid);
+ if (!stats_lock_check_privileges(reloid))
+ return false;
/* user can specify either attname or attnum, but not both */
if (!PG_ARGISNULL(ATTNAME_ARG))
{
if (!PG_ARGISNULL(ATTNUM_ARG))
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("cannot specify both attname and attnum")));
+ return false;
+ }
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,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\".\"%s\" does not exist",
attname, nspname, relname)));
+ return false;
+ }
}
else if (!PG_ARGISNULL(ATTNUM_ARG))
{
@@ -227,27 +241,33 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
/* annoyingly, get_attname doesn't check attisdropped */
if (attname == NULL ||
!SearchSysCacheExistsAttName(reloid, attname))
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column %d of relation \"%s\".\"%s\" does not exist",
attnum, nspname, relname)));
+ return false;
+ }
}
else
{
- ereport(ERROR,
+ ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("must specify either attname or attnum")));
- attname = NULL; /* keep compiler quiet */
- attnum = 0;
+ return false;
}
if (attnum < 0)
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot modify statistics on system column \"%s\"",
attname)));
+ return false;
+ }
- stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG);
+ if (!stats_check_required_arg(fcinfo, attarginfo, INHERITED_ARG))
+ return false;
inherited = PG_GETARG_BOOL(INHERITED_ARG);
/*
@@ -296,10 +316,11 @@ attribute_statistics_update(FunctionCallInfo fcinfo)
}
/* derive information from attribute */
- get_attr_stat_type(reloid, attnum,
- &atttypid, &atttypmod,
- &atttyptype, &atttypcoll,
- &eq_opr, <_opr);
+ if (!get_attr_stat_type(reloid, attnum,
+ &atttypid, &atttypmod,
+ &atttyptype, &atttypcoll,
+ &eq_opr, <_opr))
+ result = false;
/* if needed, derive element type */
if (do_mcelem || do_dechist)
@@ -579,7 +600,7 @@ get_attr_expr(Relation rel, int attnum)
/*
* Derive type information from the attribute.
*/
-static void
+static bool
get_attr_stat_type(Oid reloid, AttrNumber attnum,
Oid *atttypid, int32 *atttypmod,
char *atttyptype, Oid *atttypcoll,
@@ -596,18 +617,26 @@ get_attr_stat_type(Oid reloid, AttrNumber attnum,
/* Attribute not found */
if (!HeapTupleIsValid(atup))
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("attribute %d of relation \"%s\" does not exist",
attnum, RelationGetRelationName(rel))));
+ relation_close(rel, NoLock);
+ return false;
+ }
attr = (Form_pg_attribute) GETSTRUCT(atup);
if (attr->attisdropped)
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("attribute %d of relation \"%s\" does not exist",
attnum, RelationGetRelationName(rel))));
+ relation_close(rel, NoLock);
+ return false;
+ }
expr = get_attr_expr(rel, attr->attnum);
@@ -656,6 +685,7 @@ get_attr_stat_type(Oid reloid, AttrNumber attnum,
*atttypcoll = DEFAULT_COLLATION_OID;
relation_close(rel, NoLock);
+ return true;
}
/*
@@ -781,6 +811,10 @@ set_stats_slot(Datum *values, bool *nulls, bool *replaces,
if (slotidx >= STATISTIC_NUM_SLOTS && first_empty >= 0)
slotidx = first_empty;
+ /*
+ * Currently there is no datatype that can have more than STATISTIC_NUM_SLOTS
+ * statistic kinds, so this can safely remain an ERROR for now.
+ */
if (slotidx >= STATISTIC_NUM_SLOTS)
ereport(ERROR,
(errmsg("maximum number of statistics slots exceeded: %d",
@@ -927,15 +961,19 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
AttrNumber attnum;
bool inherited;
- 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);
+ if (!stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELSCHEMA_ARG))
+ PG_RETURN_VOID();
+ if (!stats_check_required_arg(fcinfo, cleararginfo, C_ATTRELNAME_ARG))
+ PG_RETURN_VOID();
+ if (!stats_check_required_arg(fcinfo, cleararginfo, C_ATTNAME_ARG))
+ PG_RETURN_VOID();
+ if (!stats_check_required_arg(fcinfo, cleararginfo, C_INHERITED_ARG))
+ PG_RETURN_VOID();
nspname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELSCHEMA_ARG));
nspoid = stats_schema_check_privileges(nspname);
if (!OidIsValid(nspoid))
- return false;
+ PG_RETURN_VOID();
relname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTRELNAME_ARG));
reloid = get_relname_relid(relname, nspoid);
@@ -944,31 +982,41 @@ pg_clear_attribute_stats(PG_FUNCTION_ARGS)
ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("Relation \"%s\".\"%s\" not found.", nspname, relname)));
- return false;
+ PG_RETURN_VOID();
}
if (RecoveryInProgress())
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("recovery is in progress"),
errhint("Statistics cannot be modified during recovery.")));
+ PG_RETURN_VOID();
+ }
- stats_lock_check_privileges(reloid);
+ if (!stats_lock_check_privileges(reloid))
+ PG_RETURN_VOID();
attname = TextDatumGetCString(PG_GETARG_DATUM(C_ATTNAME_ARG));
attnum = get_attnum(reloid, attname);
if (attnum < 0)
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot clear statistics on system column \"%s\"",
attname)));
+ PG_RETURN_VOID();
+ }
if (attnum == InvalidAttrNumber)
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("column \"%s\" of relation \"%s\" does not exist",
attname, get_rel_name(reloid))));
+ PG_RETURN_VOID();
+ }
inherited = PG_GETARG_BOOL(C_INHERITED_ARG);
diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c
index fdc69bc93e2..49109cf721d 100644
--- a/src/backend/statistics/relation_stats.c
+++ b/src/backend/statistics/relation_stats.c
@@ -84,8 +84,11 @@ 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);
+ if (!stats_check_required_arg(fcinfo, relarginfo, RELSCHEMA_ARG))
+ return false;
+
+ if (!stats_check_required_arg(fcinfo, relarginfo, RELNAME_ARG))
+ return false;
nspname = TextDatumGetCString(PG_GETARG_DATUM(RELSCHEMA_ARG));
nspoid = stats_schema_check_privileges(nspname);
@@ -108,7 +111,8 @@ relation_statistics_update(FunctionCallInfo fcinfo)
errmsg("recovery is in progress"),
errhint("Statistics cannot be modified during recovery.")));
- stats_lock_check_privileges(reloid);
+ if (!stats_lock_check_privileges(reloid))
+ return false;
if (!PG_ARGISNULL(RELPAGES_ARG))
{
diff --git a/src/backend/statistics/stat_utils.c b/src/backend/statistics/stat_utils.c
index e037d4994e8..dd9d88ac1c5 100644
--- a/src/backend/statistics/stat_utils.c
+++ b/src/backend/statistics/stat_utils.c
@@ -34,16 +34,20 @@
/*
* Ensure that a given argument is not null.
*/
-void
+bool
stats_check_required_arg(FunctionCallInfo fcinfo,
struct StatsArgInfo *arginfo,
int argnum)
{
if (PG_ARGISNULL(argnum))
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("\"%s\" cannot be NULL",
arginfo[argnum].argname)));
+ return false;
+ }
+ return true;
}
/*
@@ -128,13 +132,14 @@ stats_check_arg_pair(FunctionCallInfo fcinfo,
* - the role owns the current database and the relation is not shared
* - the role has the MAINTAIN privilege on the relation
*/
-void
+bool
stats_lock_check_privileges(Oid reloid)
{
Relation table;
Oid table_oid = reloid;
Oid index_oid = InvalidOid;
LOCKMODE index_lockmode = NoLock;
+ bool ok = true;
/*
* For indexes, we follow the locking behavior in do_analyze_rel() and
@@ -174,14 +179,15 @@ stats_lock_check_privileges(Oid reloid)
case RELKIND_PARTITIONED_TABLE:
break;
default:
- ereport(ERROR,
+ ereport(WARNING,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("cannot modify statistics for relation \"%s\"",
RelationGetRelationName(table)),
errdetail_relkind_not_supported(table->rd_rel->relkind)));
+ ok = false;
}
- if (OidIsValid(index_oid))
+ if (ok && (OidIsValid(index_oid)))
{
Relation index;
@@ -194,25 +200,33 @@ stats_lock_check_privileges(Oid reloid)
relation_close(index, NoLock);
}
- if (table->rd_rel->relisshared)
- ereport(ERROR,
+ if (ok && (table->rd_rel->relisshared))
+ {
+ ereport(WARNING,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot modify statistics for shared relation")));
+ ok = false;
+ }
- if (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId()))
+ if (ok && (!object_ownercheck(DatabaseRelationId, MyDatabaseId, GetUserId())))
{
AclResult aclresult = pg_class_aclcheck(RelationGetRelid(table),
GetUserId(),
ACL_MAINTAIN);
if (aclresult != ACLCHECK_OK)
- aclcheck_error(aclresult,
- get_relkind_objtype(table->rd_rel->relkind),
- NameStr(table->rd_rel->relname));
+ {
+ ereport(WARNING,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ errmsg("permission denied for relation %s",
+ NameStr(table->rd_rel->relname))));
+ ok = false;
+ }
}
/* retain lock on table */
relation_close(table, NoLock);
+ return ok;
}
@@ -318,9 +332,12 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
&args, &types, &argnulls);
if (nargs % 2 != 0)
- ereport(ERROR,
+ {
+ ereport(WARNING,
errmsg("variadic arguments must be name/value pairs"),
errhint("Provide an even number of variadic arguments that can be divided into pairs."));
+ return false;
+ }
/*
* For each argument name/value pair, find corresponding positional
@@ -333,14 +350,20 @@ stats_fill_fcinfo_from_arg_pairs(FunctionCallInfo pairs_fcinfo,
char *argname;
if (argnulls[i])
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errmsg("name at variadic position %d is NULL", i + 1)));
+ return false;
+ }
if (types[i] != TEXTOID)
- ereport(ERROR,
+ {
+ ereport(WARNING,
(errmsg("name at variadic position %d has type \"%s\", expected type \"%s\"",
i + 1, format_type_be(types[i]),
format_type_be(TEXTOID))));
+ return false;
+ }
if (argnulls[i + 1])
continue;
diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out
index 2f1295f2149..6551d6bf099 100644
--- a/src/test/regress/expected/stats_import.out
+++ b/src/test/regress/expected/stats_import.out
@@ -46,31 +46,51 @@ SELECT pg_clear_relation_stats('stats_import', 'test');
--
-- relstats tests
--
--- error: schemaname missing
+-- warning: schemaname missing, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'relname', 'test',
'relpages', 17::integer);
-ERROR: "schemaname" cannot be NULL
--- error: relname missing
+WARNING: "schemaname" cannot be NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
+-- warning: relname missing, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relpages', 17::integer);
-ERROR: "relname" cannot be NULL
---- error: schemaname is wrong type
+WARNING: "relname" cannot be NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
+--- warning: schemaname is wrong type, nothing updated
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
+WARNING: "schemaname" cannot be NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
+--- warning: relname is wrong type, nothing updated
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
+WARNING: "relname" cannot be NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
+-- warning: relation not found, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'nope',
@@ -81,19 +101,30 @@ WARNING: Relation "stats_import"."nope" not found.
f
(1 row)
--- error: odd number of variadic arguments cannot be pairs
+-- warning: odd number of variadic arguments cannot be pairs, nothing updated
SELECT pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible');
-ERROR: variadic arguments must be name/value pairs
+WARNING: 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
+WARNING: "schemaname" cannot be NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
+-- warning: argument name is NULL, nothing updated
SELECT pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'test',
NULL, '17'::integer);
-ERROR: name at variadic position 5 is NULL
+WARNING: name at variadic position 5 is NULL
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
-- starting stats
SELECT relpages, reltuples, relallvisible, relallfrozen
FROM pg_class
@@ -345,26 +376,46 @@ CREATE SEQUENCE stats_import.testseq;
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'testseq');
-ERROR: cannot modify statistics for relation "testseq"
+WARNING: cannot modify statistics for relation "testseq"
DETAIL: This operation is not supported for sequences.
+ pg_restore_relation_stats
+---------------------------
+ f
+(1 row)
+
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testseq');
-ERROR: cannot modify statistics for relation "testseq"
+WARNING: cannot modify statistics for relation "testseq"
DETAIL: This operation is not supported for sequences.
+ pg_clear_relation_stats
+-------------------------
+
+(1 row)
+
CREATE VIEW stats_import.testview AS SELECT * FROM stats_import.test;
SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname => 'testview');
-ERROR: cannot modify statistics for relation "testview"
+WARNING: cannot modify statistics for relation "testview"
DETAIL: This operation is not supported for views.
+ pg_clear_relation_stats
+-------------------------
+
+(1 row)
+
--
-- attribute stats
--
--- error: schemaname missing
+-- warning: schemaname missing, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: "schemaname" cannot be NULL
--- error: schema does not exist
+WARNING: "schemaname" cannot be NULL
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: schema does not exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'nope',
'relname', 'test',
@@ -377,14 +428,19 @@ WARNING: schema nope does not exist
f
(1 row)
--- error: relname missing
+-- warning: relname missing, nothing updated
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
+WARNING: "relname" cannot be NULL
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: relname does not exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'nope',
@@ -397,23 +453,33 @@ WARNING: Relation "stats_import"."nope" not found.
f
(1 row)
--- error: relname null
+-- warning: relname null, nothing updated
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
+WARNING: "relname" cannot be NULL
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: NULL attname, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'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
+WARNING: must specify either attname or attnum
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: attname doesn't exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -422,8 +488,13 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'null_frac', 0.1::real,
'avg_width', 2::integer,
'n_distinct', 0.3::real);
-ERROR: column "nope" of relation "stats_import"."test" does not exist
--- error: both attname and attnum
+WARNING: column "nope" of relation "stats_import"."test" does not exist
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: both attname and attnum, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -431,30 +502,50 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'attnum', 1::smallint,
'inherited', false::boolean,
'null_frac', 0.1::real);
-ERROR: cannot specify both attname and attnum
--- error: neither attname nor attnum
+WARNING: cannot specify both attname and attnum
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: neither attname nor attnum, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'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
+WARNING: must specify either attname or attnum
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: attribute is system column, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'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
+WARNING: cannot modify statistics on system column "xmin"
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
+-- warning: inherited null, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
'attname', 'id',
'inherited', NULL::boolean,
'null_frac', 0.1::real);
-ERROR: "inherited" cannot be NULL
+WARNING: "inherited" cannot be NULL
+ pg_restore_attribute_stats
+----------------------------
+ f
+(1 row)
+
-- ok: just the fixed values, with version, no stakinds
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql
index ccdc44e9236..dbbebce1673 100644
--- a/src/test/regress/sql/stats_import.sql
+++ b/src/test/regress/sql/stats_import.sql
@@ -39,41 +39,41 @@ SELECT pg_clear_relation_stats('stats_import', 'test');
-- relstats tests
--
--- error: schemaname missing
+-- warning: schemaname missing, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'relname', 'test',
'relpages', 17::integer);
--- error: relname missing
+-- warning: relname missing, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relpages', 17::integer);
---- error: schemaname is wrong type
+--- warning: schemaname is wrong type, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 3.6::float,
'relname', 'test',
'relpages', 17::integer);
---- error: relname is wrong type
+--- warning: relname is wrong type, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 0::oid,
'relpages', 17::integer);
--- error: relation not found
+-- warning: relation not found, nothing updated
SELECT pg_catalog.pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'nope',
'relpages', 17::integer);
--- error: odd number of variadic arguments cannot be pairs
+-- warning: odd number of variadic arguments cannot be pairs, nothing updated
SELECT pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'test',
'relallvisible');
--- error: argument name is NULL
+-- warning: argument name is NULL, nothing updated
SELECT pg_restore_relation_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -246,14 +246,14 @@ SELECT pg_catalog.pg_clear_relation_stats(schemaname => 'stats_import', relname
-- attribute stats
--
--- error: schemaname missing
+-- warning: schemaname missing, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'relname', 'test',
'attname', 'id',
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: schema does not exist
+-- warning: schema does not exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'nope',
'relname', 'test',
@@ -261,14 +261,14 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: relname missing
+-- warning: relname missing, nothing updated
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
+-- warning: relname does not exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'nope',
@@ -276,7 +276,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: relname null
+-- warning: relname null, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', NULL,
@@ -284,7 +284,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: NULL attname
+-- warning: NULL attname, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -292,7 +292,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: attname doesn't exist
+-- warning: attname doesn't exist, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -302,7 +302,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'avg_width', 2::integer,
'n_distinct', 0.3::real);
--- error: both attname and attnum
+-- warning: both attname and attnum, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -311,14 +311,14 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: neither attname nor attnum
+-- warning: neither attname nor attnum, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: attribute is system column
+-- warning: attribute is system column, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
@@ -326,7 +326,7 @@ SELECT pg_catalog.pg_restore_attribute_stats(
'inherited', false::boolean,
'null_frac', 0.1::real);
--- error: inherited null
+-- warning: inherited null, nothing updated
SELECT pg_catalog.pg_restore_attribute_stats(
'schemaname', 'stats_import',
'relname', 'test',
--
2.48.1