Advertisement
infogulch

Untitled

Jun 11th, 2012
108
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
SQL 3.29 KB | None | 0 0
  1. PRAGMA foreign_keys = ON;
  2. PRAGMA recursive_triggers = TRUE;
  3.  
  4. CREATE TABLE nodes (
  5.       id         INTEGER PRIMARY KEY
  6.     , isdir      INTEGER
  7.     , name       TEXT
  8. );
  9. CREATE INDEX index_name ON nodes (name);
  10.  
  11. CREATE TABLE closures (
  12.       ancestor   INTEGER NOT NULL
  13.     , descendant INTEGER NOT NULL
  14.     , pathlength INTEGER NOT NULL
  15.     , PRIMARY KEY (ancestor, descendant)
  16.     , FOREIGN KEY (ancestor)   REFERENCES nodes(id) ON UPDATE CASCADE ON DELETE CASCADE
  17.     , FOREIGN KEY (descendant) REFERENCES nodes(id) ON UPDATE CASCADE ON DELETE CASCADE
  18. );
  19. CREATE INDEX index_descendant_ancestor ON closures (descendant, ancestor);
  20.  
  21. CREATE VIEW parent_of AS
  22. SELECT id
  23.      , ancestor AS parent_id
  24.      , isdir
  25.      , name
  26. FROM nodes
  27. JOIN closures ON descendant = id AND pathlength = 1;
  28.  
  29. CREATE TABLE orphans (
  30.       id         INTEGER PRIMARY KEY
  31.     , parent_id  INTEGER
  32.     , isdir      INTEGER
  33.     , name       TEXT
  34. );
  35.  
  36. CREATE VIEW paths AS
  37. SELECT descendant AS id, GROUP_CONCAT(name, '/') AS path
  38. FROM closures
  39. JOIN nodes ON id = ancestor
  40. GROUP BY descendant
  41. ORDER BY pathlength DESC;
  42.  
  43. CREATE VIEW roots AS
  44. SELECT descendant AS id
  45. FROM closures
  46. GROUP BY descendant
  47. HAVING SUM(pathlength) = 0;
  48.  
  49. -- null parent == root
  50. CREATE TRIGGER insert_parent_of_orphans INSTEAD OF INSERT ON parent_of
  51. FOR EACH ROW
  52. WHEN NEW.parent_id IS NOT NULL AND (SELECT id FROM nodes WHERE id = NEW.parent_id LIMIT 1) IS NULL
  53. BEGIN
  54.     INSERT INTO orphans (id, parent_id, isdir, name)
  55.     VALUES (NEW.id, NEW.parent_id, NEW.isdir, NEW.name);
  56. END;
  57.  
  58. CREATE TRIGGER insert_parent_of_closures INSTEAD OF INSERT ON parent_of
  59. FOR EACH ROW
  60. WHEN NEW.parent_id IS NULL OR (SELECT id FROM nodes WHERE id = NEW.parent_id LIMIT 1) IS NOT NULL
  61. BEGIN
  62.     INSERT INTO nodes (id, isdir, name) VALUES (NEW.id, NEW.isdir, NEW.name);
  63.    
  64.     INSERT INTO closures (ancestor,descendant,pathlength)
  65.     SELECT ancestor, NEW.id, pathlength+1
  66.     FROM closures
  67.     WHERE descendant = NEW.parent_id
  68.     UNION ALL
  69.     SELECT NEW.id, NEW.id, 0;
  70.    
  71.     DELETE FROM orphans WHERE id = NEW.id;
  72.    
  73.     INSERT INTO parent_of
  74.     SELECT * FROM orphans
  75.     WHERE parent_id = NEW.id;
  76. END;
  77.  
  78. -- moving entire subtree
  79. CREATE TRIGGER update_parent_of_move_subtree INSTEAD OF UPDATE ON parent_of
  80. FOR EACH ROW
  81. WHEN NEW.parent_id != OLD.parent_id
  82. BEGIN
  83.     -- orphanize all descendants, but not self
  84.     INSERT INTO orphans (id, parent_id, isdir, name)
  85.     SELECT id, parent_id, isdir, name
  86.     FROM parent_of
  87.     WHERE id IN (SELECT descendant
  88.                  FROM closures
  89.                  WHERE ancestor = NEW.id AND descendant != NEW.id);
  90.    
  91.     -- delete all descenants from nodes, including self. Should also delete all related closures
  92.     DELETE FROM nodes WHERE id IN (SELECT descendant FROM closures WHERE ancestor = NEW.id);
  93.    
  94.     -- re-insert self with new parent, and allow all descendants to repopulate recursively
  95.     INSERT INTO parent_of (id, parent_id, isdir, name) VALUES (NEW.id, NEW.parent_id, NEW.isdir, NEW.name);
  96. END;
  97.  
  98. -- simple name change
  99. CREATE TRIGGER update_parent_of INSTEAD OF UPDATE ON parent_of
  100. FOR EACH ROW
  101. WHEN NEW.parent_id = OLD.parent_id
  102. BEGIN
  103.     UPDATE nodes
  104.     SET name = NEW.name, isdir = NEW.isdir
  105.     WHERE id = NEW.id;
  106. END;
  107.  
  108. -- Just insert everything into `parent_of` !
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement