Dies ist entstanden auf Grund von Schreibzugriff auf pgdbe-Datenbank für Programme, die nicht in Xbase++ geschrieben sind (z.B. in C#) und Using SQL INSERT and UPDATE with ISAM emulating tables, in particular with indexed columns.
Microservices sind der Weg in die Zukunft, das hat Alaska klar gemacht. Idealerweise wäre Geschäftslogik immer durch eine geeignete REST-API zur Verfügung gestellt, die externe (vielleicht nicht in Xbase++ geschriebene) Anwendungen müssten sich nicht mit der internen Struktur von ISAM-Datenbanken befassen. Dann wäre sowas wie das hier weder nötig noch wünschenswert, das ist mir klar.
Unter Umständen kann aber, zumindest für eine Übergangszeit, die Notwendigkeit vorkommen. Es gibt einige Gründe, warum nicht immer gleich Geschäftslogik-basierte APIs implementiert werden können, einschließlich:
- Fehlende Xbase++ Programmierer-Kapazität
- Zeitdruck
- Ändernde Anforderungen
- Prototyp-Entwicklungen durch nicht-Xbase++ Programmierer
...
Aber selbst wenn die externe Anwendungen doch die Struktur der Datenbank kennen (müssen), und direkten Lesezugriff für SELECT haben, kann es zumindest für Schreibzugriffe vorteilhaft sein, diese durch eine allgemeine REST-API anstatt direkt durch SQL UPDATE bzw. INSERT zu machen:
- Die Anwendungen benutzen dann schon zumindest teilweise REST-Technologie, was eine spätere Umzug auf Geschäftslogik-basierte APIs wenn vorhanden begünstigt.
- Die potentielle Probleme mit kurzzeitig inkonsistente Indexen werden vermieden.
- Einige ISAM-implementationsspezifische Details (wie Locking oder Versionierung) können standardmäßig behandelt werden, solange es nur jeweils um einen einzelnen Datensatz geht.
...
Entwurf
Der Microservice sollte als Class implementiert werden. Anwendungsspezifischer Code soll durch Vererbung implementiert werden: Datenbankverbindung bzw. das Öffnen (USE) der Tabellen, anwendungsspezifische Prüfungen, Logging u.s.w.
Als REST-Laie, folgende Requests fallen mir ein:
Code: Alles auswählen
GET url/tablename/recno GET würde ich zumindest in der ersten Implemention weglassen. Insbesondere die ?-Variante
GET url/tablename?... wäre schwer zu definieren und kann kaum mit der Macht eines SQL SELECTs mithalten.
POST url/tablename Anstatt SQL INSERT
PATCH url/tablename/recno Anstatt SQL UPDATE
DELETE url/tablename/recno Als Xbase++ DELETE implementiert
Code: Alles auswählen
{
"ErrorCode" : 0,
"ErrorMessage" : "",
"TableName" : "",
"RecNo" : 0,
"RowVersion" : 0,
"Fields" :
{
F1 : 0,
F2 : "",
...
}
}
Alles kommt im Response zurück: Auch für DELETE sollte der vorherige Inhalt des Datensatzes zurückkommen.
ErrorCode bis RecNo sollten weggelassen werden für POST und PATCH Requests.
Im Detail:
- ErrorCode: Ist wahrscheinlich überflüssig, vermutlich sollte stattdessen der HTTP Fehlercode benutzt werden.
Allerdings sollten spezifische Werte zurückgegeben werden für Fälle wie: TableName existiert nicht; Datensatz existiert nicht bzw. wurde gelöscht; RLOCK() für Datensatz scheitert; RowVersion stimmt nicht überein (sollte übrigens auch KeyVersion geprüft werden?); Feld existiert nicht; Feldinhalt vom falschen Typ (konnte nicht konvertiert werden);...
Dazu kommen bestimmt einige mehr, potentiell auch anwendungsspezifische. - ErrorMessage: Auf Englisch als Hilfe für den Programmierer bzw. mit zusätlichen Details, z.B. welche Felder fehlerhaft sind und warum.
- TableName: Der Tabellenname so wie in der Postgres Datenbank.
- RecNo: Entspricht RECNO() in Xbase++ bzw __record im SQL SELECT.
- RowVersion: Der zu erwartende/prüfende Wert von __rowversion bei POST und PATCH bzw. der aktuelle/resultierende Wert im Response.
Es ist mir noch unklar, ob vielleicht auch __keyversion geprüft werden soll.
Es werden übrigens über diese Schnittstelle keine bleibende Locks gesetzt. - Fields: Für POST und PATCH, nur die Felder, die gesetzt werden sollten (auch im Response).
Für Response zu DELETE (und GET falls implementiert), alle Felder im Datensatz.
Der Microservice muss in beiden Richtungen Typkonvertierungen (entsprechend Feldname) für die Feldwerte machen.
Vorübergehendes Schlusswort
Soweit bin ich erstmal mit den Gedanken, es erscheint mir machbar, Ihr habt bestimmt einige gute Vorschläge dazu und ich würde mich auf Zusammenarbeit freuen!
Es gibt ja einige offene Fragen, z.B. bzgl. __keyversion und (essentiell aber noch nicht erwähnt) wie am Besten Zugang zu der API beschränkt werden kann, z.B. durch eine auszuhandelde, möglicherweise ständig ändernde Session-ID - auch hier wäre ich für guten Rat dankbar!
Und auf alle Fälle Danke erstmal fürs Lesen.