Skip to content

Commit 71b1124

Browse files
committed
Delete orphaned dimension slices
When chunks are deleted, dimension slices can be orphaned, i.e., there are no chunks or chunk constraints that reference such slices. This change ensures that, when chunks are deleted, orphaned slices are also deleted.
1 parent fa19a54 commit 71b1124

File tree

6 files changed

+366
-26
lines changed

6 files changed

+366
-26
lines changed

sql/updates/pre-0.8.0--0.9.0-dev.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,3 +43,10 @@ DROP FUNCTION _timescaledb_internal.chunk_create_table(int, name);
4343
DROP INDEX _timescaledb_catalog.dimension_slice_dimension_id_range_start_range_end_idx;
4444

4545
DROP FUNCTION _timescaledb_internal.drop_hypertable(int,boolean);
46+
47+
-- Delete orphaned slices
48+
DELETE FROM _timescaledb_catalog.dimension_slice WHERE id IN
49+
(SELECT dimension_id FROM _timescaledb_catalog.chunk_constraint cc
50+
FULL OUTER JOIN _timescaledb_catalog.dimension_slice ds
51+
ON (ds.id = cc.dimension_slice_id)
52+
WHERE dimension_slice_id IS NULL);

src/chunk.c

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -647,7 +647,7 @@ dimension_slice_and_chunk_constraint_join(ChunkScanCtx *scanctx, DimensionVec *v
647647
* For each dimension slice, find matching constraints. These will be
648648
* saved in the scan context
649649
*/
650-
chunk_constraint_scan_by_dimension_slice_id(vec->slices[i], scanctx);
650+
chunk_constraint_scan_by_dimension_slice(vec->slices[i], scanctx);
651651
}
652652
}
653653

@@ -990,10 +990,26 @@ chunk_tuple_delete(TupleInfo *ti, void *data)
990990
{
991991
FormData_chunk *form = (FormData_chunk *) GETSTRUCT(ti->tuple);
992992
CatalogSecurityContext sec_ctx;
993+
ChunkConstraints *ccs = chunk_constraints_alloc(2);
994+
int i;
993995

994-
chunk_constraint_delete_by_chunk_id(form->id);
996+
chunk_constraint_delete_by_chunk_id(form->id, ccs);
995997
chunk_index_delete_by_chunk_id(form->id, true);
996998

999+
/* Check for dimension slices that are orphaned by the chunk deletion */
1000+
for (i = 0; i < ccs->num_constraints; i++)
1001+
{
1002+
ChunkConstraint *cc = &ccs->constraints[i];
1003+
1004+
/*
1005+
* Delete the dimension slice if there are no remaining constraints
1006+
* referencing it
1007+
*/
1008+
if (is_dimension_constraint(cc) &&
1009+
chunk_constraint_scan_by_dimension_slice_id(cc->fd.dimension_slice_id, NULL) == 0)
1010+
dimension_slice_delete_by_id(cc->fd.dimension_slice_id, false);
1011+
}
1012+
9971013
catalog_become_owner(catalog_get(), &sec_ctx);
9981014
catalog_delete(ti->scanrel, ti->tuple);
9991015
catalog_restore_user(&sec_ctx);
@@ -1066,7 +1082,7 @@ chunk_recreate_all_constraints_for_dimension(Hyperspace *hs, int32 dimension_id)
10661082
chunk_scan_ctx_init(&chunkctx, hs, NULL);
10671083

10681084
for (i = 0; i < slices->num_slices; i++)
1069-
chunk_constraint_scan_by_dimension_slice_id(slices->slices[i], &chunkctx);
1085+
chunk_constraint_scan_by_dimension_slice(slices->slices[i], &chunkctx);
10701086

10711087
chunk_scan_ctx_foreach_chunk(&chunkctx, chunk_recreate_constraint, 0);
10721088
chunk_scan_ctx_destroy(&chunkctx);

src/chunk_constraint.c

Lines changed: 69 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,13 @@ chunk_constraints_expand(ChunkConstraints *ccs, int16 new_capacity)
6767
ccs->constraints = repalloc(ccs->constraints, CHUNK_CONSTRAINTS_SIZE(new_capacity));
6868
}
6969

