Deutsch English
About tdbengine
Basic Course
CGI Aufbereitung
EASY Programmierung
Die Datenbank
Function reference
Bug Reporting
Support request
Home    Overview    Search    Impressum    Contact    Members
Lesson 2: The programming environment of tdbengine

Having CGI innterface introduced to you in the last lection this lection is about programming environment of the tdbengine.

Installation of the tdbengine
To be able to take part in this and the following lection you have to have tdbengine installed. You can download the program inclusive the (preliminary) developement environment under Download. Presently there are versions for Win32 (that means Windows NT, Windows 95/98) and Linux x86. The package also includes a little installation script that usually creates the following directory structure:

/home/tdbengine CGI-Programs like pdk, ddk, dmk and also test
/home/tdbengine/bin tdbengine(.exe), Log files
/home/tdbengin/database Database basic directory

Notice: In this curse we strictly use the Unix syntax for the directories. Using Windows the directories are called according to the installation device c:\home\tdbengine etc.

The programming environment of the tdbengine
The tdbengine concern a 32-bit console application. It can be used both from the console and as EASY interpreter for the CGI interface. We will dwell on EASY, tdbengine's programming language, first in the fourth lection.

The tdbengine can take over following functions depending on claim:

  • EASY compiler
  • EASY interpreter
  • Database server
EASY programs are always been compiled (translated) in a P-code before they will be executed (P-code is a machine-independent intermediate code, a technique for example also used in Java). This approach has following vantages:
  • A P-Code can be executed faster than a text-script.
  • The syntax-check is effected before execution.
  • Programs can be passed without source code.
The second item is especially important: Just imagine while transfering a database the program will be aborted becouse of a syntax error...

The third item is no longer especially relevant in times of open source but it may play a decisive role in comercial written programs.

Performance is sure enough of capital importance just as in CGI programs. At a well visited website thousands of CGI calls are send in hourly, and cumbersomely executed CGI programs can lower data throughput drastically. That's why a set of additional features was built in into tdbengine only to increase the performance. But more about it later.

The pure console application
Tdbengine can also be used totally without CGI. The following little exercise shows the use as a pure console application:


If you took up the standard setup, you would have to switch to a console (Windows-users need to open a window for promt) in the /home/tdbengine directory, if not, you would have to switch to the one in the EASY-program directory (not in the bin-directory with tdbengine(.exe) in it). Here you have to delete the file test.prg and to enter the following:

bin/tdbengine test.mod <RETURN> (bin\tdbengine test.mod in Windows)

You'll get the folowing output:

test.mod successfully compiled.

You'll see that the file test.prg was created in this directory. The following entry of

bin/tdbengine test.prg <RETURN>


content-type: text/html
Hello world...

Here we got to know tdbengine as a compiler and as an interpreter. For the next exercise we open one more console and run any text editor there. Here you have to enter the following text:

VAR Sum, product, quotient, maximum : REAL
  Write(0,'Enter a number: ')
  Write(0,'Enter one more number: ')
  WriteLn(0,'Sum = '+str(Sum))
  WriteLn(0,'Product = '+str(product))
  WriteLn(0,'Quotient = '+str(quotient,1,4))
  WriteLn(0,'Maximum = '+str(maximum))

Now save this text in /home/tdbengine under mtest.mod. The translation occurs using

bin/tdbengine mtest.mod <RETURN>

We start the program using

bin/tdbengine mtest.prg <RETURN>

Now the program asks for entry of two numbers anf following sums, products, quotients and maximum of the both numbers are displayed. This is trivial and isn't necessary at all. Now restart the program and enter "hans" for the second number. You'll get no output from the program - it purportadly crashed thus it was aborted. In such cases tdbengine writes an entry into the error.log file in the directory where tdbengine is in, too. Using

more bin/error.log <RETURN>

you can have the file displayed:

01.21.2000 09:35:14.41: 50 (Unknown designator: y:=VAL (READLN (0))) in (61)
01.21.2000 09:35:14.41: 50 (Unknown designator: Main) in (61)
01.21.2000 09:35:14.41: 50 (Unknown designator: Main) in (61)

Mostly errors are shown multiple since every procedure writes its own error massage. Every line always starts with a date specification and date. Then the error code (here 50), the appendant error massage (Unknown designator), the name of the program (only when used as CGI-program) and finally the position of the error in the P-code (61) are following.

In the majority of cases, mainly in little programs, you can affect the position of an error in the source code just becouse of this designations. Here the designation y:=Val(ReadLn(0)) suffices becouse this expression can be found only onece in this program.

