Arbeitsweise des GORM und des GORM-Managers sind hierkomisch

Im Entwickler-Forum können Implementierungsdetails sowie Alternativen der Umsetzung diskutiert werden. // Here, developers can discuss implementation details of features of their projects.
Antworten
dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

Arbeitsweise des GORM und des GORM-Managers sind hierkomisch

Beitrag von dingsda » 07.03.2014, 21:34:06

Hallo,

ich versuche ja gerade den GORM-manager umzugestalten und dabei sind mir ein paar sachen aufgefallen, die ich so etwas komisch umgesetzt finde.

in der doku heißt es:
Die Werte der Attribute bestimmen dabei die Auslegung der Felder in der Datenbank. Der Mapper kennt dabei die allgemeingültigen Werte

VARCHAR({LENGTH})
TEXT
DATE

die eigenständig in die entsprechenden SQL-Anweisungen "übersetzt" werden
diese aussage verstehe ich eigentlich so, dass wenn ich z.b. varchar(50) für ein feld angebe, dass es dann genau so behandelt wird, wie wenn ich varchar(50) in der create table-anweisung angebe. dem ist aber nicht so.
wenn ich bei create table für ein feld varchar(50) angebe dann behandelt mysql es wie

Code: Alles auswählen

varchar(50) null default null character set [table-characterset]
der gorm-manager macht daraus

Code: Alles auswählen

varchar(50) not null default '' character set [table-characterset]
das find ich doch etwas komisch.
allgemein versteh ich nicht, warum der gorm-manager diese werte überhaupt übersetzen sollte. Es funktioniert ja auch ohne. gibt es gründe warum der gorm gerade diese felder so haben möchte?
bei date könnte ich mir noch vorstellen, dass es gut ist, dass das "übersetzt" wird aber hab mir da noch nicht angeschaut wie mysql das behandelt.

dagegen sollte der GORM-Manager lieber eine "übersetzung" (umwandlung wäre hier passender) machen, wenn man für ein feld Timestamp als datentyp angibt. ansonsten kommt ne fehlermeldung von mysql, weil das erste Timestamp-feld immer als default CURRENT_TIMESTAMP bekommt sofern als default nicht etwas anderes angegeben wird. das kolidiert dann natürlich mit dem CURRENT_TIMESTAMP vom feld CreationTimestamp.

beim gorm selbst ist mir auch etwas komisches aufgefallen. bei der methode saveObject wird beim zusammenbau des insert- / update-statements geprüft, ob ein feld null-werte enthalten darf oder nicht um dann die anweisung entsprechend anzupassen. das ist auch erstmal gut. aber die umsetzung passt meiner meinung nach auch hier nicht so wirklich.

Code: Alles auswählen

private static $NULL_FIELD_IDENTIFIER = 'NULL DEFAULT NULL';

....

// check, whether the field is a null value and translate PHP null values into
// MySQL NULL value
if (stripos($this->mappingTable[$objectName][$propertyName],self::$NULL_FIELD_IDENTIFIER) === false) {
   $value = '\'' . $propertyValue . '\'';
} else {
   if (empty($propertyValue)) {
      $value = 'NULL';
   } else {
      $value = '\'' . $propertyValue . '\'';
   }
} 
wenn ein feld null enthalten darf, dann möchte der GORM, dass man das auch explizit in der ini angibt als "null default null". das ist auch wieder anders als mysql es erwartet. besser wäre es imho zu prüfen ob man "not null" angegeben hat. denn das ist es auch, was mysql als anweisung erwartet um ein feld so zu behandeln.

Code: Alles auswählen

 if (empty($propertyValue)) 


sollte eigentlich auch besser

Code: Alles auswählen

 if ($propertyValue===NULL) 
lauten. denn empty kann auch ein leerstring sein.

die Prüfung müsste also eigentlich so sein:

Code: Alles auswählen

private static $NOT_NULL_FIELD_IDENTIFIER = 'NOT NULL';

....

// check, whether the field is a null value and translate PHP null values into
// MySQL NULL value
if (stripos($this->mappingTable[$objectName][$propertyName], self::$NOT_NULL_FIELD_IDENTIFIER) === false) {
   if ($propertyValue===NULL) {
      $value = 'NULL';
   } else {
      $value = '\'' . $propertyValue . '\'';
   }
} else {
   $value = '\'' . $propertyValue . '\'';
} 
oder so:

