Deutsch English
Blog
Home
Über tdbengine
Newsletter
Abonnement
November 2003
August 2002
Dezember 2001
Mai 2001
Dezember 2000
August 2000
Juni 2000
Dezember 1999
Download
Helpware
Chat
Dokumentation
Einführungskurs
Befehlsreferenz
HOWTO - Wie kann ich...?
Projekte
Links
Benchmarks
Bug Reporting
Supportanfrage
 
Home    Überblick    Suche    Impressum    Kontakt    Mitglieder
tdbengine news vom 16.12.2000
Die letzte tdbengine news liegt schon weit zurück. Inzwischen sind viele neue Projekte mit der tdbengine realisiert worden. Einen längeren Blick Wert ist sicher http://www.plaudern.de - eine wirklich gut gemachte Diskussionsplattform.

Inzwischen liegt die tdbengine in der Version 6.2.5 vor. Sie können die Evaluations-Versionen hier downloaden.

Die wesentlichen Neuerungen:

  • Version für FreeBSD 4.x
  • Aufhebung der 64-KByte-Grenze für EASY-Programme
  • Neue Funktion: DBRights liefert die aktuellen Rechte an einer geöffneten Tabelle
  • Erweiterung des feldbezogenen Volltext-Index
  • Kleinere Verbesserungen
Version für FreeBSD 4.x
Neben Linux erfreut sich FreeBSD immer größerer Beliebtheit - vor allem beim Einsatz auf Web-Servern. Zwar gibt es hier die Möglichkeit, Linux-Programme mit Hilfe eines Emulators zum Laufen zu bringen. Höhere Performance und bessere Systemanbindung bringen freilich Programme, die direkt für dieses Unix-Derivat kompiliert wurden.

Die tdbengine für FreeBSD hat den gleichen Funktionsumfang wie die Linux-Version. Da allerdings der Compiler, mit dem die Übersetzung erfolgte, noch im Beta-Stadium ist, gilt das Gleiche für die tdbengine für FreeBSD.  

Aufhebung der 64-KByte-Grenze für EASY-Programme
Der p-Code, den die tdbengine aus einem EASY-Programm compiliert, ist frei verschiebbar, wobei Sprünge (bei Schleifen und Bedinungen) durch einen 16-Bit-Offset angegeben werden. Der Startpunkt einer Prozedur/Funktion wurde bislang ebenfalls durch einen 16-Bit-Wert angegeben. Dieser Wert wurde nun auf 32 Bit erweitert, so dass jetzt ein adressierbarer Raum von 4 GByte zur Verfügung steht. Der 16-Bit-Offset wurde belassen, weil größere relative Sprünge in der Praxis nicht vorkommen.

Etwas vereinfacht bedeutet dies nun:

  • Der Code einer Prozedur oder Funktion kann bis zu 64 KByte umfassen.
  • Der Code eines Programms kann bis zu 4 GByte groß werden.
Durch die erweiterte Addresierung musste der Programm-Vorspann verändert werden, wodurch auch eine Änderung der PRG-internen Versionsangabe notwendig wurde. Weil aber auf vielen Servern unter Umständen viele Proramme aktiv sein können, hat die neue tdbengine einen Kompatibiltäts-Lader, der Programme aus vorherigen Versionen beim Laden an die aktuelle Version anpasst. Das bedeutet nun:
  • Mit früheren Versionen der tdbengine erzeugte Programme werden von der neuen tdbengine ausgeführt.
  • Mit der neuen Version erzeugte Programme werden von früheren Versionen der tdbengine nicht mehr ausgeführt. Hier erfolgt die Fehlermeldung "Falsche Programmversion".
Eine kleine Einschränkung gibt es freilich: Wenn ein Programm auf die Systemvariable "Fehler" zugreift, muss es mit der neuen Version übersetzt werden. Also in jedem Fall die Datei tdbengine/bin/error.log beobachten!

Dazu noch ein kleiner Tipp: Verzichten Sie grundsätzlich darauf, die Systemvariablen einzusetzen, und verwendet Sie stattdessen die entsprechenden Funktionen: also anstelle von der Variablen "Fehler" die Funktion TDB_LastError verwenden!