Sure enough in bigger programs you'll be able to rapidly lose the view, mainly if the library is used (USESxyz...). Here the second parameter of the tdbengine compiler is to be used. If the position of the error in the P-code is given over at this point tdbengine will compile the source code and in addition it will show the source code translated now, in fact until the given over position of the error is reached. Therewith the runtime error (= an error that occurs first when the program runs and can't be located by the compiler beacouse of it) of the program can be located easily.

Though the programs that crush and are aborted rarely perform a task they aren't as bad as the ones that can't be aborted at all (mainly in terms of use as an CGI-program). We create another program comprosed of only of this few lines:

  WHILE 1=1

We save the program as ltest.mod, translate and run it. As expected the program is running in an infinite loop - the computer no longer responds on this console. Now surely you can press Ctrl-C at the console which forcibly will abort the program. You can also effort the "kill"-prozess in Linux or the task mannager in Windows to abort the program. But if the program is running as a CGI-application on a  computer (probably quite) far away all of those methods are not availble. Here the program will be aborted only if it is closed by the http-server due to a timeout. It can become important to end a program Da aber bis dahin vom Pogramm unter Umständen wichtige Ressourcen gebunden werden (Speicher, Prozessorleistung), kann es wichtig werden, das Programm ferngesteuert zu beenden. Dazu machen wir eine weitere Konsole auf und geben dort folgenden Befehl ein:


cat > /home/tdbengine/bin/abort <RETURN>


copy con \home\tdbengine\bin\abort <RETURN>

We put a file (containing only one character) called "abort" into the folder of tdbengine. A few moments later the program with the infinite loop will end. And if you check the folder you will find out that the "abort" file is gone, too.

With it you are given room to drop uot of a program. You simply have to copy (for instance via ftp) a file called "abort" into the folder of tdbengine. Tdbengine checks after each second of the runtime whether there is such a file, and aborts itself in case the condition is true but not without deleting this file.

Software controll using tdbengine.ini
Hint:For the following exercise you should have the newest version of the tdbengine (as of 20.01.2000) because otherwise the paths for the console application are false.

For the next experiment switch back to the text editor and enter following lines


Put this file into the /home/tdbengine/bin directory and name it "tdbengine.ini". Now start the program test.prg using

bin/tdbengine test.prg <RETURN>

Im bin-Verzeichnis finden Sie nun die Datei cgi.log mit folgendem Eintrag:

11:19:55.30 [ ] - 00:00:00.00 - 00:00:00.00 - 00:00:00.00: test.prg ()

In dieser Datei wird, falls in tdbengine.ini unter [globals] der Eintrag loccgi=1 steht, jeder Aufruf der tdbengine protokolliert. Ganz links sehen Sie die Startzeit der tdbengine. Dann folgt (in eckigen Klammern) der Inhalt der Enironment-Variablen REMOTE_ADDR, also die IP-Nummer des Klienten (nur verfügbar, wenn als CGI-Programm gestartet). Dann folgen drei Zeitangaben:

1. Übertragung der Daten vom Klienten
2. Laufzeit des Programms
3. Übertragung der Daten zum Klienten

Dass hier überall der Wert 0 steht liegt daran, dass die Ausführung des Programms test.prg viel zu schnell erfolgt (irgendwo im Mikrosekunden-Bereich).

Dann folgt der Name des Programms, und schließlich in runden Klammern die erweiterte Log-Information, die man vom Programm aus mit der Funktion SetCGILog setzen kann.

Über die Log-Datei kann man sehr genau das Laufzeitverhalten der Programme feststellen. Das kann auf stark frequentierten http-Servern mit vielen CGI-Progammaufrufen eine wesentliche Rolle spielen.

Bei unserer letzten Übung auf der Konsole geht es um die gleichzeitige Abarbeitung mehrerer CGI-Programme. Starten Sie auf einer Konsole das Programm ltest.prg (unsere Endlosschleife). Wechseln Sie dann auf eine andere Konsole und starten Sie dort das Programm test.prg. Sie erhalten hier nach etwa 10 Sekunden folgende Ausgabe:

content-type: text/html

<h2>tdbengine message</h2>

Diese Meldung (eigentlich ein HTML-Text) besagt, dass das Programm nicht ausgeführt werden konnte, weil der CGI-timeout überschritten wurde. Das bedeutet also offensichtlich, dass nur ein Proramm zur gleichen Zeit bearbeitet werden kann. Hier kommt nun die Sicherheitsstrategie der tdbengine zum Vorschein. Die tdbengine geht dabei vom ungünstigsten Fall aus, dass eine Programm wesentliche Transaktionen an einem Datenbestand vornimmt. Während einer solchen Transaktion darf kein weiteres Programm ebenfalls eine Transaktion ausführen, denn das würde zu einem inkosistenten Datenbestand führen. Also wartet die tdbengine mit der Bearbeitung des Programms erst einmal eine gewisse Zeit, ob das zuerst gestartete Programm seine Arbeit beendet. Falls dem nicht so ist, wird das zweite Programm überhaupt nicht gestartet, sondern statt dessen die obige Fehlermeldung ausgegeben.