70-
7170
static
7271
void
73-
chunk_constraint_choose_name(Name dst, bool is_dimension, int32 dimension_slice_id, const char *hypertable_constraint_name, int32 chunk_id)
72+
chunk_constraint_choose_name(Name dst,
73+
bool is_dimension,
74+
int32 dimension_slice_id,
75+
const char *hypertable_constraint_name,
76+
int32 chunk_id)
7477
{
7578
if (is_dimension)
7679
{
@@ -216,7 +219,8 @@ chunk_constraints_add_from_tuple(ChunkConstraints *ccs, TupleInfo *ti)
216219
heap_deform_tuple(ti->tuple, ti->desc, values, nulls);
217220

218221
constraint_name = DatumGetName(values[Anum_chunk_constraint_constraint_name - 1]);
219-
if (heap_attisnull(ti->tuple, Anum_chunk_constraint_dimension_slice_id))
222+
223+
if (nulls[Anum_chunk_constraint_dimension_slice_id - 1])
220224
{
221225
dimension_slice_id = 0;
222226
hypertable_constraint_name = DatumGetName(values[Anum_chunk_constraint_hypertable_constraint_name - 1]);
@@ -332,6 +336,9 @@ chunk_constraints_create(ChunkConstraints *ccs,
332336
hypertable_id);
333337
}
334338

339+
/*
340+
* Scan filter function for only getting dimension constraints.
341+
*/
335342
static bool
336343
chunk_constraint_for_dimension_slice(TupleInfo *ti, void *data)
337344
{
@@ -343,7 +350,8 @@ chunk_constraint_tuple_found(TupleInfo *ti, void *data)
343350
{
344351
ChunkConstraints *ccs = data;
345352

346-
chunk_constraints_add_from_tuple(ccs, ti);
353+
if (NULL != ccs)
354+
chunk_constraints_add_from_tuple(ccs, ti);
347355

348356
return true;
349357
}
@@ -469,34 +477,58 @@ chunk_constraint_dimension_slice_id_tuple_found(TupleInfo *ti, void *data)
469477
return true;
470478
}
471479

472-
/*
473-
* Scan for all chunk constraints that match the given slice ID. The chunk
474-
* constraints are saved in the chunk scan context.
475-
*/
476-
int
477-
chunk_constraint_scan_by_dimension_slice_id(DimensionSlice *slice, ChunkScanCtx *ctx)
480+
static int
481+
scan_by_dimension_slice_id(int32 dimension_slice_id,
482+
tuple_found_func tuple_found,
483+
void *data)
478484
{
479485
ScanKeyData scankey[1];
480-
ChunkConstraintScanData data = {
481-
.scanctx = ctx,
482-
.slice = slice,
483-
};
484486

485487
ScanKeyInit(&scankey[0],
486488
Anum_chunk_constraint_chunk_id_dimension_slice_id_idx_dimension_slice_id,
487489
BTEqualStrategyNumber,
488490
F_INT4EQ,
489-
Int32GetDatum(slice->fd.id));
491+
Int32GetDatum(dimension_slice_id));
490492

491493
return chunk_constraint_scan_internal(CHUNK_CONSTRAINT_CHUNK_ID_DIMENSION_SLICE_ID_IDX,
492494
scankey,
493495
1,
494-
chunk_constraint_dimension_slice_id_tuple_found,
496+
tuple_found,
495497
chunk_constraint_for_dimension_slice,
496-
&data,
498+
data,
497499
AccessShareLock);
498500
}
499501

502+
/*
503+
* Scan for all chunk constraints that match the given slice ID. The chunk
504+
* constraints are saved in the chunk scan context.
505+
*/
506+
int
507+
chunk_constraint_scan_by_dimension_slice(DimensionSlice *slice, ChunkScanCtx *ctx)
508+
{
509+
ChunkConstraintScanData data = {
510+
.scanctx = ctx,
511+
.slice = slice,
512+
};
513+
514+
return scan_by_dimension_slice_id(slice->fd.id,
515+
chunk_constraint_dimension_slice_id_tuple_found,
516+
&data);
517+
}
518+
519+
/*
520+
* Scan for chunk constraints given a dimension slice ID.
521+
*
522+
* Optionally, collect all chunk constraints if ChunkConstraints is non-NULL.
523+
*/
524+
int
525+
chunk_constraint_scan_by_dimension_slice_id(int32 dimension_slice_id, ChunkConstraints *ccs)
526+
{
527+
return scan_by_dimension_slice_id(dimension_slice_id,
528+
chunk_constraint_tuple_found,
529+
ccs);
530+
}
531+
500532
static bool
501533
chunk_constraint_need_on_chunk(Form_pg_constraint conform)
502534
{
@@ -592,6 +624,7 @@ chunk_constraint_create_on_chunk(Chunk *chunk, Oid constraint_oid)
592624
typedef struct ConstraintInfo
593625
{
594626
const char *hypertable_constraint_name;
627+
ChunkConstraints *ccs;
595628
} ConstraintInfo;
596629

597630
typedef struct RenameHypertableConstraintInfo
@@ -601,9 +634,15 @@ typedef struct RenameHypertableConstraintInfo
601634
} RenameHypertableConstraintInfo;
602635

603636

637+
/*
638+
* Delete a chunk constraint tuple.
639+
*
640+
* Optionally, the data argument is a ConstraintInfo.
641+
*/
604642
static bool
605643
chunk_constraint_delete_tuple(TupleInfo *ti, void *data)
606644
{
645+
ConstraintInfo *info = data;
607646
bool isnull;
608647
Datum constrname = heap_getattr(ti->tuple, Anum_chunk_constraint_constraint_name,
609648
ti->desc, &isnull);
@@ -617,6 +656,10 @@ chunk_constraint_delete_tuple(TupleInfo *ti, void *data)
617656
};
618657
Oid index_relid = get_constraint_index(constrobj.objectId);
619658

659+
/* Collect the deleted constraints */
660+
if (NULL != info && NULL != info->ccs)
661+
chunk_constraint_tuple_found(ti, info->ccs);
662+
620663
/*
621664
* If this is an index constraint, we need to cleanup the index metadata.
622665
* Don't drop the index though, since that will happend when the
@@ -665,13 +708,20 @@ chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id,
665708
RowExclusiveLock);
666709
}
667710

711+
/*
712+
* Delete all constraints for a chunk. Optionally, collect the deleted constraints.
713+
*/
668714
int
669-
chunk_constraint_delete_by_chunk_id(int32 chunk_id)
715+
chunk_constraint_delete_by_chunk_id(int32 chunk_id, ChunkConstraints *ccs)
670716
{
717+
ConstraintInfo info = {
718+
.ccs = ccs,
719+
};
720+
671721
return chunk_constraint_scan_by_chunk_id_internal(chunk_id,
672722
chunk_constraint_delete_tuple,
673723
NULL,
674-
NULL,
724+
&info,
675725
RowExclusiveLock);
676726
}
677727

src/chunk_constraint.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ typedef struct ChunkScanCtx ChunkScanCtx;
3636
extern ChunkConstraints *chunk_constraints_alloc(int size_hint);
3737
extern ChunkConstraints *chunk_constraint_scan_by_chunk_id(int32 chunk_id, Size count_hint);
3838
extern ChunkConstraints *chunk_constraints_copy(ChunkConstraints *constraints);
39+
extern int chunk_constraint_scan_by_dimension_slice(DimensionSlice *slice, ChunkScanCtx *ctx);
40+
extern int chunk_constraint_scan_by_dimension_slice_id(int32 dimension_slice_id, ChunkConstraints *ccs);
3941
extern int chunk_constraints_add_dimension_constraints(ChunkConstraints *ccs, int32 chunk_id, Hypercube *cube);
4042
extern int chunk_constraints_add_inheritable_constraints(ChunkConstraints *ccs, int32 chunk_id, Oid hypertable_oid);
4143
extern void chunk_constraints_create(ChunkConstraints *ccs, Oid chunk_oid, int32 chunk_id, Oid hypertable_oid, int32 hypertable_id);
42-
43-
extern int chunk_constraint_scan_by_dimension_slice_id(DimensionSlice *slice, ChunkScanCtx *ctx);
4444
extern void chunk_constraint_create_on_chunk(Chunk *chunk, Oid constraint_oid);
4545
extern int chunk_constraint_delete_by_hypertable_constraint_name(int32 chunk_id, char *hypertable_constraint_name);
46-
extern int chunk_constraint_delete_by_chunk_id(int32 chunk_i);
46+
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);
4848
extern void chunk_constraint_recreate(ChunkConstraint *cc, Oid chunk_oid);
4949
extern int chunk_constraint_rename_hypertable_constraint(int32 chunk_id, const char *oldname, const char *newname);

0 commit comments

Comments
 (0)