Commit ca410302 authored by Alvaro Herrera's avatar Alvaro Herrera

Fix tablespace handling for partitioned tables

When partitioned tables were introduced, we failed to realize that by
copying the tablespace handling for other relation kinds with no
physical storage we were causing the secondary effect that their
partitions would not automatically inherit the tablespace setting.  This
is surprising and unhelpful, so change it to adopt the behavior
introduced in pg11 (commit 33e6c34c3267) for partitioned indexes: the
parent relation remembers the tablespace specification, which is then
used for any new partitions that don't declare one.

Because this commit changes behavior of the TABLESPACE clause for
partitioned tables (it's no longer a no-op), it is not backpatched.

Author: David Rowley, Álvaro Herrera
Reviewed-by: Michael Paquier
Discussion: https://postgr.es/m/CAKJS1f9SxVzqDrGD1teosFd6jBMM0UEaa14_8mRvcWE19Tu0hA@mail.gmail.com
parent 1e6240a3
......@@ -1216,7 +1216,11 @@ WITH ( MODULUS <replaceable class="parameter">numeric_literal</replaceable>, REM
of the tablespace in which the new table is to be created.
If not specified,
<xref linkend="guc-default-tablespace"/> is consulted, or
<xref linkend="guc-temp-tablespaces"/> if the table is temporary.
<xref linkend="guc-temp-tablespaces"/> if the table is temporary. For
partitioned tables, since no storage is required for the table itself,
the tablespace specified here only serves to mark the default tablespace
for any newly created partitions when no other tablespace is explicitly
specified.
</para>
</listitem>
</varlistentry>
......
......@@ -333,7 +333,6 @@ heap_create(const char *relname,
case RELKIND_VIEW:
case RELKIND_COMPOSITE_TYPE:
case RELKIND_FOREIGN_TABLE:
case RELKIND_PARTITIONED_TABLE:
create_storage = false;
/*
......@@ -343,10 +342,11 @@ heap_create(const char *relname,
reltablespace = InvalidOid;
break;
case RELKIND_PARTITIONED_TABLE:
case RELKIND_PARTITIONED_INDEX:
/*
* Preserve tablespace so that it's used as tablespace for indexes
* on future partitions.
* For partitioned tables and indexes, preserve tablespace so that
* it's used as the tablespace for future partitions.
*/
create_storage = false;
break;
......
This diff is collapsed.
......@@ -122,6 +122,19 @@ typedef FormData_pg_class *Form_pg_class;
*/
#define REPLICA_IDENTITY_INDEX 'i'
/*
* Relation kinds that have physical storage. These relations normally have
* relfilenode set to non-zero, but it can also be zero if the relation is
* mapped.
*/
#define RELKIND_CAN_HAVE_STORAGE(relkind) \
((relkind) == RELKIND_RELATION || \
(relkind) == RELKIND_INDEX || \
(relkind) == RELKIND_SEQUENCE || \
(relkind) == RELKIND_TOASTVALUE || \
(relkind) == RELKIND_MATVIEW)
#endif /* EXPOSE_TO_CLIENT_CODE */
#endif /* PG_CLASS_H */
......@@ -44,6 +44,18 @@ CREATE INDEX foo_idx on testschema.foo(i) TABLESPACE regress_tblspace;
SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
where c.reltablespace = t.oid AND c.relname = 'foo_idx';
-- partitioned table
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
CREATE TABLE testschema.part12 PARTITION OF testschema.part FOR VALUES IN(1,2) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
CREATE TABLE testschema.part12_1 PARTITION OF testschema.part12 FOR VALUES IN (1);
ALTER TABLE testschema.part12 SET TABLESPACE pg_default;
CREATE TABLE testschema.part12_2 PARTITION OF testschema.part12 FOR VALUES IN (2);
-- Ensure part12_1 defaulted to regress_tblspace and part12_2 defaulted to pg_default.
SELECT relname, spcname FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_tablespace t ON c.reltablespace = t.oid
where c.relname LIKE 'part%' order by relname;
DROP TABLE testschema.part;
-- partitioned index
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
CREATE TABLE testschema.part1 PARTITION OF testschema.part FOR VALUES IN (1);
......
......@@ -61,6 +61,25 @@ SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c
foo_idx | regress_tblspace
(1 row)
-- partitioned table
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
CREATE TABLE testschema.part12 PARTITION OF testschema.part FOR VALUES IN(1,2) PARTITION BY LIST (a) TABLESPACE regress_tblspace;
CREATE TABLE testschema.part12_1 PARTITION OF testschema.part12 FOR VALUES IN (1);
ALTER TABLE testschema.part12 SET TABLESPACE pg_default;
CREATE TABLE testschema.part12_2 PARTITION OF testschema.part12 FOR VALUES IN (2);
-- Ensure part12_1 defaulted to regress_tblspace and part12_2 defaulted to pg_default.
SELECT relname, spcname FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_tablespace t ON c.reltablespace = t.oid
where c.relname LIKE 'part%' order by relname;
relname | spcname
----------+------------------
part |
part12 |
part12_1 | regress_tblspace
part12_2 |
(4 rows)
DROP TABLE testschema.part;
-- partitioned index
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
CREATE TABLE testschema.part1 PARTITION OF testschema.part FOR VALUES IN (1);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment