Solution to exercises for lecture 4: Views, Triggers, Rules and Lore
1. The World View
CREATE VIEW truth.true_now(sid, stmt_text) AS
SELECT DISTINCT s.sid, s.stmt_text
FROM truth.statement AS s
JOIN truth.true_at AS t USING (sid)
WHERE t.true_from <= now() AND
IS NULL OR
(t.true_until > now()); t.true_until
2. Trigger Happy
2.1 Automated Truth Maintenance
-- Handle inserts
CREATE FUNCTION truth.ins_stmt_fn() RETURNS trigger AS
$body$BEGIN
INSERT INTO truth.true_at
VALUES (NEW.sid, now(), NULL);
RETURN NEW;
END;
$body$ language plpgsql;
CREATE TRIGGER ins_stmt
INSTEAD OF INSERT ON truth.true_now
FOR EACH ROW EXECUTE PROCEDURE truth.ins_stmt_fn();
-- Handle deletes
CREATE FUNCTION truth.del_stmt_fn() RETURNS trigger AS
$body$BEGIN
UPDATE truth.true_at
SET true_until = now()
WHERE sid = OLD.sid AND true_from <= now() AND
IS NULL OR true_until >= now()); -- Only update the currently true statements
(true_until RETURN OLD;
END;
$body$ language plpgsql;
CREATE TRIGGER del_stmt
INSTEAD OF DELETE ON truth.true_now
FOR EACH ROW EXECUTE PROCEDURE truth.del_stmt_fn();
2.2 Automated Contradiction Maintenance
-- Handle insert into truth.contradicion
-- Using triggers and a new table:
CREATE TABLE truth.contradiction_all (
sid1 text,
sid2 text,PRIMARY KEY (sid1, sid2)
);
CREATE FUNCTION truth.con_ins_fn() RETURNS trigger AS
$body$BEGIN
INSERT INTO truth.contradiction_all
VALUES (NEW.sid1, NEW.sid2), (NEW.sid2, NEW.sid1)
ON CONFLICT DO NOTHING;
RETURN NEW;
END;
$body$ language plpgsql;
CREATE TRIGGER con_ins
AFTER INSERT ON truth.contradiction
FOR EACH ROW EXECUTE PROCEDURE truth.con_ins_fn();
-- Using a VIEW:
CREATE VIEW truth.contradiction_all AS
SELECT sid1, sid2
FROM truth.contradiction
UNION ALL
SELECT sid2, sid1
FROM truth.contradiction;
-- Handle inserts on truth.true_at with contradictions
CREATE FUNCTION truth.con_stmt_fn() RETURNS trigger AS
$body$BEGIN
UPDATE truth.true_at
SET true_until = now()
WHERE (NEW.sid, sid) IN (SELECT sid1, sid2 FROM truth.contradiction_all) AND
<= now() AND
true_from IS NULL OR true_until >= now()); -- Only update the currently true statements
(true_until RETURN NEW;
END;
$body$ language plpgsql;
CREATE TRIGGER con_stmt
INSTEAD OF INSERT ON truth.true_now
FOR EACH ROW EXECUTE PROCEDURE truth.con_stmt_fn();
3 PostgreSQL Rules
-- Handle insert to truth.true_now
CREATE RULE ins_true_now_rule AS
ON INSERT TO truth.true_now DO INSTEAD
INSERT INTO truth.true_at
VALUES (NEW.sid, now(), NULL);
-- Handle deletes to truth.true_now
CREATE RULE del_true_now_rule AS
ON DELETE TO truth.true_now DO INSTEAD
UPDATE truth.true_at
SET true_until = now()
WHERE OLD.sid = sid AND
<= now() AND
true_from IS NULL OR true_until >= now());
(true_until
-- Handle insert into truth.contradicion
CREATE RULE con_ins_rule AS
ON INSERT TO truth.contradiction DO ALSO
INSERT INTO truth.contradiction_all
VALUES (NEW.sid1, NEW.sid2), (NEW.sid2, NEW.sid1)
ON CONFLICT DO NOTHING;
-- Handle inserts on truth.true_at with contradictions
CREATE RULE ins_true_now_con_rule AS
ON INSERT TO truth.true_now DO INSTEAD
UPDATE truth.true_at
SET true_until = now()
WHERE (NEW.sid, sid) IN (SELECT sid1, sid2 FROM truth.contradiction_all) AND
<= now() AND
true_from IS NULL OR true_until >= now()); (true_until
4 World Lore
4.1 The World View Revisited
CREATE RELATION truth.true_now (
NOT NULL,
sid text NOT NULL
stmt_text text
);
<- truth.statement(sid, stmt), truth.true_at(sid, tf, tu)
truth.true_now(sid, stmt) <= now() AND
: t.true_from IS NULL OR t.true_until > now()) (t.true_until
4.2 Contradicting Lore
CREATE RELATION FROM TABLE truth.contradiction (
NOT NULL,
sid1 text NOT NULL
sid2 text -- Primary key constraint unecessary here
);
-- Note that we do not need an auxillary table, as
-- Lore-rules can be recursive without a problem
-> truth.contradiction(s2, s1); truth.contradiction(s1, s2)
Or using the SQL-like syntax:
CREATE RELATION FROM TABLE truth.contradiction (
NOT NULL,
sid1 text NOT NULL
sid2 text -- Primary key constraint unecessary here
);
CREATE FORWARD IMPLICATION truth.contradition AS
SELECT sid2, sid1 FROM truth.contradiction;
4.3 Implied Contradiction
'http://leifhka.org/in5800/data/ministry_of_truth_implications.lore';
IMPORT
-> truth.contradiction(s1, s3);
truth.implication(s1, s2), truth.contradiction(s2, s3)
<- truth.true_now(sid1, stmt1),
truth.true_now(sid2, stmt2)
truth.implication(sid1, sid2), truth.statement(sid2, stmt2);
Full Lore-script
Here you can download a complete script containing the full (non-overlapping) functionality implemented in all of this weeks exercises.