Code: Alles auswählen

private static $NOT_NULL_FIELD_IDENTIFIER = 'NOT NULL';

....

// check, whether the field is a null value and translate PHP null values into
// MySQL NULL value
if ($propertyValue===NULL && stripos($this->mappingTable[$objectName][$propertyName], self::$NOT_NULL_FIELD_IDENTIFIER) === false) {
      $value = 'NULL';
   } else {
      $value = '\'' . $propertyValue . '\'';
   } 
lg
Dingsda

edit: die sache mit dem timestamp werd ich beim überarbeiten des gorm gleich mitändern.
Zuletzt geändert von dingsda am 13.03.2014, 00:03:36, insgesamt 1-mal geändert.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Arbeitsweise des GORM und des GORM-Managers sind hierkom

Beitrag von dr.e. » 08.03.2014, 11:23:25

Hallo Dingsda,
wenn ich bei create table für ein feld varchar(50) angebe dann behandelt mysql es wie

Code: Alles auswählen

varchar(50) null default null character set [table-characterset]
der gorm-manager macht daraus

Code: Alles auswählen

varchar(50) not null default '' character set [table-characterset]
das find ich doch etwas komisch.
Das Reverse-Engeneering ist sicher eine Schwachstelle der Implementierung. Wenn du hier Verbesserungen einbringen möchtest, immer gerne. Im Code stehen dazu auch schon einige Hinweise.
allgemein versteh ich nicht, warum der gorm-manager diese werte überhaupt übersetzen sollte. Es funktioniert ja auch ohne. gibt es gründe warum der gorm gerade diese felder so haben möchte?
bei date könnte ich mir noch vorstellen, dass es gut ist, dass das "übersetzt" wird aber hab mir da noch nicht angeschaut wie mysql das behandelt.
Das wurde eingeführt um die Definition/Konfiguration zu erleichtern und SQL zu abstrahieren. Ich würde so ein Feature gerne auch weiterhin unterstützen.
dagegen sollte der GORM-Manager lieber eine "übersetzung" (umwandlung wäre hier passender) machen, wenn man für ein feld Timestamp als datentyp angibt. ansonsten kommt ne fehlermeldung von mysql, weil das erste Timestamp-feld immer als default CURRENT_TIMESTAMP bekommt sofern als default nicht etwas anderes angegeben wird. das kolidiert dann natürlich mit dem CURRENT_TIMESTAMP vom feld CreationTimestamp.
Klingt gut! :)
wenn ein feld null enthalten darf, dann möchte der GORM, dass man das auch explizit in der ini angibt als "null default null". das ist auch wieder anders als mysql es erwartet. besser wäre es imho zu prüfen ob man "not null" angegeben hat. denn das ist es auch, was mysql als anweisung erwartet um ein feld so zu behandeln.
Wenn sich das so umsetzen lässt, kannst du es gerne so anpassen. Wichtig ist nur, dass sich die API nicht grundlegend ändert.

Noch ein Hinweis: bei allen Änderungen bitte immer Abwärtskompatibilität beachten oder ein Migrations-Skript schreiben, das die bisherige Anwendung und die Migration auf die neue Semantik automatisch in bestehenden Projekten umschreibt. Migrationsdoku bitte unter http://wiki.adventure-php-framework.org ... .0_auf_2.1 erstellen.

Abschließend: vielen Dank für dein Engagement! :) Freut mich sehr, dass du dich mit dem GORM beschäftigen möchtest!
Viele Grüße,
Christian

dingsda
Beiträge: 49
Registriert: 03.02.2014, 04:00:36

Re: Arbeitsweise des GORM und des GORM-Managers sind hierkom

Beitrag von dingsda » 10.03.2014, 15:39:15

