Skip to content

Commit 2696582

Browse files
committed
Move index and constraints drop handling to event trigger
This Fixes at least two bugs: 1) A drop of a referenced table used to drop the associated FK constraint but not the metadata associated with the constraint. Fixes #43. 2) A drop of a column removed any indexes associated with the column but not the metadata associated with the index.
1 parent d6baccb commit 2696582

26 files changed

+650
-184
lines changed

sql/ddl_triggers.sql

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
CREATE OR REPLACE FUNCTION _timescaledb_internal.ddl_command_end() RETURNS event_trigger
2-
AS '@MODULE_PATHNAME@', 'timescaledb_ddl_command_end' LANGUAGE C;
1+
CREATE OR REPLACE FUNCTION _timescaledb_internal.process_ddl_event() RETURNS event_trigger
2+
AS '@MODULE_PATHNAME@', 'timescaledb_process_ddl_event' LANGUAGE C;
33

44
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_command_end;
55
--EVENT TRIGGER MUST exclude the ALTER EXTENSION tag.
66
CREATE EVENT TRIGGER timescaledb_ddl_command_end ON ddl_command_end
77
WHEN TAG IN ('ALTER TABLE','CREATE TRIGGER','CREATE TABLE','CREATE INDEX','ALTER INDEX')
8-
EXECUTE PROCEDURE _timescaledb_internal.ddl_command_end();
8+
EXECUTE PROCEDURE _timescaledb_internal.process_ddl_event();
9+
10+
DROP EVENT TRIGGER IF EXISTS timescaledb_ddl_sql_drop;
11+
CREATE EVENT TRIGGER timescaledb_ddl_sql_drop ON sql_drop
12+
EXECUTE PROCEDURE _timescaledb_internal.process_ddl_event();
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP FUNCTION _timescaledb_internal.ddl_command_end();

src/catalog.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ static const TableIndexDef catalog_table_index_definitions[_MAX_CATALOG_TABLES]
7171
[CHUNK_CONSTRAINT] = {
7272
.length = _MAX_CHUNK_CONSTRAINT_INDEX,
7373
.names = (char *[]) {
74+
[CHUNK_CONSTRAINT_CHUNK_ID_CONSTRAINT_NAME_IDX] = "chunk_constraint_chunk_id_constraint_name_key",
7475
[CHUNK_CONSTRAINT_CHUNK_ID_DIMENSION_SLICE_ID_IDX] = "chunk_constraint_chunk_id_dimension_slice_id_idx",
7576
}
7677
},

src/catalog.h

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ typedef enum CatalogTable
3434
} CatalogTable;
3535

3636
#define INVALID_CATALOG_TABLE _MAX_CATALOG_TABLES
37+
#define INVALID_INDEXID -1
38+
39+
#define CATALOG_INDEX(catalog, tableid, indexid) \
40+
(indexid == INVALID_INDEXID ? InvalidOid : (catalog)->tables[tableid].index_ids[indexid])
3741

3842
#define CatalogInternalCall1(func, datum1) \
3943
OidFunctionCall1(catalog_get_internal_function_id(catalog_get(), func), datum1)
@@ -329,7 +333,8 @@ typedef FormData_chunk_constraint *Form_chunk_constraint;
329333

330334
enum
331335
{
332-
CHUNK_CONSTRAINT_CHUNK_ID_DIMENSION_SLICE_ID_IDX = 0,
336+
CHUNK_CONSTRAINT_CHUNK_ID_CONSTRAINT_NAME_IDX = 0,
337+
CHUNK_CONSTRAINT_CHUNK_ID_DIMENSION_SLICE_ID_IDX,
333338
_MAX_CHUNK_CONSTRAINT_INDEX,
334339
};
335340

@@ -340,6 +345,13 @@ enum Anum_chunk_constraint_chunk_id_dimension_slice_id_idx
340345
_Anum_chunk_constraint_chunk_id_dimension_slice_id_idx_max,
341346
};
342347

