Skip to content

Commit abe76fc

Browse files
committed
Add support for changing chunk schema and name
Previously, chunks could be renamed and have their schema changed, but the metadata in the TimescaleDB catalog was not updated in a corresponding way. Further, renaming a chunk column was possible, which could break functionality on the hypertable. Then catalog metadata is now properly updated on name and schema changes applied to chunks. Renaming chunk columns have been blocked with an informational error message.
1 parent 6e193c6 commit abe76fc

File tree

5 files changed

+132
-3
lines changed

5 files changed

+132
-3
lines changed

src/chunk.c

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1142,3 +1142,57 @@ chunk_recreate_all_constraints_for_dimension(Hyperspace *hs, int32 dimension_id)
11421142
chunk_scan_ctx_foreach_chunk(&chunkctx, chunk_recreate_constraint, 0);
11431143
chunk_scan_ctx_destroy(&chunkctx);
11441144
}
1145+
1146+
static bool
1147+
chunk_tuple_update(TupleInfo *ti, void *data)
1148+
{
1149+
HeapTuple tuple = heap_copytuple(ti->tuple);
1150+
FormData_chunk *form = (FormData_chunk *) GETSTRUCT(tuple);
1151+
FormData_chunk *update = data;
1152+
CatalogSecurityContext sec_ctx;
1153+
1154+
namecpy(&form->schema_name, &update->schema_name);
1155+
namecpy(&form->table_name, &update->table_name);
1156+
1157+
catalog_become_owner(catalog_get(), &sec_ctx);
1158+
catalog_update(ti->scanrel, tuple);
1159+
catalog_restore_user(&sec_ctx);
1160+
1161+
heap_freetuple(tuple);
1162+
1163+
return false;
1164+
}
1165+
1166+
static bool
1167+
chunk_update_form(FormData_chunk *form)
1168+
{
1169+
ScanKeyData scankey[1];
1170+
1171+
ScanKeyInit(&scankey[0], Anum_chunk_idx_id, BTEqualStrategyNumber,
1172+
F_INT4EQ, form->id);
1173+
1174+
return chunk_scan_internal(CHUNK_ID_INDEX,
1175+
scankey,
1176+
1,
1177+
chunk_tuple_update,
1178+
form,
1179+
0,
1180+
AccessShareLock,
1181+
CurrentMemoryContext) > 0;
1182+
}
1183+
1184+
bool
1185+
chunk_set_name(Chunk *chunk, const char *newname)
1186+
{
1187+
namestrcpy(&chunk->fd.table_name, newname);
1188+
1189+
return chunk_update_form(&chunk->fd);
1190+
}
1191+
1192+
bool
1193+
chunk_set_schema(Chunk *chunk, const char *newschema)
1194+
{
1195+
namestrcpy(&chunk->fd.schema_name, newschema);
1196+
1197+
return chunk_update_form(&chunk->fd);
1198+
}

src/chunk.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,8 @@ extern void chunk_recreate_all_constraints_for_dimension(Hyperspace *hs, int32 d
7777
extern int chunk_delete_by_relid(Oid chunk_oid);
7878
extern int chunk_delete_by_hypertable_id(int32 hypertable_id);
7979
extern int chunk_delete_by_name(const char *schema, const char *table);
80+
extern bool chunk_set_name(Chunk *chunk, const char *newname);
81+
extern bool chunk_set_schema(Chunk *chunk, const char *newschema);
8082

8183
#define chunk_get_by_name(schema_name, table_name, num_constraints, fail_if_not_found) \
8284
chunk_get_by_name_with_memory_context(schema_name, table_name, num_constraints, \

src/process_utility.c

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ relation_not_only(RangeVar *rv)
141141
errmsg("ONLY option not supported on hypertable operations")));
142142
}
143143

144-
/* Change the schema of a hypertable */
144+
/* Change the schema of a hypertable or a chunk */
145145
static void
146146
process_alterobjectschema(Node *parsetree)
147147
{
@@ -161,7 +161,14 @@ process_alterobjectschema(Node *parsetree)
161161
hcache = hypertable_cache_pin();
162162
ht = hypertable_cache_get_entry(hcache, relid);
163163

164-
if (ht != NULL)
164+
if (ht == NULL)
165+
{
166+
Chunk *chunk = chunk_get_by_relid(relid, 0, false);
167+
168+
if (NULL != chunk)
169+
chunk_set_schema(chunk, alterstmt->newschema);
170+
}
171+
else
165172
hypertable_set_schema(ht, alterstmt->newschema);
166173

167174
cache_release(hcache);
@@ -626,12 +633,22 @@ process_reindex(Node *parsetree)
626633
return ret;
627634
}
628635

