yform icon indicating copy to clipboard operation
yform copied to clipboard

be_manager_relation: Löschverhalten bei "inline n-1" inkonsistent?

Open christophboecker opened this issue 5 years ago • 8 comments

(Alle Addons und der Core auf dem aktuellen Stand, YForm 3.4.1, Core 5.11, PHP 7.3)

Mit Blick auf #915 wollte ich mir das Verhalten von be_manager_relation in der Variante "inline (multiple n-1)" ansehen. Dabei fiel mir auf:

  • Lösche im Formular von Tabelle A (Haupttabelle) eines von mehreren Inline-Formularen (Tabelle B). Nachdem der Datensatz A gespeichert ist, ist der gelöschte Untersatz B auch aus Tabelle B verschwunden. Erwartetes Verhalten! Passt.

  • Lösche in der Datentabelle von Tabelle A den ganzen DAtensatz auf einen Schlag. In der Tabelle B sind die Untersätze noch immer vorhanden. Unerwartetes Verhalten! So sollte es m.E. nicht sein.

Nun frage ich mich: ist das wirklich so gewollt oder ein Bug? Und wenn Bug: im ersten oder zweiten Fall?

Mein Testszenario: zwei Tabellen A und B. Tabellen und Felder im Table_Manager angelegt.

  • A:
    • Feld "titel", text
    • Feld "detail": be_manager_Relation auf Tabelle b, Relationenfeld "xyz"
  • B:
    • Feld "titel", text
    • Feld *xyz", integer

christophboecker avatar Aug 06 '20 15:08 christophboecker

Ich würde erwarten, dass im zweiten Fall auch gelöscht wird.

gharlan avatar Aug 07 '20 09:08 gharlan

In der ersten (korrekten) Variante übernimmt rex_yform_value_be_manager_relation das Löschen: https://github.com/yakamara/redaxo_yform/blob/d4b1b250e479875e9ecc52681889cc4b7690e90f/plugins/manager/lib/yform/value/be_manager_relation.php#L387-L389

Beim Löschen eines Datensatzes gibt es zwar auch eine Aufräumaktion in rex_yform_manager_dataset: https://github.com/yakamara/redaxo_yform/blob/d4b1b250e479875e9ecc52681889cc4b7690e90f/plugins/manager/lib/yform/manager/dataset.php#L515 die aber nur n:m-Relationen bereinigt: https://github.com/yakamara/redaxo_yform/blob/d4b1b250e479875e9ecc52681889cc4b7690e90f/plugins/manager/lib/yform/manager/table.php#L333-L349

An der Stelle könnte man eingreifen, hinter das IF ein weiteres IF setzen und darin zusätzlich die Relationen vom Typ 5 (inline n-1) aufräumen:

if (5 == $field->getElement('type') && ($table_b = $field->getElement('table')) ) {
    $table_a = $deleteSql->escapeIdentifier($this->getTableName());
    $table_b = $deleteSql->escapeIdentifier($table_b);
    $relation_b = $deleteSql->escapeIdentifier($field->getElement('field'));
    $qry = "DELETE FROM $table_b WHERE NOT EXISTS (SELECT * FROM $table_a WHERE $table_a.id = $table_b.$relation_b)";
    $deleteSql->setQuery( $qry );
}

christophboecker avatar Aug 08 '20 10:08 christophboecker

Klar. Gerne als PR. Wäre eine große Hilfe. Eigentlich gehört da noch ein richtiges Löschen rein, sodass auch feldspezifische Inhalte entfernt werden können (z.B. Files bei Upload), aber wäre ein neues Issue.

dergel avatar Dec 06 '21 11:12 dergel

Ich schiebe es auf 4.1. wenn du das vorher getestet hinbekommst, top. :)

dergel avatar Dec 06 '21 11:12 dergel

Lassen wir es mal bei "4.1"; es scheint mir etwas komplizierter zu sein. Es läuft ja jetzt auch Vieles nicht mehr über direktes SQL

christophboecker avatar Dec 06 '21 13:12 christophboecker

Ich hab mir den obigen Patch wieder in meine 4.0.2-Instanz eingebaut und schau mal, wie die Verträglichkeit mit 4.0.2 ist. Da sich in dem Teil keine Änderungen beim Sprung auf 4.0 ergeben haben, erwarte ich keine Probleme.

Aber über den Lösungsansatz an sich bin ich mir unsicher. Darf man die Subformulare wirklich einfach so per SQL löschen? Oder muss es anders eingebettet werden? Also im Rahmen von "Satz löschen" auch planvoll die Subformulare bzw. deren Datensätze löschen und das nicht einer "Aufräumaktion "removeRelationTableRelicts" überlassen?

Müsste es nicht Löschüberprüfungen geben? Sowohl mein Herauslöschen eines einzelnen Subformulars als auch bei allen. immerhin könnten auch auf die Subtabelle weitere Relationen eingerichtet sein oder sie sind in einem Choice adressiert?

christophboecker avatar Mar 25 '22 19:03 christophboecker

Da hast du vollkommen Recht. Einfach per SQL ist falsch und nur eine Krücke. und eigentlich muss die ganze Reihe durchlaufen werden und bei einem Fehler, wieder alles rückgängig gemacht werden.

dergel avatar Apr 09 '22 17:04 dergel

Ich hänge mich hier mal rein, da ich eben festgestellt habe das 1-n Relationen nicht gelöscht werden, wenn der "Hauptdatensatz" gelöscht wurde.

Lösen konnten wir es nur durch einen Trigger

DELIMITER $$
CREATE TRIGGER delete_rex_news
AFTER DELETE ON rex_news
FOR EACH ROW
BEGIN
    DELETE FROM rex_news_blocks WHERE news = OLD.id;
END $$
DELIMITER ;

Dies ist aber so auch nur möglich da rex_news_blocks nicht noch weitere Tochter Tabellen hat.

skerbis avatar Jul 17 '23 09:07 skerbis