7. What’s a Graph, Really?
Nodes
Edges
Tuesday, November 23, 2010
8. Representing Graphs
CREATE TABLE message (
message_id SERIAL PRIMARY KEY,
parent_message_id INTEGER REFERENCES message,
sender email NOT NULL,
list TEXT NOT NULL,
...
);
Tuesday, November 23, 2010
11. Representing Graphs
CREATE TABLE message (
message_id SERIAL PRIMARY KEY,
sender email NOT NULL,
list TEXT NOT NULL,
...
);
CREATE TABLE edge (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message,
PRIMARY KEY(tail, head)
);
Tuesday, November 23, 2010
19. Reflexive Closure
CREATE TABLE reflexive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO reflexive_closure
SELECT tail, head FROM edge UNION
SELECT tail, tail FROM edge UNION
SELECT head, head FROM edge;
Tuesday, November 23, 2010
20. Symmetric Closure
CREATE TABLE symmetric_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO symmetric_closure
SELECT tail, head FROM edge UNION
SELECT head, tail FROM edge;
Tuesday, November 23, 2010
21. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
Tuesday, November 23, 2010
22. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO transitive_closure
Tuesday, November 23, 2010
23. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO transitive_closure
SELECT
Tuesday, November 23, 2010
24. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO transitive_closure
SELECT
Er
Tuesday, November 23, 2010
25. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO transitive_closure
SELECT
Er
Um
Tuesday, November 23, 2010
26. Transitive Closure
CREATE TABLE transitive_closure (
tail INTEGER NOT NULL REFERENCES message,
head INTEGER NOT NULL REFERENCES message
);
INSERT INTO transitive_closure
SELECT
Er
Um
Hrm...
Tuesday, November 23, 2010
28. Transitive Closure Query
WITH RECURSIVE t(tail, head, chain) AS (
SELECT tail, head, ARRAY[tail, head]
FROM edge
UNION ALL
SELECT e.tail, e.head, t.chain || e.head
FROM edge e JOIN t
ON (e.tail = t.head)
WHERE e.tail <> ANY(t.chain)
)
SELECT tail, head FROM t
Tuesday, November 23, 2010
33. Cycle Finder
WITH RECURSIVE t(tail, head, chain) AS (
SELECT tail, head, ARRAY[tail, head]
FROM edge
UNION ALL
SELECT e.tail, e.head, t.chain || e.head
FROM edge e JOIN t
ON (t.head = e.tail)
WHERE e.tail = ANY(t.chain)
)
SELECT * FROM t
Tuesday, November 23, 2010
34. Cycle Finder Function
CREATE OR REPLACE FUNCTION has_cycle()
RETURNS BOOLEAN
LANGUAGE SQL AS $$
SELECT EXISTS (
WITH RECURSIVE t(tail, head, chain) AS (
SELECT tail, head, ARRAY[tail, head]
FROM edge
UNION ALL
SELECT e.tail, e.head, t.chain || e.head
FROM edge e JOIN t
ON (t.head = e.tail)
WHERE e.tail = ANY(t.chain)
)
SELECT * FROM t
)
Tuesday, November 23, 2010
35. Cyclotomic Trigger Function
CREATE OR REPLACE FUNCTION decyclifier()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF (has_cycle()) THEN
RAISE ERROR 'No cycles allowed!';
END IF;
RETURN NEW;
END;
Tuesday, November 23, 2010
36. Cyclotomic Trigger
CREATE TRIGGER edge_decyclifier
AFTER INSERT OR UPDATE ON edge
FOR EACH STATEMENT
EXECUTE PROCEDURE decyclifier();
Tuesday, November 23, 2010
38. Tree Constraint
CREATE OR REPLACE FUNCTION count_only_heads()
RETURNS INTEGER
LANGUAGE SQL
AS $$
SELECT count(tail)
FROM edge e
WHERE NOT EXISTS (
SELECT 1 FROM edge
WHERE edge.head = e.tail
)
$$;
Tuesday, November 23, 2010
39. Tree Constraint
CREATE OR REPLACE FUNCTION one_head()
RETURNS TRIGGER
LANGUAGE plpgsql
AS $$
BEGIN
IF count_only_heads() <> 1 THEN
RAISE EXCEPTION 'This is a tree!';
END IF;
RETURN NEW;
END;
$$;
Tuesday, November 23, 2010
40. Tree Constraint
CREATE TRIGGER edge_one_head
AFTER INSERT OR UPDATE OR DELETE
ON edge
EXECUTE PROCEDURE one_head();
Tuesday, November 23, 2010