Um das Verhalten genauer untersuchen zu können, ergänzen wird unsere tdbengine.ini folgendermaßen:


Damit setzen wir die timeout-Zeit (also die Zeit des Wartens für den zweiten Prozess) auf 100 Sekunden = 100000 Millisekunden (Vorgabe ist 10 Sekunden). Nach dem Speichern starten wir wieder test.prg, wechseln dann aber auf die Konsole, auf der ja immer noch unsere Endlosschleife (ltest.prg) läuft, und beenden dieses Programm durch einen beherzten Druck auf Strg-C. Sie werden sehen, dass nahezu im gleichen Augenblick auf der anderen Konsole das Programm test.prg ganz normal abgearbeitet wird.

Mit dieser Strategie ist die tdbengine auf der sicheren Seite. Es kann jedoch sein, dass zwei Programme nichts miteinander zu tun haben, also nicht auf einen gemeinsamen Datenbestand zugreifen. In diesem Fall könnten doch die beiden Programme problemlos nebeneinander laufen, oder? Wir können diesen Zustand recht einfach herstellen, indem wir wiederum in der Datei tdbengine.ini folgende Einträge machen:


Wieder wollen wir auf der einen Konsolen das Programm ltest.prg starten, und dann auf der anderen Konsole test.prg. Sie werden sehen, dass test.prg sofort (ohne auf irgendwetwas zu warten) abgearbeitet wird.

Ohne hier zu tief ins Detail zu gehen (Semaphoren sind Thema des Fortsetzungskurses), sei hier soviel festgestellt:

Jedes Programm (.prg) kann einen eigenen Eintrag in der tdbengine.ini haben. Wird dabei unter dem Punkt "sema" ein eigener Dateiname angegeben, so kann das Programm parallel zu anderen Programmen gestartet werden.

Als Semaphor können wir uns einen Wächter mit einem Namen vorstellen. Dieser Wächter sorgt dafür, dass nur ein Prozess zu einem Zeitpunkt abgearbeitet wird. Für jedes zu startende Programm schaut die tdbengine zunächst in tdbengine.ini nach, welcher Wächter für das Programm zuständig ist. Falls kein spezieller Wächter angegeben wurde, verwendet die tdbengine den Wächter mit dem Namen "cgi".

Hinweis: Semaphoren werden von der tdbengine in Form von (physikalischen) Dateien realisiert. Wenn kein anderes Verzeichnis angegeben ist, legt tdbengine diese Dateien im aktuellen Verzeichnis an. Sollte hier kein Schreibrecht (und das Recht zum Erzeugen von Dateien) vorliegen, erhalten Sie immer die Meldung "cgi overrun".

Die HTML-Umgebung
Zum Lieferumfang der tdbengine gehören u.a.
  • pdk.prg program developement kit (Programmeditor und Compiler)
  • ddk.prg database developement kit (Datenbank-Erstellung)
  • dmk.prg database modification kit (Datenbank-Bearbeitung)
Mit diesen Kits kann man sehr einfach Programme schreiben und Datenbanken verwalten. Es handelt sich um reine CGI-Anwendungen. Also muss der http-Server aktiviert sein, und Sie benötigen einen Browser.

program develeopent kit

Geben Sie in Ihren Browser die URL http://localhost/cgi-tdb/pdk.prg ein. Sie erhalten ein Formular mit folgenden Eingabefeldern und Schaltern:
source: Eingabefeld Dateiname des EASY-Moduls
load Schalter zur interaktiven Dateiauswahl
new Schalter löscht Text im Eingabefeld und Dateinamen
compile Schalter startet den Compiler
(ohne Namen) Eingabefeld Editor für das EASY-Modul
window 2 Eingabefelder Zeilen / Spalten des Editors
refresh Schalter zeigt das gesamte Formular neu an

Wenn Sie nun den Schalter "load" drücken, wird ein weiteres CGI-Programm (scanfile.prg) gestartet, das eine intraktive Auswahl einer Datei mit der Extension ".mod" gestattet. Hier wählen wir nun "test.mod" aus, und sofort wird der Quelltext in das Editorfenster des pdk-Formulars geladen. Ebenfalls wird der Dateiname im "source"-Feld eingetragen.

Hier können wir nun den Quelltext beliebig verändern. Eine Betätigung des "compile"-Schalters führt zu folgenden Aktionen:

