Home

Benchmarks
Historie
Forum
Download
Helpware
Insider
Dokumentation
Kurs
Provider-Infos

Impressum



tdbengine news vom 4.6.2000


Wieder gibt es neue Version der tdbengine. Die derzeit gehäuften Updates sind auf die zahlreichen Anregungen aus dem Kreis der Benutzer der tdbengine zurückzuführen.
 
Im ersten Teil dieser news werden die Neuerungen der Version 6.2.3 vorgestellt. Im zweiten Teil geht es dann um die Arbeit mit Markierungen von Datensätzen, da viele Neueinsteiger doch ein wenig Probleme damit haben.

Version 6.2.3

Pfad zu Bibliotheken in tdbengine.ini

Wer häufig Programrme mit anderen Entwicklern austauscht, ärgert sich bisweilen darüber, dass eingebundene Bibliotheken nicht auf Anhieb gefiunden werden.
Steht beispielsweise im Programm

USES e:/home/tdbengine/cgitools/db_ops.mod

so muss der Linuxanwender die Verzeichnisangabe ändern. Aus diesem Grund ist jetzt möglich, in die Konfigurationsdatei tdbengine.ini unter der Abteilung [globals] in dem Eintrag »libpath« eine Pfadangabe vorzunehmen, in dem dann die via USES eingebundenen Module gesucht werden.

Beispiel:

[globals]

...
libpath=/home/tdbengine/cgitools; /sbin/cgi/mods; .
 
Achtung: Linuxanwender können als Trennzeichen zwischen zwei Verzeichnisangaben den gewohnten Doppelpunkt verwenden, Win32-Benutzer müssen das Semikolon einsetzen.


+ + + + + + + + + + + + + + + + + + + + +

Neue Operatoren

