Skip to content

Commit 501714a

Browse files
committed
Remove chunk_constraint catalog tracking for CHECK constraints
Removed chunk_constraint catalog tracking for inherited CHECK constraints on OSM (foreign-table) chunks. CHECKs are still physically created on the foreign chunk so ALTER TABLE ... INHERIT can merge them; from that point on PostgreSQL's normal inheritance handles rename/drop propagation.
1 parent 06e1fdd commit 501714a

7 files changed

Lines changed: 76 additions & 34 deletions

File tree

sql/updates/latest-dev.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
-- Inherited CHECK constraints on OSM chunks are no longer tracked in
2+
-- _timescaledb_catalog.chunk_constraint. PostgreSQL inheritance handles
3+
-- propagation, so the rows are redundant. Remove any rows left over from
4+
-- earlier versions.
5+
DELETE FROM _timescaledb_catalog.chunk_constraint cc
6+
USING _timescaledb_catalog.chunk c
7+
WHERE cc.chunk_id = c.id
8+
AND c.osm_chunk
9+
AND cc.dimension_slice_id IS NULL
10+
AND cc.hypertable_constraint_name IS NOT NULL
11+
AND cc.constraint_name = cc.hypertable_constraint_name;
12+

sql/updates/reverse-dev.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
-- Restore tracking rows for inherited CHECK constraints on OSM chunks.
2+
-- Earlier versions expected one chunk_constraint row per CHECK constraint
3+
-- inherited from the hypertable on each foreign-table chunk.
4+
INSERT INTO _timescaledb_catalog.chunk_constraint
5+
(chunk_id, dimension_slice_id, constraint_name, hypertable_constraint_name)
6+
SELECT c.id, NULL, con.conname, con.conname
7+
FROM _timescaledb_catalog.chunk c
8+
JOIN _timescaledb_catalog.hypertable ht ON ht.id = c.hypertable_id
9+
JOIN pg_class ht_class
10+
ON ht_class.relname = ht.table_name
11+
JOIN pg_namespace ht_ns
12+
ON ht_ns.oid = ht_class.relnamespace
13+
AND ht_ns.nspname = ht.schema_name
14+
JOIN pg_constraint con
15+
ON con.conrelid = ht_class.oid
16+
AND con.contype = 'c'
17+
WHERE c.osm_chunk
18+
ON CONFLICT DO NOTHING;
19+

src/chunk.c

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5065,17 +5065,11 @@ add_foreign_table_as_chunk(Oid relid, Hypertable *parent_ht)
50655065
/* insert dimension slices if they do not exist.
50665066
*/
50675067
ts_dimension_slice_insert_multi(chunk->cube->slices, chunk->cube->num_slices);
5068-
/* check constraints are not automatically created for foreign tables.
5069-
* See: ts_chunk_constraints_add_dimension_constraints.
5070-
* Collect all the check constraints from the hypertable and add them to the
5071-
* foreign table. Otherwise, cannot add as child of the hypertable (pg inheritance
5072-
* code will error. Note that the name of the check constraint on the hypertable
5073-
* and the foreign table chunk should match.
5068+
/* CHECK constraints are not inherited automatically by foreign tables, so
5069+
* clone them from the hypertable onto the foreign chunk before running
5070+
* ALTER TABLE ... INHERIT below.
50745071
*/
5075-
ts_chunk_constraints_add_inheritable_check_constraints(chunk->constraints,
5076-
chunk->fd.id,
5077-
chunk->relkind,
5078-
chunk->hypertable_relid);
5072+
ts_chunk_clone_check_constraints(relid, chunk->hypertable_relid);
50795073
chunk_create_table_constraints(parent_ht, chunk);
50805074
/* Add dimension constraints for the chunk */
50815075
ts_chunk_constraints_add_dimension_constraints(chunk->constraints, chunk->fd.id, chunk->cube);

src/chunk_constraint.c

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -858,37 +858,38 @@ ts_chunk_constraints_add_inheritable_constraints(ChunkConstraints *ccs, int32 ch
858858
return ts_constraint_process(hypertable_oid, chunk_constraint_add, &cc);
859859
}
860860

861-
/* check constraints have the same name as the one on the hypertable */
862861
static ConstraintProcessStatus
863-
chunk_constraint_add_check(HeapTuple constraint_tuple, void *arg)
862+
clone_check_constraint(HeapTuple tuple, void *arg)
864863
{
865-
ConstraintContext *cc = arg;
866-
Form_pg_constraint constraint = (Form_pg_constraint) GETSTRUCT(constraint_tuple);
864+
Form_pg_constraint con = (Form_pg_constraint) GETSTRUCT(tuple);
865+
Oid chunk_relid = *(Oid *) arg;
867866

868-
if (constraint->contype == CONSTRAINT_CHECK)
867+
if (con->contype != CONSTRAINT_CHECK)
869868
{
870-
ts_chunk_constraints_add(cc->ccs,
871-
cc->chunk_id,
872-
0,
873-
NameStr(constraint->conname),
874-
NameStr(constraint->conname));
875-
return CONSTR_PROCESSED;
869+
return CONSTR_IGNORED;
876870
}
877871

878-
return CONSTR_IGNORED;
872+
CatalogInternalCall2(DDL_CONSTRAINT_CLONE,
873+
ObjectIdGetDatum(con->oid),
874+
ObjectIdGetDatum(chunk_relid));
875+
return CONSTR_PROCESSED;
879876
}
880877

