Cela peut être fait pour fonctionner, le déclencheur qui effectue le déplacement doit simplement être défini pour chaque partition, pas pour toute la table. Commencez donc comme vous l'avez fait pour les définitions de table et le déclencheur INSERT
CREATE TABLE records (
record varchar(64) NOT NULL,
active boolean default TRUE
);
CREATE TABLE active_records (CHECK (active)) INHERITS (records);
CREATE TABLE inactive_records (CHECK (NOT active)) INHERITS (records);
CREATE OR REPLACE FUNCTION record_insert()
RETURNS TRIGGER AS $$
BEGIN
IF (TRUE = NEW.active) THEN
INSERT INTO active_records VALUES (NEW.*);
ELSE
INSERT INTO inactive_records VALUES (NEW.*);
END IF;
RETURN NULL;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER record_insert_trigger
BEFORE INSERT ON records
FOR EACH ROW EXECUTE PROCEDURE record_insert();
... prenons quelques données de test ...
INSERT INTO records VALUES ('FirstLittlePiggy', TRUE);
INSERT INTO records VALUES ('SecondLittlePiggy', FALSE);
INSERT INTO records VALUES ('ThirdLittlePiggy', TRUE);
INSERT INTO records VALUES ('FourthLittlePiggy', FALSE);
INSERT INTO records VALUES ('FifthLittlePiggy', TRUE);
Maintenant, les déclencheurs sur les partitions. La vérification if NEW.active =OLD.active est implicite dans la vérification de la valeur de active puisque nous savons ce qui est autorisé dans la table en premier lieu.
CREATE OR REPLACE FUNCTION active_partition_constraint()
RETURNS TRIGGER AS $$
BEGIN
IF NOT (NEW.active) THEN
INSERT INTO inactive_records VALUES (NEW.*);
DELETE FROM active_records WHERE record = NEW.record;
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER active_constraint_trigger
BEFORE UPDATE ON active_records
FOR EACH ROW EXECUTE PROCEDURE active_partition_constraint();
CREATE OR REPLACE FUNCTION inactive_partition_constraint()
RETURNS TRIGGER AS $$
BEGIN
IF (NEW.active) THEN
INSERT INTO active_records VALUES (NEW.*);
DELETE FROM inactive_records WHERE record = NEW.record;
RETURN NULL;
ELSE
RETURN NEW;
END IF;
END;
$$
LANGUAGE plpgsql;
CREATE TRIGGER inactive_constraint_trigger
BEFORE UPDATE ON inactive_records
FOR EACH ROW EXECUTE PROCEDURE inactive_partition_constraint();
... et testez les résultats ...
scratch=> SELECT * FROM active_records;
record | active
------------------+--------
FirstLittlePiggy | t
ThirdLittlePiggy | t
FifthLittlePiggy | t
(3 rows)
scratch=> UPDATE records SET active = FALSE WHERE record = 'ThirdLittlePiggy';
UPDATE 0
scratch=> SELECT * FROM active_records;
record | active
------------------+--------
FirstLittlePiggy | t
FifthLittlePiggy | t
(2 rows)
scratch=> SELECT * FROM inactive_records;
record | active
-------------------+--------
SecondLittlePiggy | f
FourthLittlePiggy | f
ThirdLittlePiggy | f
(3 rows)