I have a partitioned table (call it A) with a serial primary key that is referenced by another table (call it B). I know that I can't actually create a foreign key from one to the other (since I don't know from which partition the data is actually stored), so instead, I am attempting to mimic the behavior of a foreign key using check constraints. Something like the following:
CREATE TABLE A (
MyKey SERIAL PRIMARY KEY
);
CREATE TABLE B (
AKey INT, -- Should have: REFERENCES A (MyKey),
-- but can't due to Postgres limitations
);
CREATE TABLE APart1 (
Field1 INT,
PRIMARY KEY (MyKey)
) INHERITS (A);
CREATE TABLE APart2 (
Field2 INT,
PRIMARY KEY (MyKey)
) INHERITS (A);
CREATE FUNCTION ValidateKeyInA(aKey INT) RETURNS BOOL AS $$
BEGIN
PERFORM * FROM A WHERE MyKey = aKey;
IF FOUND THEN
RETURN TRUE;
END IF;
RETURN FALSE;
END;
$$ LANGUAGE PLPGSQL;
ALTER TABLE B ADD CHECK (ValidateKeyInA(AKey));
WITH aKey AS (INSERT INTO APart1 (Field1) VALUES (1) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;
WITH aKey AS (INSERT INTO APart2 (Field2) VALUES (2) RETURNING MyKey)
INSERT INTO B (AKey) SELECT * FROM aKey;
This works just fine, until I go to dump and restore the database. At that point, Postgres doesn't know that table B depends on the data in table A (and its partitions), and B happens to be dumped prior to table A. I tried to add the "DEFERRABLE" keyword to the line where I add the constraint, but Postgres doesn't support deferrable check constraints.
My proposed approach is to convert my check constraint to a constraint trigger, which I CAN defer, then import my database dump in a transaction. Is there a more straight-forward approach to this? For example, is there some way for me to tell Postgres not to dump table B until table A and all of its partitions have been dumped (e.g., add dependencies from B to the partitions of A)? Some other pattern that I should be using instead? Thank you.
CREATE FUNCTION ValidateKeyInA(aKey INT) RETURNS BOOL AS $$ SELECT count(*) > 0 FROM A WHERE Key = aKey; $$ LANGUAGE sql;