Der Text im Editor-Eingabefeld wird unter dem Namen, der im "source"-Eingabefeld steht, abgespeichert. Dann wird dieser Text compiliert. Schließlich wird "pdk.prg" automatisch wieder gestartet zunächst in das Formular das Ergebnis der Compilierung eingetragen:

test.mod successfully compiled to /cgi-tdb/test.prg

codesize: 68 bytes
variables: 0
procedures: 1

Das Ergebnis der Compilierung, in diesem Fall also /cgi-bin/test.prg, wird als Link ausgeführt, so dass man das frisch erzeugte Programm sofort testen kann (in einem neuen Browser-Fenster). Zusätzlich werden die Eingabefelder mit den bisherigen Informationen gefüllt, damit man gleich weiterarbeiten kann.

Tritt jedoch bei der Compilierung ein Fehler auf, werden zunächst Fehlerart und -position angezeigt. Zusätzlich werden in den Quelltext des Programms Zeilennummern eingeblendet, damit die Fehlerposition leichter auffindbar ist.

Um das Verhalten von pdk zu testen, verändern wir den Text von test.mod fogendermaßen:

  CGIWriteLn("content-type: text/html")
  CGIWriteLn("<html><body bgcolor=yellow>"
  CGIWriteLn("Hello world...")

Hier fehlt die schließende runde Klammer in der vierten Programmzeile. Der Druck auf den "compile"-Schalter bringt folgende Ausgabe:

error 56: ) erwartet (line 4/42)