Hinweis: Die Aufhebung der 64-Kbyte-Grenze sollte aber keineswegs dazu führen, das Sie jetzt PRGs im MByte-Bereich erzeugen. Gerade bei CGI-Programmen spielt die Ladezeit eine zwar kleine, aber doch messbare Rolle. Zu sehr aufgeblähte Programme könnten sonst der exzellente Performance der tdbengine abträglich sein.

Vorschau: Schon bald wird die tdbengine über einen intelligenen Linker verfügen. Zusammen mit der erweiterten Adressierung wird dann der Einsatz von großen EASY-Bibliotheken möglich sein.  

Neue Funktion: DBRights
Das Öffnen und Schliessen von Tabellen gehört zu den aufwendigen Operationen. Deshalb wird eine Tabelle in einem Programm üblicherweise nur einmal geöffnet, und der Tabellenhandle dann als Parameter an die jeweiligen Prozeduren übergeben.

Wenn eine Prozedur nun schreibend auf die eine Tabelle zugreifen will, kann sie das nur, wenn die Tabelle im entsprechenen Modus geöffnet wurde. Um das herauszubekommen gibt es nun die Funktion DBRights:
 
DBRIGHTS(db : REAL) : REAL
Parameter db : Tabellenhandle von OPENDB
Rückgabewert Rechte gemäß OPENDB
 

Volltextindex in einer neuen Ausbaustufe
Es kristallisiert sich immer mehr heraus, dass normale Indizes nur noch zum sortierten Schmökern in Tabellen zuwie zu deren Verknüpfung benötigt werden. Für die Suche nach Datensätzen wird hingegen immer mehr auf die Volltextindizierung zurückgegriffen.

Aus diesem Grund wurde in der Version 6.2.5 die Volltextsuche um ein Feature erweitert, dessen Erklärung etwas sophisticated, dessen Anwendung jedoch einfach ist und das den Volltextindex nochmals aufwertet.

Die Sache dreht sich um den feldbezogenen Volltextindex. Das bedeutet: die tdbengine merkt sich in den Stichwortreferenzen nicht nur den Datensatz, in dem das Stichwort vorkommt, sondern zusätzlich auch noch das Datenfeld - gleich ob es sich dabei um Stringfelder, Memos oder irgendwelche Zahlenfelder handelt.

Wer die Dokumentation zum Volltextindex gelesen hat, weiss auch, dass es bisher durchaus möglich war, bei der Funktion Scanrecs für jedes Feld eine Zahlenkonstante anzugeben: die sogenannte Maskenzahl (wegen bit-weiser Maskierung). Bei der Indizierung dieses Feldes wurde dann diese Zahl in die Referenzliste mit aufgenommen:

Beispiel:
ScanRecs(d,i,r,Fields("Name:1, Vorname:2, Ort:4"))

Hinweis: Damit die Maskenzahlen bei den Feldangaben übernommen werden, muss als Maskenfeld der Wert -1 angegeben werden.

Bei der Suche im Volltextindex (MarkTable oder MarkBits) muss eine Maske angegeben werden. Diese Such-Maske und die in jeder Referenz gespeicherte Zahl werden mittels binärem AND verknüpft, und wenn dabei eine Zahl ungleich 0 herauskommt, gilt der zugehörige Datensatz als gefunden:
MarkTable(d,i,Suchwort,'','',1,r) Suchwort ist im Feld "Name" vorhanden
MarkTable(d,i,Suchwort,'','',2,r) Suchwort ist im Feld "Vorname" vorhanden
MarkTable(d,i,Suchwort,'','',4,r) Suchwort ist im Feld "Ort" vorhanden
MarkTable(d,i,Suchwort,'','',1+4,r) Suchwort ist in wenigstens einem der Felder "Name"  oder "Ort" vorhanden

Hinweis: 0 passt auf alle Masken, sucht also in allen Feldern

Zusätzlich gab es noch den Sonderfall, dass der gesamte Datensatz (also alle Felder) indiziert wurde:
ScanRecs(d,i,r,Fields("complete"))

Dabei verwendet die tdbengine automatische Maskenzahlen: 1 für das erste Datenfeld, 2 für das zweite, 4 für das dritte usw. Und weil die Maske in einer 32-Bit-Zahl abgelegt wurde, konnten auf diese Art und Weise die ersten 32 Felder eines Datensatzes indiziert werden. Die restlichen Felder erhielten die Maske 0.