dr.e. hat geschrieben:
allgemein versteh ich nicht, warum der gorm-manager diese werte überhaupt übersetzen sollte. Es funktioniert ja auch ohne. gibt es gründe warum der gorm gerade diese felder so haben möchte?
bei date könnte ich mir noch vorstellen, dass es gut ist, dass das "übersetzt" wird aber hab mir da noch nicht angeschaut wie mysql das behandelt.
Das wurde eingeführt um die Definition/Konfiguration zu erleichtern und SQL zu abstrahieren. Ich würde so ein Feature gerne auch weiterhin unterstützen.
erleichtert es denn wirklich etwas?
bei den anderen feldtypen, die der gorm nicht "kennt" und daher auch nicht umschreibt ist die konfiguration/definition genau so einfach.
ich schreibe

Code: Alles auswählen

[tabellenname]
feld =  "int"
und das reicht vollkommen aus. das wird vom gorm-manager genau so an mysql in der create table anweisung weitergereicht:

Code: Alles auswählen

CREATE TABLE IF NOT EXIST tabellenname (
feld int
) ENGINE usw.
das wird dann von mysql so interpretiert als hätte ich geschrieben:

Code: Alles auswählen

CREATE TABLE IF NOT EXIST tabellenname (
feld INT(11) NULL DEFAULT NULL
) ENGINE usw.
bei varchar(N) wäre es genau so wenn es nicht umgeschrieben würde.

Ich frage mich einfach, warum varchar(N) nun ausgerechnet zu "varchar(N) NOT NULL DEFAULT ''" umgeschrieben wird und nicht zu "varchar(N) NULL DEFAULT NULL".
das tritt ja auch nicht erst im reenginering auf, sondern schon beim anlegen der tabellen.

was genau meinst du hier mit "sql abstrahieren"?
dr.e. hat geschrieben:Wenn sich das so umsetzen lässt, kannst du es gerne so anpassen. Wichtig ist nur, dass sich die API nicht grundlegend ändert.

Noch ein Hinweis: bei allen Änderungen bitte immer Abwärtskompatibilität beachten oder ein Migrations-Skript schreiben, das die bisherige Anwendung und die Migration auf die neue Semantik automatisch in bestehenden Projekten umschreibt. Migrationsdoku bitte unter http://wiki.adventure-php-framework.org ... .0_auf_2.1 erstellen.
wegen der Migration und der abwärtskompatibilität werd ich mir wohl noch gedanken machen müssen. muss dazu wahrscheinlich auch mal schauen, wie andere funktionen des GORMs dann auf NULL-felder reagieren.
ich werd das auf jeden fall erstmal im hinterkopf behalten und wenn ich schon etwas mehr mit dem gorm gearbeitet habe nochmal in angriff nehmen.

Benutzeravatar
dr.e.
Administrator
Beiträge: 4533
Registriert: 04.11.2007, 16:13:53

Re: Arbeitsweise des GORM und des GORM-Managers sind hierkom

Beitrag von dr.e. » 11.03.2014, 00:03:22

Hallo dingsda,

das Umschreiben erleichtert meiner Meinung nach einfach die Tipp-Arbeit bei der Definition von Objekten. Ich muss mich zudem weniger mit SQL beschäftigen, was ein weiterer Vorteil bei der Nutzung des GORM ist. Er stellt dir PHP-Methoden und Klassen zur Verfügung, mit denen du einfach die Datenverwaltung erledigen kannst. Auch die Verwaltung von Beziehungen gehen einfacher von der Hand als wenn du dir jedes Mal ein Datenmodell neu überlegen musst.

Wie gesagt: wir können das gerne ändern, allerdings ist dann wichtig, dass a) ein Migrations-Skript für die Konfigurationen vorhanden ist, b) die Dokumentation up-2-date gehalten wird und sich die API innerhalb der 2.X-Linie nicht absolut grundlegend ändert.
was genau meinst du hier mit "sql abstrahieren"?
Du kannst Objekte und mit diesen in Beziehung stehende Objekte ohne ein SQL-Statement zu schreiben abfragen/speichern/löschen.
wegen der Migration und der abwärtskompatibilität werd ich mir wohl noch gedanken machen müssen. muss dazu wahrscheinlich auch mal schauen, wie andere funktionen des GORMs dann auf NULL-felder reagieren.
ich werd das auf jeden fall erstmal im hinterkopf behalten und wenn ich schon etwas mehr mit dem gorm gearbeitet habe nochmal in angriff nehmen.
Klingt gut! :)
Viele Grüße,
Christian

Antworten

Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 1 Gast