Inconsistent/confusing handling of tablespaces for partitioned tables

From: Konstantin Knizhnik <k(dot)knizhnik(at)postgrespro(dot)ru>
To: PostgreSQL Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Inconsistent/confusing handling of tablespaces for partitioned tables
Date: 2020-12-21 15:22:23
Message-ID: 2374e17f-5c61-3a36-2088-e29e4024c051@postgrespro.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi hackers,

The following sequence of statements:

CREATE SCHEMA testschema;
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
SET default_tablespace TO pg_global;
ALTER TABLE testschema.part SET TABLESPACE pg_default;
CREATE TABLE testschema.part_78 PARTITION OF testschema.part FOR VALUES
IN (7, 8) PARTITION BY LIST (a);

Produce error
ERROR:  only shared relations can be placed in pg_global tablespace
when been executed in database with default tablespace, but produce no
error in database with assigned tablespace.

create tablespace my_tblspc location '/tmp/tblspc';
create databse test;
alter database test set tablespace my_tblspc;

There is the following code in tablecmds.c:

    else if (stmt->partbound)
    {
        /*
         * For partitions, when no other tablespace is specified, we
default
         * the tablespace to the parent partitioned table's.
         */
        Assert(list_length(inheritOids) == 1);
        tablespaceId = get_rel_tablespace(linitial_oid(inheritOids));
    }

In first case get_rel_tablespace returns 0 (because parent table has no
explicit tablespace)
and in the second: pg_default

Also I am confused that the following statement is rejected:

SET default_tablespace TO pg_default;
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
ERROR:  cannot specify default tablespace for partitioned relations

but still it is possible to set tablespace of parent table to pg_default
using alter tablespace command:

RESET default_tablespace;
CREATE TABLE testschema.part (a int) PARTITION BY LIST (a);
ALTER TABLE testschema.part SET TABLESPACE pg_default;

But ... it has no effect: testschema.part is till assumed to belong to
default tablespace.
Because of the following code in tablecmds.c:

    /*
     * No work if no change in tablespace.
     */
    oldTableSpace = rel->rd_rel->reltablespace;
    if (newTableSpace == oldTableSpace ||
        (newTableSpace == MyDatabaseTableSpace && oldTableSpace == 0))
    {
        InvokeObjectPostAlterHook(RelationRelationId,
                                  RelationGetRelid(rel), 0);

        relation_close(rel, NoLock);
        return;
    }

I found the thread discussing the similar problem:
https://www.postgresql.org/message-id/flat/BY5PR18MB3170E372542F34694E630B12F10C0%40BY5PR18MB3170.namprd18.prod.outlook.com

and looks like the decision was to change nothing and leave everything
as it is.

From my point of view the source of the problem is that pg_default
(oid=1663) is treated as database default tablespace.
pg_default stands for concrete tablespace and it is not clear why it is
treated in different way comparing with any other tablepsace.

--
Konstantin Knizhnik
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

Browse pgsql-hackers by date

  From Date Subject
Next Message Tom Lane 2020-12-21 16:03:13 Re: Dependency isn't created between extension and schema
Previous Message Arne Roland 2020-12-21 14:30:06 Re: a misbehavior of partition row movement (?)