Hinweis: In diesem Sonderfall verwendet die tdbengine automatisch den kleinen Modus 4. Zusätzlich wird je nach dem Datentyp des Feldes der Zeichensatz entsprechend angepasst.

Um den vielfältigen Indizierungsmöglichkeiten auch bei der Suche im Volltextindex gerecht zu werden, konnte die globale (via Parameter übergebene) Suchmaske im Suchstring überschrieben werden:
MarkTable(d,i,'1:Kern, 2:Ulrich'...)

findet alle Datensätze, in denen das Wort Kern im Feld "Name" und das Wort "Ulrich" im Feld "Vorname" enthalten ist.

Und weil man sich die Markierungszahlen eh' nicht so gut merken kann, darf man an deren Stelle auch einfach Feldbezeichner schreiben:
MarkTable(d,i,'Name:Kern, Vorname:Ulrich'...)

Das funktioniert sogar mit Klammern:
MarkTable(d,i,'Name:(Klier+Kern+Schwalm)')

Und weil's gar so schön ist und noch nirgendwo dokumentiert wurde: Komplexe Suchanfragen dürfen auch in einem Ramtext stehen! Der Zeilenumbruch wird als Leerzeichen interpretiert:
t:=rewrite("ramtext:searchexpression")
writeln(t,'Name:(Kern+Klier+G*z),')
writeln(t,'PLZ:(8*,9*)')
close(t)
...
MarkTable(d,i,"ramtext:searchexpression"...)

Und gleich noch ein Bonbon:

Bei ScanRecs dürfen in Fields nicht nur Felder der zu indizierenden Tabelle stehen, sondern auch Angaben in L-Feld- und R-Feld-Notation!

