Nested Set´s II: rekursives Löschen
[Zum einlesen die erste Folge]
Zur Einführung ein Bild, das in dieser Folge als grafisches Hilfsmittel dienen soll.

Nested Sets-Hirachie in ConstructrCMS
Erstellt wurde es mit dem Content Management System ConstructrCMS in der Version 3.01.4 Beta (kostenlos erhältlich unter http://constructr.phaziz.com - GPLv3).
Wir werden uns heute mit dem Löschen von Seiten beschäftigen. Was muss getan werden um Seiten zu löschen, ohne das der gesamte Baum verschruddelt wird?
Es muss festgestellt werden, an welcher Stelle im Baum die Seite gelöscht werden soll. Aus folgendem Grund: weil ab da der Baum nach dem eigentlichen Löschvorgang reorganisiert werden muss (die Zähler LFT -> Left und RGT -> Right).
Würde der Baum ab der gelöschten Seite nach dem Löschvorgang nicht reorganisiert werden, enstünde eine Lücke. Diese Lücke würde das weitere Pflegen des Bäumchens behindern - so ein Baum soll ja mal groß und stark werden.
Es muss also schon vor dem Löschen bekannt sein, welchen linken und rechten Zähler die zu löschende Seite inne hat. Außerdem benötigen wir die Information, ob nur die eigentliche Seite gelöscht werden soll, oder ob ein eventuell vorhandener Teilbaum gelöscht werden soll (Unterseiten zur Seite die gelöscht werden soll).
Nehmen wir zum Beispiel die Seite 1.2 aus dem oben gezeigten Bild. Was soll nach dem Löschen mit der Unterseite 1.2.1 geschehen? Soll die Unterseite mit gelöscht werden, oder soll die Seite an die Stelle der gelöschten Seite treten - soll die Seite in der Ebene nach oben wandern?
Wir wollen die Seite 1.2 mit allen evtl. vorhandenen Unterseiten löschen (also den gesamten Teilbaum, der die Seite 1.2 zur Wurzel hat):
Wir benötigen folgende Informationen vor dem Löschvorgang:
- ID der Seite die gelöscht werden soll
- LFT-Wert der Seite die gelöscht werden soll
- RGT-Wert der Seite die gelöscht werden soll
Die erste Maßnahme ist das löschen der Seite, mit den vorhandenen Unterseiten:
DELETE FROM TABELLE
WHERE LFT BETWEEN 16 AND 19
Warum jetzt nicht das löschen per ID (DELETE FROM TABELLE WHERE ID = ‘10′)? Weil wir mit dieser DELETE-Anweisung schon die Seite erfassen, die gelöscht werden soll - inklusive aller Unterseiten evtl. vorhandnen Unterseiten. Alle Unterseiten zu einer Seite, besizten LFT- und RGT-Werte innerhalb der LFT- und RGT-Werte dieser Seite -> das ist eine feste Regel im Konzept der Nested Set´s.
Wir haben es also geschafft den Teilbaum ab Seite 1.2 inklusive der Seite 1.2.1 zu löschen. Die Seite 1.2.1 besitzt die LFT- und RGT-Werte 17 und 18. Diese liegen innerhalb (BETWEEN) der LFT- (16) und RGT-Werte (19) der Seite 1.2.
Doch jetzt haben wir mit der Axt eine Lücke geschlagen und müssen schleunigst zusehen, das wir die entstandene Lücke versorgen. Wir reorganisieren die LFT-Werte der Seiten, die der Seite 1.2 folgten (1.3, 1.3.1 und 1.3.2):
UPDATE TABELLE
SET
LFT = LFT - ((19-16)+1)
WHERE LFT > 19
Wir reorganisieren den Baum ab der nun gelöschten Seite 1.2 wie folgt: Die LFT-Werte die größer sind als der RGT-Wert der Seite 1.2 (weil das der äußerste Zähler im gelöschten Teilbaum ist), verringern sich um den Wert 4 (mit dem Wert 4 haben wir hier zwei Seiten abgedeckt -> 1.2 und 1.2.1).
Generell ließe sich das mit dem Ausdruck ...SET LFT = LFT - ((DELETE_RGT - DELETE_LFT)+1) beschreiben, wobei DELETE_RGT und DELETE_LFT die Werte der zu löschenden Seite darstellen. Wir erinnern uns: RGT - LFT ergibt die Anzahl der Unterseiten (feste Regel). Daher auch die Addition mit 1 für die eigentliche Seite die gelöscht werden soll (1.2).
Fehlt uns noch die reorganisation der RGT-Werte:
UPDATE TABELLE
SET
RGT = RGT - (19-16+1)
WHERE RGT > 19
Diese bewirkt das auch die RGT-Werte der folgenden Seiten im Gesamtbaum (1.3, 1.3.1 und 1.3.2) verringert werden [...SET RGT = RGT - ((DELETE_RGT - DELETE_LFT)+1)].
Das Ziel ist erreicht:
- Wir haben eine beliebige Seite gelöscht.
- Wir haben die eventuell vorhandenen Unterseiten gelöscht.
- Und wir haben verhindert das die Ordnung unseres gesamten Baumes durcheinander kommt, indem wir die LFT- und RGT-Werte unserer Folgeseiten reorganisiert haben.
Rekursives Löschen in einem NestedSet´s-Baum mit allgemeingültigen Regeln.
Tags: nested sets, programmierung, strukturen
Posted in programming




