mirror of
https://github.com/timescale/timescaledb.git
synced 2025-05-26 00:00:54 +08:00
Fix rename constraint/rename index
When a constraint is backed by an index like a unique constraint or a primary key constraint the constraint can be renamed by either ALTER TABLE RENAME CONSTRAINT or by ALTER INDEX RENAME. Depending on the command used to rename different internal metadata tables would be adjusted leading to corrupt metadata. This patch makes ALTER TABLE RENAME CONSTRAINT and ALTER INDEX RENAME adjust the same metadata tables.
This commit is contained in:
parent
202692f1ef
commit
6d7edb99ba
@ -853,6 +853,12 @@ chunk_constraint_rename_hypertable_from_tuple(TupleInfo *ti, const char *newname
|
||||
NameStr(new_chunk_constraint_name));
|
||||
|
||||
new_tuple = heap_modify_tuple(tuple, tupdesc, values, nulls, repl);
|
||||
|
||||
ts_chunk_index_adjust_meta(chunk_id,
|
||||
newname,
|
||||
NameStr(*old_chunk_constraint_name),
|
||||
NameStr(new_chunk_constraint_name));
|
||||
|
||||
ts_catalog_update(ti->scanrel, new_tuple);
|
||||
heap_freetuple(new_tuple);
|
||||
|
||||
@ -860,6 +866,52 @@ chunk_constraint_rename_hypertable_from_tuple(TupleInfo *ti, const char *newname
|
||||
heap_freetuple(tuple);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust internal metadata after index/constraint rename
|
||||
*/
|
||||
int
|
||||
ts_chunk_constraint_adjust_meta(int32 chunk_id, const char *ht_constraint_name, const char *oldname,
|
||||
const char *newname)
|
||||
{
|
||||
ScanIterator iterator =
|
||||
ts_scan_iterator_create(CHUNK_CONSTRAINT, RowExclusiveLock, CurrentMemoryContext);
|
||||
int count = 0;
|
||||
|
||||
init_scan_by_chunk_id_constraint_name(&iterator, chunk_id, oldname);
|
||||
|
||||
ts_scanner_foreach(&iterator)
|
||||
{
|
||||
bool nulls[Natts_chunk_constraint];
|
||||
bool repl[Natts_chunk_constraint] = { false };
|
||||
Datum values[Natts_chunk_constraint];
|
||||
bool should_free;
|
||||
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
|
||||
HeapTuple tuple = ts_scanner_fetch_heap_tuple(ti, false, &should_free);
|
||||
HeapTuple new_tuple;
|
||||
|
||||
heap_deform_tuple(tuple, ts_scanner_get_tupledesc(ti), values, nulls);
|
||||
|
||||
values[AttrNumberGetAttrOffset(Anum_chunk_constraint_hypertable_constraint_name)] =
|
||||
CStringGetDatum(ht_constraint_name);
|
||||
repl[AttrNumberGetAttrOffset(Anum_chunk_constraint_hypertable_constraint_name)] = true;
|
||||
values[AttrNumberGetAttrOffset(Anum_chunk_constraint_constraint_name)] =
|
||||
CStringGetDatum(newname);
|
||||
repl[AttrNumberGetAttrOffset(Anum_chunk_constraint_constraint_name)] = true;
|
||||
|
||||
new_tuple = heap_modify_tuple(tuple, ts_scanner_get_tupledesc(ti), values, nulls, repl);
|
||||
|
||||
ts_catalog_update(ti->scanrel, new_tuple);
|
||||
heap_freetuple(new_tuple);
|
||||
|
||||
if (should_free)
|
||||
heap_freetuple(tuple);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
ts_chunk_constraint_rename_hypertable_constraint(int32 chunk_id, const char *oldname,
|
||||
const char *newname)
|
||||
|
@ -69,6 +69,8 @@ extern int ts_chunk_constraint_delete_by_constraint_name(int32 chunk_id,
|
||||
extern void ts_chunk_constraint_recreate(ChunkConstraint *cc, Oid chunk_oid);
|
||||
extern int ts_chunk_constraint_rename_hypertable_constraint(int32 chunk_id, const char *oldname,
|
||||
const char *newname);
|
||||
extern int ts_chunk_constraint_adjust_meta(int32 chunk_id, const char *ht_constraint_name,
|
||||
const char *oldname, const char *newname);
|
||||
|
||||
extern char *
|
||||
ts_chunk_constraint_get_name_from_hypertable_constraint(Oid chunk_relid,
|
||||
|
@ -37,6 +37,7 @@
|
||||
#include "hypertable_cache.h"
|
||||
#include "catalog.h"
|
||||
#include "scanner.h"
|
||||
#include "scan_iterator.h"
|
||||
#include "chunk.h"
|
||||
|
||||
static bool chunk_index_insert(int32 chunk_id, const char *chunk_index, int32 hypertable_id,
|
||||
@ -888,6 +889,11 @@ chunk_index_tuple_rename(TupleInfo *ti, void *data)
|
||||
chunk_index_choose_name(NameStr(chunk->fd.table_name), info->newname, chunk_schemaoid);
|
||||
Oid chunk_indexrelid = get_relname_relid(NameStr(chunk_index->index_name), chunk_schemaoid);
|
||||
|
||||
ts_chunk_constraint_adjust_meta(chunk->fd.id,
|
||||
info->newname,
|
||||
NameStr(chunk_index->index_name),
|
||||
chunk_index_name);
|
||||
|
||||
/* Update the metadata */
|
||||
namestrcpy(&chunk_index->index_name, chunk_index_name);
|
||||
namestrcpy(&chunk_index->hypertable_index_name, info->newname);
|
||||
@ -907,6 +913,68 @@ chunk_index_tuple_rename(TupleInfo *ti, void *data)
|
||||
return SCAN_DONE;
|
||||
}
|
||||
|
||||
static void
|
||||
init_scan_by_chunk_id_index_name(ScanIterator *iterator, int32 chunk_id, const char *index_name)
|
||||
{
|
||||
iterator->ctx.index =
|
||||
catalog_get_index(ts_catalog_get(), CHUNK_INDEX, CHUNK_INDEX_CHUNK_ID_INDEX_NAME_IDX);
|
||||
|
||||
ts_scan_iterator_scan_key_init(iterator,
|
||||
Anum_chunk_index_chunk_id,
|
||||
BTEqualStrategyNumber,
|
||||
F_INT4EQ,
|
||||
Int32GetDatum(chunk_id));
|
||||
ts_scan_iterator_scan_key_init(iterator,
|
||||
Anum_chunk_index_index_name,
|
||||
BTEqualStrategyNumber,
|
||||
F_NAMEEQ,
|
||||
CStringGetDatum(index_name));
|
||||
}
|
||||
|
||||
/*
|
||||
* Adjust internal metadata after index/constraint rename
|
||||
*/
|
||||
int
|
||||
ts_chunk_index_adjust_meta(int32 chunk_id, const char *ht_index_name, const char *oldname,
|
||||
const char *newname)
|
||||
{
|
||||
ScanIterator iterator =
|
||||
ts_scan_iterator_create(CHUNK_INDEX, RowExclusiveLock, CurrentMemoryContext);
|
||||
int count = 0;
|
||||
|
||||
init_scan_by_chunk_id_index_name(&iterator, chunk_id, oldname);
|
||||
|
||||
ts_scanner_foreach(&iterator)
|
||||
{
|
||||
bool nulls[Natts_chunk_index];
|
||||
bool repl[Natts_chunk_index] = { false };
|
||||
Datum values[Natts_chunk_index];
|
||||
bool should_free;
|
||||
TupleInfo *ti = ts_scan_iterator_tuple_info(&iterator);
|
||||
HeapTuple tuple = ts_scanner_fetch_heap_tuple(ti, false, &should_free);
|
||||
HeapTuple new_tuple;
|
||||
|
||||
heap_deform_tuple(tuple, ts_scanner_get_tupledesc(ti), values, nulls);
|
||||
|
||||
values[AttrNumberGetAttrOffset(Anum_chunk_index_hypertable_index_name)] =
|
||||
CStringGetDatum(ht_index_name);
|
||||
repl[AttrNumberGetAttrOffset(Anum_chunk_index_hypertable_index_name)] = true;
|
||||
values[AttrNumberGetAttrOffset(Anum_chunk_index_index_name)] = CStringGetDatum(newname);
|
||||
repl[AttrNumberGetAttrOffset(Anum_chunk_index_index_name)] = true;
|
||||
|
||||
new_tuple = heap_modify_tuple(tuple, ts_scanner_get_tupledesc(ti), values, nulls, repl);
|
||||
|
||||
ts_catalog_update(ti->scanrel, new_tuple);
|
||||
heap_freetuple(new_tuple);
|
||||
|
||||
if (should_free)
|
||||
heap_freetuple(tuple);
|
||||
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
int
|
||||
ts_chunk_index_rename(Chunk *chunk, Oid chunk_indexrelid, const char *newname)
|
||||
{
|
||||
|
@ -45,6 +45,8 @@ extern void ts_chunk_index_delete_by_name(const char *schema, const char *index_
|
||||
extern int ts_chunk_index_rename(Chunk *chunk, Oid chunk_indexrelid, const char *newname);
|
||||
extern int ts_chunk_index_rename_parent(Hypertable *ht, Oid hypertable_indexrelid,
|
||||
const char *newname);
|
||||
extern int ts_chunk_index_adjust_meta(int32 chunk_id, const char *ht_index_name,
|
||||
const char *old_name, const char *new_name);
|
||||
extern int ts_chunk_index_set_tablespace(Hypertable *ht, Oid hypertable_indexrelid,
|
||||
const char *tablespace);
|
||||
extern void ts_chunk_index_create_from_constraint(int32 hypertable_id, Oid hypertable_constraint,
|
||||
|
@ -686,3 +686,51 @@ SELECT * from _timescaledb_catalog.chunk;
|
||||
(2 rows)
|
||||
|
||||
DROP TABLE my_table;
|
||||
-- test renaming unique constraints/indexes
|
||||
CREATE TABLE t_hypertable ( id INTEGER NOT NULL, time TIMESTAMPTZ NOT NULL, value FLOAT NOT NULL CHECK (value > 0), UNIQUE(id, time));
|
||||
SELECT create_hypertable('t_hypertable', 'time');
|
||||
create_hypertable
|
||||
----------------------------
|
||||
(13,public,t_hypertable,t)
|
||||
(1 row)
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:00:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2021-01-01 00:00:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
BEGIN;
|
||||
ALTER INDEX t_hypertable_id_time_key RENAME TO t_new_constraint;
|
||||
-- chunk_index and chunk_constraint should both have updated constraint names
|
||||
SELECT hypertable_index_name, index_name from _timescaledb_catalog.chunk_index WHERE hypertable_index_name = 't_new_constraint' ORDER BY 1,2;
|
||||
hypertable_index_name | index_name
|
||||
-----------------------+-------------------------------------
|
||||
t_new_constraint | _hyper_13_26_chunk_t_new_constraint
|
||||
t_new_constraint | _hyper_13_27_chunk_t_new_constraint
|
||||
(2 rows)
|
||||
|
||||
SELECT hypertable_constraint_name, constraint_name from _timescaledb_catalog.chunk_constraint WHERE hypertable_constraint_name = 't_new_constraint' ORDER BY 1,2;
|
||||
hypertable_constraint_name | constraint_name
|
||||
----------------------------+-------------------------------------
|
||||
t_new_constraint | _hyper_13_26_chunk_t_new_constraint
|
||||
t_new_constraint | _hyper_13_27_chunk_t_new_constraint
|
||||
(2 rows)
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:01:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
ROLLBACK;
|
||||
BEGIN;
|
||||
ALTER TABLE t_hypertable RENAME CONSTRAINT t_hypertable_id_time_key TO t_new_constraint;
|
||||
-- chunk_index and chunk_constraint should both have updated constraint names
|
||||
SELECT hypertable_index_name, index_name from _timescaledb_catalog.chunk_index WHERE hypertable_index_name = 't_new_constraint' ORDER BY 1,2;
|
||||
hypertable_index_name | index_name
|
||||
-----------------------+-----------------------
|
||||
t_new_constraint | 26_5_t_new_constraint
|
||||
t_new_constraint | 27_6_t_new_constraint
|
||||
(2 rows)
|
||||
|
||||
SELECT hypertable_constraint_name, constraint_name from _timescaledb_catalog.chunk_constraint WHERE hypertable_constraint_name = 't_new_constraint' ORDER BY 1,2;
|
||||
hypertable_constraint_name | constraint_name
|
||||
----------------------------+-----------------------
|
||||
t_new_constraint | 26_5_t_new_constraint
|
||||
t_new_constraint | 27_6_t_new_constraint
|
||||
(2 rows)
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:01:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
ROLLBACK;
|
||||
|
@ -378,3 +378,31 @@ SELECT * from _timescaledb_catalog.hypertable;
|
||||
SELECT * from _timescaledb_catalog.chunk;
|
||||
|
||||
DROP TABLE my_table;
|
||||
|
||||
-- test renaming unique constraints/indexes
|
||||
CREATE TABLE t_hypertable ( id INTEGER NOT NULL, time TIMESTAMPTZ NOT NULL, value FLOAT NOT NULL CHECK (value > 0), UNIQUE(id, time));
|
||||
SELECT create_hypertable('t_hypertable', 'time');
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:00:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2021-01-01 00:00:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
|
||||
BEGIN;
|
||||
ALTER INDEX t_hypertable_id_time_key RENAME TO t_new_constraint;
|
||||
|
||||
-- chunk_index and chunk_constraint should both have updated constraint names
|
||||
SELECT hypertable_index_name, index_name from _timescaledb_catalog.chunk_index WHERE hypertable_index_name = 't_new_constraint' ORDER BY 1,2;
|
||||
SELECT hypertable_constraint_name, constraint_name from _timescaledb_catalog.chunk_constraint WHERE hypertable_constraint_name = 't_new_constraint' ORDER BY 1,2;
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:01:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
ROLLBACK;
|
||||
|
||||
BEGIN;
|
||||
ALTER TABLE t_hypertable RENAME CONSTRAINT t_hypertable_id_time_key TO t_new_constraint;
|
||||
|
||||
-- chunk_index and chunk_constraint should both have updated constraint names
|
||||
SELECT hypertable_index_name, index_name from _timescaledb_catalog.chunk_index WHERE hypertable_index_name = 't_new_constraint' ORDER BY 1,2;
|
||||
SELECT hypertable_constraint_name, constraint_name from _timescaledb_catalog.chunk_constraint WHERE hypertable_constraint_name = 't_new_constraint' ORDER BY 1,2;
|
||||
|
||||
INSERT INTO t_hypertable AS h VALUES ( 1, '2020-01-01 00:01:00', 3.2) ON CONFLICT (id, time) DO UPDATE SET value = h.value + EXCLUDED.value;
|
||||
ROLLBACK;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user