Für einfache Variablen vom Typ REAL gibt es jetzt die nachgestelten Inkrement- und Dekrement-Operatoren:
VARDEF i : REAL
  • i++ steht für i:=i+1
  • i-- steht für i:=i-1
  • + + + + + + + + + + + + + + + + + + + + +

    Zusätzliche Kommentarzeichen

    Statt der zwei aufeinanderfolgenden Punkte kann jetzt auch der Doppel-Slash als Kommentarzeichen benutzt werden:
    // Das ist ein Kommentar.

    + + + + + + + + + + + + + + + + + + + + +

    Neue Funktion InitArray

    Mit dieser Funktion können zur Laufzeit Felder re-dimensioniert werden. Damit sind dynamisch dimensionierte Felder in EASY möglich.
    Beispiel:

    VARDEF vektor : REAL[]

    ...
    high(1,vektor) // ergibt 0
    initarray(vektor[10000]
    high(1,vektor) // ergibt 10000
     
    + + + + + + + + + + + + + + + + + + + + +

    Erweiterte Syntax

    Bei folgenden Anweisungen wurde die strenge Zeileneinteilung aufgehoben:
     
    IF bool THEN ... {ELSIF bool THEN ...} [ELSE ...] END
    WHILE bool DO ... END
    REPEAT ... UNTIL bool
    RETURN [exp]
     
    »bool« steht für einen logischen Ausdruck, »...« steht für beliebige Anweisungen
     
    Die einzige Bedingung, die hier noch gilt, lautet: Ausdrücke dürfen nicht auf mehrere Zeilen verteilt werden.
     
    Um Abwärtkompatibilität zu gewährleisten, gelten noch folgende Zusatzregeln:
  • »THEN« kann am Zeilenende weggelassen werden
  • »DO« kann am Zeilenende (oder wenn keine Anweisungen vorliegen) weggelassen werden
  • Damit können trotz der Syntaxerweiterung alle früheren Programme compiliert werden.
    Beispiele für den Einsatz der erweiterten Snytax:
     
    IF n=0 THEN cgiwriteln('Kein Treffer') ELSE cgiwriteln(str(n)+' Treffer') END
     
    WHILE subst('#target#',paramstr(0)) END

    IF x=y THEN i:=10; REPEAT cgiwriteln(str(i)) UNTIL i--=0 END

    + + + + + + + + + + + + + + + + + + + + +

    Das System-Modul

    Jetzt sind alle Standardfunktionen in dem Modul »system« zusammengefasst. Dieses Modul wird automatisch in jedes Programm importiert, und zwar vor allen anderen Importen. Damit können alle Bezeichner aus diesem Modul umdefiniert werden. Nach einer Redefinition kann der Modulbezeichner »system« verwendet werden, um auf den Bezeichner der Standardbibliothek zurückzugreifen.
    Beispiel:

    VARDEF indname, dbname : STRING

    ...
    indname:=system.indname(db,1)
    dbname:=dbdir(db)+system.dbname(db)
    Da es bisher nicht möglich war, Bezeichner aus der Standardbibliothek in eigenen Programmen zu verwenden, ist dieses Feature voll abwärtskompatibel.

    + + + + + + + + + + + + + + + + + + + + +

    Kein Leerzeichen mehr vor Minus

    Die Version 6.2.3 macht Schluss mit der EASY-Eigenart, dass zwischen einem Bezeichner und einem Minus-Zeichen ein Leerzeichen eingefügt werden musste. Der Compiler löst Konflikte selbständig auf.


    Die Markierung von Datensätzen

    Die übliche Vorgehensweise, wenn es darum geht, Datensätze aus einer Tabelle auszuwählen, besteht bei EASY darin, diese Datensätze zu markieren. Jede geöffnete Tabelle hat eine (anfangs leere) Markierungsliste, die mit folgenden Funktionen der Standardbibliothek manipuliert werden kann:
  • delmarks(db) löscht die gesamte Markierungsliste
  • setmark(db,r) fügt den Datensatz mit der physikalischen Satznummer r hinzu
  • delmark(db,r) entfernt den Datensatz mit der Satznummer r aus der Liste
  • Das folgende Programmfragment liest eine gesamte Tabelle und markiert diejenigen Datensätze, auf die eine bestimmte Bedingung zutrifft:
     
    VARDEF db, i, fs : REAL
    VARDEF PLZ_gesucht : STRING
      PLZ_gesucht:='80*'
      IF db:=opendb('database/adressen.dat') THEN
        i:=0; fs:=filesize(db)
        WHILE i++<=fs DO
          readrec(db,i)
          IF getfield(db,'PLZ') like PLZ_gesucht THEN setmark(db,i) END
        END
      END
     
    Selbstverständlich ist das keine optimale Strategie, denn das Lesen einer gesamten Tabelle dauert recht lange. Wesentlich besser wäre beispielsweise hier eine indizierte Suche. Da es aber nur um das Prinzip geht, wollen wir an dieser Stelle darauf verzichten.
     
    Die Größe der Markierungsliste einer Tabelle liefert die Funktion »nmarks«:
    nmarks(db) -> Anzahl der markierten Datensätze

    Als nächsten Schritt wollen wir die gefundenen Datensätze nach Name und Vorname sortieren. Dafür bietet EASY die Funktion »sortmark«

    sortmark(db,'Name,Vorname') ->0 alles in Ordnung, sonst Fehlercode

    Selbstverständlich muss es sich bei »Name« und »Vorname« um gültige Feldbezeichner der Tabelle »db« handeln.

    Mit der Funktion »revmarks« kann die aktuelle Ordnung der Markierungsliste einer Tabelle umgedreht werden

    revmarks(db) -> Anzahl der markierten Datensätze

    Jetzt wollen wir die Treffer ausgeben. Dazu greifen wir auf die Funktionen »firstmark« und »nextmark« zurück.

    firstmark(db) -> erster Satznummer der Markierungsliste

    nextmark(db,x) -> nächste Satznummer der Markierungsliste bzgl. x
     
    VARDEF x : REAL
      x:=firstmark(db)
      WHILE x>0 DO
        cgiwrite(getfield(db,'Name')+',')
        cgiwriteln(getfield(db,'Vorname')+'<br>')
        x:=nextmark(db,x)
      END
     
    In manchen Fällen kommt es vor, dass man die Markierungsliste zwischenpeichern muss, weil z.B. kurzfristig eine weitere Selektion auf die Tabelle vorgenommen werden muss. Zu diesem Zweck bietet EASY die Funktionen »getmarks« und »putmarks«. Diese Funktionen können mit unterschiedlichen Argumenten aufgerufen werden:
     
    VARDEF marks : MARKS
    getmarks(db,marks) sichert die Markierungsliste von db in marks
    putmarks(db,marks) speichert die gesicherte Markierungsliste zurück
     
    Hinweis: putmarks überschreibt die aktuelle Markierungsliste von db.
     
    Der Datentyp MARKS kann nur mit diesen beiden Funktionen verwendet werden. Der große Vorteil, eine Variable vom Typ MARKS einzusetzen, besteht darin, dass
    • nur der wirklich benötigte Speicherplatz verwendet wird
    • die Sortierung innerhalb der Markierungslist erhalten bleibt
    Die Markierungsliste kann aber auch auf in einem REAL-Array gespeichert werden. Hier muss der Programmierer dafür sorgen, dass das REAL-Array genügend Elemente enthält, um die gesamte Liste speichern zu können:
     
    VARDEF marks : REAL[]
    ...
    initarray(marks[nmarks(db)])
    getmarks(db,marks)
    putmarks(db,marks)
     
    Nach »getmarks(db,marks)« liegen in »marks« die physikalischen Satznummern der Markierungsliste vor. Hier eine Prozedur, in der die Markierungsiste in einer externen Textdatei gespeichert wird:
     
    PROCEDURE SaveMarks(db : REAL)
    VARDEF text,i : REAL
    VARDEF marks : REAL[]
      initarray(marks[nmarks(db)])
      getmarks(db,marks)
      IF text:=rewrite('marks_save') THEN
        nloop(i,high(1,marks)-1,writeln(text,marks[i]))
        close(text)
      END
    ENDPROC
     
    Auch der Einsatz von »getmarks« und »putmarks« mit einem REAL-Array ist ordnungserhaltend. Der Vorteil liegt darin, dass die Satznummern unmittelbar greif- und manipulierbar vorliegen.
     
    Schließlich gibt es noch die Möglichkeit, eine Variable vom Type TBITS zu verwenden. Um richtig zu arbeiten, muss dieses Feld so dimensioniert werden, dass es die gesamte Tabelle abbilden kann:
     
    VARDEF marks : TBITS[]

    ...
    initarray(marks[filesize(db)])
    getmarks(db,marks)
    putmarks(db,marks)
    Hier gilt nach »getmarks(db,marks)«, dass
  • marks[x]=1 wenn der Datensatz mit der Satznummer x in der Markierungsiste ist
  • marks[x]=0 andernfalls
  • »marks« ist somit ein Abbild der Teilmenge der Tabelle, die durch die Markierungsliste festgelegt ist. Und wie bei jeder Menge, geht hier die Ordnung verloren! Der Vorteil der Verwendung von TBITS liegt vor allem darin, dass mit den Funktionen
  • bitand(b_feld1,b_feld2)
  • bitor(b_feld1,b_feld2)
  • bitandnot(b_feld1,b_feld2)
  • die wichtigsten Mengenoperationen sehr effizient durchgeführt werden können. Alle drei Funktionen liefern liefern die Cardinalität (Anzahl der Einsen) von »b_feld_1« nach der jeweiligen Operation.
  • bitand:     b_feld1 := b_feld1 geschnitten mit b_feld2
  • bitor:        b_feld1 := b_feld1 vereinigt mit b_feld2
  • bitandnot: b_feld1 := b_feld1 geschnitten mit dem Komliment von b_feld2 (Mengendifferenz)
  • Die Arbeit mit dem Datentyp TBITS ist so effizient, dass beispielsweise die Volltextsuche grundsätzlich darauf zurückgreift (»markbits«). Man wird sie immer dann einsetzen, wenn mehrere - logisch verknüpfte - Selektionen auf eine Tabelle ausgeführt werden.

    Newsletter

    Anmeldung zum Newsletter:
    Name: 
    Zusatz: 
    EMail: