-- PK with a range column/PERIOD that isn't there:
CREATETABLE temporal_rng (
id INTEGER, CONSTRAINT temporal_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
);
-- PK with a non-range column:
CREATETABLE temporal_rng (
id int4range,
valid_at TEXT, CONSTRAINT temporal_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
);
-- PK with one column plus a range:
CREATETABLE temporal_rng ( -- Since we can't depend on having btree_gist here, -- use an int4range instead of an int. -- (The rangetypes regression test uses the same trick.)
id int4range,
valid_at daterange, CONSTRAINT temporal_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
);
\d temporal_rng SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng_pk'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng_pk';
-- PK from LIKE: CREATETABLE temporal_rng2 (LIKE temporal_rng INCLUDING ALL);
\d temporal_rng2 DROPTABLE temporal_rng2;
-- no PK from INHERITS: CREATETABLE temporal_rng2 () INHERITS (temporal_rng);
\d temporal_rng2 DROPTABLE temporal_rng2; DROPTABLE temporal_rng;
-- PK with two columns plus a range: CREATETABLE temporal_rng2 (
id1 int4range,
id2 int4range,
valid_at daterange, CONSTRAINT temporal_rng2_pk PRIMARYKEY (id1, id2, valid_at WITHOUT OVERLAPS)
);
\d temporal_rng2 SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng2_pk'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng2_pk';
-- PK with a custom range type: CREATE TYPE textrange2 AS range (subtype=text, collation="C"); CREATETABLE temporal_rng3 (
id int4range,
valid_at textrange2, CONSTRAINT temporal_rng3_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
); ALTERTABLE temporal_rng3 DROPCONSTRAINT temporal_rng3_pk; DROPTABLE temporal_rng3; DROP TYPE textrange2;
-- PK with one column plus a multirange: CREATETABLE temporal_mltrng (
id int4range,
valid_at datemultirange, CONSTRAINT temporal_mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
);
\d temporal_mltrng SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng_pk';
-- PK with two columns plus a multirange: CREATETABLE temporal_mltrng2 (
id1 int4range,
id2 int4range,
valid_at datemultirange, CONSTRAINT temporal_mltrng2_pk PRIMARYKEY (id1, id2, valid_at WITHOUT OVERLAPS)
);
\d temporal_mltrng2 SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_mltrng2_pk';
-- UNIQUE with a range column/PERIOD that isn't there:
CREATETABLE temporal_rng3 (
id INTEGER, CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
);
-- UNIQUE with a non-range column:
CREATETABLE temporal_rng3 (
id int4range,
valid_at TEXT, CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
);
-- UNIQUE with one column plus a range:
CREATETABLE temporal_rng3 (
id int4range,
valid_at daterange, CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
);
\d temporal_rng3 SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; DROPTABLE temporal_rng3;
-- UNIQUE with two columns plus a range: CREATETABLE temporal_rng3 (
id1 int4range,
id2 int4range,
valid_at daterange, CONSTRAINT temporal_rng3_uq UNIQUE (id1, id2, valid_at WITHOUT OVERLAPS)
);
\d temporal_rng3 SELECT pg_get_constraintdef(oid) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; SELECT pg_get_indexdef(conindid, 0, true) FROM pg_constraint WHERE conname = 'temporal_rng3_uq'; DROPTABLE temporal_rng3;
-- UNIQUE with a custom range type: CREATE TYPE textrange2 AS range (subtype=text, collation="C"); CREATETABLE temporal_rng3 (
id int4range,
valid_at textrange2, CONSTRAINT temporal_rng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
); ALTERTABLE temporal_rng3 DROPCONSTRAINT temporal_rng3_uq; DROPTABLE temporal_rng3; DROP TYPE textrange2;
-- -- test PRIMARY KEY and UNIQUE constraints' interaction with domains --
-- range over domain: CREATE DOMAIN int4_d asintegercheck (value <> 10); CREATE TYPE int4_d_range as range (subtype = int4_d); CREATETABLE temporal_rng4 (
id int4range,
valid_at int4_d_range, CONSTRAINT temporal_rng4_pk PRIMARYKEY(id, valid_at WITHOUT OVERLAPS)
); INSERTINTO temporal_rng4 VALUES ('[1,11)', '[9,10)'); -- start bound violates domain INSERTINTO temporal_rng4 VALUES ('[1,2)', '[10,11)'); -- end bound violates domain INSERTINTO temporal_rng4 VALUES ('[1,2)', '[1,13)'), ('[1,2)', '[2,5)'); -- overlaps INSERTINTO temporal_rng4 VALUES ('[1,2)', '[1,13)'), ('[1,2)', '[20,23)'); -- okay INSERTINTO temporal_rng4 VALUES ('[1,2)', '[30,)'); -- null bound is okay DROPTABLE temporal_rng4;
CREATETABLE temporal_rng (
id int4range,
valid_at daterange
); ALTERTABLE temporal_rng ADDCONSTRAINT temporal_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS);
-- PK with USING INDEX (not possible): CREATETABLE temporal3 (
id int4range,
valid_at daterange
); CREATEINDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); ALTERTABLE temporal3 ADDCONSTRAINT temporal3_pk PRIMARYKEYUSINGINDEX idx_temporal3_uq; DROPTABLE temporal3;
-- UNIQUE with USING INDEX (not possible): CREATETABLE temporal3 (
id int4range,
valid_at daterange
); CREATEINDEX idx_temporal3_uq ON temporal3 USING gist (id, valid_at); ALTERTABLE temporal3 ADDCONSTRAINT temporal3_uq UNIQUEUSINGINDEX idx_temporal3_uq; DROPTABLE temporal3;
-- UNIQUE with USING [UNIQUE] INDEX (possible but not a temporal constraint): CREATETABLE temporal3 (
id int4range,
valid_at daterange
); CREATEUNIQUEINDEX idx_temporal3_uq ON temporal3 (id, valid_at); ALTERTABLE temporal3 ADDCONSTRAINT temporal3_uq UNIQUEUSINGINDEX idx_temporal3_uq; DROPTABLE temporal3;
-- Add range column and the PK at the same time CREATETABLE temporal3 (
id int4range
); ALTERTABLE temporal3 ADDCOLUMN valid_at daterange, ADDCONSTRAINT temporal3_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS); DROPTABLE temporal3;
-- Add range column and UNIQUE constraint at the same time CREATETABLE temporal3 (
id int4range
); ALTERTABLE temporal3 ADDCOLUMN valid_at daterange, ADDCONSTRAINT temporal3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS); DROPTABLE temporal3;
-- update the scalar part UPDATE temporal_rng SET id = '[11,12)' WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; -- update the range part UPDATE temporal_rng SET valid_at = '[2020-01-01,2021-01-01)' WHERE id = '[11,12)' AND valid_at @> '2018-01-15'::date; -- update both at once UPDATE temporal_rng SET id = '[21,22)',
valid_at = '[2018-01-02,2018-02-03)' WHERE id = '[11,12)' AND valid_at @> '2020-01-15'::date; SELECT * FROM temporal_rng ORDERBY id, valid_at; -- should fail: UPDATE temporal_rng SET id = '[1,2)',
valid_at = daterange('2018-03-05', '2018-05-05') WHERE id = '[21,22)'; -- set the scalar part to NULL UPDATE temporal_rng SET id = NULL,
valid_at = daterange('2018-03-05', '2018-05-05') WHERE id = '[21,22)'; -- set the range part to NULL UPDATE temporal_rng SET id = '[1,2)',
valid_at = NULL WHERE id = '[21,22)'; -- rejects empty: UPDATE temporal_rng SET id = '[1,2)',
valid_at = 'empty' WHERE id = '[21,22)'; SELECT * FROM temporal_rng ORDERBY id, valid_at;
-- -- range UQ: test with existing rows --
CREATETABLE temporal_rng3 (
id int4range,
valid_at daterange
);
-- update the scalar part UPDATE temporal_rng3 SET id = '[11,12)' WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; -- update the range part UPDATE temporal_rng3 SET valid_at = '[2020-01-01,2021-01-01)' WHERE id = '[11,12)' AND valid_at @> '2018-01-15'::date; -- update both at once UPDATE temporal_rng3 SET id = '[21,22)',
valid_at = '[2018-01-02,2018-02-03)' WHERE id = '[11,12)' AND valid_at @> '2020-01-15'::date; -- set the scalar part to NULL UPDATE temporal_rng3 SET id = NULL,
valid_at = daterange('2020-01-01', '2021-01-01') WHERE id = '[21,22)'; -- set the range part to NULL UPDATE temporal_rng3 SET id = '[1,2)',
valid_at = NULL WHERE id ISNULLAND valid_at @> '2020-06-01'::date; SELECT * FROM temporal_rng3 ORDERBY id, valid_at; -- should fail: UPDATE temporal_rng3 SET valid_at = daterange('2018-03-01', '2018-05-05') WHERE id = '[1,2)'AND valid_at ISNULL; -- rejects empty: UPDATE temporal_rng3 SET valid_at = 'empty' WHERE id = '[1,2)'AND valid_at ISNULL; -- still rejects empty when scalar part is NULL: UPDATE temporal_rng3 SET id = NULL,
valid_at = 'empty' WHERE id = '[1,2)'AND valid_at ISNULL; SELECT * FROM temporal_rng3 ORDERBY id, valid_at; DROPTABLE temporal_rng3;
-- update the scalar part UPDATE temporal_mltrng SET id = '[11,12)' WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; -- update the multirange part UPDATE temporal_mltrng SET valid_at = '{[2020-01-01,2021-01-01)}' WHERE id = '[11,12)' AND valid_at @> '2018-01-15'::date; -- update both at once UPDATE temporal_mltrng SET id = '[21,22)',
valid_at = '{[2018-01-02,2018-02-03)}' WHERE id = '[11,12)' AND valid_at @> '2020-01-15'::date; SELECT * FROM temporal_mltrng ORDERBY id, valid_at; -- should fail: UPDATE temporal_mltrng SET id = '[1,2)',
valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) WHERE id = '[21,22)'; -- set the scalar part to NULL UPDATE temporal_mltrng SET id = NULL,
valid_at = datemultirange(daterange('2018-03-05', '2018-05-05')) WHERE id = '[21,22)'; -- set the multirange part to NULL UPDATE temporal_mltrng SET id = '[1,2)',
valid_at = NULL WHERE id = '[21,22)'; -- rejects empty: UPDATE temporal_mltrng SET id = '[1,2)',
valid_at = '{}' WHERE id = '[21,22)'; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
-- -- multirange UQ: test with existing rows --
CREATETABLE temporal_mltrng3 (
id int4range,
valid_at datemultirange
);
-- update the scalar part UPDATE temporal_mltrng3 SET id = '[11,12)' WHERE id = '[1,2)' AND valid_at @> '2018-01-15'::date; -- update the multirange part UPDATE temporal_mltrng3 SET valid_at = '{[2020-01-01,2021-01-01)}' WHERE id = '[11,12)' AND valid_at @> '2018-01-15'::date; -- update both at once UPDATE temporal_mltrng3 SET id = '[21,22)',
valid_at = '{[2018-01-02,2018-02-03)}' WHERE id = '[11,12)' AND valid_at @> '2020-01-15'::date; -- set the scalar part to NULL UPDATE temporal_mltrng3 SET id = NULL,
valid_at = datemultirange(daterange('2020-01-01', '2021-01-01')) WHERE id = '[21,22)'; -- set the multirange part to NULL UPDATE temporal_mltrng3 SET id = '[1,2)',
valid_at = NULL WHERE id ISNULLAND valid_at @> '2020-06-01'::date; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at; -- should fail: UPDATE temporal_mltrng3 SET valid_at = datemultirange(daterange('2018-03-01', '2018-05-05')) WHERE id = '[1,2)'AND valid_at ISNULL; -- rejects empty: UPDATE temporal_mltrng3 SET valid_at = '{}' WHERE id = '[1,2)'AND valid_at ISNULL; -- still rejects empty when scalar part is NULL: UPDATE temporal_mltrng3 SET id = NULL,
valid_at = '{}' WHERE id = '[1,2)'AND valid_at ISNULL; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at; DROPTABLE temporal_mltrng3;
-- -- test a range with both a PK and a UNIQUE constraint --
TRUNCATE temporal_rng; INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; -- id matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; -- date matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; SELECT * FROM temporal_rng ORDERBY id, valid_at;
TRUNCATE temporal_rng; INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; -- id matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; -- date matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; SELECT * FROM temporal_rng ORDERBY id, valid_at;
TRUNCATE temporal_rng; INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO NOTHING; -- id matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO NOTHING; -- date matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO NOTHING; SELECT * FROM temporal_rng ORDERBY id, valid_at;
TRUNCATE temporal_rng; INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_rng ORDERBY id, valid_at;
TRUNCATE temporal_rng; INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_rng (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal_rng_pk DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_rng ORDERBY id, valid_at;
-- with a UNIQUE constraint:
CREATETABLE temporal3 (
id int4range,
valid_at daterange, CONSTRAINT temporal3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
);
TRUNCATE temporal3; INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; -- id matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT DO NOTHING; -- date matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT DO NOTHING; SELECT * FROM temporal3 ORDERBY id, valid_at;
TRUNCATE temporal3; INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; -- id matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; -- date matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO NOTHING; SELECT * FROM temporal3 ORDERBY id, valid_at;
TRUNCATE temporal3; INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO NOTHING; -- id matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO NOTHING; -- date matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO NOTHING; SELECT * FROM temporal3 ORDERBY id, valid_at;
TRUNCATE temporal3; INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal3 ORDERBY id, valid_at;
TRUNCATE temporal3; INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2000-01-01', '2010-01-01')); -- with a conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[1,2)', daterange('2010-01-01', '2020-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal3 (id, valid_at) VALUES ('[2,3)', daterange('2005-01-01', '2006-01-01')) ON CONFLICT ONCONSTRAINT temporal3_uq DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal3 ORDERBY id, valid_at;
DROPTABLE temporal3;
-- -- ON CONFLICT: multiranges --
TRUNCATE temporal_mltrng; INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
TRUNCATE temporal_mltrng; INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
TRUNCATE temporal_mltrng; INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO NOTHING; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
TRUNCATE temporal_mltrng; INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
TRUNCATE temporal_mltrng; INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng_pk DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_mltrng ORDERBY id, valid_at;
-- with a UNIQUE constraint:
CREATETABLE temporal_mltrng3 (
id int4range,
valid_at datemultirange, CONSTRAINT temporal_mltrng3_uq UNIQUE (id, valid_at WITHOUT OVERLAPS)
);
TRUNCATE temporal_mltrng3; INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT DO NOTHING; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at;
TRUNCATE temporal_mltrng3; INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO NOTHING; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at;
TRUNCATE temporal_mltrng3; INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO NOTHING; -- id matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO NOTHING; -- date matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO NOTHING; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at;
TRUNCATE temporal_mltrng3; INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT (id, valid_at) DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at;
TRUNCATE temporal_mltrng3; INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2000-01-01', '2010-01-01'))); -- with a conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO UPDATESET id = EXCLUDED.id + '[2,3)'; -- id matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[1,2)', datemultirange(daterange('2010-01-01', '2020-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO UPDATESET id = EXCLUDED.id + '[3,4)'; -- date matches but no conflict INSERTINTO temporal_mltrng3 (id, valid_at) VALUES ('[2,3)', datemultirange(daterange('2005-01-01', '2006-01-01'))) ON CONFLICT ONCONSTRAINT temporal_mltrng3_uq DO UPDATESET id = EXCLUDED.id + '[4,5)'; SELECT * FROM temporal_mltrng3 ORDERBY id, valid_at;
DROPTABLE temporal_mltrng3;
-- -- test FK dependencies --
-- can't drop a range referenced by an FK, unless with CASCADE CREATETABLE temporal3 (
id int4range,
valid_at daterange, CONSTRAINT temporal3_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
); CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal3 (id, PERIOD valid_at)
); ALTERTABLE temporal3 DROPCOLUMN valid_at; ALTERTABLE temporal3 DROPCOLUMN valid_at CASCADE; DROPTABLE temporal_fk_rng2rng; DROPTABLE temporal3;
-- -- test FOREIGN KEY, range references range --
-- test table setup DROPTABLE temporal_rng; CREATETABLE temporal_rng (id int4range, valid_at daterange); ALTERTABLE temporal_rng ADDCONSTRAINT temporal_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS);
-- Can't create a FK with a mismatched range type CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at int4range,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk2 PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk2 FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng (id, PERIOD valid_at)
);
-- works: PERIOD for both referenced and referencing CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng (id, PERIOD valid_at)
); DROPTABLE temporal_fk_rng2rng;
-- with mismatched PERIOD columns:
-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) -- REFERENCES part should specify PERIOD CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng (id, valid_at)
); -- (parent_id, valid_at) REFERENCES (id, valid_at) -- both should specify PERIOD: CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_rng (id, valid_at)
); -- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) -- FOREIGN KEY part should specify PERIOD CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_rng (id, PERIOD valid_at)
); -- (parent_id, valid_at) REFERENCES [implicit] -- FOREIGN KEY part should specify PERIOD CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_rng
); -- (parent_id, PERIOD valid_at) REFERENCES (id) CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng (id)
); -- (parent_id) REFERENCES (id, PERIOD valid_at) CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id) REFERENCES temporal_rng (id, PERIOD valid_at)
); -- with inferred PK on the referenced table: -- (parent_id, PERIOD valid_at) REFERENCES [implicit] CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng
); DROPTABLE temporal_fk_rng2rng; -- (parent_id) REFERENCES [implicit] CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id) REFERENCES temporal_rng
);
-- should fail because of duplicate referenced columns: CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD parent_id) REFERENCES temporal_rng (id, PERIOD id)
);
CREATETABLE temporal_fk2_rng2rng (
id int4range,
valid_at daterange,
parent_id1 int4range,
parent_id2 int4range, CONSTRAINT temporal_fk2_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk2_rng2rng_fk FOREIGNKEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at)
);
\d temporal_fk2_rng2rng DROPTABLE temporal_fk2_rng2rng;
-- -- test ALTER TABLE ADD CONSTRAINT --
CREATETABLE temporal_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
); ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng (id, PERIOD valid_at); -- Two scalar columns: CREATETABLE temporal_fk2_rng2rng (
id int4range,
valid_at daterange,
parent_id1 int4range,
parent_id2 int4range, CONSTRAINT temporal_fk2_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
); ALTERTABLE temporal_fk2_rng2rng ADDCONSTRAINT temporal_fk2_rng2rng_fk FOREIGNKEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_rng2 (id1, id2, PERIOD valid_at);
\d temporal_fk2_rng2rng
-- with inferred PK on the referenced table, and wrong column type: ALTERTABLE temporal_fk_rng2rng DROPCONSTRAINT temporal_fk_rng2rng_fk, ALTERCOLUMN valid_at TYPE tsrange USING tsrange(lower(valid_at), upper(valid_at)); ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng; ALTERTABLE temporal_fk_rng2rng ALTERCOLUMN valid_at TYPE daterange USING daterange(lower(valid_at)::date, upper(valid_at)::date);
-- with inferred PK on the referenced table: ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng;
-- should fail because of duplicate referenced columns: ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk2 FOREIGNKEY (parent_id, PERIOD parent_id) REFERENCES temporal_rng (id, PERIOD id);
-- slide the edge across a referenced transition: UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-02-20') WHERE id = '[1,2)'; -- should fail: UPDATE temporal_fk_rng2rng SET valid_at = daterange('2018-01-02', '2018-05-01') WHERE id = '[1,2)'; UPDATE temporal_fk_rng2rng SET parent_id = '[8,9)'WHERE id = '[1,2)';
DELETEFROM temporal_rng WHERE id = '[5,6)'; --should not fail yet. COMMIT; -- should fail here.
-- -- test FK referenced updates NO ACTION --
TRUNCATE temporal_rng, temporal_fk_rng2rng; ALTERTABLE temporal_fk_rng2rng DROPCONSTRAINT temporal_fk_rng2rng_fk; ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng ONUPDATE NO ACTION; -- a PK update that succeeds because the numeric id isn't referenced: INSERTINTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'; -- a PK update that succeeds even though the numeric id is referenced because the range isn't: DELETEFROM temporal_rng WHERE id = '[5,6)'; INSERTINTO temporal_rng (id, valid_at) VALUES
('[5,6)', daterange('2018-01-01', '2018-02-01')),
('[5,6)', daterange('2018-02-01', '2018-03-01')); INSERTINTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); UPDATE temporal_rng SET valid_at = daterange('2016-02-01', '2016-03-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-02-01', '2018-03-01'); -- A PK update sliding the edge between two referenced rows: INSERTINTO temporal_rng (id, valid_at) VALUES
('[6,7)', daterange('2018-01-01', '2018-02-01')),
('[6,7)', daterange('2018-02-01', '2018-03-01')); INSERTINTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES
('[4,5)', daterange('2018-01-15', '2018-02-15'), '[6,7)'); UPDATE temporal_rng SET valid_at = CASEWHEN lower(valid_at) = '2018-01-01'THEN daterange('2018-01-01', '2018-01-05') WHEN lower(valid_at) = '2018-02-01'THEN daterange('2018-01-05', '2018-03-01') END WHERE id = '[6,7)'; -- a PK update shrinking the referenced range but still valid: -- There are two references: one fulfilled by the first pk row, -- the other fulfilled by both pk rows combined. INSERTINTO temporal_rng (id, valid_at) VALUES
('[1,2)', daterange('2018-01-01', '2018-03-01')),
('[1,2)', daterange('2018-03-01', '2018-06-01')); INSERTINTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES
('[1,2)', daterange('2018-01-15', '2018-02-01'), '[1,2)'),
('[2,3)', daterange('2018-01-15', '2018-05-01'), '[1,2)'); UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-03-01') WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update growing the referenced range is fine: UPDATE temporal_rng SET valid_at = daterange('2018-01-01', '2018-03-01') WHERE id = '[1,2)'AND valid_at @> '2018-01-25'::date; -- a PK update shrinking the referenced range and changing the id invalidates the whole range (error): UPDATE temporal_rng SET id = '[2,3)', valid_at = daterange('2018-01-15', '2018-03-01') WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update changing only the id invalidates the whole range (error): UPDATE temporal_rng SET id = '[2,3)' WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update that loses time from both ends, but is still valid: INSERTINTO temporal_rng (id, valid_at) VALUES
('[2,3)', daterange('2018-01-01', '2018-03-01')); INSERTINTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES
('[5,6)', daterange('2018-01-15', '2018-02-01'), '[2,3)'); UPDATE temporal_rng SET valid_at = daterange('2018-01-15', '2018-02-15') WHERE id = '[2,3)'; -- a PK update that fails because both are referenced: UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01'); -- a PK update that fails because both are referenced, but not 'til commit:
BEGIN; ALTERTABLE temporal_fk_rng2rng ALTERCONSTRAINT temporal_fk_rng2rng_fk
DEFERRABLE INITIALLY DEFERRED;
UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01'); COMMIT; -- changing the scalar part fails: UPDATE temporal_rng SET id = '[7,8)' WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01'); -- then delete the objecting FK record and the same PK update succeeds: DELETEFROM temporal_fk_rng2rng WHERE id = '[3,4)'; UPDATE temporal_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01');
TRUNCATE temporal_rng, temporal_fk_rng2rng; ALTERTABLE temporal_fk_rng2rng ADDCONSTRAINT temporal_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_rng; -- a PK delete that succeeds because the numeric id isn't referenced: INSERTINTO temporal_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-01-01', '2018-02-01')); DELETEFROM temporal_rng WHERE id = '[5,6)'; -- a PK delete that succeeds even though the numeric id is referenced because the range isn't: INSERTINTO temporal_rng (id, valid_at) VALUES
('[5,6)', daterange('2018-01-01', '2018-02-01')),
('[5,6)', daterange('2018-02-01', '2018-03-01')); INSERTINTO temporal_fk_rng2rng (id, valid_at, parent_id) VALUES
('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); DELETEFROM temporal_rng WHERE id = '[5,6)'AND valid_at = daterange('2018-02-01', '2018-03-01'); -- a PK delete that fails because both are referenced: DELETEFROM temporal_rng WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01'); -- a PK delete that fails because both are referenced, but not 'til commit:
BEGIN; ALTERTABLE temporal_fk_rng2rng ALTERCONSTRAINT temporal_fk_rng2rng_fk
DEFERRABLE INITIALLY DEFERRED;
DELETEFROM temporal_rng WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01'); COMMIT; -- then delete the objecting FK record and the same PK delete succeeds: DELETEFROM temporal_fk_rng2rng WHERE id = '[3,4)'; DELETEFROM temporal_rng WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01');
-- -- test FOREIGN KEY, multirange references multirange --
-- test table setup DROPTABLE temporal_mltrng; CREATETABLE temporal_mltrng ( id int4range, valid_at datemultirange); ALTERTABLE temporal_mltrng ADDCONSTRAINT temporal_mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS);
-- Can't create a FK with a mismatched multirange type CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at int4multirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk2 PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk2 FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at)
);
CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at)
); DROPTABLE temporal_fk_mltrng2mltrng;
-- with mismatched PERIOD columns:
-- (parent_id, PERIOD valid_at) REFERENCES (id, valid_at) -- REFERENCES part should specify PERIOD CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, valid_at)
); -- (parent_id, valid_at) REFERENCES (id, valid_at) -- both should specify PERIOD: CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_mltrng (id, valid_at)
); -- (parent_id, valid_at) REFERENCES (id, PERIOD valid_at) -- FOREIGN KEY part should specify PERIOD CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at)
); -- (parent_id, valid_at) REFERENCES [implicit] -- FOREIGN KEY part should specify PERIOD CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, valid_at) REFERENCES temporal_mltrng
); -- (parent_id, PERIOD valid_at) REFERENCES (id) CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id)
); -- (parent_id) REFERENCES (id, PERIOD valid_at) CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id) REFERENCES temporal_mltrng (id, PERIOD valid_at)
); -- with inferred PK on the referenced table: -- (parent_id, PERIOD valid_at) REFERENCES [implicit] CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng
); DROPTABLE temporal_fk_mltrng2mltrng; -- (parent_id) REFERENCES [implicit] CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id) REFERENCES temporal_mltrng
);
-- should fail because of duplicate referenced columns: CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD parent_id) REFERENCES temporal_mltrng (id, PERIOD id)
);
CREATETABLE temporal_fk2_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id1 int4range,
parent_id2 int4range, CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_fk2_mltrng2mltrng_fk FOREIGNKEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at)
);
\d temporal_fk2_mltrng2mltrng DROPTABLE temporal_fk2_mltrng2mltrng;
-- -- test ALTER TABLE ADD CONSTRAINT --
CREATETABLE temporal_fk_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id int4range, CONSTRAINT temporal_fk_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
); ALTERTABLE temporal_fk_mltrng2mltrng ADDCONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at);
-- Two scalar columns: CREATETABLE temporal_fk2_mltrng2mltrng (
id int4range,
valid_at datemultirange,
parent_id1 int4range,
parent_id2 int4range, CONSTRAINT temporal_fk2_mltrng2mltrng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
);
ALTERTABLE temporal_fk2_mltrng2mltrng ADDCONSTRAINT temporal_fk2_mltrng2mltrng_fk FOREIGNKEY (parent_id1, parent_id2, PERIOD valid_at) REFERENCES temporal_mltrng2 (id1, id2, PERIOD valid_at);
\d temporal_fk2_mltrng2mltrng
-- should fail because of duplicate referenced columns: ALTERTABLE temporal_fk_mltrng2mltrng ADDCONSTRAINT temporal_fk_mltrng2mltrng_fk2 FOREIGNKEY (parent_id, PERIOD parent_id) REFERENCES temporal_mltrng (id, PERIOD id);
-- slide the edge across a referenced transition: UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-02-20')) WHERE id = '[1,2)'; -- should fail: UPDATE temporal_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2018-01-02', '2018-05-01')) WHERE id = '[1,2)'; UPDATE temporal_fk_mltrng2mltrng SET parent_id = '[8,9)'WHERE id = '[1,2)';
DELETEFROM temporal_mltrng WHERE id = '[5,6)'; --should not fail yet. COMMIT; -- should fail here.
-- -- test FK referenced updates NO ACTION --
TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; ALTERTABLE temporal_fk_mltrng2mltrng DROPCONSTRAINT temporal_fk_mltrng2mltrng_fk; ALTERTABLE temporal_fk_mltrng2mltrng ADDCONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at) ONUPDATE NO ACTION; -- a PK update that succeeds because the numeric id isn't referenced: INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'; -- a PK update that succeeds even though the numeric id is referenced because the range isn't: DELETEFROM temporal_mltrng WHERE id = '[5,6)'; INSERTINTO temporal_mltrng (id, valid_at) VALUES
('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))),
('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); INSERTINTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES
('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); -- A PK update sliding the edge between two referenced rows: INSERTINTO temporal_mltrng (id, valid_at) VALUES
('[6,7)', datemultirange(daterange('2018-01-01', '2018-02-01'))),
('[6,7)', datemultirange(daterange('2018-02-01', '2018-03-01'))); INSERTINTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES
('[4,5)', datemultirange(daterange('2018-01-15', '2018-02-15')), '[6,7)'); UPDATE temporal_mltrng SET valid_at = CASEWHEN lower(valid_at) = '2018-01-01'THEN datemultirange(daterange('2018-01-01', '2018-01-05')) WHEN lower(valid_at) = '2018-02-01'THEN datemultirange(daterange('2018-01-05', '2018-03-01')) END WHERE id = '[6,7)'; -- a PK update shrinking the referenced multirange but still valid: -- There are two references: one fulfilled by the first pk row, -- the other fulfilled by both pk rows combined. INSERTINTO temporal_mltrng (id, valid_at) VALUES
('[1,2)', datemultirange(daterange('2018-01-01', '2018-03-01'))),
('[1,2)', datemultirange(daterange('2018-03-01', '2018-06-01'))); INSERTINTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES
('[1,2)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[1,2)'),
('[2,3)', datemultirange(daterange('2018-01-15', '2018-05-01')), '[1,2)'); UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update growing the referenced multirange is fine: UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-03-01')) WHERE id = '[1,2)'AND valid_at @> '2018-01-25'::date; -- a PK update shrinking the referenced multirange and changing the id invalidates the whole multirange (error): UPDATE temporal_mltrng SET id = '[2,3)', valid_at = datemultirange(daterange('2018-01-15', '2018-03-01')) WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update changing only the id invalidates the whole multirange (error): UPDATE temporal_mltrng SET id = '[2,3)' WHERE id = '[1,2)'AND valid_at @> '2018-01-15'::date; -- a PK update that loses time from both ends, but is still valid: INSERTINTO temporal_mltrng (id, valid_at) VALUES
('[2,3)', datemultirange(daterange('2018-01-01', '2018-03-01'))); INSERTINTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES
('[5,6)', datemultirange(daterange('2018-01-15', '2018-02-01')), '[2,3)'); UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2018-01-15', '2018-02-15')) WHERE id = '[2,3)'; -- a PK update that fails because both are referenced: UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); -- a PK update that fails because both are referenced, but not 'til commit:
BEGIN; ALTERTABLE temporal_fk_mltrng2mltrng ALTERCONSTRAINT temporal_fk_mltrng2mltrng_fk
DEFERRABLE INITIALLY DEFERRED;
UPDATE temporal_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); COMMIT; -- changing the scalar part fails: UPDATE temporal_mltrng SET id = '[7,8)' WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01'));
TRUNCATE temporal_mltrng, temporal_fk_mltrng2mltrng; ALTERTABLE temporal_fk_mltrng2mltrng ADDCONSTRAINT temporal_fk_mltrng2mltrng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_mltrng (id, PERIOD valid_at); -- a PK delete that succeeds because the numeric id isn't referenced: INSERTINTO temporal_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))); DELETEFROM temporal_mltrng WHERE id = '[5,6)'; -- a PK delete that succeeds even though the numeric id is referenced because the range isn't: INSERTINTO temporal_mltrng (id, valid_at) VALUES
('[5,6)', datemultirange(daterange('2018-01-01', '2018-02-01'))),
('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); INSERTINTO temporal_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); DELETEFROM temporal_mltrng WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); -- a PK delete that fails because both are referenced: DELETEFROM temporal_mltrng WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); -- a PK delete that fails because both are referenced, but not 'til commit:
BEGIN; ALTERTABLE temporal_fk_mltrng2mltrng ALTERCONSTRAINT temporal_fk_mltrng2mltrng_fk
DEFERRABLE INITIALLY DEFERRED;
DELETEFROM temporal_mltrng WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')); COMMIT;
-- -- FK between partitioned tables: ranges --
CREATETABLE temporal_partitioned_rng (
id int4range,
valid_at daterange,
name text, CONSTRAINT temporal_paritioned_rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS)
) PARTITION BY LIST (id); CREATETABLE tp1 partition OF temporal_partitioned_rng FORVALUESIN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); CREATETABLE tp2 partition OF temporal_partitioned_rng FORVALUESIN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)'); INSERTINTO temporal_partitioned_rng (id, valid_at, name) VALUES
('[1,2)', daterange('2000-01-01', '2000-02-01'), 'one'),
('[1,2)', daterange('2000-02-01', '2000-03-01'), 'one'),
('[2,3)', daterange('2000-01-01', '2010-01-01'), 'two');
CREATETABLE temporal_partitioned_fk_rng2rng (
id int4range,
valid_at daterange,
parent_id int4range, CONSTRAINT temporal_partitioned_fk_rng2rng_pk PRIMARYKEY (id, valid_at WITHOUT OVERLAPS), CONSTRAINT temporal_partitioned_fk_rng2rng_fk FOREIGNKEY (parent_id, PERIOD valid_at) REFERENCES temporal_partitioned_rng (id, PERIOD valid_at)
) PARTITION BY LIST (id); CREATETABLE tfkp1 partition OF temporal_partitioned_fk_rng2rng FORVALUESIN ('[1,2)', '[3,4)', '[5,6)', '[7,8)', '[9,10)', '[11,12)'); CREATETABLE tfkp2 partition OF temporal_partitioned_fk_rng2rng FORVALUESIN ('[2,3)', '[4,5)', '[6,7)', '[8,9)', '[10,11)', '[12,13)');
UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-02-13') WHERE id = '[2,3)'; -- move a row from the first partition to the second UPDATE temporal_partitioned_fk_rng2rng SET id = '[4,5)'WHERE id = '[1,2)'; -- move a row from the second partition to the first UPDATE temporal_partitioned_fk_rng2rng SET id = '[1,2)'WHERE id = '[4,5)'; -- should fail: UPDATE temporal_partitioned_fk_rng2rng SET valid_at = daterange('2000-01-01', '2000-04-01') WHERE id = '[1,2)';
-- -- partitioned FK referenced updates NO ACTION --
TRUNCATE temporal_partitioned_rng, temporal_partitioned_fk_rng2rng; INSERTINTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2016-01-01', '2016-02-01')); UPDATE temporal_partitioned_rng SET valid_at = daterange('2018-01-01', '2018-02-01') WHERE id = '[5,6)'; INSERTINTO temporal_partitioned_rng (id, valid_at) VALUES ('[5,6)', daterange('2018-02-01', '2018-03-01')); INSERTINTO temporal_partitioned_fk_rng2rng (id, valid_at, parent_id) VALUES ('[3,4)', daterange('2018-01-05', '2018-01-10'), '[5,6)'); UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-02-01', '2016-03-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-02-01', '2018-03-01'); -- should fail: UPDATE temporal_partitioned_rng SET valid_at = daterange('2016-01-01', '2016-02-01') WHERE id = '[5,6)'AND valid_at = daterange('2018-01-01', '2018-02-01');
-- -- partitioned FK referenced deletes NO ACTION --
UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-02-13')) WHERE id = '[2,3)'; -- move a row from the first partition to the second UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[4,5)'WHERE id = '[1,2)'; -- move a row from the second partition to the first UPDATE temporal_partitioned_fk_mltrng2mltrng SET id = '[1,2)'WHERE id = '[4,5)'; -- should fail: UPDATE temporal_partitioned_fk_mltrng2mltrng SET valid_at = datemultirange(daterange('2000-01-01', '2000-04-01')) WHERE id = '[1,2)';
-- -- partitioned FK referenced updates NO ACTION --
TRUNCATE temporal_partitioned_mltrng, temporal_partitioned_fk_mltrng2mltrng; INSERTINTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2016-01-01', '2016-02-01'))); UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2018-01-01', '2018-02-01')) WHERE id = '[5,6)'; INSERTINTO temporal_partitioned_mltrng (id, valid_at) VALUES ('[5,6)', datemultirange(daterange('2018-02-01', '2018-03-01'))); INSERTINTO temporal_partitioned_fk_mltrng2mltrng (id, valid_at, parent_id) VALUES ('[3,4)', datemultirange(daterange('2018-01-05', '2018-01-10')), '[5,6)'); UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-02-01', '2016-03-01')) WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-02-01', '2018-03-01')); -- should fail: UPDATE temporal_partitioned_mltrng SET valid_at = datemultirange(daterange('2016-01-01', '2016-02-01')) WHERE id = '[5,6)'AND valid_at = datemultirange(daterange('2018-01-01', '2018-02-01'));
-- -- partitioned FK referenced deletes NO ACTION --
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.47Bemerkung:
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.