diff --git a/src/chunk.c b/src/chunk.c index 9ef5ead14..54c427f1c 100644 --- a/src/chunk.c +++ b/src/chunk.c @@ -400,7 +400,7 @@ chunk_create_table(Chunk *chunk, Hypertable *ht) .type = T_CreateStmt, .relation = makeRangeVar(NameStr(chunk->fd.schema_name), NameStr(chunk->fd.table_name), 0), .inhRelations = list_make1(makeRangeVar(NameStr(ht->fd.schema_name), NameStr(ht->fd.table_name), 0)), - .tablespacename = hypertable_select_tablespace(ht, chunk), + .tablespacename = hypertable_select_tablespace_name(ht, chunk), .options = get_reloptions(ht->main_table_relid), }; Oid uid, diff --git a/src/chunk_index.c b/src/chunk_index.c index 5fe9a6250..2e7d8d580 100644 --- a/src/chunk_index.c +++ b/src/chunk_index.c @@ -195,6 +195,35 @@ chunk_adjust_attnos(IndexInfo *ii, Relation htrel, Relation idxrel, Relation chu chunk_adjust_expr_attnos(ii, htrel, idxrel, chunkrel); } +#define CHUNK_INDEX_TABLESPACE_OFFSET 1 + + +/* + * Pick a chunk index's tablespace at an offset from the chunk's tablespace in + * order to avoid colocating chunks and their indexes in the same tablespace. + * This hopefully leads to more I/O parallelism. + */ +static Oid +chunk_index_select_tablespace(Relation htrel, Relation chunkrel) +{ + Cache *hcache = hypertable_cache_pin(); + Hypertable *ht = hypertable_cache_get_entry(hcache, htrel->rd_id); + Tablespace *tspc; + Oid tablespace_oid = InvalidOid; + + Assert(ht != NULL); + + tspc = hypertable_get_tablespace_at_offset_from(ht, chunkrel->rd_rel->reltablespace, + CHUNK_INDEX_TABLESPACE_OFFSET); + + if (NULL != tspc) + tablespace_oid = tspc->tablespace_oid; + + cache_release(hcache); + + return tablespace_oid; +} + /* * Create a chunk index based on the configuration of the "parent" index. */ @@ -213,6 +242,7 @@ chunk_relation_index_create(Relation htrel, Datum indclass; oidvector *indclassoid; List *colnames = create_index_colnames(template_indexrel); + Oid tablespace = InvalidOid; /* * Convert the IndexInfo's attnos to match the chunk instead of the @@ -239,6 +269,15 @@ chunk_relation_index_create(Relation htrel, get_rel_name(RelationGetRelid(template_indexrel)), get_rel_namespace(RelationGetRelid(chunkrel))); + /* + * Determine the index's tablespace. Use the main index's tablespace, or, + * if not set, select one at an offset from the chunk's tablespace. + */ + if (OidIsValid(template_indexrel->rd_rel->reltablespace)) + tablespace = template_indexrel->rd_rel->reltablespace; + else + tablespace = chunk_index_select_tablespace(htrel, chunkrel); + chunk_indexrelid = index_create(chunkrel, indexname, InvalidOid, @@ -246,7 +285,7 @@ chunk_relation_index_create(Relation htrel, indexinfo, colnames, template_indexrel->rd_rel->relam, - template_indexrel->rd_rel->reltablespace, + tablespace, template_indexrel->rd_indcollation, indclassoid->values, template_indexrel->rd_indoption, diff --git a/src/hypertable.c b/src/hypertable.c index 73f18d1c0..18ec16afc 100644 --- a/src/hypertable.c +++ b/src/hypertable.c @@ -282,7 +282,7 @@ hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid) * chunks in the same closed (space) dimension. This ensures chunks in the same * "space" partition will live on the same disk. */ -char * +Tablespace * hypertable_select_tablespace(Hypertable *ht, Chunk *chunk) { Dimension *dim; @@ -318,7 +318,39 @@ hypertable_select_tablespace(Hypertable *ht, Chunk *chunk) Assert(i >= 0); /* Use the index of the slice to find the tablespace */ - return NameStr(tspcs->tablespaces[i % tspcs->num_tablespaces].fd.tablespace_name); + return &tspcs->tablespaces[i % tspcs->num_tablespaces]; +} + +char * +hypertable_select_tablespace_name(Hypertable *ht, Chunk *chunk) +{ + Tablespace *tspc = hypertable_select_tablespace(ht, chunk); + + if (NULL == tspc) + return NULL; + + return NameStr(tspc->fd.tablespace_name); +} + +/* + * Get the tablespace at an offset from the given tablespace. + */ +Tablespace * +hypertable_get_tablespace_at_offset_from(Hypertable *ht, Oid tablespace_oid, int16 offset) +{ + Tablespaces *tspcs = tablespace_scan(ht->fd.id); + int i = 0; + + if (NULL == tspcs || tspcs->num_tablespaces == 0) + return NULL; + + for (i = 0; i < tspcs->num_tablespaces; i++) + { + if (tablespace_oid == tspcs->tablespaces[i].tablespace_oid) + return &tspcs->tablespaces[(i + offset) % tspcs->num_tablespaces]; + } + + return NULL; } static inline Oid diff --git a/src/hypertable.h b/src/hypertable.h index 9d1752162..da706662c 100644 --- a/src/hypertable.h +++ b/src/hypertable.h @@ -30,6 +30,8 @@ extern Chunk *hypertable_get_chunk(Hypertable *h, Point *point); extern Oid hypertable_relid(RangeVar *rv); extern bool is_hypertable(Oid relid); extern bool hypertable_has_tablespace(Hypertable *ht, Oid tspc_oid); -extern char *hypertable_select_tablespace(Hypertable *ht, Chunk *chunk); +extern Tablespace *hypertable_select_tablespace(Hypertable *ht, Chunk *chunk); +extern char *hypertable_select_tablespace_name(Hypertable *ht, Chunk *chunk); +extern Tablespace *hypertable_get_tablespace_at_offset_from(Hypertable *ht, Oid tablespace_oid, int16 offset); #endif /* TIMESCALEDB_HYPERTABLE_H */ diff --git a/test/expected/drop_chunks.out b/test/expected/drop_chunks.out index 0f16fbfd6..6f4ccf85d 100644 --- a/test/expected/drop_chunks.out +++ b/test/expected/drop_chunks.out @@ -318,15 +318,15 @@ SET timezone = '+1'; INSERT INTO PUBLIC.drop_chunk_test_ts VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1'); INSERT INTO PUBLIC.drop_chunk_test_tstz VALUES(now()-INTERVAL '5 minutes', 1.0, 'dev1'); SELECT * FROM test.show_subtables('drop_chunk_test_ts'); - Child ------------------------------------------ - _timescaledb_internal._hyper_4_19_chunk + Child | Tablespace +-----------------------------------------+------------ + _timescaledb_internal._hyper_4_19_chunk | (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_tstz'); - Child ------------------------------------------ - _timescaledb_internal._hyper_5_20_chunk + Child | Tablespace +-----------------------------------------+------------ + _timescaledb_internal._hyper_5_20_chunk | (1 row) BEGIN; @@ -337,8 +337,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_ts'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) SELECT drop_chunks(interval '1 minute', 'drop_chunk_test_tstz'); @@ -348,8 +348,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_tstz'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) ROLLBACK; @@ -361,8 +361,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_ts'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) SELECT drop_chunks(now()-interval '1 minute', 'drop_chunk_test_tstz'); @@ -372,8 +372,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_tstz'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) ROLLBACK; @@ -405,8 +405,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_date'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) ROLLBACK; @@ -418,8 +418,8 @@ BEGIN; (1 row) SELECT * FROM test.show_subtables('drop_chunk_test_date'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) ROLLBACK; diff --git a/test/expected/index.out b/test/expected/index.out index d6e445a74..ba655c50f 100644 --- a/test/expected/index.out +++ b/test/expected/index.out @@ -398,7 +398,7 @@ SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); ----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+------------- _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1 _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2 - _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | + _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | tablespace1 (3 rows) -- Creating a new index should propagate to existing chunks, including @@ -418,7 +418,7 @@ SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); ----------------------------------------+-------------------------------------------------------------------+--------------------+--------+---------+-----------+------------- _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_idx | {time,temp,device} | f | f | f | tablespace1 _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_time_device_idx | {time,temp,device} | f | f | f | tablespace2 - _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | + _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_index_test_device_idx | {time,temp,device} | f | f | f | tablespace1 _timescaledb_internal._hyper_5_5_chunk | _timescaledb_internal._hyper_5_5_chunk_time_temp_idx | {time,temp,device} | f | f | f | tablespace2 (4 rows) diff --git a/test/expected/reindex.out b/test/expected/reindex.out index 091c033c0..8f9423da3 100644 --- a/test/expected/reindex.out +++ b/test/expected/reindex.out @@ -21,13 +21,13 @@ SELECT * FROM test.show_columns('reindex_test'); (2 rows) SELECT * FROM test.show_subtables('reindex_test'); - Child ----------------------------------------- - _timescaledb_internal._hyper_1_1_chunk - _timescaledb_internal._hyper_1_2_chunk - _timescaledb_internal._hyper_1_3_chunk - _timescaledb_internal._hyper_1_4_chunk - _timescaledb_internal._hyper_1_5_chunk + Child | Tablespace +----------------------------------------+------------ + _timescaledb_internal._hyper_1_1_chunk | + _timescaledb_internal._hyper_1_2_chunk | + _timescaledb_internal._hyper_1_3_chunk | + _timescaledb_internal._hyper_1_4_chunk | + _timescaledb_internal._hyper_1_5_chunk | (5 rows) -- show reindexing diff --git a/test/expected/sql_query.out b/test/expected/sql_query.out index 6f55b8e99..3ac8ea897 100644 --- a/test/expected/sql_query.out +++ b/test/expected/sql_query.out @@ -122,10 +122,10 @@ INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 1, 22.5); INSERT INTO "int_part" VALUES('2017-01-20T09:00:01', 2, 22.5); --check that there are two chunks SELECT * FROM test.show_subtables('int_part'); - Child ----------------------------------------- - _timescaledb_internal._hyper_2_5_chunk - _timescaledb_internal._hyper_2_6_chunk + Child | Tablespace +----------------------------------------+------------ + _timescaledb_internal._hyper_2_5_chunk | + _timescaledb_internal._hyper_2_6_chunk | (2 rows) SELECT * FROM "int_part" WHERE object_id = 1; diff --git a/test/expected/tablespace.out b/test/expected/tablespace.out index 916ac10fc..328446952 100644 --- a/test/expected/tablespace.out +++ b/test/expected/tablespace.out @@ -77,25 +77,33 @@ SELECT * FROM show_tablespaces('tspace_2dim'); --insert into another chunk INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown'); -SELECT relname, spcname FROM pg_class c -INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid) -INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname); - relname | spcname -------------------+------------- - _hyper_1_1_chunk | tablespace1 - _hyper_1_2_chunk | tablespace2 +SELECT * FROM test.show_subtables('tspace_2dim'); + Child | Tablespace +----------------------------------------+------------- + _timescaledb_internal._hyper_1_1_chunk | tablespace1 + _timescaledb_internal._hyper_1_2_chunk | tablespace2 (2 rows) +--indexes should inherit the tablespace of their chunk +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Unique | Primary | Exclusion | Tablespace +----------------------------------------+--------------------------------------------------------------------+--------------------+--------+---------+-----------+------------- + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1 +(4 rows) + -- SET ROLE :ROLE_DEFAULT_PERM_USER_2; -- User doesn't have permission on tablespace1 --> error -CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1; -ERROR: permission denied for tablespace tablespace1 +CREATE TABLE tspace_1dim(time timestamp, temp float, device text); -- Grant permission to tablespace1 SET ROLE :ROLE_DEFAULT_PERM_USER; GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2; SET ROLE :ROLE_DEFAULT_PERM_USER_2; -CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1; +CREATE TABLE tspace_1dim(time timestamp, temp float, device text); +ERROR: relation "tspace_1dim" already exists SELECT create_hypertable('tspace_1dim', 'time'); NOTICE: Adding NOT NULL constraint to time column time (NULL time values not allowed) create_hypertable @@ -103,6 +111,12 @@ NOTICE: Adding NOT NULL constraint to time column time (NULL time values not al (1 row) +SELECT attach_tablespace('tablespace1', 'tspace_1dim'); + attach_tablespace +------------------- + +(1 row) + SELECT attach_tablespace('tablespace2', 'tspace_1dim'); attach_tablespace ------------------- @@ -120,17 +134,33 @@ SELECT * FROM _timescaledb_catalog.tablespace; INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue'); INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown'); -SELECT relname, spcname FROM pg_class c -INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid) -INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname); - relname | spcname -------------------+------------- - _hyper_1_1_chunk | tablespace1 - _hyper_1_2_chunk | tablespace2 - _hyper_2_3_chunk | tablespace1 - _hyper_2_4_chunk | tablespace2 +SELECT * FROM test.show_subtablesp('tspace_%'); + Parent | Child | Tablespace +-------------+----------------------------------------+------------- + tspace_2dim | _timescaledb_internal._hyper_1_1_chunk | tablespace1 + tspace_2dim | _timescaledb_internal._hyper_1_2_chunk | tablespace2 + tspace_1dim | _timescaledb_internal._hyper_2_3_chunk | tablespace1 + tspace_1dim | _timescaledb_internal._hyper_2_4_chunk | tablespace2 (4 rows) +--indexes should inherit the tablespace of their chunk, unless the +--parent index has a tablespace set, in which case the chunks' +--corresponding indexes are pinned to the parent index's +--tablespace. The parent index can have a tablespace set in two cases: +--(1) if explicitly set in CREATE INDEX, or (2) if the main table was +--created with a tablespace, because then default indexes will be +--created in that tablespace too. +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); + Table | Index | Columns | Unique | Primary | Exclusion | Tablespace +----------------------------------------+--------------------------------------------------------------------+--------------------+--------+---------+-----------+------------- + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_1_chunk | _timescaledb_internal._hyper_1_1_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_1_2_chunk | _timescaledb_internal._hyper_1_2_chunk_tspace_2dim_device_time_idx | {time,temp,device} | f | f | f | tablespace1 + _timescaledb_internal._hyper_2_3_chunk | _timescaledb_internal._hyper_2_3_chunk_tspace_1dim_time_idx | {time,temp,device} | f | f | f | tablespace2 + _timescaledb_internal._hyper_2_4_chunk | _timescaledb_internal._hyper_2_4_chunk_tspace_1dim_time_idx | {time,temp,device} | f | f | f | tablespace1 +(6 rows) + --detach tablespace1 from all tables. Due to lack of permissions, --should only detach from 'tspace_1dim' (1 tablespace) SELECT detach_tablespace('tablespace1'); diff --git a/test/expected/truncate_hypertable.out b/test/expected/truncate_hypertable.out index 89668fab1..6a347f30e 100644 --- a/test/expected/truncate_hypertable.out +++ b/test/expected/truncate_hypertable.out @@ -45,12 +45,12 @@ SELECT * FROM _timescaledb_catalog.chunk; (4 rows) SELECT * FROM test.show_subtables('"two_Partitions"'); - Child ----------------------------------------- - _timescaledb_internal._hyper_1_1_chunk - _timescaledb_internal._hyper_1_2_chunk - _timescaledb_internal._hyper_1_3_chunk - _timescaledb_internal._hyper_1_4_chunk + Child | Tablespace +----------------------------------------+------------ + _timescaledb_internal._hyper_1_1_chunk | + _timescaledb_internal._hyper_1_2_chunk | + _timescaledb_internal._hyper_1_3_chunk | + _timescaledb_internal._hyper_1_4_chunk | (4 rows) SELECT * FROM "two_Partitions"; @@ -85,8 +85,8 @@ SELECT * FROM _timescaledb_catalog.chunk; -- should be empty SELECT * FROM test.show_subtables('"two_Partitions"'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) SELECT * FROM "two_Partitions"; @@ -140,8 +140,8 @@ WARNING: FIRING trigger when: BEFORE level: STATEMENT op: TRUNCATE cnt: WARNING: FIRING trigger when: AFTER level: STATEMENT op: TRUNCATE cnt: trigger_name _test_truncate_after -- should be empty SELECT * FROM test.show_subtables('"two_Partitions"'); - Child -------- + Child | Tablespace +-------+------------ (0 rows) SELECT * FROM "two_Partitions"; diff --git a/test/sql/tablespace.sql b/test/sql/tablespace.sql index 852c87ef3..42e776396 100644 --- a/test/sql/tablespace.sql +++ b/test/sql/tablespace.sql @@ -57,22 +57,24 @@ SELECT * FROM show_tablespaces('tspace_2dim'); --insert into another chunk INSERT INTO tspace_2dim VALUES ('2017-01-20T09:00:01', 24.3, 'brown'); -SELECT relname, spcname FROM pg_class c -INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid) -INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname); +SELECT * FROM test.show_subtables('tspace_2dim'); + +--indexes should inherit the tablespace of their chunk +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); -- SET ROLE :ROLE_DEFAULT_PERM_USER_2; -- User doesn't have permission on tablespace1 --> error -CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1; +CREATE TABLE tspace_1dim(time timestamp, temp float, device text); -- Grant permission to tablespace1 SET ROLE :ROLE_DEFAULT_PERM_USER; GRANT CREATE ON TABLESPACE tablespace1 TO :ROLE_DEFAULT_PERM_USER_2; SET ROLE :ROLE_DEFAULT_PERM_USER_2; -CREATE TABLE tspace_1dim(time timestamp, temp float, device text) TABLESPACE tablespace1; +CREATE TABLE tspace_1dim(time timestamp, temp float, device text); SELECT create_hypertable('tspace_1dim', 'time'); +SELECT attach_tablespace('tablespace1', 'tspace_1dim'); SELECT attach_tablespace('tablespace2', 'tspace_1dim'); SELECT * FROM _timescaledb_catalog.tablespace; @@ -80,9 +82,15 @@ SELECT * FROM _timescaledb_catalog.tablespace; INSERT INTO tspace_1dim VALUES ('2017-01-20T09:00:01', 24.3, 'blue'); INSERT INTO tspace_1dim VALUES ('2017-03-20T09:00:01', 24.3, 'brown'); -SELECT relname, spcname FROM pg_class c -INNER JOIN pg_tablespace t ON (c.reltablespace = t.oid) -INNER JOIN _timescaledb_catalog.chunk ch ON (ch.table_name = c.relname); +SELECT * FROM test.show_subtablesp('tspace_%'); +--indexes should inherit the tablespace of their chunk, unless the +--parent index has a tablespace set, in which case the chunks' +--corresponding indexes are pinned to the parent index's +--tablespace. The parent index can have a tablespace set in two cases: +--(1) if explicitly set in CREATE INDEX, or (2) if the main table was +--created with a tablespace, because then default indexes will be +--created in that tablespace too. +SELECT * FROM test.show_indexesp('_timescaledb_internal._hyper%_chunk'); --detach tablespace1 from all tables. Due to lack of permissions, --should only detach from 'tspace_1dim' (1 tablespace) diff --git a/test/sql/utils/testsupport.sql b/test/sql/utils/testsupport.sql index 445760247..b749224e5 100644 --- a/test/sql/utils/testsupport.sql +++ b/test/sql/utils/testsupport.sql @@ -198,19 +198,22 @@ END $BODY$; CREATE OR REPLACE FUNCTION test.show_subtables(rel regclass) -RETURNS TABLE("Child" regclass) LANGUAGE SQL STABLE AS +RETURNS TABLE("Child" regclass, + "Tablespace" name) LANGUAGE SQL STABLE AS $BODY$ - SELECT objid::regclass - FROM pg_depend d + SELECT objid::regclass, (SELECT t.spcname FROM pg_tablespace t WHERE t.oid = c.reltablespace) + FROM pg_depend d, pg_class c WHERE d.refobjid = rel AND d.deptype = 'n' AND d.classid = 'pg_class'::regclass + AND d.objid = c.oid ORDER BY d.refobjid, d.objid; $BODY$; CREATE OR REPLACE FUNCTION test.show_subtablesp(pattern text) RETURNS TABLE("Parent" regclass, - "Child" regclass) LANGUAGE PLPGSQL STABLE AS + "Child" regclass, + "Tablespace" name) LANGUAGE PLPGSQL STABLE AS $BODY$ DECLARE schema_name name = split_part(pattern, '.', 1); @@ -223,7 +226,8 @@ BEGIN RETURN QUERY SELECT refobjid::regclass, - objid::regclass + objid::regclass, + (SELECT t.spcname FROM pg_class cc, pg_tablespace t WHERE cc.oid = d.objid AND t.oid = cc.reltablespace) FROM pg_class c, pg_depend d WHERE format('%I.%I', c.relnamespace::regnamespace::name, c.relname) LIKE format('%I.%s', schema_name, table_name) AND d.refobjid = c.oid