636+
/*
637+
* Rename a hypertable or a chunk.
638+
*/
629639
static void
630640
process_rename_table(Cache *hcache, Oid relid, RenameStmt *stmt)
631641
{
632642
Hypertable *ht = hypertable_cache_get_entry(hcache, relid);
633643

634-
if (NULL != ht)
644+
if (NULL == ht)
645+
{
646+
Chunk *chunk = chunk_get_by_relid(relid, 0, false);
647+
648+
if (NULL != chunk)
649+
chunk_set_name(chunk, stmt->newname);
650+
}
651+
else
635652
hypertable_set_name(ht, stmt->newname);
636653
}
637654

@@ -642,7 +659,17 @@ process_rename_column(Cache *hcache, Oid relid, RenameStmt *stmt)
642659
Dimension *dim;
643660

644661
if (NULL == ht)
662+
{
663+
Chunk *chunk = chunk_get_by_relid(relid, 0, false);
664+
665+
if (NULL != chunk)
666+
ereport(ERROR,
667+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
668+
errmsg("cannot rename column \"%s\" of hypertable chunk \"%s\"",
669+
stmt->subname, get_rel_name(relid)),
670+
errhint("Rename the hypertable column instead.")));
645671
return;
672+
}
646673

647674
dim = hyperspace_get_dimension_by_name(ht->space, DIMENSION_TYPE_ANY, stmt->subname);
648675

test/expected/alter.out

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,3 +130,32 @@ SELECT * FROM alter_after;
130130
Tue Aug 22 09:19:14 2017 | 12.5 | 3 | 7
131131
(7 rows)
132132

133+
-- Need superuser to ALTER chunks in _timescaledb_internal schema
134+
\c single :ROLE_SUPERUSER
135+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
136+
id | hypertable_id | schema_name | table_name
137+
----+---------------+-----------------------+------------------
138+
2 | 2 | _timescaledb_internal | _hyper_2_2_chunk
139+
(1 row)
140+
141+
-- Rename chunk
142+
ALTER TABLE _timescaledb_internal._hyper_2_2_chunk RENAME TO new_chunk_name;
143+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
144+
id | hypertable_id | schema_name | table_name
145+
----+---------------+-----------------------+----------------
146+
2 | 2 | _timescaledb_internal | new_chunk_name
147+
(1 row)
148+
149+
-- Set schema
150+
ALTER TABLE _timescaledb_internal.new_chunk_name SET SCHEMA public;
151+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
152+
id | hypertable_id | schema_name | table_name
153+
----+---------------+-------------+----------------
154+
2 | 2 | public | new_chunk_name
155+
(1 row)
156+
157+
-- Test that we cannot rename chunk columns
158+
\set ON_ERROR_STOP 0
159+
ALTER TABLE public.new_chunk_name RENAME COLUMN time TO newtime;
160+
ERROR: cannot rename column "time" of hypertable chunk "new_chunk_name"
161+
\set ON_ERROR_STOP 1

test/sql/alter.sql

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,3 +56,20 @@ AND a.attnum > 0
5656
ORDER BY c.relname, a.attnum;
5757

5858
SELECT * FROM alter_after;
59+
60+
-- Need superuser to ALTER chunks in _timescaledb_internal schema
61+
\c single :ROLE_SUPERUSER
62+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
63+
64+
-- Rename chunk
65+
ALTER TABLE _timescaledb_internal._hyper_2_2_chunk RENAME TO new_chunk_name;
66+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
67+
68+
-- Set schema
69+
ALTER TABLE _timescaledb_internal.new_chunk_name SET SCHEMA public;
70+
SELECT * FROM _timescaledb_catalog.chunk WHERE id = 2;
71+
72+
-- Test that we cannot rename chunk columns
73+
\set ON_ERROR_STOP 0
74+
ALTER TABLE public.new_chunk_name RENAME COLUMN time TO newtime;
75+
\set ON_ERROR_STOP 1

0 commit comments

Comments
 (0)