881-
/* Adds only inheritable check constraints */
882-
int
883-
ts_chunk_constraints_add_inheritable_check_constraints(ChunkConstraints *ccs, int32 chunk_id,
884-
const char chunk_relkind, Oid hypertable_oid)
878+
/*
879+
* Clone CHECK constraints from a hypertable onto a foreign-table chunk.
880+
*
881+
* Foreign tables do not inherit CHECK constraints automatically, so we
882+
* have to recreate the hypertable's CHECKs on the foreign chunk under
883+
* the same name before running ALTER TABLE ... INHERIT. PostgreSQL will
884+
* then merge the foreign chunk's CHECKs with the parent's and propagate
885+
* subsequent renames or drops via normal inheritance.
886+
*/
887+
void
888+
ts_chunk_clone_check_constraints(Oid chunk_relid, Oid hypertable_oid)
885889
{
886-
ConstraintContext cc = {
887-
.chunk_relkind = chunk_relkind,
888-
.ccs = ccs,
889-
.chunk_id = chunk_id,
890-
};
891-
return ts_constraint_process(hypertable_oid, chunk_constraint_add_check, &cc);
890+
ts_process_utility_set_expect_chunk_modification(true);
891+
ts_constraint_process(hypertable_oid, clone_check_constraint, &chunk_relid);
892+
ts_process_utility_set_expect_chunk_modification(false);
892893
}
893894

894895
void

src/chunk_constraint.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ extern TSDLLEXPORT int ts_chunk_constraints_add_inheritable_constraints(ChunkCon
5656
const char chunk_relkind,
5757
Oid hypertable_oid,
5858
Oid table_id);
59-
extern TSDLLEXPORT int ts_chunk_constraints_add_inheritable_check_constraints(
60-
ChunkConstraints *ccs, int32 chunk_id, const char chunk_relkind, Oid hypertable_oid);
59+
extern void ts_chunk_clone_check_constraints(Oid chunk_relid, Oid hypertable_oid);
6160
extern TSDLLEXPORT void ts_chunk_constraints_insert_metadata(const ChunkConstraints *ccs);
6261
extern TSDLLEXPORT Constraint *ts_chunk_constraint_dimensional_create(const Dimension *dim,
6362
const DimensionSlice *slice,

tsl/test/expected/chunk_utils_internal.out

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1021,6 +1021,16 @@ SELECT * FROM test.show_constraints('child_hyper_constr');
10211021
-------------------------+------+---------+-------+---------------------------------+------------+----------+-----------
10221022
hyper_constr_temp_check | c | {temp} | - | (temp > (10)::double precision) | f | f | t
10231023

1024+
-- inherited CHECK constraints on OSM chunks are not tracked in chunk_constraint
1025+
SELECT cc.constraint_name, cc.hypertable_constraint_name, cc.dimension_slice_id
1026+
FROM _timescaledb_catalog.chunk c
1027+
JOIN _timescaledb_catalog.chunk_constraint cc ON cc.chunk_id = c.id
1028+
WHERE c.table_name = 'child_hyper_constr'
1029+
ORDER BY cc.constraint_name;
1030+
constraint_name | hypertable_constraint_name | dimension_slice_id
1031+
-----------------+----------------------------+--------------------
1032+
constraint_19 | | 19
1033+
10241034
-- TEST foreign key trigger: deleting data from foreign table measure
10251035
-- does not error out due to data in osm chunk
10261036
\set ON_ERROR_STOP 0

tsl/test/sql/chunk_utils_internal.sql

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,6 +641,13 @@ SELECT * FROM hyper_constr WHERE time > 200 and time < 400 order by time;
641641
--TEST verify the check constraint exists on the OSM chunk
642642
SELECT * FROM test.show_constraints('child_hyper_constr');
643643

644+
-- inherited CHECK constraints on OSM chunks are not tracked in chunk_constraint
645+
SELECT cc.constraint_name, cc.hypertable_constraint_name, cc.dimension_slice_id
646+
FROM _timescaledb_catalog.chunk c
647+
JOIN _timescaledb_catalog.chunk_constraint cc ON cc.chunk_id = c.id
648+
WHERE c.table_name = 'child_hyper_constr'
649+
ORDER BY cc.constraint_name;
650+
644651
-- TEST foreign key trigger: deleting data from foreign table measure
645652
-- does not error out due to data in osm chunk
646653
\set ON_ERROR_STOP 0

0 commit comments

Comments
 (0)