Deutsch English
Blog
Home
Über tdbengine
Newsletter
Download
Helpware
Chat
Dokumentation
Einführungskurs
Befehlsreferenz
HOWTO - Wie kann ich...?
Schnipsel
Projekte
Links
Benchmarks
Bug Reporting
Supportanfrage
 
Home    Überblick    Suche    Impressum    Kontakt    Mitglieder
Wie kann ich dynamische Programme schreiben?

Was ist damit überhaupt gemeint?
Die tdbengine ist ja bekanntlich Datenbankengine, Interpreter und Compiler in einem.
Sind wir mal froh, dass der in EASY geschrieben Quelltext compiliert werden kann. Viele potentielle Fehler im Code, die ohne den Compiler zwangsläufig erst zur Laufzeit vom Interpreter entdeckt würden, würden uns ein wahres Datenchaos bescheren. Stellen Sie sich vor, mitten im Backupvorgang entdeckt der Interpreter, dass ein Funktionsparameter vom falschen Typ übergeben wird und bricht ab. Haben Sie nun ein Backup oder haben Sie keines?

Manchmal wäre es aber schon nützlich, wenn man die starren Strukturen etwas auflockern könnte. Dies könnte helfen, Quellcodes etwas abstrakter zu halten, um sie in anderen Projekten leichter wieder zu verwenden. Auch würde es uns erlauben, dem Nutzer unserer Anwendungen mächtige Werkzeuge zur Verfügung zu stellen. In anderen Datenbanksystemen, wie MS ACCESS, hat man ja schliesslich auch einen SQL-Editor mit dem man sehr viel (im Rahmen von SQL) anstellen kann.

Zum Glück bietet die tdbengine hier gleich mehrere Möglichkeiten, wie Sie dynamisch den Programmfluss bestimmen können. Diese möchte ich Ihnen im Folgenden etwas genauer erklären. DO _"weiterlesen()"


DO _
Mit DO in Kombination mit dem _ (Unterstrich) kann man beliebige Ausdrücke auswerten und anschliessend ausführen.

Beispiel

VAR x : STRING = "cgiwriteln('hallo welt')"
DO _x

Erst zur Laufzeit, genauer genommen, wenn der Interpreter in der 2. Zeile am Unterstrich "angekommen" ist, wird der Inhalt der Variablen x ausgewertet. Hier freilich kein Kunststück, ihr Inhalt ist ja fest vorgegeben.
DO veranlasst die tdbengine den Ausdruck, den der Unterstrich _ liefert, auszuführen. In diesem Fall also hätten wir das ganze sicherlich viel einfacher haben können:

CGIWriteLn('hallo welt')

hätte völlig ausgereicht.

Noch ein Beispiel:

PROCEDURE deletefromadressen(nID : INTEGER)
    //exemplarische Löschroutine
    ...
    DelRec(dbADRESSEN, FindAuto(dbADRESSEN, nID))
    ...
ENDPROC


PROCEDURE deletefromniederlassungen(nID : INTEGER)
    ...
    DelRec(dbNIEDERL, FindAuto(dbNIEDERL, nID))
    ...
ENDPROC


PROCEDURE delete(cTabelle : STRING; nID : INTEGER)
    VAR x : STRING = "deletefrom"+cTabelle+"("+Str(nID)+")"
     //werte x zur Laufzeit aus UND "starte" dessen Ergebnis
    DO _x
ENDPROC

Nehmen wir an, jede Tabelle in unserem Projekt verlangt gewisse tabellenspezifische Aufräumarbeiten von uns, wenn Datensätze gelöscht werden. Es soll jedoch anwendungsweit immer eine eigene Routine delete() aufgerufen werden. Diese Routine wiederrum soll nun dafür sorgen, dass die zur jeweiligen Tabelle gehörende deletefrom...() Prozedur ausgeführt wird. Freilich hätten wir das auch mit einem IF-THEN-ELSIF-ELSE-ENDMonstrum bewerkstelligen können. Mit jeder neuen Tabelle aber würde dieser IF-Baum wachsen - bei manchen Projekten ein unter Umständen sehr unübersichtliches Unterfangen.
Im Beispiel sind es die Variablen, die den weiteren Programmablauf bestimmen - und zwar erst zur Laufzeit.


Die Funktion Val()

Val() evaluiert beliebige Strings. Zumindest versucht Val() dies. Auf gut Deutsch macht Val() aus einer Zeichenkette ein Zahl.

Beispiele

VAR c1 : STRING = "123"
VAR c2 : STRING = "123 + 321 + 1 / 2 * 3"
VAR c3 : STRING = "Val(c1) + Val(c2)"
VAR c4 : STRING = "Val('999' + Str(Val(c3),0,2))"

VAR n : REAL

SetPara("nv 0")

n:=Val(c1)   // n = 123
n:=Val(c2)   // n = 445,5
n:=Val(c3)   // n = 568,5
n:=Val(c4)   // n = 999568,5

Sie sehen, mit Val()können nahezu beliebige Zeichenketten evaluiert werden. Dabei dürfen diese sogar auf Funktionen und Variablen des Programms zugreifen. Allerdings muss dazu der Laufzeitschalter nv auf 0 gestellt werden.


Die Funktion ExecProg()

ExecProg(cFilename : STRING)

Kompiliert und führt beliebige EASY-Programme aus.
cFilename darf dabei sowohl auf eine Datei als auch auf einen ramtext: verweisen.

(Sehr einfaches) Beispiel:

PROCEDURE Main
   VAR c : STRING
   VAR f : INTEGER = Rewrite("ramtext:code")

   WriteLn(f, "Procedure XYZ : String")
   WriteLn(f, "  RETURN 'xyz'")
   WriteLn(f, "Endproc")
   WriteLn(f, "")
   WriteLn(f, "c := xyz")
   Close(f)

   ExecProg("ramtext:code")

   CGIWriteLn(c)
ENDPROC

Hier wird erst zur Laufzeit ein ramtext:code geschrieben, der anschliessend mit ExecProg() kompiliert und ausgeführt wird.

Interessante Anwendungsmöglichkeiten stellen hierfür sicherlich dynamische Selektionsprogramme dar, die erst zur Laufzeit aus Teilbausteinen individuell zusammengebaut werden. Ein (sehr komplexes) Anwendungsgebiet wäre hier zum Beispiel die Auswertung und Umsetzung von SQL-Statements nach EASY-Code.


Weiterführende Links:

/Dokumentation/Laufzeitschalter


Autor: Thomas Friebel <tf@tdb.de>





tdbengine Anwendungen im Web:

Open-Source Web CMS


Open-Source Bug-Tracking


Free wiki hosting

Open-Source Wiki-System

Kostenloses Foren-Hosting

Diät mit tdbengine 8-)

tdbengine chat
irc.tdbengine.org
#tdbengine

   Copyright © 2003-2004 tdb Software Service GmbH
   Alle rechte vorbehalten. / All rights reserved
   Letzte Änderung: 20.12.2004


ranking-charts.de

Programmers Heaven - Where programmers go!