Allow pg_set_relation_stats() to set relpages to -1.

While the default value for relpages is 0, if a partitioned table with
at least one child has been analyzed, then the partititoned table will
have a relpages value of -1.

Author: Corey Huinker
Discussion: https://postgr.es/m/CADkLM=fajh1Lpcyr_XsMmq-9Z=SGk-u+_Zeac7Pt0RAN3uiVCg@mail.gmail.com
This commit is contained in:
Jeff Davis 2024-10-18 10:44:15 -07:00
parent 1bd4bc85ca
commit b391d882ff
4 changed files with 70 additions and 4 deletions

View File

@ -30197,7 +30197,7 @@ DETAIL: Make sure pg_wal_replay_wait() isn't called within a transaction with a
</para> </para>
<para> <para>
The value of <structfield>relpages</structfield> must be greater than The value of <structfield>relpages</structfield> must be greater than
or equal to <literal>0</literal>, or equal to <literal>-1</literal>,
<structfield>reltuples</structfield> must be greater than or equal to <structfield>reltuples</structfield> must be greater than or equal to
<literal>-1.0</literal>, and <structfield>relallvisible</structfield> <literal>-1.0</literal>, and <structfield>relallvisible</structfield>
must be greater than or equal to <literal>0</literal>. must be greater than or equal to <literal>0</literal>.

View File

@ -99,11 +99,16 @@ relation_statistics_update(FunctionCallInfo fcinfo, int elevel)
{ {
int32 relpages = PG_GETARG_INT32(RELPAGES_ARG); 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, ereport(elevel,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("relpages cannot be < 0"))); errmsg("relpages cannot be < -1")));
table_close(crel, RowExclusiveLock); table_close(crel, RowExclusiveLock);
return false; return false;
} }

View File

@ -135,9 +135,45 @@ SELECT
'stats_import.testview'::regclass); 'stats_import.testview'::regclass);
ERROR: cannot modify statistics for relation "testview" ERROR: cannot modify statistics for relation "testview"
DETAIL: This operation is not supported for views. 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; 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 DETAIL: drop cascades to type stats_import.complex_type
drop cascades to table stats_import.test drop cascades to table stats_import.test
drop cascades to sequence stats_import.testseq drop cascades to sequence stats_import.testseq
drop cascades to view stats_import.testview drop cascades to view stats_import.testview
drop cascades to table stats_import.part_parent

View File

@ -95,4 +95,29 @@ SELECT
pg_catalog.pg_clear_relation_stats( pg_catalog.pg_clear_relation_stats(
'stats_import.testview'::regclass); '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; DROP SCHEMA stats_import CASCADE;