Thread
-
Re: [PATCH] Add pg_get_tablespace_ddl() function to reconstruct CREATE TABLESPACE statement
Manni Wood <manni.wood@enterprisedb.com> โ 2025-11-03T23:49:23Z
On Fri, Oct 31, 2025 at 10:36โฏAM Jim Jones <jim.jones@uni-muenster.de> wrote: > Hi Manni, > > Thanks for the patch! > > On 29/10/2025 02:23, Manni Wood wrote: > > This patch creates a function pg_get_tablespace_ddl, designed to > > retrieve the full DDL statement for a tablespace. Users can obtain the > > DDL by providing the tablespace name, like so: > > > > SELECT pg_get_tablespace_ddl('regress_owner_tblsp'); > > pg_get_tablespace_ddl > > > > > --------------------------------------------------------------------------------------------------- > > CREATE TABLESPACE regress_owner_tblsp OWNER regress_user LOCATION > > '' WITH (random_page_cost = 3); > > > Here my first comments regarding usability: > > == quoted identifier == > > Tablespace names containing quoted identifiers cannot be parsed: > > postgres=# CREATE TABLESPACE "My TS" LOCATION '/tmp/ts'; > CREATE TABLESPACE > postgres=# SELECT pg_get_tablespace_ddl('"My TS"'); > ERROR: tablespace ""My TS"" does not exist > > The following works, but I guess it shouldn't: > > postgres=# SELECT pg_get_tablespace_ddl('My TS'); > pg_get_tablespace_ddl > ----------------------------------------------- > CREATE TABLESPACE "My TS" LOCATION '/tmp/ts'; > (1 row) > > The same applies for unicode characters: > > postgres=# CREATE TABLESPACE "๐" LOCATION '/tmp/ts'; > CREATE TABLESPACE > postgres=# SELECT pg_get_tablespace_ddl('"๐"'); > ERROR: tablespace ""๐"" does not exist > postgres=# SELECT pg_get_tablespace_ddl('๐'); > pg_get_tablespace_ddl > -------------------------------------------- > CREATE TABLESPACE "๐" LOCATION '/tmp/ts'; > (1 row) > > > == option precision == > > There is a precision loss in the options: > > postgres=# CREATE TABLESPACE ts OWNER u1 LOCATION '/tmp/ts' WITH > (seq_page_cost = 1.12345678910, random_page_cost = 1.12345678910, > effective_io_concurrency = 17, maintenance_io_concurrency = 18); > CREATE TABLESPACE > postgres=# SELECT pg_get_tablespace_ddl('ts'); > > pg_get_tablespace_ddl > > > --------------------------------------------------------------------------------------------------------------------------------------------- > --------------------------------- > CREATE TABLESPACE ts OWNER u1 LOCATION '/tmp/ts' WITH (random_page_cost > = 1.12346, seq_page_cost = 1.12346, effective_io_concurrency = 17, m > aintenance_io_concurrency = 18); > (1 row) > > \db shows it as in the CREATE TABLESPACE statement: > > postgres=# \db+ ts > > List of tablespaces > Name | Owner | Location | Access privileges | > Options > | Size | Description > > ------+-------+----------+-------------------+----------------------------------------------------------------------------------------------- > -------------------------+---------+------------- > ts | u1 | /tmp/ts | | > > {seq_page_cost=1.12345678910,random_page_cost=1.12345678910,effective_io_concurrency=17,mainte > nance_io_concurrency=18} | 0 bytes | > (1 row) > > > == permissions == > > Is it supposed to be visible to all users? > > postgres=# CREATE USER u1; > CREATE ROLE > postgres=# CREATE TABLESPACE ts LOCATION '/tmp/ts'; > CREATE TABLESPACE > postgres=# SET ROLE u1; > SET > postgres=> SELECT pg_get_tablespace_ddl('ts'); > pg_get_tablespace_ddl > ---------------------------------------------------- > CREATE TABLESPACE ts OWNER jim LOCATION '/tmp/ts'; > (1 row) > > Note that \db does not allow it: > > postgres=> SELECT CURRENT_USER; > current_user > -------------- > u1 > (1 row) > > postgres=> \db+ ts > ERROR: permission denied for tablespace ts > > > Best, Jim > > > Hi, Jim Thanks for reviewing my very first patch! == quoted identifier == I see that Postgres already has the SQL function has_tablespace_privilege that behaves the same way as this patch's pg_get_tablespace_ddl. # create tablespace "My TS" location '/tmp/has_space'; CREATE TABLESPACE # select has_tablespace_privilege('My TS', 'create'); rollback; โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ has_tablespace_privilege โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ t โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ (1 row) # select has_tablespace_privilege('"My TS"', 'create'); rollback; ERROR: 42704: tablespace ""My TS"" does not exist # create tablespace "๐" location '/tmp/has_elephant'; CREATE TABLESPACE # select has_tablespace_privilege('๐', 'create'); rollback; โโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ has_tablespace_privilege โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ t โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโ (1 row) # select has_tablespace_privilege('"๐"', 'create'); rollback; ERROR: 42704: tablespace ""๐"" does not exist Does the existence of this behavior in an existing function make the same behavior less surprising for this patch's function? == option precision == Thanks for pointing this out. I have attached a v2 of the patch that just uses the original text the user entered for the spcoptions. This is much better, and it made the code smaller. I have added "1.1234567890" to one of the tests to show that this works. == permissions == I'm not sure what to think of this. psql's "\db+" does not let me show the tablespace. But if, as user 'u1', I select from pg_tablespace directly, I have the permissions to do so: postgres> select current_user; rollback; โโโโโโโโโโโโโโโโ โ current_user โ โโโโโโโโโโโโโโโโค โ u1 โ โโโโโโโโโโโโโโโโ (1 row) postgres> select * from pg_catalog.pg_tablespace; rollback; โโโโโโโโโฌโโโโโโโโโโโโโฌโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ oid โ spcname โ spcowner โ spcacl โ spcoptions โ โโโโโโโโโผโโโโโโโโโโโโโผโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ 1663 โ pg_default โ 10 โ [NULL] โ [NULL] โ โ 1664 โ pg_global โ 10 โ [NULL] โ [NULL] โ โ 19971 โ ts โ 10 โ [NULL] โ {seq_page_cost=1.12345678910,random_page_cost=1.12345678910,effective_io_concurrency=17,maintenance_io_concurrency=18} โ โโโโโโโโโดโโโโโโโโโโโโโดโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ (3 rows) So if the information is obtainable by selecting from pg_catalog.pg_tablespace, it seems defensible to make the same data available via pg_get_tablespace_ddl. Thoughts? Thanks again for reviewing my patch, -Manni