I have a tree encoded in a MySQL database as edges:
CREATE TABLE items (
num INT,
tot INT,
PRIMARY KEY (num)
);
CREATE TABLE tree (
orig INT,
term INT
FOREIGN KEY (orig,term) REFERENCES items (num,num)
)
For each leaf in the tree, items.tot is set by someone. For interior nodes, items.tot needs to be the sum of it's children. Running the following query repeatedly would generate the desired result.
UPDATE items SET tot = (
SELECT SUM(b.tot) FROM
tree JOIN items AS b
ON tree.term = b.num
WHERE tree.orig=items.num)
WHERE EXISTS
(SELECT * FROM tree WHERE orig=items.num)
(note this actually doesn't work but that's beside the point)
Assume that the database exists and the invariant are all ready satisfied.
The question is:
What is the most practical way to update the DB while maintaining this requirement? Updates may move nodes around or alter the value of tot on leaf nodes. It can assumed that leaf nodes stay as leaf nodes, interior nodes stay as interior nodes and the whole thing remains a proper tree.
Some thoughts I have had:
- Full Invalidation, after any update, recompute everything (Um... No)
- Set a trigger on the items table to update the parent of any row that is updated
- This would be recursive (updates trigger updates, trigger updates, ...)
- Doesn't work, MySQL can't update the table that kicked off the trigger
- Set a trigger to schedule an update of the parent of any row that is updated
- This would be iterative (get an item from the schedule, processing it schedules more items)
- What kicks this off? Trust client code to get it right?
- An advantage is that if the updates are ordered correctly fewer sums need to be computer. But that ordering is a complication in and of it's own.
An ideal solution would generalize to other "aggregating invariants"
FWIW I know this is "a bit overboard", but I'm doing this for fun (Fun: verb, Finding the impossible by doing it. :-)