tree tricks osdc_melbourne_20101124
TRANSCRIPT
Tree TricksOSDC Melbourne 2010/11/24Copyright(C) 2010 by David Fetter
All Rights Reserved.
Tuesday, November 23, 2010
What’s a Tree, Really?
Plant
Perennial
Woody
Secondary branches
Off ground
Apical Dominance
Tuesday, November 23, 2010
What’s a Tree, Really?
Graph
Directed
Connected
Acyclic
Max(indegree) = 1
Tuesday, November 23, 2010
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
Representing GraphsCREATE 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
Reflexive ClosureCREATE TABLE reflexive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO reflexive_closureSELECT tail, head FROM edge UNIONSELECT tail, tail FROM edge UNIONSELECT head, head FROM edge;
Tuesday, November 23, 2010
Symmetric Closure
CREATE TABLE symmetric_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO symmetric_closureSELECT tail, head FROM edge UNIONSELECT head, tail FROM edge;
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO transitive_closure
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO transitive_closureSELECT
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO transitive_closureSELECTEr
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO transitive_closureSELECTErUm
Tuesday, November 23, 2010
Transitive ClosureCREATE TABLE transitive_closure ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message);
INSERT INTO transitive_closureSELECTErUmHrm...
Tuesday, November 23, 2010
Transitive Closure QueryWITH RECURSIVE t(tail, head, chain) AS ( SELECT tail, head, ARRAY[tail, head] FROM edgeUNION 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
What’s a Tree, Really?
Graph
Directed
Connected
Acyclic
Max(indegree) = 1
Tuesday, November 23, 2010
Max(indegree) = 1
CREATE TABLE edge ( tail INTEGER NOT NULL REFERENCES message, head INTEGER NOT NULL REFERENCES message, PRIMARY KEY(tail, head));
ALTER TABLE edge ADD UNIQUE(head)
Tuesday, November 23, 2010
Cycle FinderWITH RECURSIVE t(tail, head, chain) AS ( SELECT tail, head, ARRAY[tail, head] FROM edgeUNION 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
Cycle Finder FunctionCREATE OR REPLACE FUNCTION has_cycle()RETURNS BOOLEANLANGUAGE 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
Cyclotomic Trigger FunctionCREATE OR REPLACE FUNCTION decyclifier()RETURNS TRIGGERLANGUAGE plpgsqlAS $$BEGIN IF (has_cycle()) THEN RAISE ERROR 'No cycles allowed!'; END IF; RETURN NEW;END;
Tuesday, November 23, 2010
Cyclotomic Trigger
CREATE TRIGGER edge_decyclifier AFTER INSERT OR UPDATE ON edge FOR EACH STATEMENT EXECUTE PROCEDURE decyclifier();
Tuesday, November 23, 2010
Tree ConstraintCREATE OR REPLACE FUNCTION count_only_heads()RETURNS INTEGERLANGUAGE SQLAS $$SELECT count(tail)FROM edge eWHERE NOT EXISTS ( SELECT 1 FROM edge WHERE edge.head = e.tail)$$;
Tuesday, November 23, 2010
Tree ConstraintCREATE OR REPLACE FUNCTION one_head()RETURNS TRIGGERLANGUAGE plpgsqlAS $$BEGIN IF count_only_heads() <> 1 THEN RAISE EXCEPTION 'This is a tree!'; END IF; RETURN NEW;END;$$;
Tuesday, November 23, 2010
Tree Constraint
CREATE TRIGGER edge_one_head AFTER INSERT OR UPDATE OR DELETE ON edge EXECUTE PROCEDURE one_head();
Tuesday, November 23, 2010