Jede eindeutige Prozedur ist durch ein Programm definiert, das eine oder mehrere Datenbanktabellen migriert. Diese Verarbeitung muss UUMGSPExxxnn heißen, wobei xxx die Wurzel einer zu migrierenden Tabelle und nn zwei Ziffern bezeichnet (damit ggf. mehrere Verarbeitungen zur Verfügung stehen). Funktionsprinzip:
Beschreibung der Migrationsverarbeitung
Die Migrationsverarbeitung umfasst folgende Elemente:
- Zunächst einige Zeilen, mit denen sich die Prozedur direkt anstoßen lässt.
- Das Unterprogramm RAZ_UUMGSPExxxnn mit dem die ursprüngliche Situation wiederhergestellt werden kann, falls die Prozedur erneut gestartet werden muss.
- Das Unterprogramm MAJ_UUMGSPExxxnn, welches die Migrationsprozedur umfasst.
- Das Unterprogramm PATCH.
- Das Unterprogramm UTI_MOUL.
Diese Unterprogramme werden im Folgenden beschrieben.
In den nachstehenden Beispielen wird davon ausgegangen, dass die Verarbeitung UUMGTRTZMY01 dem eindeutigen Migrationsunterschritt der einzigen Tabelle ZMYTABLE entspricht. Vor der erneuten Ordnerfreigabe wurden folgende Vorgänge durchgeführt:
- Gemäß der oben erwähnten Regel wurde die Tabelle ZMYTABLE umbenannt (die mit den alten Werten belegte Tabelle heißt standardmäßig UZMYTABLE).
- Die neue Tabelle ZMYTABLE wurde mit der neuen Struktur angelegt, ist aber noch leer.
Die Tabelle ZMYTABLE wird auf Basis der Daten in der Tabelle UZMYTABLE von der Migrationsprozedur belegt.
Vorgelagerte Zeilen
Mit den vorgelagerten Zeilen kann die Verarbeitung direkt aus dem Editor heraus mithilfe der Funktion Ausführung angestoßen werden. Hierbei finden sich in der Regel folgende Zeilen:
# Definition des aktuellen Ordners und Lesen der Ordnertabellen
Local Char FOLDER(30) : FOLDER = nomap
# Name der Migrationsprozedur
Local Char PROG(20) : PROG="UUMGTRTZMY01"
If !GSERVEUR
Call SAIDOS(FOLDER,"") From SAIDOS
Endif
If FOLDER<> ""
If clalev([F:ADS])=0 : Local File ADOSSIER [ADS] : Endif
Read [ADS] DOSSIER=[L]FOLDER : If fstat : Raz [F:ADS] : Endif
# Öffnen der Protokolldatei und Anzeige eines temporären Fensters
If !GSERVEUR
Call TEMPON("O") From GESECRAN
Call OUVRE_TRACE(PROG) From LECFIC
Endif
# Prozeduraufruf
Call MAJ_UUMGSPEZMA00(FOLDER)
# Schließen der Protokolldatei
If !GSERVEUR
Call TEMPOFF From GESECRAN
Call FERME_TRACE From LECFIC
Call LEC_TRACE From LECFIC
Endif
Endif
End
Unterprogramm zum Zurücksetzen
Das mit
Subprog RAZ_UUMGTRTZMY01(FOLDER)
deklarierte Unterprogramm dient dazu, die alte Situation wiederherzustellen, um die Prozedur erneut anstoßen zu können.
Es müssen mindestens die folgenden grundlegenden Schritte durchgeführt werden:
- Prüfung, ob die alten Tabellen existieren:
# Suche nach der alten Tabelle zu der zu belegenden Tabelle (ici UZMYTABLE)
Call MIGTABNAME(FOLDER,"ZMYTABLE",OLDTABLE,ERR) From TRTMIG
If ERR : End : Endif
# Ist die alte Tabelle tatsächlich vorhanden?
If filinfo(filpath("FIL",OLDTABLE,"fde",[F:ADS]DOSSIER),0)<0
End
Endif - Es werden nur Fehlerprotokolle erstellt (keine Fortschritts- oder Hinweismeldungen)
- Leeren der Tabelle(n), in die von der MAJ-Prozedur Daten eingefügt werden. Hierfür steht folgendes Unterprogramm zur Verfügung:
# unwiderrufliches Leeren der Tabelle ZMYTABLE
Call MIGTABRAZ(FOLDER,"ZMYTABLE",ERR)
If ERR : End : Endif - Müssen Tabellen teilweise geleert werden, die von mehreren Verarbeitungen gemeinsam verwendet werden, sind klassische Transaktionen folgenden Typs zu verwenden:
Trbegin [...] : Delete [...] Where ... : Commit - Zurücksetzen der bereits zu dieser Tabelle migrierten Flussdaten mithilfe des folgenden Unterprogramms:
# Derzeit keine migrierten Zeilen
Call MIGRAZKEY(FOLDER,"UUMGTRTZMY01",ERR) From TRTMIG
Unterprogramm zum Aktualisieren
Das Unterprogramm MAJ_UUMGTRTZMY01 zum Umschlüsseln des Inhalts der Tabelle UZMYTABLE, aus der die Tabelle ZMYTABLE belegt wird, muss folgende Aufgaben ausführen:
- Zunächst muss der Name der Migrationsprozedur definiert werden
Local Char PROG(20) : PROG="UUMGTRTZMY01" - Der Status der Prozedur wird mit dem folgenden Unterprogramm aktualisiert (auch wenn eine einleitende Bedingung den Start nicht erforderlich macht, wenn nichts verarbeitet werden muss: der Status muss Beendet sein, damit die Prozedur als erfolgt angesehen wird und die folgenden gestartet werden können). Andernfalls wird der Status auf läuft gesetzt:
# Integer CURSTAT für die Statusverwaltung (lokales Menü 21)
# Die möglichen Werte lauten In Warteschlange, Läuft, Abgeschlossen...
# Wurde die Prozedur angestoßen, gilt CURSTAT = 2
# Ist die Prozedur abgeschlossen, gilt CURSTAT = 3
# Im Fehlerfall ist CURSTAT auf den Wert 7 zu setzen
# In der Folge enthält die Variable PROG den Prozedurnamen
# (z. B. UUMGTRTZMY01)
Call MIGSTKENDFLG (DOSSIER,PROG,CURSTAT,ERR) From TRTMIG - Die Existenz dieser und der vorherigen Tabellen wird analog zum Initialisierungsunterprogramm mit dem Unterprogramm MIGTABNAME geprüft. Im Fehlerfall muss der Aufgabenstatus mit dem Unterprogramm MIGSTKENDFLG auf den richtigen Wert (7) gesetzt werden.
- Danach werden die für die Migration notwendigen Tabellen geöffnet. Öffnen der internen Tabellen der Migrationsprozedur:
Call MIG_OUVRE From TRTMIG - Bei der Verwendung der Protokolldateien ist Zurückhaltung geboten (es muss nicht zu jeder Zeile ein Protokoll angelegt werden – so manche Migration ist bereits an mangelndem Plattenplatz für die Protokolldateien gescheitert). Zu empfehlen ist eine Protokolldatei, die mit einer Nachricht vom Typ "Start des Aktualisierungsunterschrittes für Tag xxx" beginnt, gefolgt von einer Zeile mit einem Zeitstempel und einer Meldung wie "Prozessbeginn um: ". Diese Protokolldateien greifen auf die folgenden Unterprogramme zu:
# Protokollzeile, wenn ERR=0, andernfalls Fehlerzeile
Call ECR_TRACE("message",ERR) From GESECRAN
# Mit Zeitstempel versehene Zeile der Protokolldatei
Call ECR_TIME("message") From DOSSUB Um die Laufzeit beim Einfügen in Tabellen zu verringern, werden die Indizes gelöscht. Es bleibt nur der erste zu Beginn der Prozedur aktive Index. Die Indizes werden am Ende der Prozedur von folgenden Unterprogrammen erneut erstellt:
Call MIGTABINIT(FOLDER,"ZMYTABLE",ERR) From TRTMIG
Dies setzt jedoch voraus, dass zum Ausführungszeitpunkt keine andere Prozedur mit der Tabelle arbeitet. Während der Ausführung der Prozedur darf keine andere Prozedur aus der Tabelle lesen, die Tabelle ändern oder in die Tabelle einfügen. Wenn mehrere Prozeduren auf die Tabelle zugreifen sollen, darf nicht dieses Unterprogramm verwendet werden.
- Der erste zu verarbeitende Schlüssel findet sich dann in der Verarbeitungsschleife. Wird die Migration nach einer Unterbrechung wiederaufgenommen, ist dieser Schlüssel nicht leer. Nach dem Schlüssel wird mit dem im Folgenden beschriebenen Unterprogramm gesucht:
# TBMKEY(1..NBMKEY) Tabelle mit den Schlüsselwerten
# oder das Lesen fortsetzen. Es werden mindestens die Komponenten
# des letzten verarbeiteten Schlüsselwertes gefunden, es kann aber
# ein Segment hinzugefügt werden, dem zu einem Mehrfachschlüssel das erreichte
# Unterbrechungslevel zu entnehmen ist. TBMKEY muss vor dem Aufruf leer sein
# Wird der Parameter leer zurückgegeben, war kein aktueller Schlüsselwert vorhanden
# (die Prozedur wird dann von Beginn an wiederaufgenommen).
# Mit NBMKEY wird die Anzahl der erwarteten Werte definiert
# NBL und NBUP sind Zähler für die gelesenen und aktualisierten Zeilen, bevor folgender Befehl gegeben wird:
Call MIGGETKEY (FOLDER,PROG,NBMKEY,TBMKEY,NBL,NBUP,ERR)
& From TRTMIG - Es kann dann in die Leseschleife der alten Tabelle(n) und in die Schreibschleife der neuen Tabellen verzweigt werden. Aus Performancegründen ist es vorzuziehen, isolierte Lesebefehle zu vermeiden und stattdessen mit Link zu arbeiten, vorzugsweise mit inner Joins (Syntax Where CLE ~=... ). Wenn aus Initialisierungs- oder Steuerungsgründen aus einer "kleinen" Tabelle gelesen werden muss (unter "klein" werden an dieser Stelle Tabellen mit mehr als 1.000 Zeilen verstanden), empfiehlt es sich häufig, den benötigten Tabelleninhalt in Speichervariablen zu schreiben, bevor in die Schleife verzweigt wird.
- Um Fehler beim Schreiben einer zu großen Anzahl von Zeilen zu vermeiden, werden die geschriebenen Zeilen gezählt, und die Schleife wird nach jeweils N Zeilen unterbrochen (mithilfe der globalen Variable GMAXUPDTRS kann N beispielsweise auf den Wert 50.000 gesetzt werden).
- Auf Performancegründen empfiehlt sich die Verwendung der Writeb-Anweisung (diese wurde mit der in Version 6.4 verwendeten Engine eingeführt). Mit dieser Anweisung werden die Datensätze gruppiert. Dies wirkt sich insbesondere bei mehrschichtigen Architekturen positiv auf die Performance aus. Die Anweisung kann nur verwendet werden, wenn die Tabelle in der Schleife nicht erneut gelesen wird (z. B. um zu prüfen, ob ein bestimmter Datensatz bereits existiert). Writeb setzt voraus, dass der Gruppierungsfaktor von einer Systemvariable namens adxwrb gesetzt wird (10 hat sich als guter Wert erwiesen). Um im Fehlerfall sämtliche aktuellen Schlüssel wiederherstellen zu können, müssen die geschriebenen Schlüsselwerte auf einen Stapel gelegt werden (Fehler treten im Zusammenhang mit der Flush-Anweisung auf, nicht bei Writeb). Es kann das folgende Unterprogramm verwendet werden:
# Schlüssel auf einen Stapel legen
# KEY_ARRAY ist eine mit
# Local Char KEY_ARRAY(N)(adxwrb) zu Beginn der Verarbeitung deklarierte alphanumerische Tabelle
# (Die Größe N richtet sich nach der Größe der Schlüsselwerte)
# NUMBER ist eine Shortint- Variable, der die Anzahl von Schlüsseln auf dem Stapel zu entnehmen ist
# KEY_VALUE ist bei mehrteiligen Schlüsseln der codierte Schlüsselwert
Call STK (KEY_ARRAY, NUMBER,KEY_VALUE) From TRTMIG - Nach dem Verlassen der Schleife (nach N Durchläufen oder bei Verarbeitungsende) wird eine Flush-Anweisung für die Tabelle gegeben (bei Verwendung von Writeb). Diese Anweisung kann einen Fehler verursachen. Ist ein Fehler aufgetreten und ist adxwrbgrößer als 1, kann man die Schlüssel finden, in denen der Fehler in der Tabelle KEY_ARRAY auftreten kann, in den adxwrbersten Indizes: es erfolgt ein Rollback, bevor die Prozedur den Status Beendet mit Fehlern erhält und die Verarbeitung beendet wird.
- Wenn diese korrekt abläuft, wird die Anzahl der gelesenen und aktualisierten Zeilen mit folgendem Aufruf aktualisiert:
Call MIGSTKKEY (FOLDER,PROG,NBMKEY,TBMKEY,NBL,NBUP,ERR)
& From TRTMIG
Anschließend wird ein Commit gegeben. - Danach kann getestet werden, ob eine Stoppanweisung gegeben wurde. Ist dies nicht der Fall und sind noch nicht alle Zeilen verarbeitet worden, werden erneut N Schleifendurchläufe gestartet. Der Test auf Existenz einer Stoppanweisung wird mit dem folgenden Unterprogramm durchgeführt:
# Die Variable STOP wird bei Existenz einer Stoppanweisung mit dem Wert 0 zurückgegeben.
Call MIGSTKPROGRESS (FOLDER,PROG,STOP,ERR) From TRTMIG - Wurde eine Stoppanweisung gegeben (oder ist die Verarbeitung abgeschlossen), werden folgende Vorgänge ausgeführt:
# Indexierung der verarbeiteten Tabelle(n)
# (nur, wenn MIGTABINIT verwendet wurde)
Call MIGTABEND(FOLDER,"ZMYTABLE",ERR) From TRTMIG
# Der Überwachungsinstanz das Verarbeitungsende signalisieren
Call MIGTRTEND(FOLDER,PROG) From TRTMIG
Call ECR_TIME(PROG+" : Aufgabe abgeschlossen") From DOSSUB
Danach können die Tabellen geschlossen, ggf. noch vorhandene Ressourcen freigegeben und das Unterprogramm mit der End-Anweisung angehalten werden.
Unterprogramm PATCH
Mit dem Unterprogramm PATCH kann die Migration gestartete werden. Der Patch muss nur sicherstellen, dass die Tabelle ADOSSIER geöffnet ist. Danach liest er den dem zu verarbeitenden Ordner entsprechenden Datensatz und stößt die Migrationsprozedur an. Codebeispiel für den Patch:
Subprog PATCH(FOLDER)
Value Char FOLDER
# Kein Aufruf im Supervisorordner
If FOLDER=GDOSX3 : End : Endif
#Belegung der Klasse [F:ADS]
If clalev([F:ADS])=0 Local File ADOSSIER [ADS] : Endif
Read [ADS] DOSSIER=FOLDER : If fstat : Raz [F:ADS] : Endif
# Anstoßen der Prozedur
Call MAJ_UUMGTRTZMY01(FOLDER)
End
Unterprogramm UTI_MOUL
Mit diesem Unterprogramm kann die Migration während der Ordnerfreigabe angestoßen werden. Es entspricht im Großen und Ganzen dem Unterprogramm PATCH. Die Prüfung der Tabelle ADOSSIER kann jedoch entfallen, und es muss auch nicht der dem zu verarbeitenden Ordner entsprechende Datensatz gelesen werden, da dies von der aufrufenden Verarbeitung übernommen wird. Die einzige Aufgabe von UTI_MOL ist daher, die entsprechende Prozedur anzustoßen. Codebeispiel für den Patch:
Subprog UTIL_MOUL(FOLDER)
Value Char FOLDER
# Kein Aufruf im Supervisorordner
If FOLDER=GDOSX3 : End : Endif
# Prozeduraufruf
Call MAJ_UUMGTRTZMY01(FOLDER)
End
Eingabepunkt MIGTAB
Wenn manche der individuellen Flusstabellen auf analoge Weise verarbeitet werden sollen (d. h. auf dieselbe Weise wie bei Beginn der Ordnerfreigabe umbenennen, dann mit der neuen Struktur anlegen), sind folgende Schritte durchzuführen:
- Der Eingabepunkt MIGTAB wird dazu verwendet vorzugeben, dass eine individuelle Flusstabelle im ersten Schritt (Umbenennung und Löschen der überflüssigen Indizes) auf dieselbe Weise verarbeitet werden soll wie die Standardtabellen.
- Hierfür sind im Supervisorordner (bzw. bei dreischichtigen Architekturen im Referenzordner) die individuellen Tabellen zu beschreiben, deren Struktur sich bei der Versionsänderung ändert. Andernfalls werden die neuen Flusstabellen nicht leer und mit der neuen Struktur angelegt.
- Es handelt sich hierbei um eine Ausnahme von der Regel, dass im Allgemeinen keine individuellen Tabellen im Supervisorordner angelegt werden. Der Grund ist einfach: Für diesen Sonderfall muss ein Referenzdictionary zur Verfügung stehen. Das einzige verfügbare bei zweischichtigen Architekturen (häufigster Fall) ist der Supervisorordner (bei Sage X3 der Ordner "X3"). Es ist auch darauf hinzuweisen, dass im Supervisorordner angelegte individuelle Tabellen ohne Ankündigung bei Installation einer neuen Version des Supervisorordners wieder gelöscht werden können. Individuelle Tabellen in X3 sind daher als temporär zu betrachten. Eine Sicherung der Tabellenbeschreibung sollte an einer anderen Stelle vorhanden sein.
- Da Standardtabellen aus individuellen Tabellen belegt werden können, muss bei der Versionsänderung nicht unbedingt eine neue individuelle Tabelle angelegt werden. In diesem Fall wird die individuelle Tabelle mit dem Eingabepunkt MIGTAB umbenannt, und für eventuell noch notwendige Aktualisierungen werden die Eingabepunkte in den Standard- oder Zusatzprozeduren verwendet. Im Zieldictionary müssen keine neuen Tabellen angelegt werden.
Wenn dieser Eingabepunkt nicht verwendet wird, werden die durch einen individuellen Aktivitätscode geschützten individuellen Tabellen nicht angefasst. Sie behalten ihren alten Zustand. Wenn die Versionsänderung sich nicht auf die individuellen Tabellen auswirkt (was häufig der Fall sein wird), entspricht dies der Standardvorgehensweise.
Jedes Sonderfeld in einer Standardflusstabelle, dessen Inhalt so übertragen werden muss, erfordert keine besonderen Vorsichtsmaßnahmen: Die Standardmigrationsverarbeitungen verwenden Klassenzuweisungen für die Durchführung von Datenkopien.
Der Name der Verarbeitung, in der sich der Eingabepunkt MIGTAB befindet, hängt von der auf SAFE X3 beruhenden Software ab. Im Falle von Sage X3 liegt der Eingabepunkt MIGTAB in der Verarbeitung TRTMIGTABX3.
In diese Verarbeitung sind Zeilen der folgenden Art einzubauen:
Call MIGTABTABADD(DOSSIER,"ZMYTABLE","ZMY","index",
& NBTAB,WTABLE,WTABLEJ,WABRJ,WTABIDX,ERR) From TRTMIG
Die oben angegebenen Variablennamen sind überwiegend fest:
- DOSSIER ist der Ordnercode.
- Der Name der zu migrierenden Tabelle lautet hier beispielhaft "ZMYTABLE".
- "ZMY" entspricht der Abkürzung der alten Tabelle nach der Umbenennung. Ist diese Variable nicht belegt, wird eine temporäre Abkürzung im Format U## oder W## festgelegt, wobei es sich bei ## um einen numerischen Wert handelt.
In keinem Fall wird diese Abkürzung in den Verarbeitungen verwendet: In den Prozeduren wird eine andere temporäre Abkürzung verwendet: [XXXM], wobei XXX die Abkürzung der migrierten Tabelle ist. - NBTAB enthält die Nummer der als zu migrierend definierten Flusstabelle (bei jedem Aufruf von TRTMIG wird diese Variable inkrementiert).
- WTABLE, WTABLEJ, WABRJ, WTABIDX sind Tabellen, die sämtliche mit den bereits deklarierten Flusstabellen verbundenen Elemente enthalten.
- ERR weist im Fehlerfall einen Wert auf.
Eingabepunkte der Standardmigrationsverarbeitungen
In allen Standardmigrationsprozeduren stehen Eingabepunkte zur Verfügung, mit denen in die Logik der Standardtabellenübertragung eingegriffen werden kann. Dabei handelt es sich um die folgenden Eingabepunkte:
- Mit CRITSEL kann die Variable CRITERESPE belegt werden, um die zu verarbeitenden Daten zu filtern. Der verwendende Kontext ist in dem Anhang definiert, in dem die Migrationsprozeduren beschrieben sind.
- Mit VERIFSEL werden die Felder der alten, während der Verarbeitung gelesenen Tabellen erneut berechnet. Datensätze, die nicht erneut geschrieben werden sollen, werden mit ISVALID = 0 ggf. von der Verarbeitung ausgeschlossen. Der verwendende Kontext ist in dem Anhang definiert, in dem die Migrationsprozeduren beschrieben sind.