diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index f8a0d76d12..ad663c94d7 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -30197,7 +30197,7 @@ DETAIL: Make sure pg_wal_replay_wait() isn't called within a transaction with a The value of relpages must be greater than - or equal to 0, + or equal to -1, reltuples must be greater than or equal to -1.0, and relallvisible must be greater than or equal to 0. diff --git a/src/backend/statistics/relation_stats.c b/src/backend/statistics/relation_stats.c index 26f15061e8..1a6d1640c3 100644 --- a/src/backend/statistics/relation_stats.c +++ b/src/backend/statistics/relation_stats.c @@ -99,11 +99,16 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel) { int32 relpages = PG_GETARG_INT32(RELPAGES_ARG); - if (relpages < 0) + /* + * Partitioned tables may have relpages=-1. Note: for relations with + * no storage, relpages=-1 is not used consistently, but must be + * supported here. + */ + if (relpages < -1) { ereport(elevel, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("relpages cannot be < 0"))); + errmsg("relpages cannot be < -1"))); table_close(crel, RowExclusiveLock); return false; } diff --git a/src/test/regress/expected/stats_import.out b/src/test/regress/expected/stats_import.out index cd1b80aa43..495e9b0348 100644 --- a/src/test/regress/expected/stats_import.out +++ b/src/test/regress/expected/stats_import.out @@ -135,9 +135,45 @@ SELECT 'stats_import.testview'::regclass); ERROR: cannot modify statistics for relation "testview" DETAIL: This operation is not supported for views. +-- relpages may be -1 for partitioned tables +CREATE TABLE stats_import.part_parent ( i integer ) PARTITION BY RANGE(i); +CREATE TABLE stats_import.part_child_1 + PARTITION OF stats_import.part_parent + FOR VALUES FROM (0) TO (10); +ANALYZE stats_import.part_parent; +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent'::regclass; + relpages +---------- + -1 +(1 row) + +-- although partitioned tables have no storage, setting relpages to a +-- positive value is still allowed +SELECT + pg_catalog.pg_set_relation_stats( + relation => 'stats_import.part_parent'::regclass, + relpages => 2::integer); + pg_set_relation_stats +----------------------- + t +(1 row) + +-- nothing stops us from setting it to -1 +SELECT + pg_catalog.pg_set_relation_stats( + relation => 'stats_import.part_parent'::regclass, + relpages => -1::integer); + pg_set_relation_stats +----------------------- + t +(1 row) + DROP SCHEMA stats_import CASCADE; -NOTICE: drop cascades to 4 other objects +NOTICE: drop cascades to 5 other objects DETAIL: drop cascades to type stats_import.complex_type drop cascades to table stats_import.test drop cascades to sequence stats_import.testseq drop cascades to view stats_import.testview +drop cascades to table stats_import.part_parent diff --git a/src/test/regress/sql/stats_import.sql b/src/test/regress/sql/stats_import.sql index 3e9f6d9124..108b0c4558 100644 --- a/src/test/regress/sql/stats_import.sql +++ b/src/test/regress/sql/stats_import.sql @@ -95,4 +95,29 @@ SELECT pg_catalog.pg_clear_relation_stats( 'stats_import.testview'::regclass); +-- relpages may be -1 for partitioned tables +CREATE TABLE stats_import.part_parent ( i integer ) PARTITION BY RANGE(i); +CREATE TABLE stats_import.part_child_1 + PARTITION OF stats_import.part_parent + FOR VALUES FROM (0) TO (10); + +ANALYZE stats_import.part_parent; + +SELECT relpages +FROM pg_class +WHERE oid = 'stats_import.part_parent'::regclass; + +-- although partitioned tables have no storage, setting relpages to a +-- positive value is still allowed +SELECT + pg_catalog.pg_set_relation_stats( + relation => 'stats_import.part_parent'::regclass, + relpages => 2::integer); + +-- nothing stops us from setting it to -1 +SELECT + pg_catalog.pg_set_relation_stats( + relation => 'stats_import.part_parent'::regclass, + relpages => -1::integer); + DROP SCHEMA stats_import CASCADE;