Beispiel:
ScanRecs(d,i,r,Fields("Konto.Beschreibung,Posten.Bezeichnung...

Gewünscht  ...

Es hat sich nun herausgestellt, dass man in den meisten Fällen die Möglichkeiten der Bit-Operationen garnicht ausnutzt. Manchen Anwendern würde es völlig ausreichen, entweder in einzelnen Feldern oder im gesamten Datensatz zu suchen (und nicht in Feldkombinationen), wenn nur nicht die Suche auf die ersten 32 Felder begrenzt wäre.

... und erfüllt.

Freilich wollten wir dazu die Suchmaske nicht auf 1000 Bit aufblähen (soviele Felder verträgt die TDB derzeit). Und wenn nur in einzelnen Feldern gesucht wird, reicht es aus, wenn die Suchmaske mit der gespeicherten Maske auf exakte Übereinstimmung geprüft wird.

Um diesen Modus anzuschalten, gibt es das neue Punktkommando: EM (= exact match)
.em 0 (Maske wird mit Suchmaske wie bisher mit BitAnd verknüpft, default)
.em 1 (Maske wird mit Suchmaske auf Gleichheit geprüft)

Wird im exact-match-Modus die Funktion ScanRecs (oder ScanRec oder UnScanRec)  mit Fields("complete") aufgerufen, so wird für jedes Datenfeld die entsprechende Feldnummer als Maske zu den Referenzen gespeichert, es werden also alle Felder (mit Ausnahme von REL und BLOB) indiziert und mit der entsprechenden Kennzahl versehen.

Zum Abschluss noch ein Tipp:

Setzen Sie nach ".em 1" den Modus wieder auf den default-Wert (.em 0) zurück, damit bisherige Applikationen nicht plötzlich ganz unwerwartete Ergebnisse liefern.

Zusätzliches

Die Volltextindizierung mit fields("complete") kann auf die ersten n Datenfelder einer Tabelle eingeschränkt werden:
fields("complete:12") Es werden nur die ersten 12 Felder der Tabelle in den Volltextindex übernomen

Die Syntax für die Suche im Volltextindex ist nun folgendermaßen rekursiv definiert:

Volltextsuche ::= Suchterm { (Vereinigungsoperator | Differenzoperator) Suchterm}.
Suchterm ::= Suchfaktor {Schnittoperator Suchfaktor}.
Suchfaktor ::= [Komplementoperator] [Suchmaske] ( Suchwort | "(" Volltextsuche ")" ).
Suchmaske ::= Zahlenkonstante | Feldbezeichner.
Suchwort ::= Zeichenfolge aus Buchstaben, '*', '?' und dem via Paramter übergebenen erweiterten Alphabet.

Hinweis: Wie bei numerischen Ausdrücken werden Differenzoperator und Komplementoperator durch das gleiche Zeichen ausgedrückt.

Wer die Syntaxdefinition (in EBNF) lesen kann sieht sofort, dass die Suchmaske an den Suchfaktor gekoppelt ist. Ist bei einem Suchfaktor keine Suchmakse angegeben, wird 0 (also siche in allen Feldern) als Defaultwert angenommen. Da ein Suchfaktor auch ein - in runden Klammern eingeschlossener - Suchausdruck sein darf, kann die Suchmaske auch direkt vor eine Klammer gesetzt werden und gilt dann für sämtliche Bestandteile innerhalb der Klammer, wobei dort einzelne Suchfaktoren wiederum eigene Suchmasken haben können.

Wichtig: Auch der Komplementoperator ist an den Suchfaktor gekoppelt (und bindet demnach am stärksten). Das bedeutet, dass eine Suche auch mit diesem Operator beginnen kann:

-Name:Müller

findet alle Datensätze, in denen im Feld Name das Wort "Müller" nicht vorkommt!

Beispiele:

Ausdruck ist gleichbedeutend mit sucht
Name:Müller + Huber Name:Müller + 0:Huber im Feld "Name" das Wort Müller oder irgendwo das Wort "Huber"
Name:(Müller + Huber) Name:Müller + Name:Huber Im Feld "Name" das Wort "Müller" oder "Huber" (oder beides)
Name:(Müller - Westernhagen Name:Müller - Name:Westernhagen Im Feld "Name" ist das Wort "Müller" enthalten, nicht aber das Wort "Westernhagen"
PLZ:(80* + 81*) - Ort:München (PLZ:80* + PLZ:81*) - Ort:München Datensätze mit den PLZs "80???" und "81???", deren Ortsbezeichnung nicht "München" ist
Familienstand:ledig - Ort:München Ledige, die nicht in München wohnen  
-Familienstand:ledig -Ort:München -(Familienstand:ledig + Ort:München) alle nichtledigen Nicht-Münchner
-(Familienstand:ledig, Ort:München) -Familienstand:ledig + -Ort:München nicht ledig oder nicht in München (oder beides)

Hinweis: Hier wurden die Standardoperatoren angenommen:

"-" : Differenzoperator und Komplementoperator
"+" : Vereinigungsoperator
"," : Schnittoperator


Kleinere Verbesserungen
In der vorliegenden Version 6.2.5 ist "unter der Haube" bereits sehr viel Code in Richtung 64-Bit getrimmt worden. Das bringt auf i386 kompatiblen Maschinen zwar keinen Performancegewinn (diesen Prozessoren ist der Zugriff auf "ungerade" Adressen relativ egal), ist aber Grundvoraussetzung für den geplanten Einsatz auf die kommende Generation von 64-Bit-Prozessoren.

-----------------

Die Einfügeelemente in Templates waren bisher auf 64 Kbyte begrenzt. Auch diese Grenze ist mit der vorliegenden Version gefallen.

-----------------

Bei der Funktion "Ramtext_Insert" gab es nach der Umstellung auf inkrementell wachsende Ramtexte in der Linux-Version ein Speicherproblem, das jetzt nicht mehr vorkommt.

-----------------

Die Funktion "ExecMacro" funktioniert nunmehr in allen Versionen auch mit relativen Pfaden.

-----------------

Die tdbengine erkennt nun auch zirkuläre Refenzen in defekten Indexdateien (beispielsweise nach einem Serverabsturz) und verweilt nicht mehr in einer Endlosschleife, sondern gibt eine entsprechende Meldung in "error.log" aus.

In der Linux-Version ist eine erst Vorabversion von Socket-Funktionalität eingebaut. Mit

copyfile(URL,'ramtext')

können bei bestehender Internetverbindung Tempates via http-Protokoll von entfernten Rechnern geholt werden. Die tdbengine verwendet dabei das Protokoll HTTP/1.1, das auch mit virtuellen Hosts (und chunked documents) zurechtkommt.


Das war's für diesmal.

Viel Erfolg mit der tdbengine wünscht

Ulrich K



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: 05.05.2004


ranking-charts.de

Programmers Heaven - Where programmers go!