CGIWriteLn("<html><body bgcolor=yellow>"

2:   CGIWriteLn("content-type: text/html")
3:   CGIWriteLn("")
4:   CGIWriteLn("<html><body bgcolor=yellow>"
5:   CGIWriteLn("Hello world...")
6:   CGIWriteLn("</body></html>")

Sie können nun sofort in die entsprechende Zeile gehen (mit dem Cursor selbstverständlich) und dort die fehlende Klammer ergänzen. Die Zeilennummern werden vom Compiler ignoriert. Aus diesem Grund dürfen Sie auch dann, wenn Zeilenummern ausgegeben werden, weitere Zeilen einfügen, weglöschen usw (die Zeilennummern werden übrigens vor dem Abspeichern wieder automatisch entfernt).

Hinweis: Sie können sich mit pdk auch den Quelltext von pdk (pdk.mod) selbst ansehen. Allerdings sollten Sie hier keine Änderungen vonehmen, da ansonsten das wesentliche Programmierwerkzeug u.U. nicht mehr funktioniert.

Bevor wir uns nun dem nächsten Program zuwenden, wollen wir ein neues Verzeichnis anlegen. Drücken Sie dazu nochmals den Schalter "load". Hier wechseln sie zunächst in das Verzeichnis "database" und wählen dort den Punkt "new directory". Geben Sie "address" ein und drücken Sie die RETURN-Taste. Damit haben Sie das Verzeichnis /home/tdbengine/database/address angelegt.

database developement kit

Das nächste Programm, das wir uns näher ansehen, ist ddk.prg. Es dient zum Erzeugen und Umstrukturieren von Datenbanken. Geben Sie die URLhttp://localhost/cgi-tdb/ddk.prg ein, und Sie erhalten wiederum ein Formular, diesmal mit folgenden Eingabefeldern und Schaltern:

database Eingabefeld Datename der Tabelle (*.dat)
load Schalter zur interaktiven Dateiauswahl
new Schalter zum Löschen der Eingabefelder
restructure Schalter zum Umstruktieren einer bestehenden Tabelle
generate Schalter zum Anlegen einer neuen Tabelle
(ohne Namen) Eingabefeld Editor für die Tabellenstruktur
window 2 Eingabefelder Zeilen / Spalten des Editors
refresh Schalter zeigt das gesamte Formular neu an

Geben Sie nun im Feld database folgends ein:


In das (große) Textfeld machen Sie folgende Angaben:


Jetzt drücken Sie den Schalter "generate" und erhalten (falls kein Tippfehler vorliegt) diese Antwort des Programms:

database/address/address.dat successfully generated

database: /home/tdbengine/database/address/adress.dat
records: 0
fields: 9

Damit haben wir eine neue Tabelle erzeugt. Ausgangspunkt ist eine Strukturbeschreibung, also eine Text-Datei, die wie eine Ini-Datei aufgebaut ist. Unter der Abteilung [STRUCTURE] werden die einzelnen Datenfelder festgelegt. Jede Felddefinition beginnt immer mit "field_" und wird fortlaufend durchnumeriert. Die zugrunde liegende Datenbank kann Tabellen mit jeweils bis zu 1000 Feldern verarbeiten. Nach dem Gleichheitszeichen folgt der Feldname und dann, durch ein Komma abgtrennt, der Feldtyp. Allgemein also:


Das hat zunächst zur Folge, dass im Feldnamen (auch mit Feld-Label bezeichnet) kein Komma enthalten sein kann. Allerdings gibt es für den Feldnamen noch weitere Einschränkungen:

Ein Feldname darf nur aus Buchstaben, Ziffern und dem Unterstrich bestehen. Er darf nicht mit einer Ziffer beginnen.

Der Feldtyp wird immer durch den Typnamen angegeben, eventuell ergänzt um weitere Typangaben. In unserer Tabelle tritt nur der Typ "STRING" auf, der beliebige alphanmerische Daten speichern kann. Der Typ "STRING" bedarf immer einer weiteren Angabe, mit der die maximal zu speichernde Zeichenzahl festgelegt wird.

Folgende Datentypen stehen zur Verfügung:

  • AUTO,Startnummer
  • BLOB
  • DATE
  • LINK,Zieltabelle
  • MEMO
  • NUMBER,Speichergröße,Nachkommastellen,Null-Leer-Unterscheidung
  • REL,Zieltabelle
  • SELECT,Auswahlliste
  • STRING,max_Zeichenzahl
  • TIME
Beim Typ "NUMBER" ergeben sich je nach angegebener Speichergöße unterschiedliche Zahlenformate:

Speichergröße Wertbereich
1             0 bis 255
2             -32.768 bis +32.767
4             -2.147.483.648 bis 2.147.483.647
6             Fließkomma mit 11-stelliger Genauigkeit (altes TDB-Format)
8             Fließkomma mit doppelter Genauigkeit (neues TDB-Format)

Die Anzahl der Nachkommastellen (bei Fließkommazahlen) spielt nur eine untergeordnete Bedeutung, intern werden die Daten immer mit voller Genauigkeit gespeichert und verarbeitet.

Hinweis: Sie sollten bei Fließkommazahlen immer den neuen Typ (8) verwenden, da hier nicht nur der wesentlich genauer, sondern zudem auch wesentlich schneller gerechnet werden kann.

Hier noch einige Bemerkungen zu den Datentypen:

AUTO führt zu einem Feld des Typs NUMBER,4 mit automatischer Hochzählung bei jedem neuen Datensatz. Wird kein Startwert angegeben, so beginnt die Zählung mit 1. Enthält eine Tabelle ein AUTO-Feld, so wird über dieses Feld zudem automatisch ein Index angelegt (Tabellenname.INR), un es muss zusätzlich unter der Abteilung [INDEX] ein sogenannter ID-Index festgelegt werden:


BLOB steht für Binary Large OBjects. Felder dieses Types können (im Prinzip) beliebig große Binärdaten speichern, wie zum Beispiel Bilder, Sounds etc. Diese Felder werden in diesem Kurs nicht verwendet.

BOOLEAN führen zu einem NUMBER,1-Feld, das jedoch nur die Werte 0 (für falsch, trifft nicht zu) oder 1 (für wahr, trifft zu) annehmen kann.

DATE speichert ein Datum in NUMBER,4-Form. Es kennt zwar keine vorchristlichen Termine (negative Werte), dafür aber auch keine Jahrtausend-Probleme.

LINK benötigt als zusätzliche Angabe den Namen einer Zieltabelle. Das Feld speichert dann die Autonummer der Zieltabelle, und ermöglicht somit recht einfach die Bildung von 1:n-Relationen. LINK-Felder bilden den Kern des ADL-Systems (Automatic Data Link = Automatische Datenverknüpfung). LINK-Felder werden in diesem Kurs nicht verwendet.

MEMO speichert beliebig langen (unformatierten) Text. Sie werden in einer eigenen Datei abgelegt (Tabellenname.MMO). In der Tabellendatei selbst steht nur ein Verweis auf den Beginn des Textes (als NUMBER,4).

NUMBER speichert Zahlen mit dem bereits angegebenen Wertbereich. Zusätzlich kann mit "U" angegeben werden, ob eine Unterscheidung Null/undefiniert gewünscht wird. Diese Unterscheidung erhöht den Speicherbedarf um ein Byte.

REL erlaubt n:m-Relationen mit Hilfe des ADL-Systems. Sie werden zwar in diesem Kurs nicht implizit behandelt, wir begegnen ihnen aber in Verbindung mit der Volltext-Indizierung#

SELECT definiert ein Auswahlfeld. Die Konstanten des Auswahlfeldes werden einfach - durch Komma getrennt - angegeben.



Es wird ein NUMBER,1-Feld erzeugt, das entweder 0 enthält, wenn noch kein Wert zugewiesen wurde, oder die Nummer der entsprechenden Konstante (1 für ledig, 2 für verheiratet...)

STRING speichert Zeichenketten, die alle Zeichen (inclusive chr(0)) enthalten dürfen.

TIME speichert eine Zeitangabe im NUMBER,2-Format (Anzahl der Minuten seit Mitternacht). Für genauere Zeitangaben muß ein Fließkomma-Typ gewählt werden, wobei Sekunden als Minutenbruchteile angegeben werden Die Funktionen "now" und "timestr" können mit Zeitangaben bis 1/1.000-tel Sekunden arbeiten.

Wir werden in diesem Kurs vorwiegend mit STRING und MEMO arbeiten.

Sie können mit ddk.prg eine einmal angelegte Tabelle jederzeit umstrukturieren, d.h. Felder hinzufügen, wegnehmen, in der Reihenfolge oder im Typ verändern. Beachten Sie jedoch, dass der Inhalt eines Feldes unwiderruflich verloren ist, wenn das Feld bei einer Umstrukturierung entfernt wurde.

Wenn Sie ein Feld im Zuge eine Umstruktuierung umbenennen wollen, so müssen Sie die Ursprungsnamen in runden Klammern an das Ende der Felddefinition stellen. Beispiel:


Bei der Umstrukturierung wird dann der Inhalt des (bisherigen) Feldes "Name" in das (neue) Feld "Familienname" übertragen.

database modification kit

Als letztes unserer Werkzeuge wollen wir das database modification kit dmk.prg betrachten. Es erlaubt alle Basisoperationen mit einer Tabelle:

  • Eingabe von neuen Datensätzen
  • Verändern von bestehenden Datensätzen
  • Löschen von Datensätzen
  • Sequentielle Suche nach Datensätzen
Darüber hinaus kann dmk noch ein paar weitergehende Operationen mit Tabellen:
  • Volltext-Indizierung und -Suche über die ersten 8 Felder der Tabelle
  • Suchen und Ersetzen von Datenfeldern
  • Export von beliebigen Spaltenkombinationen im ASCII- und ANSI-Format
Eingabe von Datensätzen

Wenn Sie den Schalter "open", können Sie unsere Datenbank "address.dat" auswählen. Nachdem die Tabelle bislang leer ist, müssen wir erst ein paar Datensätze eingeben. Dazu wählen wir nun den Punkt "append new record". Wir erhalten ein Eingabeformular mit genau den Feldern, die wir in unserer Tabelle angelegt haben. Wenn Sie das Formular ausgefüllt haben, drücken Sie den Schalter "append", und schon wird der Datensatz in der Tabelle angezeigt. Geben Sie auf diese Art und Weise eine handvoll Datensätze ein, damit die weiteren Möglichkeiten des Programms sinnvoll getestet werden können.

Editieren eines Datensatzes

In der Tabelle werden immer zwei Links eingefügt: "edit" und "delete". Wenn Sie "edit" auswählen, können Sie den entsprechenden Datensatz editieren. Dazu wird der Datensatz im Eingabeformular angezeigt. Sie können nun beliebige Änderungen vornehmen. Mit "save" wird der Datensatz zurückgeschrieben. "append new record" fügt den geänderten Datensatz an die Tabelle an. Das ist praktisch, wenn sich zwei Datensätze nur wenig unterscheiden. Man gibt einen ein, wählt "edit", trägt die Unterschiede des zweiten ein und speichert den Satz dann neu.

Löschen eines Satzes

Betätigt man den Link "delete", wird der entsprechende Datensatz gelöscht. Es erfolgt hier aber eine Sicherheitsabfrage, denn ein gelöschter Datensatz ist wirklich aus der Tabelle entfernt. Deshalb wird zunächst der ausgewähle Datensatz komplett angezeigt, und man kann nun wählen, ob der Satz wirklich gelöscht ("delete") werden soll, oder ob man es lieber unterlässt ("cancel").

Auswahl der angezeigten Felder

Wenn Sie nichts weiter auswählen, werden die ersten acht Felder einer Datenbank in der Tabelle angezeigt. Über dem Schalter "view" können Sie aber eine beliebige Auswahl aus den Feldern treffen (unter Windows erfolgt die Mehrfachauswahl mit der Strg-Taste, unter Linux durch einfaches Anklicken). Beachten Sie, dass der Inhalt von Memofeldern nicht in der Tabelle ausgegeben wird. Hier wird nur "leer" ausgegeben, wenn kein Inhalt vorhanden ist, andernfalls "Memo".

Suchen in der Tabelle

Solange eine Tabelle aus nur ein paar Datensätzen besteht, reicht der Überblick, den die Tabellenform bietet. Immerhin hat man dabei eine bestimmte Zahl (kann unter "recs/page" eingegeben werden) von Datensätzen im Direktzugriff, und man kann mit den Schaltern am Ende der Tabelle "navigieren":

<< zum Anfang der Tabelle
< eine Seite zurück
> eine Seite weiter
>> an das Tabellenende

Die tdbengine ist aber in der Lage, sehr große Tabellen mit Millionen von Datensätzen zu verwalten. Um hier einen Datensatz bzw. eine Datensatzmenge zu selektieren, müssen bestimmte Mechanismen bereitgestellt werden. Dmk.prg arbeitet dabei mit einer Kombination aus "sequentieller Suche" und "Volltext-Suche". Die Ergebnisse werden mit logischem "und" verknüpft, so dass nur diejenigen Datensätze zur Anzeige kommen, die beide Kriterien erfüllen.

Die genaue Syntax einer Selektion in EASY werden wir erst später im Kurs kennenlernen. Hier reicht erst einmal eine einfache Form:

Feldname Vergleichsoperator Konstante

Die Feldnamen haben Sie in der Strukturdefinition festgelegt. Nachdem wir in unserer Tabelle nur STRING-Felder haben, wollen wir an dieser Stelle auch nur die wichtigsten Vergleichsoperatoren für STRINGs besprechen

= genaue Gleichheit
> lexikalisch nach
>= lexikalisch gleich oder nach
< lexikalisch vor
<= lexikalisch gleich oder vor
<> ungleich
like Mustervergleich mit den Wildcards "?" und "*"
in Mengenvergleich

The constants have always to be given in simple or double quotation marks. Using  of volumes the list of constants is given in Beim Mengenvergleich wird eine Aufzählung von Konstanten in eckigen Klammern angegeben.

Beispiele für Selektionen:

Name = "Huber"
Vorname >= "M"
PLZ like "80*"
Ort <> "München"
Strasse like "h*platz*"
Ort in ["München","Hamburg","Berlin"]

Derartige logische Grundausdrücke können mit logischen Operatoren (AND OR NOT) zu komplexen logischen Aussagen verknüpft werden:

Beispiele für zusammengesetzte Selektionen:

Ort like "M*" AND Name in ["Müller","Huber","M??er"]
PLZ = "80335" OR PLZ = "80336"

Eine Selektion können Sie im Eingabefeld "select" eintragen und dann den zugehörigen Schalter drücken. Sie sehen in der Statusanzeige, wie viele Datensätze gefunden wurden ("selected"), und es werden nur noch solche Datensätze angezeigt, die die Selektion erfüllen.

Hinweis: Bei Feldnamen wird Groß/Kleinschreibung unterschieden (ebenso wie bei allen selbstdefinierten Bezeichnern).

Die Eingabe einer Selektion führt zu einer sequentiellen Suche in der Tabelle. Diese heisst so, weil im Prinzip die gesamte Tabelle Datensatz für Datensatz (=sequentiell) geprüft wird, ob die Selektion zutrifft oder nicht. "Im Prinzip" deshalb, weil die tdbengine selbstverständlich alle verfügbaren Zusatzinformationen (wie beispielsweise Indizes) heranzieht, um die Anfrage möglichst schnell beantworten zu können.


Das database modification kit legt für jede einmal geöffnete Tabelle einen feldselektiven Volltextindex über die ersten acht Felder an. Dieser Index wird bei jeder Änderung der Tabelle (Neueinabe, Editieren, Löschen) mitgepflegt, also laufend aktualisert. Feldselektiv nennen wir den Volltextindex, weil darin nicht nur Datensatz, sondern auch Datenfeld des Vorkommens von Wörtern gespeichert wird.

Zur Bildung eines Volltextindex werden die Feldinhalte eines Datensatzes nach Wörtern untersucht. Als Wort gilt hierbei eine zusammenhängende Folge von Buchstaben. Jedes neu gefundene Wort wird in eine eigene Tabelle eingetragen. Zusätzlich wird eine "Referenzliste" erstellt, in der festgehalten wird, welches Wort in welchem Datensatz (und in welchem Feld) gefunden wurde.

Bei der Suche im Volltextindex wird die Vorgehensweise umgekehrt. Hier wird das gesuchte Wort zunächst in Tabelle mit den extrahierten Wörtern (über einen Index, also sehr schnell) gesucht. Daraufhin stehen über die Referenzliste alle Datensätze der Ausgangstabelle zur Verfügung, in denen das Wort vorkommt. Diese Suche erfolgt extrem schnell und ist immer dann mit Vorteil einsetzbar, wenn ganze Wörter (oder Wortfragmente) in Datenfeldern gesucht werden.

Geben Sie in das Eingabefeld "search" ein Wort ein und drücken Sie dann den zugehörigen Schalter. Sofort wird Ihnen das Ergebnis der Volltextsuche angezeigt. Dabei wird das Wort (wie bereits gesagt) in den ersten acht Datenfeldern der Tabelle gesucht. Sie können auch die Wildcards "?" und "*" mit der gewohnten Bedeutung benutzen ("*" für eine beliebige Zeichenfolge, "?" für genau ein Zeichen). Sie können auch die Operatoren '+' (für logisches oder) und ',' (für logisches und) verwenden:

Hamburg + München wenigstens eines der Wörter kommt vor
Hamburg , München beide Wörter kommen gemeinsam vor

Wenn Sie das Vorkommen eines Wortes in einem bestimmten Feld prüfen wollen, kommen Sie einfach den Felddnamen und einen Doppelpunkt dem gesuchten Wort voranstellen:


Wiederum kann hier nur ein Teil der Möglichkeiten der Volltextsuche beschreiben werden. Eine genauere Analyse und der Einsatz der Volltextindizierung in eigenen CGI-Programmen ist Gegenstand eines Folgekurses.

Sortierreihenfolge ändern

Im Eingabefeld "sort" kann eine Sortierreihenfolge angegeben werden, die allerdings nur zum Tragen kommt, wenn über sequientielle Suche und/oder Volltextsuche eine Teiltabelle festgelegt wurde. Geben Sie hier die Sortierreihenfolge durch die entsprechenden Feldnamen (durch Komma getrennt) ein.



In diesem Fall wird die Teil-Tabelle zunächst nach Namen sortiert, bei gleichen Namen wird auch noch der Vorname herangezogen. Die Sortierung erfolgt lexikalisch aufsteigend, also "A" vor B". Sie können die Reihenfolge aber auch umdrehen, indem Sie ein Minuszeichen dem jeweligen Feldnamen voranstellen:


Datensätze exportieren

Sie können sich auch die gesamte Tabelle oder den (via Selektion oder Volltextsuche) definierten Ausschnitt daraus "downloaden". Es werden alle Felder (mit Ausnahme von Memos und Blobs) exportiert, die auch für die Tabellenanzeige unter "view" angegeben wurden. Sie haben die Wahl zwischen "ASCII Tab delimited" und "ANSI Tab delimited". "ASCII" und "ANSI" geben die Sonderzeichen (Umlaute etc.) gemäß DOS (ASCII) oder Windows/Linux (ANSI) aus. Die einzelnen Felder werden durch das Tab-Zeichen getrennt.

Die exportierten Datei können Sie irgendwo auf Ihrer Platte speichern und dann direkt in anderen Programmen weiterverarbeiten, wie beispielsweise MS-Word oder MS-Excel.

So the standard toolkit is now completely introduced to you:

Being pure console application tdbengine can be used as EASY interpretor, compiler and to search for runtime errors.

Using the program developement kit you can write, compile and run programs. The database developement kit is preeminently suitable for creating of tables. And finally the database modification kit allows all basic operations in a table. Surely that are no end-user applications. If you want to provide a public address-database Wenn Sie eine Adressen-Datenbank zur allgemeinen Verfügung stellen wollen, werden Sie selbstverständlich eigene (individuelle) Eingabemasken verwenden und ebenso spezielle Auswertungen realisieren wollen. Dies sind die Themen der nächsten Folgen unseres Kurses.

1. EASY-Programme werden vor der Ausführung in einen speziellen P-Code übersetzt. Warum werden die Programmtexte nicht direkt interpretiert, wie etwa bei PERL?

2. Was versteht man unter einem "Laufzeitfehler"

3. Wie kann man ein von der tdbengine gerade ausgeführtes CGI-Programm vorzeitig beenden?

4. In der Datei tdbengine.ini steht u.a. folgender Eintrag:


    Was folgt daraus, wenn das CGI-Programm address.prg gestartet wird?

5. Was bedeutet BLOB?

6. Geben Sie die Selektionen an, mit der in unserer Adress-Tabelle gefunden werden:

  a) Alle "Münchner"
  b) Alle "Huber" und "Müller" aus dem PLZ-Gebiet "7"

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

   Copyright © 2003-2004 tdb Software Service GmbH
   Alle rechte vorbehalten. / All rights reserved
   Last changed: 04.05.2004
{Fehler für :execmacro{execmacro="sessionspy"}

Programmers Heaven - Where programmers go!