348+
enum Anum_chunk_constraint_chunk_id_constraint_name_idx
349+
{
350+
Anum_chunk_constraint_chunk_id_constraint_name_idx_chunk_id = 1,
351+
Anum_chunk_constraint_chunk_id_constraint_name_idx_constraint_name,
352+
_Anum_chunk_constraint_chunk_id_constraint_name_idx_max,
353+
};
354+
343355
/************************************
344356
*
345357
* Chunk index table definitions

src/chunk.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,6 @@ chunk_fill_stub(Chunk *chunk_stub, bool tuplock)
566566
ScannerCtx ctx = {
567567
.table = catalog->tables[CHUNK].id,
568568
.index = catalog->tables[CHUNK].index_ids[CHUNK_ID_INDEX],
569-
.scantype = ScannerTypeIndex,
570569
.nkeys = 1,
571570
.scankey = scankey,
572571
.data = chunk_stub,
@@ -868,7 +867,6 @@ chunk_scan_internal(int indexid,
868867
ScannerCtx ctx = {
869868
.table = catalog->tables[CHUNK].id,
870869
.index = catalog->tables[CHUNK].index_ids[indexid],
871-
.scantype = ScannerTypeIndex,
872870
.nkeys = nkeys,
873871
.data = data,
874872
.scankey = scankey,

src/chunk_constraint.c

Lines changed: 81 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -356,8 +356,6 @@ chunk_constraint_tuple_found(TupleInfo *ti, void *data)
356356
return true;
357357
}
358358

359-
#define NO_INDEXSCAN -1
360-
361359
static int
362360
chunk_constraint_scan_internal(int indexid,
363361
ScanKeyData *scankey,
@@ -370,7 +368,7 @@ chunk_constraint_scan_internal(int indexid,
370368
Catalog *catalog = catalog_get();
371369
ScannerCtx scanctx = {
372370
.table = catalog->tables[CHUNK_CONSTRAINT].id,
373-
.scantype = (indexid == NO_INDEXSCAN) ? ScannerTypeHeap : ScannerTypeIndex,
371+
.index = CATALOG_INDEX(catalog, CHUNK_CONSTRAINT, indexid),
374372
.nkeys = nkeys,
375373
.scankey = scankey,
376374
.data = data,
@@ -380,9 +378,6 @@ chunk_constraint_scan_internal(int indexid,
380378
.scandirection = ForwardScanDirection,
381379
};
382380

383-
if (indexid != NO_INDEXSCAN)
384-
scanctx.index = catalog->tables[CHUNK_CONSTRAINT].index_ids[indexid];
385-
386381
return scanner_scan(&scanctx);
387382
}
388383

@@ -413,6 +408,38 @@ chunk_constraint_scan_by_chunk_id_internal(int32 chunk_id,
413408
lockmode);
414409
}
415410

411+
static int
412+
chunk_constraint_scan_by_chunk_id_constraint_name_internal(int32 chunk_id,
413+
const char *constraint_name,
414+
tuple_found_func tuple_found,
415+
tuple_found_func tuple_filter,
416+
void *data,
417+
LOCKMODE lockmode)
418+
{
419+
ScanKeyData scankey[2];
420+
421+
422+
ScanKeyInit(&scankey[0],
423+
Anum_chunk_constraint_chunk_id_constraint_name_idx_chunk_id,
424+
BTEqualStrategyNumber,
425+
F_INT4EQ,
426+
Int32GetDatum(chunk_id));
427+
428+
ScanKeyInit(&scankey[1],
429+
Anum_chunk_constraint_chunk_id_constraint_name_idx_constraint_name,
430+
BTEqualStrategyNumber,
431+
F_NAMEEQ,
432+
DirectFunctionCall1(namein, CStringGetDatum(constraint_name)));
433+
434+
return chunk_constraint_scan_internal(CHUNK_CONSTRAINT_CHUNK_ID_CONSTRAINT_NAME_IDX,
435+
scankey,
436+
2,
437+
tuple_found,
438+
tuple_filter,
439+
data,
440+
lockmode);
441+
}
442+
416443
/*
417444
* Scan all the chunk's constraints given its chunk ID.
418445
*
@@ -625,6 +652,8 @@ typedef struct ConstraintInfo
625652
{
626653
const char *hypertable_constraint_name;
627654
ChunkConstraints *ccs;
655+
bool delete_metadata;
656+
bool drop_constraint;
628657
} ConstraintInfo;
629658

630659
typedef struct RenameHypertableConstraintInfo
@@ -652,24 +681,29 @@ chunk_constraint_delete_tuple(TupleInfo *ti, void *data)
652681
ObjectAddress constrobj = {
653682
.classId = ConstraintRelationId,
654683
.objectId = get_relation_constraint_oid(chunk->table_id,
655-
NameStr(*DatumGetName(constrname)), false),
684+
NameStr(*DatumGetName(constrname)), true),
656685
};
657686
Oid index_relid = get_constraint_index(constrobj.objectId);
658687

659688
/* Collect the deleted constraints */
660-
if (NULL != info && NULL != info->ccs)
689+
if (NULL != info->ccs)
661690
chunk_constraint_tuple_found(ti, info->ccs);
662691

663-
/*
664-
* If this is an index constraint, we need to cleanup the index metadata.
665-
* Don't drop the index though, since that will happend when the
666-
* constraint is dropped.
667-
*/
668-
if (OidIsValid(index_relid))
669-
chunk_index_delete(chunk, index_relid, false);
692+
if (info->delete_metadata)
693+
{
694+
/*
695+
* If this is an index constraint, we need to cleanup the index
696+
* metadata. Don't drop the index though, since that will happend when
697+
* the constraint is dropped.
698+
*/
699+
if (OidIsValid(index_relid))
700+
chunk_index_delete(chunk, index_relid, false);
670701

671-
catalog_delete(ti->scanrel, ti->tuple);
672-
performDeletion(&constrobj, DROP_RESTRICT, 0);
702+
catalog_delete(ti->scanrel, ti->tuple);
703+
}
704+
705+
if (info->drop_constraint && OidIsValid(constrobj.objectId))
706+
performDeletion(&constrobj, DROP_RESTRICT, 0);
673707

674708
return true;
675709
}
@@ -695,10 +729,13 @@ hypertable_constraint_tuple_filter(TupleInfo *ti, void *data)
695729

696730
int
697731
chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id,
698-
char *hypertable_constraint_name)
732+
char *hypertable_constraint_name,
733+
bool delete_metadata, bool drop_constraint)
699734
{
700735
ConstraintInfo info = {
701736
.hypertable_constraint_name = hypertable_constraint_name,
737+
.delete_metadata = delete_metadata,
738+
.drop_constraint = drop_constraint
702739
};
703740

704741
return chunk_constraint_scan_by_chunk_id_internal(chunk_id,
@@ -708,6 +745,23 @@ chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id,
708745
RowExclusiveLock);
709746
}
710747

748+
int
749+
chunk_constraint_delete_by_constraint_name(int32 chunk_id, const char *constraint_name,
750+
bool delete_metadata, bool drop_constraint)
751+
{
752+
ConstraintInfo info = {
753+
.delete_metadata = delete_metadata,
754+
.drop_constraint = drop_constraint
755+
};
756+
757+
return chunk_constraint_scan_by_chunk_id_constraint_name_internal(chunk_id,
758+
constraint_name,
759+
chunk_constraint_delete_tuple,
760+
NULL,
761+
&info,
762+
RowExclusiveLock);
763+
}
764+
711765
/*
712766
* Delete all constraints for a chunk. Optionally, collect the deleted constraints.
713767
*/
@@ -716,6 +770,8 @@ chunk_constraint_delete_by_chunk_id(int32 chunk_id, ChunkConstraints *ccs)
716770
{
717771
ConstraintInfo info = {
718772
.ccs = ccs,
773+
.delete_metadata = true,
774+
.drop_constraint = true,
719775
};
720776

721777
return chunk_constraint_scan_by_chunk_id_internal(chunk_id,
@@ -728,6 +784,11 @@ chunk_constraint_delete_by_chunk_id(int32 chunk_id, ChunkConstraints *ccs)
728784
int
729785
chunk_constraint_delete_by_dimension_slice_id(int32 dimension_slice_id)
730786
{
787+
ConstraintInfo info = {
788+
.delete_metadata = true,
789+
.drop_constraint = true,
790+
};
791+
731792
ScanKeyData scankey[1];
732793

733794
ScanKeyInit(&scankey[0],
@@ -736,12 +797,12 @@ chunk_constraint_delete_by_dimension_slice_id(int32 dimension_slice_id)
736797
F_INT4EQ,
737798
Int32GetDatum(dimension_slice_id));
738799

739-
return chunk_constraint_scan_internal(NO_INDEXSCAN,
800+
return chunk_constraint_scan_internal(INVALID_INDEXID,
740801
scankey,
741802
1,
742803
chunk_constraint_delete_tuple,
743804
NULL,
744-
NULL,
805+
&info,
745806
RowExclusiveLock);
746807
}
747808

src/chunk_constraint.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ extern int chunk_constraints_add_dimension_constraints(ChunkConstraints *ccs, in
4242
extern int chunk_constraints_add_inheritable_constraints(ChunkConstraints *ccs, int32 chunk_id, Oid hypertable_oid);
4343
extern void chunk_constraints_create(ChunkConstraints *ccs, Oid chunk_oid, int32 chunk_id, Oid hypertable_oid, int32 hypertable_id);
4444
extern void chunk_constraint_create_on_chunk(Chunk *chunk, Oid constraint_oid);
45-
extern int chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id, char *hypertable_constraint_name);
45+
extern int chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id, char *hypertable_constraint_name, bool delete_metadata, bool drop_constraint);
4646
extern int chunk_constraint_delete_by_chunk_id(int32 chunk_id, ChunkConstraints *ccs);
4747
extern int chunk_constraint_delete_by_dimension_slice_id(int32 dimension_slice_id);
48+
extern int chunk_constraint_delete_by_constraint_name(int32 chunk_id, const char *constraint_name, bool delete_metadata, bool drop_constraint);
4849
extern void chunk_constraint_recreate(ChunkConstraint *cc, Oid chunk_oid);
4950
extern int chunk_constraint_rename_hypertable_constraint(int32 chunk_id, const char *oldname, const char *newname);
5051

0 commit comments

Comments
 (0)