Diplomarbeit

Evaluierung der Datenbankverwaltung
strukturierter Dokumente mit einem
objektrelationalen Datenbanksystem
(Informix-Universal-Server)
ausgeführt am :
Institut für Integrierte Publikations- und Informationssysteme
GMD – Forschungszentrum Informationstechnik GmbH
in Darmstadt
Unter Betreuung von
Prof.Dr. Erich J. Neuhold
Dr. Klemens Böhm
Dr. Yangjun Chen
durch
Michael Fuchs

Inhaltsverzeichnis
1

EINLEITUNG..................................................................................................................... 5
1.1 VORBEMERKUNG.................................................................................................................5
1.2 AUFBAU DIESER ARBEIT.......................................................................................................7

2

OBJEKTRELATIONALE DATENBANKSYSTEM IUS (INFORMIX UNIVERSAL SERVER)......8
2.1 DIE VERSCHIEDENE DATENBANKKATEGORIEN......................................................................8
2.2 DIE OBJEKTRELATIONALE DATENBANK IUS.........................................................................9

3

SGML : STRUKTUR UND VERWALTUNG........................................................................11
3.1 DIE STRUKTUR VON SGML...............................................................................................11
3.2 KONFIGURATION UND VERWALTUNG VON SGML-DOKUMENTEN........................................14

4

SYSTEMARCHITEKTUR DER SGML-VERWALTUNG......................................................16
4.1 ARCHITEKTUR DES GESAMTSYSTEMS.................................................................................16
4.2 BASIS-DATENTYPEN DER OBJEKTRELATIONALEN DATENBANK...........................................17
4.3 SELBSTERSTELLTE DATENTYPEN........................................................................................18
4.4 DATENBANK-TABELLEN.....................................................................................................18

DocElemTable vom Typ docElem...............................................................................19
NonFlatElemTable vom Typ nonFlatElem + docElem...............................................20
4.5 DER SGML-PARSER : SP...................................................................................................22

4.5.1 Beschreibung des SP.......................................................................................22
4.5.2 Benutzung des SP............................................................................................23
4.6 ABLAUF DER DATENBANKORGANISATION...........................................................................24

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
4.6.1 Erstellen der Datenbank-Tabellen und -Typen...............................................24
4.6.2 Ablauf : Einfügen eines Dokumentes.............................................................25
4.6.3 Aufrufen der Funktionen................................................................................28
5

IUS- SCHNITTSTELLEN-FUNKTIONEN...........................................................................29
5.1 IUS-SP SCHNITTSTELLEN-FUNKTIONEN : SGML-PARSER-MODUL.....................................29

5.1.1 SP- Funktionen, die ESQL/C-Funktionen aufrufen (Sprache : C++)...........29
5.2 IUS-SP SCHNITTSTELLE ALS ESQL/C-MODUL...................................................................31

5.2.1 Funktionen zum Aufbauen einer Client-Verbindung.......................................32
5.2.2 Funktionen zum Generieren der Datenbank...................................................32
5.2.3 Funktionen zum Generieren der Indizes.........................................................33
5.2.4 Informations- und Navigations-Hilfsfunktionen.............................................35
5.3 SGML-API-FUNKTIONEN (API=APLICATION PROGRAM INTERFACE)..................................36

5.3.1 Spezielle Abfrage-Funktionen.........................................................................36
5.3.2 Ausgabe-Funktionen.......................................................................................39
5.3.3 Funktionen zur Navigation im Dokument.......................................................39
5.3.4 Info-Funktionen über Dokumente, DTDs und Elemenenttypen.....................40
5.3.5 Funktionen speziell für strukturierte Elemente (Datenbank-Objekte)............41
5.3.6 Funktionen speziell für flache Datenbank-Objekte........................................42
5.3.7 Hilfs-Funktionen zur Navigation, speziell in flachen Textteilen.....................43
5.3.8 Hilfs-Funktionen zur Abfrage, speziell in flachen Textteilen..........................44
6

DER ALGORITHMUS : GETALLCONTAINING...................................................................46
6.1 PROBLEME MIT INCLUSIONS/EXCLUSIONS BEI DER FRAGMENTIERUNG...............................46
6.2 DEFINITIONEN FÜR DEN ALGORITHMUS..............................................................................48
6.3 BESCHREIBUNG DES ALGORITHMUS...................................................................................49

6.3.1 Funktionen, die in den Körpern der drei Schleifen aufgerufen werden.........49
6.3.2 Hilfsfunktionen, die für die Schleifenterminierung benötigt werden..............50
6.3.3 Die elementaren Funktionen...........................................................................51
6.3.4 Der Gesamt-Algorithmus................................................................................52
6.4 BEWEIS MIT INDUKTION ZUR RICHTIGKEIT DES SATZES......................................................53

7

EXPERIMENTE................................................................................................................ 57
7.1 BASIS-ELEMENTE DER EXPERIMENTE................................................................................57

7.1.1 Die SGML-Test-Dokumente............................................................................57
7.1.2 Die verschiedenen Konfigurationen...............................................................58

Seite 3t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
7.2 EXPERIMENT (I+II): DOKUMENTBEZOGENE QUERIES UND GESAMT-OPERATIONEN
(EINFÜGEN, AUSGEBEN).....................................................................................................60

7.2.1 Beschreibung der Experimente.......................................................................60
7.2.2 Ergebnisse des Experiments (I+II).................................................................61
7.2.3 Analyse der Ergebnisse...................................................................................61
7.3 EXPERIMENT (III) : DOKUMENTBEZOGENE EINZEL-FUNKTIONEN.......................................62

7.3.1 Beschreibung des Experiments (III)...............................................................62
7.3.2 Ergebnisse des Experiments (III)....................................................................63
7.3.3 Analyse der Ergebnisse...................................................................................63
7.4 EXPERIMENT (IV): DATENBANK-QUERY MIT VERSCHIEDENEN KONFIGURATIONEN.............64

7.4.1 Beschreibung des Experiments (IV)................................................................64
7.4.2 Ergebnisse des Experiments (IV)....................................................................64
7.4.3 Analyse der Ergebnisse...................................................................................64
7.5 EXPERIMENT (V) : VORAUSPARSEN VS. AD-HOC-PARSEN....................................................65

7.5.1 Beschreibung des Experiments (V).................................................................65
7.5.2 Ergebnisse des Experiments (V).....................................................................66
7.5.3 Analyse der Ergebnisse...................................................................................66
8

SCHLUSSBEMERKUNG.................................................................................................... 67

ANHANG A............................................................................................................................ 69
DIE DTD FÜR SHAKESPEARE DRAMEN......................................................................................69

ANHANG B............................................................................................................................ 71
DIE SUPERDTD-INSTANZ 'SDTDI_PLAY', ERSTELLT VON DER DTD 'SHAKSPER.DTD' AUS
ANHANG A........................................................................................................................71

ANHANG C............................................................................................................................ 76
DAS SQL-SCRIPT 'CREATE.SQL' ZUM ERSTELLEN DER DATENBANK-TYPEN UND -TABELLEN......76

ANHANG D............................................................................................................................ 81
DAS SQL-SKRIPT 'INITS.SQL' ZUM INITIALISIEREN DER DATENBANKTABELLEN...........................81

ABBILDUNGSVERZEICHNIS................................................................................................... 85
TABELLENVERZEICHNIS...................................................................................................... 86
LITERATURVERZEICHNIS..................................................................................................... 87

Seite 4t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

1 Einleitung

1.1

Vorbemerkung
Man findet in der heutigen Zeit in fast allen Lebensbereichen multimediale Informationen,

die durch fortschreitende Rechnertechnologie, sinkende Beschaffungskosten und Vereinfachung
der Hard- und Softwarebedinung zu erklären ist. Einen wesentlichen Anteil trägt natürlich auch
das Internet, das ohne multimediale Informationen gar nicht mehr denkbar ist.
Neben Video und Audio kommen wir mit dem Internet auf ein wichtiges Medium, den
Text. Eine Seite im Internet ist als besonderer Text abgespeichert. Man nennt diese Textform
HTML und steht für "Hyper Text Markup Language" . HTML ist aber kein einfacher Text,
sondern eine Sprache (wie das Wort "Language" schon ausdrückt) mit syntaktischen und
semantischen Regeln und ist ein Dialekt aus der Familie SGML (Standard Generalized Markup
Language).
Mit SGML hat man die Möglichkeit, Teile des Textes mit sogenannten Markups
hervorzuheben und auch Zusatzinformationen oder Optionen (Attribute) über den Inhalt zu
bestimmen. Diese hervorgehobenen Textteile kann man dann gesondert behandeln. Beispiele
für diese 'Sonderbehandlung' sind : Sprünge ausführen, Informationen über den Inhalt oder
Inhalte selbst abfragen, Schrift des Inhalts ändern usw. Diese Hervorhebungen kann man
jedoch nur optimal nutzen, wenn auch mehrere SGML-Texte zusammen abgespeichert sind
und es Möglichkeiten gibt, um diese markierten Textteile auch von mehreren Dokumenten
abzufragen. So etwas ist mit Textverarbeitungssystemen, im herkömmlichen Sinne, nur schwer
bis überhaupt nicht möglich.

Seite 5t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Um

Daten

abzuspeichern

und

sie

dann

später

abzufragen,

hat

sich

die

Datenbanktechnologie bewährt. Hierbei hat sich das relationale Datenbankschema in den
letzten Jahren als populärstes Schema hervorgetan. Für dieses Datenbankschema gab es eine
Reihe von Optimierungen, die eine sehr schnelle Abfrage von Daten ermöglicht.
Das Problem bei der Verwaltung von multimedialen Informationen mit einer relationalen
Datenbank ist aber schon an dem Beipiel 'großer Text' zu illustrieren. Die relationale
Datenbank hat nur einfache Datentypen. Unter anderem können Texte, nur bis zu einer
gewissen Größe, in der Datenbank gespeichert werden. SGML-Textteile können aber beliebig
groß sein und somit ist das relationale Datenbankschema, in seinem Ursprung, nicht Ideal für
die Verwaltung von multimedialen Informationen. Wenn man diese Dokumentteile (und dessen
Behandlung) jetzt nicht nur als Felder in einer Datenbank, sondern mehr als Objekte, ansieht,
dann bietet sich das objektorientierte DBMS (DatenBank Management System) an. Eine
solche Verwirklichung besteht in dem System HyperStorM (Hypermedia Document Storage
and Modelling) ([BANY95]) welches auf dem objektorientierten Datenbanksystem 'VODAK'
([IPSI95]) entwickelt wurde.
Die im Laufe der Jahre gewonnenen Erkenntnisse zur Optimierung von 'Queries' in
relationalen Datenbanken wurde genutzt, um ein neues Datenbankschema zu entwickeln,
welches auch den Objektgedanken integriert. Man nennt es das objektrelationale DBMS. Mit
diesem DBMS kann man alle Vorteile einer relationalen Datenbank nutzen und zusätzlich
Objektkonzepte behandeln. Somit können wir in einem solchen System, multimediale Objekte
speichern und darauf zugreifen. Eine genauere Diskussion über das Auswählen des geeigneten
Datenbankschemas liefert [Sto96].
In dieser Arbeit sollen nun die Ideen und Erfahrungen von HyperStorM übernommen und
auf ein solches objektrelationales DBMS projeziert werden. Das hierbei gewählte
objektrelationale System ist IUS (Informix Universal Server). Mit einer Menge von
'build in'-Funktionen und einigen Innovationen wurden dann Evaluierungen vorgenommen.
Diese Experimente stützen sich wiederum teilweise auf die Erfahrungen, die in HyperStorM
beobachtet wurden.

Seite 6t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

1.2

Aufbau dieser Arbeit
Im folgenden Unterkapitel, gibt es ein Übersicht, wie diese Arbeit mit seinen 8 Kapiteln

aufgebaut ist.
Kapitel 2 soll einen Überblick über das objektrelationale Datenbankschema geben und
geht dabei insbesondere auf das gewählt System IUS ein. Im Kapitel 3 werden dann Grundsätze von SGML erläutert und Verwaltungsmechanismen beschrieben. Die Architektur
einzelner Komponenten (wie zum Beispiel der SGML-Parser, die Datenbank, usw.) sowie des
Gesamtsystems wird in Kapitel 4 aufgezeigt. Danach folgt die Beschreibung der
Implementierten Funktionen im Kapitel 5. Motivation, Beschreibung und Verifikation des
Algorithmus getAllContaining, der das Fragmentieren von Dokumenten mit komplexer DTD
erleichtern soll, sind im Kapitel 6 zu finden. Der evaluierende Teil der Arbeit in Form von fünf
Experimenten befindet sich im Kapitel 7. Zum Ende, in Kapitel 8, gibt es, nach einer
Zusammenfassung noch ein paar abschließende Bemerkungen und eine Aussicht. Im Anhang
befinden sich ausführliche Beispiele für eine DTD, Super-DTD-Instanz und SQL-Skripten.

Seite 7t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

2 Objektrelationale Datenbanksystem IUS
(Informix Universal Server)
Im folgenden Kapitel werden in Unterkapitel 2.1 verschiedene Datenbankkategorien
genannt und miteinander verglichen. In 2.2 wird dann das Datenbanksystem IUS vorgestellt.
2.1

Die verschiedene Datenbankkategorien.
Seit den letzten zwei Jahrzehnten haben sich Datenbanktechniken schnell entwickelt und

es stehen der Welt unterschiedliche Datenbank- und Informationssysteme zur Verfügung. Diese
Systeme können nach Stonebraker [Sto96] in vier Kategorien klassifiziert werden:
1. Text oder Bildverarbeitungssystem (keine Datenbank)
2. Relationale Datenbank mit einfachen Datentypen und SQL (Standard Query Language)
3. Objektorientierte Datenbank mit komplexen Datentypen
4. Objektrelationale Datenbak mit komplexen Daten und ESQL (Extended SQL)
Vorteil von der Kategorie 1 ist die Einfachheit im Behandeln der Objekte, es gibt jedoch
keinerlei Datenbankfunktionalitäten. Kategorie 2 ist die weit verbreitetste Datenbankform. Mit
einem solchen Datenbanksystem operiert man auf einfachen Datentypen. Die Behandlung von
Daten durch Queries wurde im Lauf der Jahre optimiert. Alle Anwendungsfälle, die keine
komplexeren Datentypen benötigen, werden optimal mit der relationalen Datenbank
unterstützt. Komplexe Datentypen können, wenn überhaupt, nur umständlich mit relationalen
Datenbanksystemen verwaltet werden. Um komplexe Datentypen zu behandeln, wurde das
objektorientierte Datenbanksystem entwickelt. In Kategorie 3 ist die Modellierung eines

Seite 8t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Objektes sehr flexibel und einfach, der Zugriff dagegen ist sehr komplex. Um von der
Einfachheit und Mächtigkeit des relationalen Zugriffs zu profitieren, wurde die realtionale
Datenbanktechnik für Modellierung und Zugriff auf komplexe Datentypen erweitert. Diese
neuen Systeme gehören zu Kategorie 4. Auf einem solchen objektrelationalen System wurde
diese Arbeit implementiert und evaluiert. Das gewählte objektrelationale System trägt den
Namen IUS (Informix Universal Server). Andere Beispiele für die Ausnutzung der
verschiedenen Kategorien kann man im Kapitel 14 in [Sto96] finden.
2.2

Die objektrelationale Datenbank IUS
Das objektrelationale Datenbanksystem IUS kann als Basis wie ein relationales

Datenbanksystem betrachtet werden. Es gibt zusätzlich neue Datentypen zur Einbettung von
verschiedenen multimedialen Informationen. Hauptsächlich handelt es sich dabei um
Datentypen wie : lvarchar, clob oder collection . Diese Datentypen werden genauer im
nächsten Kapitel beschrieben, in dem auch die Architektur des Systems skizziert wird.
Außerdem gibt es die Möglichkeit, frei definierte Funktionen und Prozeduren zu erstellen.
Diese Funktionen können dann aufgerufen werden, sowie in ein SQL-Statement eingebunden
werden. Beispielsweise kann man ein Funktion mit execute function bzw. execute procedure
aufrufen. Die Sammlung der Funktionen zur Manipulation von Datenbankinhalten, die vom
Benutzer definiert wurden, nennt man 'DataBlade'.

In SQL-Statements kann man sowohl im select-Teil sowie im where-Teil eine Funktion
einbauen. Im Folgenden sind einige Beispiele für neue Datentypen und deren Benutzung in
dieser Arbeit.

collection (Liste,Menge)
benutzt bei Index-Einträgen

clob (große Texte bis 4 GB)
benutzt für flache Text-Objekte

lvarchar (varible Zeichenketten bis 32 KB)
content-model

opaque (private Datentypen)

Seite 9t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Die Funktions-Einbindung kann Beispielsweise folgendermaßen geschehen:

execute function getAll("10|-1","NAME")
In diesem Beispiel wird die DataBlade-Funktion getAll aufgerufen und das Ergebnis wird

in die vorher ausgewählte Ausgabe übergeben. Die Eingabe-Parameter sind vom Typ
char(128). Man kann also 128 Zeichen lange Strings als Parameter übergeben. Als Rückgabe
bekommt man ein clob.

select etName
from nonFlatElemTable
where isContainedIn(own_id , 10)
Dieses SQL-Statement bindet eine DataBlade-Funktion in die 'where-clause' mit ein.

Berechnet werden alle Namen aus der nonFlatElemTable, die in dem Element mit der oid 10
enthalten sind. own_id ist ein Feld der Datenbanktabelle nonFlatElemTable und wird während
der Query mit entsprechenden Zwischenwerten gefüllt.

Seite 10t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

3 SGML : Struktur und Verwaltung
In diesem Kapitel werden einige Grundkenntnisse über die Struktur in Unterkapitel 3.1
vermittel. In 3.2 geht es um die Verwaltung von SGML-Dokumenten, auch anhand eines
Beispiels, sowie speziell gewählte Verwaltungsmechanismen. Es handelt sich hierbei um das
Konfigurieren von Dokumenten.
3.1

Die Struktur von SGML
Im Folgenden werden Beschreibungen der Sprache SGML gebracht. Diese Einführung

dient nur als Auffrischung der Kenntnisse von SGML und ist keinerlei Ersatz für die gesamte
Lehre in SGML. Ausführlichere Beschreibungen, Definitionen und Grammatiken finden sich in
Practical SGML([Her94]).
SGML steht für 'Standard Generalized Markup Language'. Ein SGML-Dokument
besteht aus 2 Teilen. Der erste Teil ist ein Dokument mit markierten Textteilen und der zweite
Teil ist eine Definitionsdatei, zur Definition verschiedener Dokumenttypen. (z.B. Brief, Bericht,
Drama). Man nennt diese Datei die DTD (Dokument Type Definition). Dadurch werden
Syntax und Grammatik der markierten Textteile für die jeweiligen Typen festgelegt. Diese
Textteile nennt man Dokument-Elemente. Die Markierung dieser Dokument-Elemente im
Dokument geschieht mit sogenannten Markups und bestehen aus dem Elementtyp-Namen und
Zeichen, die es als Markierung kennzeichnen und angeben, ob es sich um den Beginn oder das
Ende der Markierung handelt. Zusammengesetzt nennt man diese Zeichenfolge Starttag bzw.
Endtag. Ein Starttag hat die Form : "<ETName>" und das Endtag : "</ETName>". In jedem
Element können sich weitere Elemente befinden. Welche Elemente in einem anderen Element
enthalten sein dürfen, wird für jedes Element in der DTD definiert. Man nennt die Definition,

Seite 11t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
die eine 'enthalten'-Beziehung definiert, das Content-Model. Zusätzlich können auch
Metainformationen von Elementtypen definiert werden. Diese Metainformationen nennt man
Attribute und sind jeweils auf die Dokument-Elemente bezogen.
In Abbildung 3.1-1 ist ein SGML-Dokument mit entsprechenden Kommentaren und in
Abbildung 3.1-2 ist die dazugehörende DTD vom Dokumenttyp 'article'. Wie man erkennen
kann, gibt es auch Starttags ohne die entsprechenden Endtags, wie im Beispiel bei 'author'
oder 'paragr'. In einem solchen Fall kann man nur mit der DTD entscheiden, wo sich das Ende
befindet. Ausfühlicher wird dieses Problem im Experiment (V), Kapitel 7 ab der Seite 65 noch
einmal behandelt. Die Elementente, die den eigentlichen Text beinhalten, nennt man
nichtstrukturierte Dokument-Elemente und haben als Content-Model (#PCDATA).
PCDATA steht für Parsed Character DATA. Beispiele dieser Elemente kann man in der DTD
in Abbildung 3.1-2 finden. Es handelt sich um die Elemente title, author, abstact, caprion,
paragraph und acknowl. Die Definitionen im Einzelnen findet man in [Her94].
<article status="final">  article hat ein Attribut namens 'status' mit dem Wert 'final'
<title>From Structured Document to Novel Query Facilities</title>
<author>D. David</author>
<author>R. John  Das ist ein Author ohne Endtag !
... ...
<abstract>
Structured documents (e.g., SGML) can benefit a lot from
database support and more specifically from object-oriented
database(OODB) management systems
</abstract>
<section>
<sectitle>Introduction</sectitle>
......
<body><paragr>This paper is organized as follows.
Section 2 introduces the SGML standard. The mapping
from SGML to the O2 DBMS is defined in
Section 3. Section 4 presents the extension ...
</body>
</section>
<section>
<sectitle>SGML preliminaries</sectitle>
<body><paragr>In this section, we present the main features
of SGML. (A general presentation is clearly beyond
the scope of this paper.)
</body>
</section>
... ...
</article>
Abbildung 3.1-1:

Eine Beispiel-Dokumnet vom Dokumenttyp 'article'

Seite 12t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

DTD:
<!DOCTYPE
<!ELEMENT
<!ATTLIST
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ATTLIST
<!ELEMENT
<!ATTLIST

article [
article
article
title
author
abstract
section
sectitle
subsectn
body
figure
figure
picture
picture

<!ELEMENT
<!ENTITY
<!ELEMENT
<!ATTLIST
<!ELEMENT

caption
fig
paragr
figure
acknowl

(title,author+,affil,abstract,section+,acknowl)>
status (final|draft) draft>
(#PCDATA)>  Parsed Character Data;
(#PCDATA)>
Ist der eigentliche Inhalt eines
(#PCDATA)>
terminalen Elementes.
((title, body+) | (title, body*,subsectn+))>
(#PCDATA)>
(title, body+)>
(figure | paragr)>
(picture, caption?)>
lable ID #IMPLIED
EMPTY>
sizex NMTOKEN "16cm"
sizey NMTOKEN #IMPLIED
file
ENTITY #IMPLIED
(#PCDATA)>
SYSTEM
"/u/chris/SGML/image1" NDATA>
(#PCDATA)>
reflable IDREF #REQUIRED>
(#PCDATA)>

]>
Abbildung 3.1-2:

Eine Beispiel-DTD vom Dokumenttyp 'article'

Seite 13t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

3.2

Konfiguration und Verwaltung von SGML-Dokumenten
Dieses Unterkapitel beschäftigt sich mit Verwaltungs- und Konfigurations-Mechanismen,

die HyTime Standards entsprechen. Näheres über HyTime erfährt man in [BAK95].
Bei der Verwaltung von SGML-Dokumenten hat man die Möglichkeit, jedes
strukturierte Dokument-Element als eigenes Datenbankobjekt zu speichern. Dies wird auch in
der Abbildung 3.2-4 deutlich. Hier ist das Beispiel-Dokument als Baum dargestellt. In dem
Baum entspricht jeder Knoten einem eigenen Datenbank-Objekt. Die flachen DatenbankObjekte bilden die Blätter dieses Baumes und sind in der Baumdarstellung mit einem Rahmen
versehen.

author

title

author

David

author

abstract

sectitle

John

Introduction
From Stuctured
Documtent...Facilit

.......

section

Structured documents
.....management system

section

sectitle

body

.......

body

prelimitinaries
paragraph

paragraph

This paper organazed as follows... In this section, we present ....
...the extension ....
...the scope of this paper) ...
Abbildung 3.2-3:

Repräsentation des Beispieldokuments – Dokumentelement = Knoten

Weiterhin gibt es auch die Möglichkeit, die Speicherung der Dokument-Elemente in einer
anderen Weise zu organisieren. Extremfall wäre die Speicherung des SGML-Textes, ohne
Strukturierung und als Ganzes. Eine Mischung aus diesen zwei Extremen wurde für diese
Arbeit gewählt.Bei dieser Variante (hybride Speicherung [BAK95]) ist es nun möglich,
bestimmte Dokument-Elemente zusammenzufassen und als komplett markierte Textteile in
flache Datenbank-Objekte zu speichern. In Abbildung 3.2-4 ist wieder das Beispieldokument
in Baum-Darstellung. In diesem Falle sind aber die Dokument-Elemente vom Typ 'sectitle',
'body', 'paragraph' zu einem flachen Datenbank-Objekt zusammengefaßt. Diese verschiedenen

Seite 14t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Repräsentationsmöglichkeiten (Konfigurationen) werden bei der Verwaltung berücksichtigt.
Auf diese zusammengefaßten, flachen Datenbank-Objekte kann nun mit individuellen
Mechanismen zugegriffen werden. Neben den klassischen C-String-Funktionen, hat man auch
die Möglichkeit, den ganzen, flachen Teil als PAT-Trees oder PAT Arrays abzuspeichern, wie
es im Kapitel 5 in [GBS92] beschrieben ist.
Im Kapitel 7 werden unterschiedliche Konfigurationen evaluiert und dann die
entsprechenden Vor- bzw. Nachteile dazu erörtert.

Abbildung 3.2-4:

Repräsentation des Beispieldokuments - zusammengefaßte Elemente
author

title

author

author

abstract

section

....... section

.......

David
John
ctitle>Introduction</sectitle>
<sectitle>SGML preliminaries</sectitle>...
.....
<body><paragr>In this section, we present the main features of SGML. (A general presentation is clearly be
ody><paragr>This paper is organized as follows.Section 2 introduces the SGML standard. The mapping from SGML to the O2 DBMS is defined in Section 3. Section 4 presents the extension ...
...
ody>
</body>
From Stuctured
Documtent...Facilit

Structured documents
.....management system

Seite 15t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

4 Systemarchitektur der SGML-Verwaltung
Im folgenden Kapitel wird die Architektur des Verwaltungssystems vorgestellt. Im
Unterkapitel 4.1 gibt es eine Beschreibung des Gesamtsystems. Weiterhin gibt es in 4.2 ein
Überblick über Datentypen, die benutzt wurden und in 4.3 über die selbsterstellten Datentypen.
Es folgt eine Auflistung der zehn Datenbanktabellen in 4.4 sowie eine Skizzierung des SGMLParsers in 4.5. Die Einbindung von Funktionen in der Datenbank, sowie der Ablauf des
Einfügens eines SGML-Dokuments werden anhand von Beispielen in Unterkapitel 4.6 gezeigt.
4.1

Architektur des Gesamtsystems
Im Folgenden wird ein Überblick, über das gesamte System gegeben. Unter anderem

wird in Abbildung 4.1-5 die Architektur des Gesamtsystems skizziert. Außerdem werden die
Schnittstellen genannt und der Bezug zum SGML-Parser angegeben.
Der SGML-Parser SP ist in mehrere Komponenten aufgeteilt, wobei hier nur die
Komponenten genannt sind, die direkt mit der SGML-Datenbankverwaltung zu tun haben. Die
in der Abbildung links befindliche Komponente ist eine C++-Klasse (elementOutput), die aus
einer DTD eine SuperDTD-Instanz erstellt. Genaueres über diese Generierung befindet sich im
Kapitel 4.6.2. Die rechte Komponente hingegen ist eine Klasse (ModFuncs), die Funktionen
der ESQL-Schnittstelle aufruft. Diese Funktionen sind im wesentlichen zum Erstellen der
Dokument-Elemente und der Index-Strukturen. In dieser Komponente wird auch die
Konfigurations-Datei ausgelesen und ebenso werden die Index-Informationen aus der
SuperDTD-Instanz geholt.
Die ESQL/C-Schnittstelle ist eine Sammlung von Funktionen, die in der Sprache C
implementiert sind und eine extended SQL-Schnittstelle verwenden. Diese ESQL/C-Sprache

Seite 16t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
wird dann mit einem 'Precompiler' zu einem C-Quellcode und hinterher zu einem ausführbaren
Objekt compiliert.
Zu SQL-Abfragen und Aufrufen wird dann das sogenannte Datablade als
Kommunikationsmittel benutzt. Das Datablade besteht aus Funktionen, deren AufrufSchnittstellen direkt in IUS integriert sind und dynamisch aus einer 'library' (sgml_server.so)
geladen und ausgeführt werden.

execute function
oder SQL-Abfragen

SP-Komponente
zum
Erstellen der
SDTD-Instanz

SP-Komponente
zum
Einfügen
in die
Datenbank

ESQL/C -

C++

Schnittstelle

SGML-Parser
DataBlade API

Index-Strukturen
Dokumente
SuperDTDInstanzen

Abbildung 4.1-5:

4.2

Architektur des Gesamtsystems

Basis-Datentypen der objektrelationalen Datenbank
Die

Tabelle

4.2-1

in

diesem

Unterkapitel

listet

die

Basis-Datentypen

der

objektrelationalen Datenbank auf. Insbesondere sind das die Datentypen von SQL und der
Schnittstellen-Sprache C.
SQL
char
int
boolean
varchar

C
mi_char
mi_integer
mi_boolean
mi_lvarchar*

clob
collection

MI_LO_HANDLE*
MI_COLLECTION *

Tabelle 4.2-1:

Beschreibung
entspricht dem char in C
entspricht dem int in C
entspricht dem int in C, mit true oder false als 1 oder 0
Zeiger auf ein String mit variabler Zeichenanzahl(max.
32KB)
Handle auf ein Dateiartigen Text (max. 4 GB)
Handle auf eine geordnete/ungeordnete Liste oder
Menge

Datentypen von den verschiedenen Schnittstellen

Seite 17t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
4.3

Selbsterstellte Datentypen
Die in Tabelle 4.2-1 aufgelisteten Datentypen werden als Basis für selbsterstellte

Datentypen benutzt. Diese selbsterstellten Datentypen werden mit einer Formbeschreibung und
einem Beispiel in Tabelle 4.3-2 skizziert, die sich im folgenden Unterkapitel befindet.
Name
Position

Basistyp
spezielle Form
mi_lvarchar* "<oid>|<offset>"

id_type
DocElemRef
DocIDRef
IndexValue

mi_integer
mi_integer
positiv
mi_integer. positiv
mi_lvarchar* "<oid>|<ocurrence>"

Tabelle 4.3-2:

4.4

Beispiel
"10|-1",
"32|400"
10
55
10
Bsp.: "20|2" ,
"100|-1"

Bemerkung
Strukturiert
 offset=-1

Strukturiert
 occurrence=-1

Selbsterstellte Datentypen und ihre Abstammung

Datenbank-Tabellen
Im flogenden Unterkapitel werden zehn Tabellen aufgelistet. Diese Tabellen werden zur

Speicherung von Dokumenten und Metainformationen benutzt.
DocumentTable : In dieser Tabelle wird der 'Kopf' der Datei gespeichert. Der Kopf
besteht aus name, dem Namen des Dokumentes (mit Pfad, wenn dieser beim Einfügen mit
angegeben wurde) und aus Referenzen dtdref bzw. root zur DTD und zum Wurzel-Element
des Dokuments. own_id ist die oid des Datenbankobjekts.
DocumentTable vom Typ document
Feldname
Feldtyp
Beschreibung
own_id
id_type
Eindeutiger Bezeichner des Datenbankobjektes document
name
varchar(128) Der Name des SGML-Dokumentes mit Pfad
dtdref
id_type
Die oid der zugehörigen DTD
root
id_type
Die oid des Wurzel-Elementes des Dokuments
DtdTable : Hier werden die Informationen der DTD abgespeichert. name ist der
Dokumenttyp-Name und config ist der Inhalt der Konfigurations-Datei.
DtdTable vom Typ dtd
Feldname
Feldtyp
own_id
id_type
name
varchar(128)
config
clob

Beschreibung
Eindeutiger Bezeichner des Datenbankobjektes dtd
Der Name des Dokumenttyps der DTD
Konfiguration der zugehörigen DTD

EtypeTable : In dieser Tabelle werden die einzelnen Elementtypen gespeichert. name ist
der Elementtyp-Name, der zusammen mit dtdref eindeutig wird. dtdref ist die Referenz auf die
entsprechende DTD. Die Definition des Elementtyps ist mit contentmodel in der Tabelle

Seite 18t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
repräsentiert. pcdataindexed gibt an, ob für diesen Elementtyp ein PCDATA-Index angelegt
ist.
EtypeTable vom Typ etype
Feldname
Feldtyp
own_id
id_type
name
varchar(128)
contentmodel
lvarchar
dtdref
id_type
pcdataindexed boolean

Beschreibung
Eindeutiger Bezeichner des Datenbankobjektes etype
Der Name des Elementtyps
Das Contentmodel des Elementtyps
Die oid der zugeörigen DTD
Flag, ob der Elementtyp im PCDATA-Index ist oder nicht

Die folgenden drei Tabellen vom Typ docElem, nonFlatElem und flatElem stehen in
Beziehung zu einander. Wie in Abbildung 4.4-6 zu erkennen ist, sind die Typen nonFlatElem
und flatElem, Erben vom Typ docElem. In den entsprechenden Tabellen werden jedoch nur
die Felder beschrieben, die diese Typen nicht gemeinsam haben.

Ist vom
Typ

Ist vom
Typ

docElem

flatElem
Abbildung 4.4-6 :

nonFlatElem

Das Vererbungsverhältnis zwischen docElem, nonFlatElem und flatElem.

DocElemTable : In diese Tabelle werden die Felder doc, up, succ, pred, aller
Dokument-Elemente gespeichert. doc ist eine Referenz auf das Dokument-Objekt, das in der
DocumentTable gespeichert ist. up hat als Inhalt die oid des logischen Vater-Elements und in
succ bzw. pred sind die oids des logischen Vorgängers bzw. Nachfolgers gespeichert.
DocElemTable vom Typ docElem
Feldname
Feldtyp
Beschreibung
own_id
id_type
Eindeutiger Bezeichner des Datenbankobjektes docElem
doc
id_type
Die oid des Dokumentes
up
id_type
Die oid des Vater-Elements
succ
id_type
Die oid des Nachfolger-Elements
pred
id_type
Die oid des Vorgänger-Elements
NonFlatElemTable : Diese Tabelle enthält für die strukturierten Dokument- Elemente
zusätzlich (zur DocElemTable) die Felder down und etName. down ist die oid des ersten
Sohnes und etName der Name des Elementtyps.

Seite 19t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
NonFlatElemTable vom Typ nonFlatElem + docElem
Feldname
Feldtyp
Beschreibung
down
id_type
Die oid des am weitesten linken Sohnes
etName
varchar(128) Der Name des Elements
FlatElemTable : Diese Tabelle enthält für die flachen Dokument-Elemente zusätzlich
(zur DocElemTable) das Feld flat, welches einen großen Text als Inhalt hat und in dem
mehrere flache Dokument-Elemente zusammengefaßt abgespeichert werden.
FlatElemTable vom Typ flatElem + docElem
Feldname
Feldtyp
Beschreibung
flat
clob
Der Text (bis 4 GB) des flachen Elementes
AttRecTable : Hier werden die Attribute der strukturierten Dokument- Elemente
gespeichert. element ist dann die oid des strukturierten Dokument-Elements und name, value
beinhaltet dann den Text des Attribut-Namens und –Wertes
AttrRecTable vom Typ attRec
Feldname
Feldtyp
element
id_type
name
varchar(128)
value
varchar(128)

Beschreibung
Die oid des Elements
Der Name des Attributes des Elementes
Der Attributwert des Attributs

AttribIndexTable : attrName und attrValue sind Name und Wert des Attributs, die zu
dem Elementtyp mit der oid elementType gehören. In positions sind dann die Index-Einträge
abgelegt. Ein Index-Eintrag ('indexValue') besteht aus der oid des Dokument-Elements und
der Anzahl des Auftretens innerhalb des Datenbankobjektes. Handelt es sich bei dem
Datenbankobjekt um ein strukturiertes Dokument-Element, wird als Anzahl -1 angegeben.
AttribIndexTable vom Typ attribIndex
Feldname
Feldtyp
Beschreibung
elementType
id_type
Die oid des Elementtyps für den Index
attrName
varchar(128)
Der Name des Attributes für den Index
attrValue
varchar(128)
Der Attributwert für den Index
positions
setof(indexValue) Index-Eintrag : oid des Elements | Anz.-Auftreten
StructIndexTable : Der strukturierte Index besteht aus einem externen Elementtyp und
einem internen Elementtyp und dem Inhalt des internen Elements, content. Der externe/interne
Elementtyp wird in dieser Tabelle durch die Referenzen extElemType/intElemType
repräsentiert. extElemType/intElemType sind die oids der entsprechenden Elementtypen.
positions ist wie oben beschrieben.

Seite 20t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
StructIndexTable vom Typ structIndex
Feldname
Feldtyp
Beschreibung
extElemType
id_type
Die oid des äußeren Elementtyps für den strukt. Index
intElemType
id_type
Die oid des inneren Elementtyps für den strukt. Index
content
varchar(128)
Der Text-Inhalt des inneren Elementes für den Index
positions
setof(indexValue) Index-Eintrag : oid des Elements | Anz.-Auftreten
PCDATAIndexTable : Der PCDATA-Index besteht aus einer Referenz auf den
Elementtyp, elementType, und dem Inhalt des Elements, content. positions ist wie oben
beschrieben.
PCDATAIndexTable vom Typ pcdataIndex
Feldname
Feldtyp
Beschreibung
ElementType
id_type
Die oid des für den PCDATA-Index
Content
varchar(128)
Der Text-Inhalt des Elementes für den Index
Positions
setof(indexValue) Index-Eintrag : oid des Elements | Anz.-Auftreten
In Abbildung 4.4-7 wird ein Zusammenspiel der oben beschriebenen sechs Tabellen
skizziert, die direkt mit der Dokumentspeicherung zu tun haben. In der DocumentTable wird
der Name und eine Referenz auf die entprechende DTD gespeichert. Diese DTD wird in der
DTDtable repräsentiert. In dieser DTDtable wird der Dokumenttyp-Name gespeichert, sowie
die Menge der entsprechenden Elementtypes und die Konfiguration. Normalerweise werden
die Elemente eines Dokuments in vier Tabellen aufgeteilt. (DocElemTable, NonFlatElemTable,
AttrRecTable und FlatElemTable).
FlatElemTable
flat
"Text zu Elem1"
"Text zu Elem4"
"Text zu Elem6"
"Text zu Elem8"
"Text zu Elem10"

NonFlatElemTable
down
etName
1
"E0"
3
"E2"
4
"E3"
6
"E5"
8
"E7"
10
"E9"

Abbildung 4.4-7:

4.5

DocElemTable
own_id doc up succ pred
0
1 1
1 0
2
2 3
2 2
5
4
2 3
5
2 2
7
3
6
2 5
7
2 2
5
8
2 7
9
3 10
3 9
-

DocumentTable
own_id name
dtdref
1
"Dok1"
2
2
"Dok2"
1
3
"Dok3"
1

attrRecTable
element name
2
Attr2
3
Attr3

root
0
2
9

value
AW2
AW3

DocumentTable
own_id name etypes config
1
"DTD1" {...}
"...."
2
"DTD2" {...}
"...."
3
"DTD3" {...}
"...."

Zusammenspiel der Tabellen, die zur Speicherung der Dokumente beteiligt sind.

Der SGML-Parser : SP
Im diesem Unterkapitel wird der Parser selbst, sowie seine Parameter anhand von

Beispielen beschrieben. Ebenso wird ein Überblick geliefert, welche Klassen bzw.
Sourcecode-Dateien extra für diese Arbeit implementiert wurden.

Seite 21t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
4.5.1 Beschreibung des SP
Der SP (SGML-Parser) wird zur Überprüfung und Einfügung von SGML-Dokumenten
bezüglich ihrer DTD benutzt. Man kann auch eine DTD ohne ein Dokument parsen. Der SP
geht bei dieser Überprüfung, sowohl auf den Syntax, wie auf die Grammatik ein. Fehler
werden angezeigt. Neben der Fehlermeldung steht noch die Koordinate, bei der dieser Fehler
aufgetreten ist. Wird die Option zum Einfügen gewählt, werden alle korrekt geparsten
Dokument-Elemente in die Datenbank eingefügt. Die Konfigurations-Datei bestimmt hierbei,
welche Elemente flach und welche strukturiert eingefügt werden sollen. Beim Einfügen werden
SGML-Index-Strukturen generiert. Die Information, für welche Elemente ein Index angelegt
werden soll, ist in der SuperDTD-Instanz, die sich in der Datenbank befindet, enthalten.
Der Name des SP-Programmes ist „nsgmls“. Die Optionen, die dabei in der
Komandozeile

eingegeben

werden

sind

"-x"

"-y"

und

"-X".

Die

C++-Dateien

elementOutput.cxx (SuperDTD-Instanz-Erstellen) und ModFuncs.cxx (DB-Einfügen) sind
speziell für die diese Zwecke entwickelt worden. ModFuncs.cxx wird dabei von dem Parser
benutzt und ruft die Schnittstellenfunktionen von der ESQL/C-Datei functions.ec auf.

Seite 22t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

4.5.2 Benutzung des SP
Im Folgenden gibt es eine genaue Beschreibung der Parameter von 'nsgmls':
Die Option "-x <konfigurations-Datei> <Dokument-Name>"
Funktion :

Das Dokument mit dem Namen Dokument-Name (kompletter Pfad)
wird geparst und in die Datenbank eingefügt. Die KonfigurationsDatei ist dabei der Name der Datei (kompletter Pfad), in der alle
Namen der Dokument-Elemente zeilenweise stehen, die strukturiert
abgespeichert werden sollen.

Beispiel :

nsgmls -y SGML-DB -x /sample/config /sample/hamlet.sgml
Das Dokument hamlet.sgml wird unter der Konfiguration in config in
die Datenbank SGML-DB eingefügt.

Die Option "-X <Dokument-Name>
Funktion :

Das Dokument mit dem Namen Dokument-Name (kompletter Pfad)
wird geparst und von der dazugehöhrenden DTD wird eine
SuperDTD-Instanz erstellt. Der Name der Instanz besteht dann aus
dem Dokumenttypnamen plus Zusätze.

Beispiel :

nsgmls -X /home/sample/hamlet.sgml
Das Dokument hamlet.sgml ist vom Dokumenttyp "PLAY" . Somit
wird die SuperDTD-Instanz mit dem Namen "SDTDi_PLAY" erstellt.

Die Option "-y <DB-name> ....."
Funktion :

Beim Einfügen muß man die Datenbank angeben. DB-name ist der
Name der gewälten Datenbank.

Beispiel :

nsgmls -y ius_sgml –x cfg hamlet.sgm
Ein Dokument mit dem Namen hamlet.sgm und der Konfiguration cfg
wird mit diesem Befehl in die Datenbank ius_sgml eingefügt.

Seite 23t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
4.6

Ablauf der Datenbankorganisation
In diesem Unterkapitel wird die Datenbankorganisation diskutiert. Dabei sind die

Stationen, im einzelnen, das Erstellen der Datenbank, das Einfügen eines Dokuments (und
dessen Vorbereitungen) und schließlich das Abfragen von Daten.
4.6.1 Erstellen der Datenbank-Tabellen und -Typen
Zum Erstellen und Initialisieren der Datenbank-Tabellen und –Typen, existieren SQLSkripte, die mit Hilfe von dem 'Utility' dbaccess aufgerufen werden können. Es handelt sich
hierbei um die Skripte : create.sql, inits.sql und delete.sql.

create.sql erstellt alle Datentypen, die in der Datenbank verwendet werden sowie alle
Tabellen.

inits.sql initialisiert die Tabellen mit Null-Werten und richtet auch die notwendigen
Elementtypen sowie die DTD-Referenzobjekte ein.

delete.sql löscht alle Datentypen, Tabellen und deren Inhalte. Dieses Skript ist
hauptsächlich zur Behandlung von Updates, die auch Tabellendesign oder Datentypen
betreffen.

Zum Erstellen des SGML-DataBlades wird die 'library' sgml_server.so kompiliert und
mit dem SQL-Skript func.sql werden die Funktionen in die Datenbank eingefügt. Die Skripte
create.sql und inits.sql sind im Anhang C und D aufgelistet.

Seite 24t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

4.6.2 Ablauf : Einfügen eines Dokumentes
Das Einfügen eines Dokumentes in die Datenbank wird in der
illustriert.
SGMLDTD

Abbildung 4.6-8

SGMLSDTD-Instanz

SP

Benutzer

SDTD-Instanz
als Dokument
in DB

SGMLDokument

SGMLDokument
in DB

SP
KonfigurationsDatei

Abbildung 4.6-8:

modifizierte
SGMLSDTD-Instanz

SP

SGMLDTD

Ablaufdiagramm - Einfügen eines SGML-Dokuments in die Datenbank.

Als Vorbereitung wird aus der SGML-DTD des Dokumentes eine SuperDTD-Instanz
generiert. Dieses Dokument enthält im wesentlichen alle Informationen aus der DTD, plus
zusätzliche Informationen, die die Erstellung der Indizes betrifft. Diese Generierung wird mit
Default-Werten durch den SGML-Parser durchgeführt. Um die drei Indexstrukturen zu
bestimmen, werden entsprechende Einträge durch den Benutzer in die Super-DTD-Instanz
eingetragen. Im wesentlichen handelt es sich um Attribute der entsprechenden Super-DTDInstanz-Elemente .
Im Dokumentelement vom Typ <ELEM> gibt es das Attribut ELEMINDEX, das als
Attributwert 'Y' oder 'N' annehmen kann. Ist der Attributwert 'Y', dann wird ein Index für
PCDATA angelegt, daß heißt, ein Indexeintrag enthält die Elementtyp-Id, den entsprechenden
Dokument-Elements und die Positionen, bei denen der Inhalt auftritt. Falls der Attributeintrag
'N' entspricht, wird kein Index erstellt. Ein weiteres Attribut trägt den Namen

Seite 25t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
STRUCTINDEXED und enthält alle Elementtyp-Namen, für die ein strukturierter Index
angelegt werden soll. ELEMNAME ist der Name des externen Elementtyps und in
STRUCTINDEXED befinden sich alle Namen der internen Elementtypen. Ein Indexeintrag
enthält die Elementtyp-Id des externen und des internen Elementtyps, sowie den Inhalt des
internen Dokument-Elements und eine Menge aller Positionen, bei denen der Inhalt auftritt.
Beispiel :
SuperDTD-Instanz-Zeile :
<ELEM

elemName="NAME"..ELEMINDEX='Y'

STUKTINDEX='VORNAME,...' ...>
</ELEM>
Dokument-Zeilen :
<NAME>
<VORNAME>Michael </VORNAME>
<NACHNAME>Fuchs</NACHNAME>
</NAME>
PCDATAIndex-Instanz :
[ET-Id_von(NAME), "Michael Fuchs", {("10|-1"),("15|2")}]
Um den eindeutigen Elementtyp zu bestimmen, wird die oid des Elementtyps im Index
verwendet. In diesem Beispiel handelt es sich um die oid des Elementtyps NAME. Der Inhalt
"Michael Fuchs" kommt im strukturierten Element mit der Position 10|-1 vor und in dem
flachen Dokument-Element, mit der oid 15, zweimal vor.
structIndex-Instanz :
[ET-Id_von(NAME),ET-Id_von(VORNAME), "Michael ", {(10,-1)}]
Das

Gleiche,

was

für

die

PCDATAIndex-Instanz

gilt,

gilt

auch

für

die

structIndex-Instanz. Der Inhalt eines Elementes ist aber nur die erste Bedingung für den Index.

Seite 26t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Das Element, das "Michael" beihalten soll und vom Elementtyp VORNAME ist, muß auch
noch in einem Element vom Typ NAME enthalten sein.
Ein weiterer Elementtyp in der SuperDTD-Instanz ist <ATTRIBUTE>. Hier ist das
Attribut ATTRINDEX für den Attribut-Index verantwortlich. Hat es den Attributwert 'Y',
dann wird eine Index-Instanz angelegt, die die oid, sowie den Attribut-Name und den AttributWert des entsprechenden Elementtyps enthält und ebenso die Positionen, bei denen dieses
Attribute-Paar auftritt. Ist der Attributwert 'N', wird kein Index angelegt.
Beispiel :
SuperDTD-Instanz-Zeilen :
<ELEM elemName="NAME"..>
<ATTRIBUTE

attName='NACHNAME' ...attrIndex='Y'.....>

</ATTRIBUTE>
</ELEM>
Dokument-Zeile :
<NAME NACHNAME="Fuchs">
....
</NAME>
AttribIndex-Instanz :
[ET-Id_von(NAME), "NACHNAME", "Fuchs ",{("10|-1"),("15|2")}]
Die AttribIndex-Instanz hat, verglichen mit der structIndex-Instanz, andere Bedingungen,
die für "Fuchs" herrschen. "Fuchs" ist hier ein Attributwert vom Attribut NACHNAME und
gehört zu einem Element vom Typ NAME. Ein Beispiel für eine DTD mit der zugehörigen
SuperDTD-Instanz ist im Anhang A beigefügt.

Seite 27t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

4.6.3 Aufrufen der Funktionen
Die Funktions-Einbindung kann Beispielsweise folgendermaßen geschehen:

execute function hasAttrValueRegex("4|0","TABLES","N?N*");
In diesem Beispiel wird die DataBlade-Funktion hasAttrValueRegex aufgerufen und das

Ergebnis wird in die vorher ausgewählte Ausgabe übergeben. Die Eingabe-Parameter sind alle
vom Typ char(128). Als Rückgabe bekommt man den int-Wert 1, falls das Attribut TABLES
im Element mit der Position 4|0 den regulären Ausdruck N?N* enthält, sonst 0.

select getDocNamebyOid(doc)
from FlatElemTable
where isInside(own_id,"Michael Fuchs")
Dieses SQL-Statement bindet eine DataBlade-Funktion in die 'where-clause' und eine

DataBlade-Funktion in die 'select-clause' ein. Berechnet werden alle Dokument-Namen, die in
irgendeinem flachen Dokument-Element "Michael Fuchs" beinhalten. own_id und doc sind
Felder aus der FlatElemTable.

Seite 28t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

5 IUS- Schnittstellen-Funktionen
Das Kapitel fünf beschäftigt sich mit den Funktionen, die als Schnittstelle für das
objektrelationale Datenbanksystem fungieren. Die Auflistung ist in drei Teile untergliedert. Der
erste Teil (5.1) befaßt sich mit den Funktionen, die zum SP gehören. Sie sind in der Sprache
C++ verfaßt und rufen im wesentlichen ESQL/C Funktionen auf. Diese ESQL/C-Funktionen
werden im zweiten Teil (5.2) aufgelistet. Im dritten Teil (5.3) gibt es eine Darstellung aller
Funktionen, die in API/C implementiert und teilweise als DataBlade-Funktionen in die
Datenbank integriert wurden.
5.1

IUS-SP Schnittstellen-Funktionen : SGML-Parser-Modul
Dieses Unterkapitel listet alle Funktionen auf, die in der C++-Datei ModFuncs.cxx

implementiert sind. Diese Funktionen werden direkt während des Parsens vom SP aufgerufen,
um DTD-konforme Dokument-Komponenten, direkt in die Datenbank einzufügen oder
entsprechende Vorbereitungen dafür zu treffen. Die Funktionen selbst rufen dann wieder
ESQL/C-Funktionen auf, die im darauffolgenden Unterkapitel beschrieben werden. Diese
externen Funktionsaufrufe werden in der Funktionsbeschreibung mit "" und kursiv
dargestellt.
5.1.1 SP- Funktionen, die ESQL/C-Funktionen aufrufen (Sprache : C++)
int daiInterInit(char * docName, char * dtdName,
char* isFragment, char* OIDUp, char* OFFUp, char* OIDLeft,
char* OFFLeft,char* OIDRight,char* OFFRight)
Funktion
Herstellen der Verbindung zur Datenbank  make_connection, ein
Dokument-Datenbankobjekt mit dem Namen docName erstellen und die
SuperDTD-Instanz von der DTD mit dem Namen dtdName auslesen und
Index Abfragestrings erstellen  create_doc.

Seite 29t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

Rückgabewert
Beispiel

IsFragment, OIDUp, OFFp, OIDLeft, OFFLeft, OIDRight, OFFRight
werden zum derzeitigen Implementierungsstand nicht genutzt.
0: Dokument-Objekt erfolgreich angelegt
-1: Fehler ist aufgetreten
daiInterInit("hamlet.sgm","PLAY",NULL,...,NULL,NULL)

void daiInterClose()
Funktion
Aufrufen der zum Schließen der Verbindung zur Datenbank
 close_connection
Rückgabewert Keiner
void daiInterStartTag(char * elemName)
Funktion
Das Dokument-Element mit dem Namen elemName wurde mit dem Starttag
geöffnet. Dabei wird entschieden, ob dieses Dokument-Element in ein flaches
oder strukturiertes Datenbankobjekt gespeichert wird. Soll elemName
strukturiert gespeichert werden, wird es mit  createStructElem angelegt
und mit  subInsertElem in die logische Datenbankstruktur eingefügt.
(Spezialfall: Die Dokument-Wurzel wird mit  insertRoot eingefügt). Soll
das Element elemName flach gespeichert werden, wird es an den flachen Teil
angefügt. (Sonderfall : Das Dokument-Element ist das erste Element im
flachen Teil  ein neuer flacher String wird angelegt )
Rückgabewert Keiner
Beispiel
daiInterStartTag("ACT")
void daiInterEndTag(char *elemName)
Funktion
Das 'Endtag' des Dokument-Elementes mit dem Namen elemName ist
erreicht. Wenn es sich um ein strukturiertes Element handelt, wird es vom
internen Elementstack genommen. Wenn zu diesem strukturierten Element
ein flaches Vorgänger-Element existiert, wird der gesamte flache Teil
gespeichert  createStructElem + subInsertElem. Handelt es sich aber bei
dem Element elemName um ein flaches Element, wird dieses an den flachen
Teil angehängt. Dabei wird der strukturierte Index aufgebaut
 shouldStrPCDATAIndexed + insertInStrPCDATAIndex
Rückgabewert Keiner
Beispiel
daiInterEndTag("ACT")
void daiInterBeginTagClose()
Funktion
Eine Spezialbehandlung für 'Starttags' mit fehlendem 'Endtag'. Das 'Endtag'
wird zugefügt. Dies entspricht dem Prinzip des Vorrausparsens.
Rückgabewert Keiner
void daiInterAttr(char * attrName, char * attrVal, char * attrType)
Funktion
Das Attribut mit dem Namen attrName und dem Wert attrVal wird im
strukturierten Falle als Datenbankobjekt angelegt  insertStructAttribs oder
im flachen Fall an den Starttag-Namen angefügt. Dabei wird der Atribut-

Seite 30t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

Rückgabewert
Beispiel

Index aufgebaut  insertInAttribIndex. attrType wird zum momentanen
Zeitpunkt nicht berücksichtigt.
Keiner
daiInterAttr("NAME","Fuchs",NULL)

void daiInterPcdataStr(char * str)
Funktion
Der PCDATA-Teil mit dem Text-Pointer
str
wird als eigenes
Datenbankobjekt angelegt  createStructElem (statt dem Element-Namen,
wird „flat“ als Parameter übergeben) und gespeichert  subInsert, oder dem
flachen Teil zugefügt.
Dabei wird der PCDATA-Index aufgebaut -> insertInPCDATAIndex.
Rückgabewert Keiner
Beispiel
daiInterPcdataStr("Dies ist der Inh. eines PCDATA-Elements")
void getConfig(char *Filename)
Funktion
das Config-File mit dem Namen Filename, das alle Element-Namen enthält,
dessen Elemente strukturiert gespeichert werden sollen, wird ausgelesen und
von den Namen wird eine Tabelle im Hauptspeicher für isFlat erstellt.
Rückgabewert Keiner
Beispiel
getConfig("/home/fuchs/samples/config_for_PLAY")
int isFlat(char *elemName)
Funktion
Aus der im Hauptspeicher befindlichen Tabelle der strukturierten Elemente
wird ermittelt, ob das Element mit dem Namen elemName flach oder
strukturiert in die Datenbank gespeichert werden soll.
Rückgabewert 0 : elemName ist strukturiert (in der Tabelle enthalten)
1 : elemName ist flach
Beispiel
isFlat("SCENE")
5.2

IUS-SP Schnittstelle als ESQL/C-Modul
Im folgenden Unterkapitel werden die Funktionen beschrieben, die in ESQL/C-Datei

functions.ec implementiert sind. Diese Funktionen bilden die eigentliche Schnittstelle zwischen
SP und IUS. Es wurde dabei eine Unterteilung in Funktionskategorien vorgenommen. Im
Einzelnen geht es um Funktionen, die sich mit der Client-Server-Verbindung befassen, die zum
Generieren der Datenbank sowie der Indizes benutzt werden. Das Schnittstellenmodul benötigt
natürlich auch einige Abfragefunktionen.
5.2.1 Funktionen zum Aufbauen einer Client-Verbindung
int make_connection(char* conn_name_p)
Funktion
Errichten einer Verbindung zur Datenbank conn_name_p.
Rückgabewert 1: Verbindung wurde erfolgreich aufgebaut
0: Fehler ist aufgetreten
Beispiel
make_connection("sgml_db@athen")

Seite 31t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
int close_connection()
Funktion
Schließt die aktuelle Verbindung zur Datenbank.
Rückgabewert Keiner
5.2.2 Funktionen zum Generieren der Datenbank
documentRef createDoc(char* p_name, char* p_DTDname)
Funktion
Erstellt ein Dokument-Objekt mit dem Namen p_name und eine DTDReferenz zu der DTD mit dem Namen p_DTDname, liest die zu dieser DTD
gehörende SuperDTD-Instanz aus und erstellt einen String zur Abfrage,
welches Element für einen Index in Frage kommt
(AttribIndex, PCDATAIndex oder StrPCDATAIndex)
Rückgabewert oid: Dokument-Objekt
-1: Fehler ist aufgetreten
Beispiel
createDoc("hamlet.sgm","PLAY")
int insertRoot(documentRef p_doc, docElemRef p_elem)
Funktion
Erstellt ein Element-Datenbank-Objekt mit der oid p_elem und macht beim
Dokument-Datenbank-Objekt mit der oid p_doc, p_elem zum WurzelElement
Rückgabewert 1: Wurzel-Element wurde erfolgreich angelegt
0: Fehler ist aufgetreten
Beispiel
createDoc(2,4)
docElemRef createStructElem(char* p_text, documentRef p_doc)
Funktion
Falls p_text  "flat" wird ein Element-Datenbank-Objekt in der
nonFlatElemTable mit dem Namen p_text erstellt. Falls p_text = "flat" wird
ein Element-Datenbank-Objekt in der flatElemTable. Das Datenbank-Objekt
bekommt eine Referenz auf das Dokument-Objekt mit der oid p_doc
Rückgabewert oid: Dokument-Objekt
-1: Fehler ist aufgetreten
Beispiel
createStructElem("ACT",4)
int setFlatContent(docElemRef p_elem, char* p_text)
Funktion
In das flache Datenbank-Objekt mit der oid p_elem wird der Text p_text
gespeichert.
Rückgabewert 1: erfolgreiches Update des flachen Datenbank-Objekts
-1: Fehler ist aufgetreten
Beispiel
setFlatContent(5,"Dies ist ein Inh eines PCDATA-Elems")
int setStructAttrVal(docElemRef p_elem, char* p_name, char* p_value)
Funktion
Fügt ein strukturiertes Attribut-Objekt in die Datenbank ein, mit der Referenz
p_elem auf das strukturierte Dokument-Element, dem Attribut-Name
p_name und dem Attribut-Wert p_value.
Rückgabewert oid: Attribut- Datenbank- Objekt
-1: Fehler ist aufgetreten
Beispiel
setStructAttrVal(4,"NAME","Fuchs")

Seite 32t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
int subInsert(docElemRef p_son, docElemRef p_parent)
Funktion
Fügt ein strukturiertes Dokument-Element p_son in die Datenbank ein.
Dabei wird es , vom logischen her gesehen, als ganz rechter Sohn von
p_parent eingefügt
Rückgabewert oid: Attribut-Datenbank-Objekt
-1: Fehler ist aufgetreten
Beispiel
setStructAttrVal(6,4)
5.2.3 Funktionen zum Generieren der Indizes
void getSDTDattribs(char *DTD_param)
Funktion
Erstellt die drei Index-Strings von der SuperDTD-Instanz, die von der DTD
mit dem Namen DTD_param abstammt. Diese Index-Strings sind für die
Abfragefunktionen :
shouldStructIndexed, shouldAttrIndexed, shouldPCDATAIndexed.
Rückgabewert Keiner
Beispiel
getSDTDattribs("PLAY")
int shouldStructIndexed(char *exName,char *inName)
Funktion
Ermittelt, ob für die Strukturbeziehung der zwei Elementtypen mit dem
Namen exName und inName ein Index angelegt werden soll. Dabei wird der
erstellte String von getSDTDattribs benutzt.
Rückgabewert 1: Index soll angelegt werden
0: Index soll nicht angelegt werden.
Beispiel
shouldStructIndexed("ACT","ACTTITLE")
int shouldAttrIndexed(char *etName,char *p_name)
Funktion
Ermittelt, ob für das Attribut mit dem Namen p_name vom Elementtyp mit
dem Namen etName ein Index angelegt werden soll. Dabei wird der erstellte
String von getSDTDattribs benutzt.
Rückgabewert 1: Index soll angelegt werden
0: Index soll nicht angelegt werden.
Beispiel
shouldAttrIndexed("NAME","Nachname")
int shouldPCDATAIndexed(char *etName)
Funktion
Ermittelt, ob für den Elementtyp mit dem Namen etName ein Index angelegt
werden soll. Dabei wird der erstellte String von getSDTDattribs benutzt.
Rückgabewert 1: Index soll angelegt werden
0: Index soll nicht angelegt werden.
Beispiel
shouldPCDATAIndexed("ACTTITLE")
int createAttrIndex(docElemRef etype, char* p_name)
Funktion
Legt für das Attribut mit dem Namen p_name vom Elementtyp mit der oid
etype einen Index an, falls dieser nicht existiert.
Rückgabewert 1: Index existiert
0: Index existierte nicht und wurde erstellt
Beispiel
createAttrIndex(getElem("NAME"),"Nachname")

Seite 33t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
int createStructIndex(docElemRef exEtype, docElemRef inEtype)
Funktion
Legt für die Struktur der Elementtypen mit der externen Element-oid
exEtype und der internen Element-oid inEtype einen Index an, falls dieser
nicht existiert.
Rückgabewert 1: Index existiert
0: Index existierte nicht und wurde erstellt
Beispiel
createStructIndex(getElem("ACT"),getElem("ACTTITLE"))
int createPCDATAIndex(docElemRef etype)
Funktion
Legt für den Elementtyp mit der oid etype einen Index an, falls dieser nicht
existiert.
Rückgabewert 1: Index existiert
0: Index existierte nicht und wurde erstellt
Beispiel
createPCDATAIndex(getElem("ACTTITLE"))
int InsertInAttribIndex(docElemRef etype, char* p_name, char* p_value,
docElemRef p_elem)
Funktion
Legt für das Attribut mit dem Namen p_name von dem Element-Typ mit der
Elementtyp-oid etype den Indexeintrag mit dem Attributwert p_value und
der Dokument-Element-oid p_elem an.
Rückgabewert 1: erfolgreich angelegt
-1: Fehler ist aufgetreten
Beispiel
InsertInAttribIndex(getElem("NAME"),"Nachname","Fuchs",8))
int InsertInStrPCDATAIndex(docElemRef exEtype, docElemRef exEtype,
char* p_value, docElemRef p_elem)
Funktion
Legt für die Elementtyp Beziehung mit der externen Elementtyp-oid exEtype
und die interne Elementtyp-oid inEtype den Indexeintrag mit dem Text
p_value und der Dokument-Element-oid p_elem an.
Rückgabewert 1: erfolgreich angelegt
-1: Fehler ist aufgetreten
Beispiel
InsertInStrPCDATAIndex(getElem("ACT"),getElem("ACTTITLE"),
"ACT IV",9)

int InsertInPCDATAIndex(docElemRef etype, char* p_value,docElemRef p_elem)
Funktion
Legt für den Elementtyp mit der oid etype den Indexeintrag mit dem Text
p_value und der Dokument-Element-oid p_elem an.
Rückgabewert 1: Erfolgreich angelegt
0: Fehler ist aufgetreten
Beispiel
InsertInPCDATAIndex(getElem("ACTTITLE"),"ACT IV",9)

Seite 34t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

5.2.4 Informations- und Navigations-Hilfsfunktionen
int getElem(char *p_name)
Funktion
Liefert die oid des Elementtyps mit dem Namen p_name
Rückgabewert oid: Elementtyp
-1: nicht existent
Beispiel
getElem("ACT")
int getETName(docElemRef etype)
Funktion
Liefert die Namen des Elementtypes mit der oid etype
Rückgabewert Name: Elementtyp
"":
nicht existent
Beispiel
getETName(5)
docElemRef physGetUp(docElemRef p_elem) /* Version ESQL */
Funktion
Liefert die oid des Vaters vom Dokument-Element mit der oid p_elem
Rückgabewert oid: Vater
-1: nicht existent
Beispiel
physGetUp(8)

Seite 35t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

5.3

SGML-API-Funktionen (API=Aplication Program Interface)
Das letzte Unterkapitel beschreibt die Funktionen, die auf der Server-Seite zur

Behandlung der Daten in IUS zuständig sind. Bei diesen Funktionen handelt es sich, sowohl
um erweiterte SQL-Funktionen, die mit 'execute function', direkt in SQL aufgerufen werden,
als auch um Funktionen, die nur als Hilfsfunktionen dienen und in der Library sgml_server.so
zur Verfügung stehen. Zuerst werden die speziellen Abfrage-Funktionen genannt. Anschließend
folgen zwei Augabefunktionen, gefolgt von Navigations- und Informations-Funktionen für
Dokumente und deren Elemente. Die letzten Auflistungen zeigen dann Funktionen, die speziell
für strukturierte bzw. flache Elemente implementiert wurden. Alle Parameter vom Datentyp
mi_lvarchar* werden in den Beispielen zur Vereinfachung als einfacher "String" dargestellt.
Um eine Library-Funktion mit einem solchen Datentyp zu behandeln, müßte man die Funktion
mi_lvarchar_to_string( ) bzw. mi_string_to_lvarchar( ) zum Konvertieren verwenden. Die
genauen Definitionen befinden sich im Handbuch [INF97].
5.3.1 Spezielle Abfrage-Funktionen
Im Folgenden werden die Funktionen für spezielle Queries und Werte-Bestimmung
aufgelistet.
mi_lvarchar *getAttrValue(position elem_pos, mi_lvarchar *pattName)
Funktion
Ermittelt den Attributwert von dem Element mit der Position elem_pos und
dem Attribut mit dem Namen pattName
Rückgabewert Attributwert
"" nicht existent
Beispiel
execute function getAttrValue("10|100","Nachname")
Bemerkung

Die Position in dem obigen Beispiel wird als String übergeben und entspricht
dem Paar von zwei Integer-Werten, 10 und 100. Die Transformation von
String zu 'Integer|Integer' wird jeweils in der Funktion übernommen. Der
erste Integer-Wert entspricht der oid und der zweite entspricht dem Offset in
dem flachen Element. Wenn das Element nicht flach ist, ist der Offset : -1.

mi_integer

hasAttrValue(position elem_pos,mi_lvarchar *pattName,
mi_lvarchar *pattValue)
Funktion
Ermittelt von dem Element mit der Position elem_pos und dem Attribut
pattName, ob der betreffende Attributwert gleich pattValue ist.
Rückgabewert 1: Abfrage ist wahr
0: sonst
Beispiel
execute function hasAttrValue("10|100","Nachname","Fuchs")

Seite 36t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
mi_integer

hasAttrValueRegex(position elem_pos,mi_lvarchar *pattName,
mi_lvarchar *pattRegEx)
Funktion
Ermittelt von dem Element mit der Position elem_pos und dem Attribut
pattName, ob pattRegEx ein regulärer Ausdruck von dem betreffenden
Attributwert ist.
Rückgabewert 1: Abfrage ist wahr
0: sonst
Beispiel
execute function hasAttrValueRegex("10|100","Nachname","?u*")
mi_integer
Funktion

hasTextualContent(position elem_pos,mi_lvarchar *text)
Ermittelt von dem Element mit der Position elem_pos, ob dessen Inhalt text
entspricht.
Rückgabewert 1: Abfrage ist wahr
0: sonst
Beispiel
execute function hasTextualContent("10|200","ein Bsp-Inhalt")
mi_integer
Funktion

hasTextContRegex(position elem_pos,mi_lvarchar *RegEx)
Ermittelt von dem Element mit der Position elem_pos, ob RegEx ein
regulärer Ausdruck von dessen Inhalt ist.
Rückgabewert 1: Abfrage ist wahr
0: sonst
Beispiel
execute function hasTextualContentRegex("10|200","^ein?B*")
mi_lvarchar *getETName(position elem_pos)
Funktion
Ermittelt den Namen des Elements mit der Position elem_pos
Rückgabewert Element-Name
"" : nicht exitistent
Beispiel
execute function getETName("10|200")
mi_intege
Funktion

isContainedIn(position son, position father)
Ermittelt, ob das Element mit der Position son in dem Element mit der
Position father, enthalten ist.
Rückgabewert 1: Abfrage ist wahr
0: sonst
Beispiel
execute function isContainedIn("10|200","9|-1")
In den folgenden Abfrage-Funktionen ist der Rückgabewert unter Vorbehalt ausgewählt
worden. Zu dem Implementierungszeitpunkt dieser Arbeit, war der Datentyp clob der
geeignetste. In Zukunft könnte man sich auch andere Datentypen zur Rückgabe vorstellen. Als
Beispiel gäbe es die Möglichkeit, Datentypen wie collection oder file als Rückgabewert zu
nutzen.
MI_LO_HANDLE *getContaining(position elem_pos)
Funktion
Ermittelt alle Positionen der Elemente vom Dokument, in denen das Element
mit Position elem_pos enthalten ist.
Rückgabewert Text:
alle Positionen als Zeilen
NULL: Fehler ist aufgetreten
Beispiel
execute function isContainedIn("10|200")

Seite 37t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
MI_LO_HANDLE *getAll(position elem_pos,mi_lvarchar *pname)
Funktion
Ermittelt alle Positionen der Elemente mit dem Namen pname in preorder im
betreffenden Dokument von der Position elem_pos an.
Rückgabewert Text:
alle Positionen als Zeilen
NULL: Fehler ist aufgetreten
Beispiel
execute function getAll("8|-1","SCENE")
MI_LO_HANDLE *getObjs(mi_integer pelem)
Funktion
Ermittelt alle Positionen der Elemente vom Elementtyp mit der oid pelem.
Rückgabewert Text:
alle Positionen als Zeilen
NULL: Fehler ist aufgetreten
Beispiel
execute function getObjs(getETId("SCENE"))
MI_LO_HANDLE
Funktion
Rückgabewert
Beispiel

*getObjsByAttr(mi_integer pelem, mi_lvarchar *pattName,
mi_lvarchar *pattVal)
Ermittelt alle Positionen der Elemente vom Elementtyp mit der oid pelem,
bei denen das Attribut pattName den Attributwert pattVal hat.
Text:
alle Positionen als Zeilen
NULL: Fehler ist aufgetreten
execute function
getObjsByAttr(getETId("NAME"),"Nachname","Chen")

MI_LO_HANDLE
Funktion
Rückgabewert
Beispiel

*getObjsByAttrWithRegEx(mi_integer *elem_name,
mi_lvarchar *pattName, mi_lvarchar *pattRegEx)
Ermittelt alle Positionen der Elemente vom Elementtyp mit der oid pelem,
bei denen das Attribut pattName, pattRegEx ein regulärer Ausdruck für den
Attributwert ist.
Text:
alle Positionen als Zeilen
NULL: Fehler ist aufgetreten
execute function
getObjsByAttrWithRegEx(getETId("NAME"),"Nachname","?uch*")

MI_LO_HANDLE *getContentByPosition(mi_integer etype,mi_lvarchar *content)
Funktion
Ermittelt alle Positionen der Elemente vom Typ etype mit dem Inhalt
content.
Rückgabewert Text:
alle Positionen als Zeilen (nur vom exitierenden Index)
NULL: Fehler ist aufgetreten
Bemerkung
Die Funktion wurde zum Testen des PCDATA-Index implementiert, enthält
aber zur Zeit keine vollständige Abfrage. Ist der entsprechende Index nicht
vorhanden, wird ein Fehler gemeldet.
MI_LO_HANDLE
Funktion
Rückgabewert
Bemerkung

*getElemsByPosition(mi_integer exEtype,
mi_integer inEtype, mi_lvarchar *content)
Ermittelt alle Positionen der Elemente vom Typ inEtype mit dem Inhalt
content, welche in Elementen vom Elementtyp exEtype enthalten sind.
Text:
alle Positionen als Zeilen (nur vom exitierenden Index)
NULL: Fehler ist aufgetreten
Die Funktion wurde zum Testen des strukturierten Index implementiert,
enthält aber zur Zeit keine vollständige Abfrage. Ist der entsprechende Index
nicht vorhanden, wird ein Fehler gemeldet.

Seite 38t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
5.3.2 Ausgabe-Funktionen
MI_LO_HANDLE *getElemText(position elem_pos)
Funktion
Ermittelt den Inhalt des Elementes (mit Markup) mit der Position elem_pos.
Rückgabewert Text:
Element-Inhalt mit Markup
NULL: Fehler ist aufgetreten
Beispiel
execute function getElemText("10|200")
mi_lvarchar *getElemScreen(position elem_pos,mi_char **akt_pos,mi_char **stack)
Funktion
Ermittelt den Inhalt des Elementes (mit Markup) mit der Position elem_pos.
Der Inhalt wird dabei auf eine voreingestellte Bildschirmgröße begrenzt. Die
Position, bei der die maximale Zeilenanzahl erreicht worden ist, wird mit dem
Zeiger akt_pos eingelesen und auch wieder zurückgeliefert. Dazu wird der
Element-Stack mit dem Zeiger stack ausgelesen und wieder zurückgeliefert.
Diese Funktion dient als Hilfsroutine zum bildschirmweisen Ausgeben eines
großen Elementes. Die Zeiger akt_pos und stack müssen dabei
zwischengespeichert und immer wieder übergeben werden.
Rückgabewert Text:
Element-Inhalt mit Markup (begrenzt auf Bildschirmgröße)
NULL: Fehler ist aufgetreten
Beispiel
getElemScreen("10|200",&aktPos,&aktStack)
5.3.3 Funktionen zur Navigation im Dokument
position
Funktion

getRoot(position p_elem)
Ermittelt die Position der Dokument-Wurzel von dem Dokument-Element
mit der Position p_elem.
Rückgabewert Position: Wurzel
-1 :
nicht existent
Beispiel
execute function getRoot("10|200")
position
Funktion

getRootbyDocName(mi_lvarchar *DocName)
Ermittelt die Position der Dokument-Wurzel von dem Dokument mit dem
Namen DocName.
Rückgabewert Position: Wurzel
-1 :
nicht existent
Beispiel
execute function getRootbyDocName("hamlet.sgm")
position
Funktion

up(position elem_pos)
Ermittelt die Position des Vater-Elementes von dem Dokument-Element mit
der Position p_elem.
Rückgabewert Position: Vater-Element
-1:
nicht existent
Beispiel
execute function up("10|200")
position
Funktion

down(position elem_pos)
Ermittelt die Position des ersten Sohnes von dem Dokument-Element mit der
Position p_elem.
Rückgabewert Position: erster Sohn
-1:
nicht existent
Beispiel
execute function down("10|200")

Seite 39t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
position
Funktion

succ(position elem_pos)
Ermittelt die Position des Nachfolger-Elementes von dem DokumentElement mit der Position p_elem.
Rückgabewert Position: Nachfolger-Element
-1:
nicht existent
Beispiel
execute function succ("10|200")
position
Funktion

pred(position elem_pos)
Ermittelt die Position des Vorgänger-Elementes von dem Dokument-Element
mit der Position p_elem.
Rückgabewert Position: Vorgänger-Element
-1:
nicht existent
Beispiel
execute function pred("10|200")
5.3.4 Info-Funktionen über Dokumente, DTDs und Elemenenttypen
mi_integer
Funktion

getETStuff(mi_integer p_elem,mi_char **PName,mi_integer *PDTDid)
Ermittelt den Namen und die DTD-oid des Elementtyps mit der oid p_elem
und gibt sie im Pointer Pname bzw. PDTDid zurück.
Rückgabewert 0: Ermittlung ergolgreich
-1: Fehler ist aufgetreten
Beispiel
getETStuff(5,&resname,&resdtd)
mi_integer
Funktion

getETypeID(mi_lvarchar *PName,mi_integer PDTDid)
Ermittelt die oid des Elementtypes mit dem Namen Pname und der DTD-oid
PDTDid
Rückgabewert oid: Elementtype
-1: nicht existent
Beispiel
getETypeID("SCENE",2)
mi_lvarchar *getETypeName(mi_integer p_elem)
Funktion
Ermittelt den Namen des Elementtyps mit der oid p_elem.
Rückgabewert Name: Elementtyp
"":
nicht existent
Beispiel
getETypeName(5)
mi_integer
Funktion

getDoc(position p_elem)
Ermittelt die oid des Dokuments von dem Dokument-Element mit der
Position p_elem.
Rückgabewert oid: Dokument
"": nicht existent
Beispiel
execute function getDoc("10|200")

Seite 40t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
mi_integer
Funktion

getDTD(position p_elem)
Ermittelt die oid der DTD von dem Dokument-Element mit der Position
p_elem.
Rückgabewert oid: DTD
"": nicht existent
Beispiel
execute function getDTD("10|200")
mi_lvarchar *getAllContaining(mi_lvarchar *Doctype)
Funktion
Ermittelt für jeden Elementtyp vom Dokumenttyp Doctype die Menge aller
indirekt oder direkt enthaltenen Elementtypen.
Rückgabewert Elementtypen+Menge aller entahltenen Elementtypen
"": nicht existent
Beispiel
execute function getAllContaining("PLAY")
mi_lvarchar *getDTDFragment(mi_integer etype)
Funktion
Ermittelt die DTD, die benötigt wird um ein einzelnes Element vom
Elementtyp mit der oid etype zu parsen.
Rückgabewert DTDFragment
"":
nicht existent
Beispiel
execute function getDoc(getETypeID("SCENE",2))
5.3.5 Funktionen speziell für strukturierte Elemente (Datenbank-Objekte)
docElemRef physGetUp(docElemRef p_elem)
Funktion
Ermittelt den Vater des strukturierten Elements mit der oid p_elem.
Rückgabewert oid: Vater
-1: nicht existent
Beispiel
execute function physGetUp(11)
docElemRef physGetDown(docElemRef p_elem)
Funktion
Ermittelt den 1. Sohn des strukturierten Elements mit der oid p_elem.
Rückgabewert oid: ganz linker Sohn
-1: nicht existent
Beispiel
execute function physGetUp(11)
docElemRef physPred(docElemRef p_elem)
Funktion
Ermittelt den Vorgänger des strukturierten Elements mit der oid p_elem.
Rückgabewert oid: Vorgänger
-1: nicht existent
Beispiel
execute function physPred(11)
docElemRef physSucc(docElemRef p_elem)
Funktion
Ermittelt den Nachfolger des Datenbank-Dokument-Elementes mit der oid
p_elem.
Rückgabewert oid: Vorgänger
-1: nicht existent
Beispiel
execute function physSucc(11)
mi_lvarchar *physName(docElemRef p_elem)
Funktion
Ermittelt den Name des strukturierten Elements mit der oid p_elem.

Seite 41t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Rückgabewert

Name: Datenbank-Dokument-Element
"":
nicht existent

Beispiel

execute function physName(11)

mi_lvarchar *getPhysAttribs(docElemRef p_elem)
Funktion
Ermittelt die Attribute als String des strukturierten Elements mit der oid
p_elem.
Rückgabewert Attribut-String
"": nicht existent
Beispiel
execute function getPhysAttribs(11)
docElemRef getNextObj(docElemRef p_elem,mi_char *elem_name )
Funktion
Ermittelt, im Dokument, das nächste strukturierte Dokument-Element vom
Element mit der oid p_elem, das den Namen elem_name trägt.
Rückgabewert oid: nächstes, strukturiertes Element
-1: nicht existent
Beispiel
execute function getNextObj(11,"ACT")
5.3.6 Funktionen speziell für flache Datenbank-Objekte
mi_integer is_flat(docElemRef p_elem)
Funktion
Ermittelt , ob ein Dokument-Element mit der oid p_elem flach ist oder nicht
Rückgabewert 0: Dokument-Element ist nicht flach
1: Dokument-Element ist flach
Beispiel
execute function is_flat(11)
mi_integer *getFlatText(docElemRef elem_pos, mi_char **PPuffer)
Funktion
Holt den Text aus dem flachen Dokument-Element mit der oid elem_pos und
legt das Ergebnis im String-Zeiger *PPuffer ab
Rückgabewert Länge: Elementtext
-1:
nicht existent
Beispiel
getFlatText(11)
docElemRef getNextFlatText(docElemRef p_elem,mi_lvarchar *pname,
mi_lvarchar **pflat,mi_integer PDTDid)
Funktion
Holt den Text und die oid des nächsten flachen Dokument-Element von dem
flachen Objekt mit der oid p_elem von der DTD mit der oid PDTDid, indem
der Markup mit dem Namen p_name vorkommt. Die Puffer-Adresse des
Textes wird dabei mit der Adresse *pflat zurückgeliefert.
Rückgabewert oid: nächstes flaches Element
-1: nicht existent
Beispiel
getNextFlatText(10,"SCENE",&restext,getDTD("10|0"))

Seite 42t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
5.3.7 Hilfs-Funktionen zur Navigation, speziell in flachen Textteilen
mi_integer findBackward(mi_char *searchStr,mi_integer ofs,mi_char *whatStr)
Funktion
Sucht whatStr in searchStr rückwärts von der Zeichenposition ofs an.
Rückgabewert Zeichenposition des gesuchten Strings
-1: Suche erfolglos
Beispiel
findBackward("Zu Suchender Text",5,"Such")
mi_integer findForward(mi_char *searchStr,mi_integer ofs,mi_char *whatStr)
Funktion
Sucht whatStr in searchStr vorwärts von der Zeichenposition ofs an.
Rückgabewert Zeichenposition des gesuchten Strings
-1: Suche erfolglos
Beispiel
findForward("Zu Suchender Text",5,"Such")
mi_integer

findCorrespBackward(mi_char *FlatElem,mi_integer offset,
mi_char *ElementTypeName)
Funktion
Sucht rückwärts in FlatElem nach dem Starttag mit dem Namen
ElementTypeName, das zu dem Endtag mit dem Namen
ElementTypeName an der Zeichenposition offset gehört.
Rückgabewert offset: gefundenes Starttag
-1
Fehler ist aufgetreten
Beispiel
findCorrespBackward("%~<A>Text%~</A>",9,"A")
mi_integer

findCorrespForward(mi_char *FlatElem,mi_integer offset,
mi_char *ElementTypeName)
Funktion
Sucht vorwärts in FlatElem nach dem Endtag mit dem Namen
ElementTypeName, das zu dem Starttag mit dem Namen
ElementTypeName an der Zeichenposition offset gehört.
Rückgabewert offset: gefundenes Endtag
-1
Fehler ist aufgetreten
Beispiel
findCorrespForward("%~<A>Text%~</A>",9,"A")
mi_integer

getElementTypeName(mi_char *searchStr,mi_integer ofs,
mi_char **ElementTypeName)
Funktion
Ermittelt in searchStr an der Stelle ofs den Namen und ob es sich um ein
Starttag, Endtag oder kein tag handelt. Der Zeiger auf den resultierenden
Namen wird mit dem Zeiger *ElementTypeName zurückgeliefert
Rückgabewert
1: Name ist ein Starttag
0: Name ist kein tag
-1: Name ist ein Endtag
Beispiel
getElementTypeName("%~<NAME>Text",0,"Such")

Seite 43t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
mi_integer
Funktion

testElemPos(mi_char *searchStr,mi_integer ofs)
Ermittelt in searchStr an der Stelle ofs ob es sich um ein Starttag, Endtag
oder kein tag handelt.
Rückgabewert
1 Name ist ein Starttag
0 Name ist kein tag
-1 Name ist ein Endtag
Beispiel
testElemPos("...%~</NAME>Text...",15)
mi_integer
Funktion

testElemName(mi_char *searchStr,mi_integer ofs,mi_char *what)
Ermittelt in searchStr an der Stelle ofs ob es sich bei what um ein Starttag,
Endtag oder kein tag handelt.
Rückgabewert
1: Name ist ein Starttag
0: Name ist kein tag
-1: Name ist ein Endtag
Beispiel
testElemName("%~<NAME>Text",0,"NAME")
5.3.8 Hilfs-Funktionen zur Abfrage, speziell in flachen Textteilen
mi_integer
Funktion

match(mi_char *pattern, mi_char *search)
Ermittelt, ob der reguläre Ausdruck pattern in dem String search
vorkommt.
Rückgabewert 0: pattern ist kein regulärer Ausdruck in search
1: pattern ist regulärer Ausdruck in search
Beispiel
match("Dies ist ein Beispiel-String","Bei*l?St?i*")
mi_integer

getAllinFlat(mi_char *pflat,position elem_pos,mi_char *pname,
mi_char **PPuffer);
Funktion
Ermittelt, alle Positionen von Elementen mit dem Namen pname aus pflat
von der Position elem_pos an in preorder und fügt sie zeilenweise dem
Puffer mit dem Stringzeiger *PPuffer hinzu.
Rückgabewert Anzahl:
ermittelte Positionen
Beispiel
getAllinFlat("%~<NAME>Text..%~</NAME>","10|0","NAME",&resStr)
mi_integer

getObjsByAttrinFlat(mi_char *pflat, position elem_pos,
mi_char *pname,mi_char *AttName,mi_char *AttVal, mi_char **PPuffer);
Funktion
Ermittelt, alle Positionen von Elementen mit dem Namen pname und dem
Attributnamen AttName und dem Attributwert AttVal aus pflat in preorder
und fügt die Positionen zeilenweise dem Puffer mit dem Stringzeiger
*PPuffer hinzu.
Rückgabewert Anzahl:
ermittelte Positionen
Beispiel
getObjsByAttrinFlat(flat,"10|0","NAME","VORNAME",
"Michael",&resString)

Seite 44t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
mi_integer

getObjsByAttrWithRegExinFlat(mi_char *pflat,position elem_pos,
mi_char *text,mi_char *AttName, mi_char *attRegEx,mi_char **PPuffer)
Funktion
Ermittelt, alle Positionen von Elementen mit dem Namen pname und dem
Attributnamen AttName, bei denen attRegEx ein regulärer Ausdruck des
Attributwerts ist. Der String pflat wird dabei in preorder durchsucht und
fügt die Positionen zeilenweise dem Puffer mit dem Stringzeiger *PPuffer
hinzu.
Rückgabewert Anzahl:
ermittelte Positionen
Beispiel
getObjsByAttrinFlat(flat,"10|0","NAME","VORNAME",
"Mi??a*",&resString)

mi_integer
Funktion

getElemTextinFlat(mi_char *pflat,position elem_pos,mi_char **PPuffer)
Holt den Inhalt des flachen Elements mit der Position elem_pos mit
kompletten Markup und fügt diesen dem Puffer mit dem Stringzeiger
*PPuffer hinzu.
Rückgabewert 1: falls das Element im flachen Teil nur PCDATA enthielt.
0: sonst
( speziell für getElemText für den Zeilenumbruch)
Beispiel
getElemTextinFlat(flat,"10|40",&resStr)
mi_integer

getElemScreeninFlat(mi_char *pflat,position elem_pos,
position cutpos,mi_char **PPuffer,mi_integer *akt_offset,
mi_integer *akt_enter)
Funktion
Holt den Inhalt des Elements mit der Position elem_pos mit komplettem
Markup. Dabei wird der Inhalt eingeschränkt. Angefangen wird bei der
Position cutpos und zurückgeliefert wird nur eine vordefinierte Anzahl von
Zeilen. Das Ergebnis wird in den Puffer mit dem Stringzeiger *PPuffer
hinzugefügt. Außerdem wird der Offset von der Stopposition sowie die
Anzahl der ausgeführten Zeilenumbrüche in den Zeigern akt_offset und
akt_enter zurückgeliefert.
Rückgabewert 1: falls das Element im flachen Teil nur PCDATA enthielt.
0: sonst
( speziell für getElemScreen für den Zeilenumbruch)
Beispiel
getElemScreeninFlat(flat,"9|-1","10|200",&resStr,&rofs,&rCR)

Seite 45t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

6 Der Algorithmus : getAllContaining
Dieses Kapitel beschreibt Motivation, Beschreibung und Verifikation des Algorithmus
getAllContaining. Mit der Motivation beginnt dieses Kapitel in 6.1 und kommt dann in
Unterkapitel 6.2 zur Definition, sowie in 6.3 zur Beschreibung des Algorithmus. Da Vieles von
der Richtigkeit dieses Algorithmus abhängt, wird in 6.4 ein intuitiver Induktionsbeweis geführt,
um die Korrektheit zu garantieren.
6.1

Probleme mit Inclusions/Exclusions bei der Fragmentierung
Dieses Unterkapitel soll eine Motivation für den Algorithmus getAllContaining geben.

Im wesentlichen wird diese Motivation durch Probleme mit Inclusions und Exclusions
hervorgerufen.
Bei der Konfiguration eines SGML-Dokumenttyps werden alle Namen der
Elementtypen, die als eigenes Datenbankobjekt gespeichert werden sollen (nonFlatElement),
in eine Konfigurations-Datei geschrieben. Alle anderen Elementtypen von diesem Dokumenttyp
werden zusammengefaßt und in einem flachen Text-Block (flatElement) in die Datenbank
eingefügt. Nach Lemma 3+4 in [Bö97], dürfen flache Elementtypen keine strukturierten
Elementtypen enthalten und wenn ein Elementtyp erst mal als flach deklariert worden ist, dann
kann er nicht mehr in einen strukturierten Elementtyp umgewandelt werden.
Eine Inclusion ist ein Elementtyp, der in der Definition eines Elementtyps eine besondere
Rolle spielt. Ein Beispiel ist die Fußnote: +(FN). Wenn eine Elementtyp-Definition diese
Inclusion beinhaltet, dann können alle Elemente, die in diesem Element enthalten sind auch eine
Fußnote (Element vom Typ 'FN') enthalten.
Der folgende Ausschnitt aus einer DTD dient als Beispiel :

Seite 46t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

<!ELEMENT A (C)*

+(FN)>

<!ELEMENT B (C)*>
<!ELEMENT C (D?, E+)>
Der Elementtyp FN ist eine Inclusion in der Definition vom Elementtyp A, daß heißt, FN
darf in jedem Dokument-Element vom Typ A enthalten sein (muß aber nicht). Aus der Sicht
von A gesehen, verhält sich das genauso bei C. Die Fußnote FN darf aber auch in C enthalten
sein, da C der direkte Nachfolger von A ist. Weiterhin darf FN auch in D und E enthalten sein,
denn sie sind indirekte Nachfolger von A. Exclusions werden genauso definiert wie Inclusions,
mit dem Unterschied, daß ein Exclusion-Typ nicht enthalten sein darf und das gilt auch für alle
direkt oder indirekt enthaltenen Elementtypen.
(Genaue Definitionen in [Her94])
Diese Inclusions erschweren nun die Berechnung der flachen Fragmente, weil es nicht so
einfach vorhersagbar ist, welche Elemente in Welchen vorhanden sein dürfen. Der folgende
Algorithmus getAllContaining soll zur Lösung dieses Problems beitragen. Da man von dem
'worst case' ausgehen muß, kann man die Exclusions vernachlässigen, denn sie beeinflussen
nicht das absolute 'enthalten_in'-Modell.
Der Algorithmus baut im wesentlichen einen DTD-Baum auf, berücksichtigt dabei alle
Inclusions und berechnet danach den transitiven Abschluß. Als Ergebnis erhält man, für jeden
Elementtyp die Menge aller direkt oder indirekt enthaltenen Elementtypen. Beim Konfigurieren
muß man also bei jedem Elementtyp, der flach eingefügt werden soll, auch alle Elementtypen
flach einfügen, die in der Ergebnis-Menge enthalten sind.
Wenn in diesem Algorithmus auch noch Exclusions genauso berücksichtigt werden, dann
ist es leicht möglich, eine Fragment-DTD zu erzeugen, um nur einzelne Dokument-Elemente
zu parsen. Das Ergebnis wäre dann nicht 'alle enthaltenen Elementtypen' sondern 'alle zu
berücksichtigenden Elementtypen' als Menge. Man müßte dann nur noch die Element- und
Attribut-Definitionen dieser Elementtypen als eine DTD zusammenfassen. Diese Funktion
wurde implementiert und dessen Beschreibung kann man in Kapitel 5.3.4 finden.

Seite 47t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
6.2

Definitionen für den Algorithmus
Im folgenden Unterkapitel werden einige Definitionen dargestellt, die benötigt werden,

um den Algorithmus besser zu verstehen. Die Definitionen bilden auch die Grundlage für die
Verifikation.
EC[0]
Container von ET mit
id : e0
iS (includedSet)
cS (containedSet)
sS (sonSet)
Tabelle 6.2-3:

EC[1]
Container von ET mit
id : e1
iS (includedSet)
cS (containedSet)
sS (sonSet)

...
...
...
...

EC[M]
container von ET mit
id : eM
iS (includedSet)
cS (containedSet)
sS (sonSet)

Illustration des benutzten Datentyps für den Algorithmus

Vorgaben :
-

alle Set, sind Mengen von Kontainer(-Pointern) (siehe Tabelle 6.2-3)

-

alle sS haben als anfänglichen Inhalt das contentModel des jeweiligen Elementtyps

-

alle iS haben als anfänglichen Inhalt die inclusion Types des jeweiligen Elementtyps

-

alle cS (die eigentliche Ergebnismenge) ist anfänglich leer.

-

nach Abbildung des Container-Arrays auf einen ADT sind die Söhne in sS
und die Wurzel ist EC[0] (erfolgreiches Parsen der DTD zum DTD-Baum vorausgesetzt)

Ein Wort zu Zyklen :
-

um zu vermeiden, daß indirekte Zyklen entstehen, muß man vor dem Bearbeiten eines
Sohnes, diesen mit dem gesamten Stack vergleichen. Nur wenn dieser Sohn nicht auftritt,
darf er behandelt werden !

Direkte

Zyklen : a  b und b  a

Indirekte Zyklen : a  b und b  c und c  d und d  b
versteckte Zyklen : wenn ein direkter oder indirekter Zyklus durch Weiterleiten
der Inclusions ensteht, aber vorher nicht feststellbar ist !

Seite 48t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
6.3

Beschreibung des Algorithmus
Dieses Unterkapitel beschreibt den Algorithmus in allen Einzelheiten. Es handelt sich

hierbei im Groben um drei verschachtelte Schleifen, die jeweils Funktionen aufrufen. Zum
Überprüfen der Terminierungsbedingung werden noch einige Hilfsfunktionen genannt.
6.3.1 Funktionen, die in den Körpern der drei Schleifen aufgerufen werden

In Abbildung 6.3-9werden die elementaren Funktionen beschrieben. Dabei ist in der
linken Spalte die Beschreibung in der Form eines DTD-Baumes skizziert ist, während in der
rechten Spalte der Algorithmus der einzelnen Funktionen in einem Pseudocode beschrieben
wird.

down (before):

down (after):

father +( If1..IfK )

father +( If1..IfK )
e

.........

a
If1 ... IfK ...

son 1 +( Is11..Is1L )

c

son 1 +( Is11..Is1L )
+( If1..IfK )

succ (before) :

succ (after):

father +( If1..IfK )

father +( If1..IfK )
b
d

son 1
+( Is11..Is1L )
+( If1..IfK )

son 2

son 1

.......

+( Is11..Is1L )

+( Is11..Is1L )
+( If1..IfK )

up (before) :

c
son 2

...

+( Is21..Is2L )
+( If1..IfK )

up (after) :

father

father
d
b

son 1

.......

son N

Tabelle 6.3-4:

son 1

.......

son N

down(container father)
( init(son.sS) ; init(son.iS) )
a) father.sS := father.sS  father.iS
b) father.cS := father.cS  father.sS
c) if (son  leaf) then
son.iS :=(son.iS  father.iS) / {son}
d) push(father,stack) /* father auf stack */
e) return(son) /* mit son weiter */
succ(container son1)
( init(next(son).sS) ; init(next(son).iS) )
a) father := top(father) /* Top of the stack */
b) father.cS := father.cS  son.cS
/* results to father */
c) if (next(son)  leaf) then
next(son).iS := (next(son).iS  father.iS)
/ {next(son)}
d) next(son).cS := next(son).cS  next(son).sS
e) return(next(son)) /* mit next(son) weiter */
up(container sonN)
a) father := top(father) /* Top of the stack */
b) father.cS := father.cS  sonN.cS
/* results to father */
c) pull(stack) /* father vom stack */
d) return(father) /* weiter mit father */

Darstellung der Funktionen down, succ, up links grafisch, rechts als Pseudo-Code

Seite 49t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS

6.3.2 Hilfsfunktionen, die für die Schleifenterminierung benötigt werden
 up_is_root( root , akt ) testet den aktuellen father (top of stack) und ist true,
wenn up(akt)=root
 no_succ(akt) testet den nächsten in der Menge sS
vom aktuellen father (top of stack) und ist true, falls keiner exitiert
 no_down(akt) testet sS von akt und liefert true, falls diese leer ist.

getAllContaining(array_of_container from_DTD)
akt:=root ; push(root,stack)
Loop1 while akt=root or not(up_is_root(akt))

3
2
1

Loop2 while akt=root or not(no_succ(akt))
3

Loop3 while akt=root or not(no_down(akt))
3) akt:=down(akt)

2

2) akt:=succ(akt)

bis der Stack
leer ist

Breitensuche
bis rechter Sohn
Tiefensuche
bis Blatt

1) akt:=up(akt)
If not(no_succ(akt)) -> akt:=succ(akt)

Abbildung 6.3-9:

Algorithmus getAllContained in einem Struktogramm mit grafischer Erklärung

Idee :
Der Baum wird durch Tiefensuche abgearbeitet, und dabei werden die Inclusion-Regeln
beachtet. Ergebnisse werden beim backtracking (Postorder) vom rechten Sohn und bei dem
Besuch der Bruder-Knoten von den anderen Söhnen geliefert. (up-b und succ-b ).
Bei der Tiefensuche : alle included Types werden auch zu Söhnen gemacht. Alle Söhne
bekommen dann durch down bzw succ die included Types des Vaters weitergeleitet :
son_i.iS := (son_i.iS  father.iS)
Dabei ergibt sich ein Sonderfall (siehe Abbildung 6.3-10)

Seite 50t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
r
a
c

d
i

Abbildung 6.3-10:

b
e

i

i

i
i

i

Sonderfall, beim Weiterleiten der included Types des Vaters an seine Söhne

Es dürfen also nur die included Types weitergeleitet werden, die nicht zyklisch sind
(d.h. I  I.iS) . Das wird jeweils in down und succ durch die Mengen-Differenz vermieden :
son_i.iS := (son_i.iS  father.iS) / {son_i}. Die Initialisierung aller Söhne vor der Behandlung
(in down und succ) garantiert, daß die Sub-Bäume der Element-Types wieder in aller Reinheit
betrachtet werden können.
(  wichtig für die mehrmalige Betrachtung von Elementtypen)
6.3.3 Die elementaren Funktionen
Im Folgenden werden die Funktionen von Tabelle 6.3-4 näher erläutert.
zu down :
 Initialisiert die Mengen des ersten Sohnes
(iS:=includedTypeDef, sS:=contentModel,cS:={})
 setzt die includedTypes vom aktuellen Knoten als Söhne, denn included Types sind auch
gleichzeitig Söhne
 setzt alle Söhne in die Ergebnismenge(=alle Nachkommen vom aktuellen Knoten)
als Zwischenergebnis.
 setzt die includedTypes vom aktuellen Knoten in die includedTypes-Menge des ersten
Sohnes (ganz links) außer Sohn 1 selbst (falls er ein includedType des Vaters ist ->
Vermeidung von Zyklen), denn alle included Types des Vaters sind auch included Types aller
Nachkommen.
 dann mit dem ersten Sohn weiter ....
 Tiefensuche (deep search first)

Seite 51t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
zu succ :
 Initialisiert die Mengen des (i+1)-ten Sohnes
(iS:=includedTypeDef, sS:=contentModel,cS:={})
 der i-te Sohn liefert die Ergebnismenge(=alle seine Nachkommen) an den aktuellen Vater,
denn alle seine Nachkommen sind auch Nachkommen des Vaters
 setzt alle includedTypes des aktuellen Vaters in die includedType-Menge seines jüngeren
Bruders (Sohn i+1), außer den Bruder selbst (falls er ein includedType des Vaters ist ->
Vermeidung von Zyklen), denn alle included Types des Vaters sind auch included Types
aller Nachkommen.
 dann mit Bruder weiter ...
 Besuch der Bruderknoten

zu up :
 der aktuelle Sohn liefert die Ergebnismenge(=alle seine Nachkommen) an den aktuellen
Vater, denn alle seine Nachkommen sind auch Nachkommen des Vaters
 backtracking

6.3.4 Der Gesamt-Algorithmus
Im Folgenden wird die Algorithmusbeschreibung von Abbildung 6.3-9 näher erläutert.
zu getAllContaining :
 Die Sonderabfragen beim Spezialfall, daß die Wurzel weniger als zwei Nachkommen hat,
kann man in der Implementierung als vorausgesetzt annehmen. Für den Algorithmus soll es
genügen, daß alle 3 Funktionen (down, succ, up) den Sonderfall akt=LostNode behandeln :
top(stack)=up(LostNode)  LostNode=down(LostNode)  LostNode=succ(LostNode),
wobei LostNode wie ein Null-Blatt zu sehen ist.
 durch down ist die Ergebnismenge der vorletzten Generation (Väter mit nur Blättern als
Söhne) als richtig gewährleistet
 ansonsten geben alle Generationen durch succ und up jeweils ihre Ergebnismenge an ihren
Vater weiter (backtracking)

Seite 52t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
 Da Zyklen von getAllContaining durch Prüfung vermieden werden und der DTD-Baum mit
gesetzten included Types als Vorbedingung auch keine Zyklen enthalten dürfen, entsteht ein
ADT-Baum, der einem durch die gesetzten incType-Bäume erweiterten DTD-Baum
entspricht
 Loop 3 terminiert, da an jedem Ast ein Blatt existiert (Abbruchbedingung für Loop 3)
 Loop 2 terminiert, da Loop 2 und jeder Knoten nur eine endliche Anzahl von Söhnen hat

(diese Annzahl wird nur von down verändert, also nur beim

ersten Sohn)

 Loop 1 terminiert, da Loop 3+2 terminieren und der Baum endlich ist (keine Zyklen) und

als endlicher Keller nur mit down gefüllt ist .

6.4

Beweis mit Induktion zur Richtigkeit des Satzes
Im letzten Unterkapitel befindet sich die Verifikation des Algorithmus getAllContaining.

Es handelt sich hierbei um einen intuitiven Induktions-Beweis.
Satz (Proposition) :
Der Algorithmus getAllContaining arbeitet korrekt mit den vorgegebenen Bedingungen.

Induktionsanfang(Basis) :
n ist die Anzahl der in der DTD vorkommenden included Types
n = 0:keine included Types
 DTD-Baum in Postorder

n = 1:es existiert nur ein included Type : I
 wenn der Elementtyp durch down oder succ erreicht wird, wird I zum Sohn gemacht bei

jedem down bzw. succ wird I jeweils an die Söhne weitergeleitet mit Ausnahme von I
selbst (keine Zyklen) ! Diese Schritte werden dann mit den jeweiligen Söhnen
fortgesetzt, bis zu den Blättern (deep search first) und dann mit up wieder zurück.
(backtracking). Die Ergebnisauswertung ist dann wie oben beschrieben.

Seite 53t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Induktionsschritt :

wenn die Induktionsannahme für n gilt,
n Inc.ETypes

dann gilt sie auch für n+1. Also wenn der

InduktionsSchritt

Algorithmus für n included Types funktioniert,
dann funktioniert er auch für (n+1)-ten
included Type ! (siehe Abbildung 6.4-11)

n+1 Inc.ETypes

Abbildung 6.4-11:
Der Baum vor und nach dem Induktionsschritt

Folgende Fälle sind dabei für included Type (n+1) oder I(n+1) zu beachten :
I. I(n+1) ist Sohn eines Elementtyps, der selbst kein included Type ist.
II. I(n+1) ist Sohn eines included Type

Für jeden der beiden Fälle gilt folgender Fall :
 I(n+1) ist flach, denn wenn I(n+1) strukturiert ist, wird (bis auf die Sonderbehandlung bei der
incuded Type - Mengenverarbeitung) in jedem Knoten wie ein Sohn behandelt.
 Ohne die Allgemeinheit zu verletzen, nehmen wir an, daß I(n+1) der Letzte included Type in
der included Type Menge ist, (also auch der der ganz rechte Sohn des aktuellen Vaters)
und alle included Types vorher wurden schon korrekt verarbeitet .
 Durch die Inititialisierungen in down und succ werden außerdem versteckte Zyklen
außeinandergebrochen (das gilt nicht für direkte und indirekte Zyklen)

zu Fall 1) <!ELEMENT start

--

(ET 1,...,ETm) +(I1,...,In ,I(n+1))>

 Wenn I(n+1) in der DTD gesetzt war, dann ist bei down(start) folgendes passiert:
- init setzt den ersten Sohn auf die Anfangswerte
- dann wird I(n+1) als Sohn von start gesetzt (down-a)
– und in die Menge iS des ersten Sohnes gebracht (down-b)
 Der Fall erster Sohn=I(n+1) kann nicht auftreten, da sonst start ein Blatt wäre
- diese Schritte (in down) werden solange wiederholt, bis ein Blatt erreicht wird. (dort :

Seite 54t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
Ausnahmebehandlung  keine Weitergabe von included Types)
- nach jedem down ist I(n+1) wieder der letzte in der Menge iS des betroffenen Sohnes
- nach jedem down ist I(n+1) auch der ganz rechte Sohn des betroffenen Vaters.
 Beim am weitesten linken und unteren Blatt des Teilbaumes von start (start2), wird
mit succ der Bruder dieses Blattes erreicht, mit dem dann fortgefahren wird,
wie mit start und die Weiterleitungen des Vaters übernimmt jetzt succ
(succ-b und succ-c)! (also ist I(n+1) wieder immer ganz rechts)
- Wenn der aktuelle Knoten ein Blatt ist, geht es jeweils mit succ sofort weiter. Die
Ergebnisse hat dann der aktuelle Vater bereits durch down-b bekommen, denn ein Blatt
hat keine Nachfolger
- Wenn der aktuelle Knoten strukturiert ist, dann enthält der Knoten ja bereits alle
sS-Mengen seines Unterbaumes jeweils durch succ-b und up-b. Diese gibt er alle
seinem Vater weiter.
- bis dann jeweils I(n+1) als ganz rechter Sohn erreicht wird
 Das ist das erste Mal, daß I(n+1) behandelt wird. Jedesmal, wenn I(n+1) behandelt wird,
gibt es eine Ausnahmebehandlung
 keine Weitergabe des Vaters von {akt} an akt.iS (sonst Zyklus)

 Wenn I(n+1) dann behandelt wurde, ist er auch gleichzeitig der letzte Sohn eines
Knotens !
 Mit up wird dann wieder der Vater ermittelt und eine Ebene zurückgegangen und auch
das Ergebnis des ganz rechten Sohnes (in diesem Falle I(n+1) ) zurückgeliefert.
 Dort wird wieder weiterverfahren wie mit start2 (also ist I(n+1) in allen Knoten des
DTD-Baumes ganz rechts, außer in sich selbst)
 Schließlich gelangt man zum ganz rechten Knoten von start und liefert mit up-b das
letzte Ergebnis.

Seite 55t

ABBILDUNGS- UND TABELLEN-VERZEICHNIS
zu Fall 2)

In
In
In

In+1
In+1

In+1

Abbildung 6.4-12:

Die Auswirkungen im DTD-Baum , wenn I(n+1) Sohn eines included Types ist.

 um bei Fall 2 eine normale Behandlung wie bei Fall 1 zu erhalten werden in down und
succ die Initialisierungen vorgenommen, d.h. jedesmal, wenn ein Sohn behandelt wird
(durch down oder succ), werden die für die Steuerung notwendigen Mengen iS und sS
auf den Startwert zurückgesetzt. Dadurch werden versteckte Zyklen zumindest
unterbrochen (das Erkennen ist nicht das Aufgabe dieses Algorithmus)
 Die einzigen Zyklen, die dann noch bleiben sind die direkten oder indirekten Zyklen, die
als Vorbedingung ja nicht vorhanden sein dürfen (im Algorithmus wären sie zu
erkennen, wenn ein Sohn im stack schon vorkommt)
 Wenn die versteckten Zyklen nicht mehr entstehen können, dann kann man wie bei Fall
1 vorgehen, also : I(n) = start , denn dann wird der Baum von I(n) nur noch wie ein ganz
normaler Teilbaum betrachtet und das jedesmal, als wenn das erste mal wäre ...

Da also auch n+1 gilt, arbeitet der Algorithmus mit den vorgegebenen
Bedingungen korrekt.

Seite 56t

KAPITEL 7 EXPERIMENTE

7 Experimente
Das Experiment-Kapitel im Folgenden besteht im Wesentlichen aus der Grundbeschreibung in Unterkapitel 7.1 und aus fünf Experimenten 7.2 bis 7.5. In jedem Experiment
werden, nach einer Beschreibung des Experiments, die Ergebnisse vorgestellt und nachfolgend
analysiert.
7.1

Basis-Elemente der Experimente
Das folgende Unterkapitel definiert alle grundsätzlichen Experiment-Bedingungen für die

Experimente (I )– (V).
7.1.1 Die SGML-Test-Dokumente
Für die Experimente wurden große SGML-Dokumente benutzt. Hierzu eigneten sich
besonders Dramen von William Shakespeare, die sich im Internet befanden.
Die ausgewählten Dramen waren :

Hamlet

Richard der III. (rich_iii.sgm) mit 275 KB

Othello

(hamlet.sgm) mit 283 KB

(othello.sgm) mit 253 KB

Jedes dieser Dramen ist vom Dokumenttyp 'PLAY', was auch gleichzeitig der Name des
Root-Elements ist. Weiterhin ist jedes Drama in fünf Akte (Elementtype 'ACT') aufgeteilt und
im Schnitt beinhaltet jeder Akt vier Szenen (Elementtype 'SCENE'). Insgesamt wird jede Zeile
(Elementtyp 'LINE') als eigenes Dokument-Element notiert. Durchschnittlich gibt es in einem
Drama ca. 4000 Dokument-Elemente vom Typ 'LINE'.

KAPITEL 7 EXPERIMENTE
7.1.2 Die verschiedenen Konfigurationen
Für die drei Dramen wurden verschiedene Konfigurationen ausgewählt. Identifizierend
für die verschiedenen Konfigurationen ist jeweils der größte flache Teil. Die Summe aller
flachen Teile ergibt ca. 300 KB, da noch Zusatzinformationen mit in die flachen Fragmente
gespeichert werden. Die Konfiguration wird dem SP über eine Konfigurationsdatei vermittelt,
in der alle strukturierten Elementtyp-Namen zeilenweise stehen (in Großbuchstaben). Zum
korrekten Auswählen wurde der Algorithmus 'getAllContaining' entwickelt, dessen
Beschreibung und Verifikation in Kapitel 6 zu finden sind. Hier nun die vier verschiedenen
Konfigurationen im Einzelnen :

300 KB

-> das SGML-Dokument wird in einem flachen Fragment gespeichert.

In der Konfigurationsdatei befindet sich nur :
PLAY

60 KB

-> hier wird das Dokument in fünf Akte á 60 KB gespeichert.

In der Konfigurationsdatei befinden sich :
PLAY
PLAYTITLE
FM
PERSONAE
SCNDESCR
PLAYSUBT
INDUCT
ACT

15 KB

-> in ungefähr 22 Szenen á 15 KB wird das Dokument Fragmentiert.

PLAY
PLAYTITLE
FM
PERSONAE
SCNDESCR
PLAYSUBT
INDUCT
ACT
ACTTITLE
SCENE

KAPITEL 7 EXPERIMENTE

0,22 KB -> es gibt 4000 bis 5000 Zeilen á 0,22 KB im Durchschnitt, als Unterteilung
PLAY
PLAYTITLE
FM
PERSONAE
SCNDESCR
PLAYSUBT
INDUCT
INDUCTTITLE
SUBHEAD
ACT
ACTTITLE
SCENE
SCENETITLE
SPEECH
SPEAKER
STAGEDIR
LINE

Die Werte sind nur als -Werte zu sehen. Die genauen Zahlen sind für die Experimente
nicht interessant. In allen Experimenten wurde von keinen zusätzlichen Indexstrukturen wie
PCDATAIndex, attribIndex oder structIndex gebrauch gemacht. Es wurden natürlich
Datenbankspezifische Indizes aufgebaut.
Alle Experiment wurden mehrmals und auf verschiedenen Rechnern durchgeführt. Das
ganze auch in verschiedenen Reihenfolgen. Daraus ergab sich, daß die Ergebnisse unabhängig
von der Anzahl der Datensätze, der Reihenfolge der Operationen und der Leistung der
Workstation war.
7.2
mit
(I)
(II)

Experiment (I+II): Dokumentbezogene Queries und Gesamt-Operationen
(Einfügen, Ausgeben).
Navigationsmitteln wie down, succ, um die Suche in Preorder durchzuführen
speziellen Stringsuch-Operationen im Flachen, die massiv das datenbankinterne
Wissen ausnutzen.

KAPITEL 7 EXPERIMENTE
Die Experimente (I+II) sind Bestandteil dieses Kapitels. Die Beschreibung aller
Experimente ist in drei Schritte gegliedert. Es wurden in beiden Experimenten die gleichen
Funktionen benutzt, aber mit verschiedenen Vorraussetzungen. Die Funktionen sind im
Einzelnen getAll, getElemText (Element-Ausgabe) und das Einfügen.
7.2.1 Beschreibung der Experimente
Das Ziel des Experiments ist die Ermittlung der Vor- und Nachteile verschiedener
Konfigurationen. Hierbei wurden die Dramen jeweils in die vier oben beschriebenen
Konfigurationen aufgeteilt und in die Datenbank eingefügt. Dieses Einfügen wurde jeweils
zeitlich gemessen und dann als Durchschnittszeit für die jeweilige Konfiguration ausgewertet.
Als Gegenstück wurden diese Zeitmessungen auch für die Ausgabe des jeweils ganzen
Dokuments ermittelt. Auch hier wurde die Druchschnittszeit jeder Konfiguration von allen drei
Dokumenten berechnet.
Die Funktion getAll(Wurzel-Element,Elementtyp-Name) ist dann die spezielle Abfragefunktion, die zeitlich gemessen wird. Die Elementtypen, die dabei in den Dokumenten in
Preorder gesucht wurden waren die Elemente :

SCENE

->

kommt ca.

20 mal vor

STAGEDIR ->

kommt ca.

140 mal vor

LINE

kommt ca.

4000 mal vor

->

KAPITEL 7 EXPERIMENTE

7.2.2 Ergebnisse des Experiments (I+II)
In Tabelle 7.2-5 sind die Ergebnisse der Zeitmessung (in Sekunden). In den ersten drei
Zeilen

(ohne

die

Überschrift)

sind

die

Ergebnisse

von

getAll(root,etype)

mit

root=getRootbyDocName("hamlet.sgm") und etype  {'SCENE', 'STAGEDIR', 'LINE'}.
Das Ganze gilt auch für die 'root' von rich_iii.sgm und othello.sgm.
In diesen Zeilen und in der Zeile der Ausgabe gibt es zwei Spalten pro Konfiguration.
Die linke Spalte zeigt dabei die Zeit an, die mit String-Suchalgorithmen und spezielles Wissen
über die datenbankinterne Repräsentation, in flachen Fragmenten, ausnutzt. Wenn dabei auf ein
flaches Fragment gestoßen wurde, aktivierte es die Funktion getAllinFlat, um den flachen Teil
mit String-C-Funktionen zu durchsuchen. Es handelt sich hierbei um das Experiment (II). Die
rechte Spalte dagegen, liefert die Zeiten von Experiment (I), das beim Suchen in PreorderReihenfolge die Navigations-Funktionen down und succ verwendet (up wird durch einen 'stack'
ersetzt).
Das Einfügen geschieht über den SGML-Parser. Dieser hat seine eigenen Navigationsfunktionen. Somit gibt es hier keine, zwei zu unterscheidende, Navigationsmöglichkeiten.
Das erklärt die einzelne Spalte.
alles flach
(1 x 300 KB)
SCENE
(20-ETypes) 2,0 s 582,0 s
STAGEDIR (134 ETypes) 1,0 s 580,7 s
LINE
(4014 ETypes) 1,7 s 580,0 s
Ausgeben
2,0 s 312,0 s
Einfuegen
11,7 s
Tabelle 7.2-5:

grob aufgeteilt
(5 x 60 KB)
16,7 s 140,3 s
16,3 s 140,0 s
17,0 s 140,0 s
20,0 s 150,0 s
45,7 s

mittel aufgeteilt
(22 x 15 KB)
52,0 s 110,3 s
53,3 s 110,3 s
53,3 s 110,3 s
65,3 s 123,3 s
113,7 s

fein (nur hamlet)
(5000 x 0,22 KB)
4609,0 s
4602,0 s
4546,0 s
4555,0 s
4556,0 s
4585,0 s
5090,0 s
5098,0 s
7449,7 s

Experiment (I+II) zum vergleichen von verschiedenen Konfigurationen .

7.2.3 Analyse der Ergebnisse
Die Konfiguration 'fein' ist mit den anderen Konfigurationen nicht mehr vergleichbar, was
die frappanten Zahlen zeigen. Da es sich in dem Dokument um ca. 6000 Elementtypen handelt,
wurden auch dementsprechend viele Datenbankoperationen benötigt. Diese sind mit Sicherheit
teurer, als String-Operationen in 'C'. Ein 1:1 Abbildung von allen Dokument-Elementen auf
Datenbankojekten scheint also eine zu feine Granularität zu besitzen und ist deshalb nicht
empfehlenswert in diesem Zusammenhang.
Da die Algorithmen speziell mit einem ganzen Dokument zu tun haben, schneidet in der
Wertung von Experiment (II) die Konfiguration 'alles flach' am besten ab. Der eine, flache Teil
wird mit einer Datenbankoperation geladen und dann im Speicher mit effizienten C-Funktionen

KAPITEL 7 EXPERIMENTE
durchsucht. Je mehr Fragmente zu druchsuchen waren (5 und 22), desto mehr
Datenbankoperationen wurden benötigt. Das schlägt sich auch in den Zeiten nieder.
Betrachtet man jedoch das Resultat von Experiment (I), also die rechten Spalten, dann
kann man einen deutlichen Zeitanstieg bei der Konfiguration 'alles flach' feststellen. Es wurde
bei diesen Operationen zwar mit Cache gearbeitet, aber die Navigationen down und succ im
flachen Teil stellten sich als nicht sehr effizient heraus. Das ist auch die Motivation für das
Experiment (III), das im Folgenden beschrieben wird.
Fazit : für Dokumentbezogene Queries, die massiv das interne Wissen ausnutzen, ist die
Konfiguration 'alles flach' die für die Performanz am besten geeignete Konfiguration. Das gilt
jedoch nicht für Einzel-Operationen wie die Navigations-Funktionen.
7.3

Experiment (III) : Dokumentbezogene Einzel-Funktionen
In diesem Unterkapitel wird das Experiment (III) beschrieben. Die Funktionen, die hier

zum Evaluieren benutzt wurden, sind im wesentlichen Navigations-Funktionen und die
Ausgabe von kleinen Elementen.
7.3.1 Beschreibung des Experiments (III)
Ziel des Experiments war es, für die im Experiment (I+II) verwendeten Konfigurationen,
(ohne die Konfiguration 'fein') einige Einzel-Funktionen zu vergleichen. Es handelte sich hierbei
hauptsächlich um die Funktionen up, succ, pred sowie die Ausgabe von einzelnen Elementen
vom Typ 'SCENE' und 'LINE'. Damit die Ergebnisse in den Sekundenbereich kamen, wurden
bei den Navigations-Funktionen Verschachtelungen und Sequenzen ausgeführt.
Die Ziele wurden nach verschiedenen Gesichtspunkten ausgewählt, die auch auf die
Schwächen (worst case) des Navigierens in flachen Fragmenten eingingen. Im wesentlichen
handelte es sich hierbei um folgende Dokument-Elemente im Dokument :

LLP

Position des letzten Dokument-Elements vom Typ 'LINE'

FSFA

Position der ersten Szene ('SCENE') im ersten Akt ('ACT')

LSFA

Position der letzten Szene ('SCENE') im ersten Akt ('ACT')

4.LL

Position des viert letzten Elements vom Typ 'LINE'

7.3.2 Ergebnisse des Experiments (III)
In Tabelle 7.3-6 sind die Ergebniszeiten zusammengefaßt. In der ersten Spalte von
Tabelle 7.3-6, werden die Aktionen beschrieben, deren Zeiten für die verschiedenen

KAPITEL 7 EXPERIMENTE
Konfigurationen (in Sekunden) in den darauffolgenden Spalten angegeben werden. Die Zahlen
in dieser ersten Spalte geben dabei die Häufigkeit der dahinter beschriebenen Aktionen an.
Alle Funktionsaufrufe wurden zehn mal durchgeführt, bis auf 'up', denn hier hatte der
'worst case' große Einwirkung auf das Zeitverhalten.

10 x Ausgabe : SCENE
10 x Ausgabe : LINE
3 x up(up(up(up(LLP))))
10 x succ(succ(succ(succ(FSFA))))
10 x pred(pred(pred(pred(LSFA))))
10 x pred(pred(pred(pred(LLP))))
10 x succ(succ(succ(succ(4.LL))))
Tabelle 7.3-6:

alles flach grob aufgeteilt
(1 x 300 KB)
(5 x 60 KB)
7,0 sec
4,0 sec
7,0 sec
3,0 sec
21,0 sec
5,0 sec
12,0 sec
5,0 sec
9,0 sec
4,0 sec
9,0 sec
4,0 sec
8,0 sec
4,0 sec

mittel
aufgeteilt
(22 x 15 KB)
14,0 sec
3,0 sec
6,0 sec
15,0 sec
15,0 sec
3,0 sec
3,0 sec

Ergebniszeiten von speziellen Funktions-Sequenzen

7.3.3 Analyse der Ergebnisse
Man kann in
erkennen, daß es auch ungünstige Fälle für die gröber aufgeteilten Konfigurationen gibt.
In diesem Experiment hatte die Konfiguration '(5x60 KB)' die beste Performanz. Das liegt
wohl daran, daß diese dokumentbezogenen Einzel-Funktionen von zwei Tatsachen profitieren.
Erstens sind die flachen Fragmente nicht so groß und die Navigation im Flachen dauert nicht so
lange und zweitens werden nur, im speziellen Falle, fünf Datenbankoperationen benötigt.
Fazit : Bei dokumentbezogenen Einzel-Funktionen ist das Performanz-Verhalten bei den
verschiedenen Konfigurationen eher durchwachsen. Insgesamt liegen die Vorteile bei der
Konfiguration '(5x60 KB)'.

KAPITEL 7 EXPERIMENTE

7.4

Experiment (IV): Datenbank-Query mit verschiedenen Konfigurationen
Im Gegensatz zu den Experimenten (I-III) handelt es sich bei der Query im

Experiment (IV), im folgenden Unterkapitel, nicht um eine dokumentbezogene Query sondern
um eine datenbankbezogene Query.
7.4.1 Beschreibung des Experiments (IV)
Die Funktion getObjs(etype) sucht (im Gegensatz zu getAll) die gesamte Datenbank
nach etype ab, daß heißt, alle Dokumente, deren DTD diesen etype beinhalten. Zu diesem
Zweck wurden die drei Dramen jeweils drei mal mit der gleichen Konfiguration eingefügt,
getObjs(etype) mit den etype-Namen 'ACT' und 'SCENE' durchgeführt und zeitlich gemessen.
Ziel des Experiments (IV) war, die verschiedenen Konfigurationen zu vergleichen und
das Ergebnis auch neben die Ergebnisse der Experimente (I-III) zu halten.
7.4.2 Ergebnisse des Experiments (IV)
alles flach
(1 x 300 KB)
21,0 sec
21,0 sec

mittel aufgeteilt
(22 x 15 KB)
getObjs - act
3,5 sec
getObjs - scene
4,0 sec
In
Tabelle 7.4-7 werden die Ergebniszeiten (in Sekunden) zusammengefaßt.
Tabelle 7.4-7:

grob aufgeteilt
(5 x 60 KB)
3,5 sec
71,0 sec

Ergebniszeiten von Datenbank-Query getObjs mit verschiedenen Konfigurationen

7.4.3 Analyse der Ergebnisse
Durch die Tatsache, daß bei einer Aufteilung nach dem Elementtyp 'SCENE', alle
Szenen auch strukturiert vorliegen, kann man alle Elementtypen 'SCENE' bzw. 'ACT' mit
einer Query bestimmen. Das schlägt sich natürlich auch in den Zeiten in Tabelle 7.4-7 nieder.
Die Konfiguration 'grob' kann nur Vorteile aus der Aufteilung nach 'ACT' ziehen. Was
sich aber negativ bei getObjs(ID('SCENE')) ausgleicht.
Bei der Konfiguration 'alles flach' spielt es keine Rolle, nach welchen Elementtypen
gefahndet wird, genausowenig, wie oft diese Vorkommen. Es ist nichts anderes, als ein
Hintereinanderausführen von getAll für alle in Frage kommenden Dokumente.
Fazit : Wenn es um datenbankorientierte Queries geht, kann die Granularität nicht fein
genug sein. In Experiment (I) war die optimale Konfiguration, in Bezug auf Performanz, die
Konfiguration 'alles flach', während das Optimum in Experiment (III) von Konfiguration 'grob'

KAPITEL 7 EXPERIMENTE
erreicht wurde. Im Experiment (IV) war dann die feinste Granularität gefragt und die
Konfiguration 'mittel' war die optimale Fragmentierung. Aus technischen und zeitlichen
Gründen konnten die Experimente (III+IV) nicht mit der Konfiguration 'fein' durchgeführt
werden. Mit Sicherheit hätten aber, bei dieser Konfiguration, alle getObjs-Anfragen die
vier Sekunden-Grenze nicht überschritten.
Es gibt also keine optimale Konfiguration, denn für die verschiedenen Bedürfnisse gab es
keine Konfiguration, die nicht mit Nachteilen behaftet gewesen wäre. Will man also die
optimale Konfiguration, in Bezug auf Performanz erhalten, muß man sich im Klaren sein,
welche Anforderungen das System optimal erfüllen soll.

7.5

Experiment (V) : Vorausparsen vs. ad-hoc-Parsen
In dem letzten Unterkapitel der Experimente wird ein Vergleich zwischen zwei

grundsätzlich verschiedenen Behandlungsmethoden von flachen Elementen gezogen besonders in Bezug auf nicht vollständig markierte Dokument-Elemente.
7.5.1 Beschreibung des Experiments (V)
Im Kapitel 5.2 in [Bö97] ist beschrieben, welche Vorteile es haben kann, alle
Elementtypen mit vollständiger Markierung in die flachen Datenbank-Objekte zu speichern. In
diesem Experiment sollen Strukturerkennungs-Mechanismen miteinander verglichen werden.
Da gibt es zum ersten das 'Vorausparsen'. Wie eben erwähnt, findet dann eine Funktion, die
die Struktur erkennen soll, in flachen Datenbankobjekten eine vollständige Markierung vor. Es
werden dann keinerlei Information mehr von der DTD benötigt. Zum zweiten gibt es die
Möglichkeit, Markups wegzulassen, wie es in SGML erlaubt ist. In diesem Fall ist also die
Markierung nicht vollständig. Eine strukturerkennende Funktion benögtigt also eine
(Fragment-)DTD, mit der dann das flache Datenbankobjekt erneut geparst wird
('ad-hoc-Parsen').
Als strukturerkennende Funktion wurden Navigations-Funktionen wie up und succ
benutzt, um nach mehrmaligem Aufrufen einer Funktion ein 'worst-' bzw. 'best case' Verhalten
zu ermitteln. Bei der 'ad-hoc' Version reicht es aus, das flache Datenbank-Objekt einmal zu
Parsen, um die unterste Schranke für die Ausführungszeit zu ermitteln.
Als Untersuchungs-Objekte wurden wieder Teile aus dem Drama 'Hamlet' ausgewählt.
Es konnten allerdings nur zwei Konfigurationen zum Vergleich herangezogen werden, denn bei
der Konfiguration 'mittel aufgeteilt' konnte die Zeit nicht mehr gemessen werden. Übrig

KAPITEL 7 EXPERIMENTE
blieben die Konfigurationen 'alles flach' und 'grob aufgeteilt'. Für das adhoc-Parsen wurde für
dieses Experiment eigens der erste Akt von Hamlet zum SGML-Dokument umgewandelt und
dementsprechend wurde auch die Fragment-DTD für 'ACT' mit allen benötigten Definitionen
erstellt. Die Zeit des Parsens von diesem neuen Dokument wurde dann ausgewertet
7.5.2 Ergebnisse des Experiments (V)
In Tabelle 7.5-8 ist das Ergebnis (Zeit in Sekunden) abgebildet. Als 'worstcase' wurde die
Navigationsfunktion 'up' mit dem schlechtesten Erfolgsfall aufgerufen. Das kann man erreichen,
indem man vom letzten, enthaltenen Elementtyp von 'PLAY' bzw. 'ACT' wieder in diese VaterElemente zurückspringt. In diesem Fall müssen nämlich alle Elemente beim Suchen 'überquert'
werden, bevor das Ziel erreicht wird. Im 'bestcase' sprang succ eine 'LINE' (ca. 200 Bytes)
weiter.

SP
300 KB (Etype play)
60 KB (Etype act)
Tabelle 7.5-8:

0,50 sec
0,18 sec

Vorausparsen
worstcase bestcase
0,11 sec
0,05 sec
0,03 sec
0,01 sec

Ergebnis - Vorausparsen vs. adhoc-Parsen

7.5.3 Analyse der Ergebnisse
Aus Tabelle 7.5-8 geht eindeutig hervor, das die Zeiten zwischen SP und Vorausparsen
mindestens um den Faktor fünf auseinander liegen. Dieser Faktor ist nur eine Abschätzung, da
es sich bei den Zeiten vom SP auch nur um eine untere Schranke handelt.

KAPITEL 8 SCHLUSSBEMERKUNG

8 Schlußbemerkung
In dieser Arbeit wurde eine Implementiertung eines Verwaltungssystems für SGMLDokumente entworfen und realisiert. Hierzu wurde ein objektrelationales Datenbanksystem als
Implementierungsgrundlage gewählt. Der Name dieses objektrelationalen Datenbanksystems
ist IUS - Informix Universal Server. Als Vorlage zur Strategie der Verwaltung, diente das
Datenbanksystem HyperStorM, das auf einem objektorientierten DBMS namens VODAK
basiert. Die Verwaltungsform , die in diesem objektorientierten DBMS gewählt wurde, ist eine
hybride Form. Man kann hierbei durch Konfiguration bestimmen, welche Dokument-Elemente
1:1 als Datenbankobjekt oder welche zusammengefaßt als flacher Text in ein Datenbankobjekt
gespeichert werden. Zum Konfigurieren wird erstens eine Datei benutzt, in der alle
strukturierten Elemente zeilenweise notiert werden und zweitens die SuperDTD-Instanz, die
die DTD (Dokument Type Definition) als Dokument repräsentiert. Die SuperDTD-Instanz
wird als Dokument in die Datenbank eingefügt und kann somit mit Funktionen und Methoden
für Dokumente behandelt werden. Es müssen keine zusätzlichen Zugriffs-Funktionen
implementiert werden. Außerdem enthält die SuperDTD-Instanz Informationen über zu
erstellende Indexstrukturen und gesonderte Mengen von Inclusions und Exclusions. Mit diesen
Mengen ist es möglich, komplexere Dokumenttypen zu behandeln. Zu diesem Zweck wurde
ein Algorithmus entwickelt, der mit Hilfe dieser Inclusion/Exclusion-Mengen ein komplettes
'enthalten Modell' berechnen kann. Man ist mit diesem Ergebnis in der Lage, für jedes
Dokument-Element, alle enthaltenen Elemente zu bestimmen – Inclusions eingeschlossen. Für
diesen Algorithmus wurde ein Korrektheitsbeweis durchgeführt.

KAPITEL 8 SCHLUSSBEMERKUNG
Ein weiteres Ziel dieser Arbeit war es, das objektrelationale Datenbanksystem zu
evaluieren und dabei immer ein Vergleich mit dem Vorgängersystem im Auge zu behalten.
Hierzu wurden fünf Experimente durchgeführt. Die Versuchs-Objekte waren hierbei drei große
Dramen von William Shakespeare in SGML-Fassung. Im wesentlichen wurden diese
Dokumente mit vier verschiedenen Konfigurationen in die Datenbank eingefügt und diverse
Ausgabe- und Abfrage-Funktionen zeitlich gemessen. Wie auch schon im objektorientierten
Vorgängersystem, gab es auch im objektrelationalen DBMS keine optimale Konfiguration für
alle gestellten Aufgaben. Vielmehr machten die Experimente deutlich, wie vorteilhaft man die
Konfigurationsmechanismen und Methoden, die die Dokumentstruktur ausnutzen, nutzen
kann, um eine optimale Performanz für die individuellen Anforderungen zu erhalten.
Dieser zum Testen entwickelte Prototyp eines objektrelationalen DBMS muß in Zukunft
noch Funktionen und Operationen erhalten, die das Datenbanksystem zu einem kompletten
Verwaltungssystem macht. Funktionen wie Ändern, Löschen oder, wie im Vorgängersystem
vorhandene, semantische Auswertung von Hyperlinks, sind noch zu implementieren. Dazu
kommt noch eine Benutzerschnittstelle im Internet, die gerade in Arbeit ist, sowie
Schnittstellen zu den Sprachverwandten HTML und XML. Darüber hinaus wäre eine
Automatisierung der Konfiguration denkbar. Beim aktuellen Stand wird die Konfiguration mit
unterstützenden Hilfroutinen noch vom Benutzer, per Hand erstellt.

KAPITEL 8 SCHLUSSBEMERKUNG

Anhang A

Die DTD für Shakespeare Dramen

<!-- DTD for Shakespeare
-->
<!ENTITY amp "&">
<!ELEMENT play
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
+)>
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT

J. Bosak

1994.03.01, 1997.01.02

playtitle
personaetitle
acttitle
scenetitle
inducttitle
fm
p
personae

- - (playtitle,fm,personae,scndescr,
playsubt,induct?,act+)>
- - (#PCDATA)>
- - (#PCDATA)>
- - (#PCDATA)>
- - (#PCDATA)>
- - (#PCDATA)>
- - (p+)>
- - (#PCDATA)>
- - (personaetitle, (persona | pgroup)

pgroup
persona
grpdescr
scndescr
playsubt
induct

-

<!ELEMENT act
<!ELEMENT scene
<!ELEMENT speech

-

(persona+, grpdescr)>
(#PCDATA)>
(#PCDATA)>
(#PCDATA)>
(#PCDATA)>
(inducttitle,(scene+|
(speech|stagedir|subhead)+))>
- - (acttitle, scene+)>
- - (scenetitle, (speech | stagedir |
subhead)+)>
- - (speaker+, (line |
stagedir | subhead)+)>

KAPITEL 8 SCHLUSSBEMERKUNG

<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT
<!ELEMENT

speaker
line
stagedir
lstagedir
subhead

-

-

(#PCDATA)>
(lstagedir | #PCDATA)+>
(#PCDATA)>
(#PCDATA)>
(#PCDATA)>

KAPITEL 8 SCHLUSSBEMERKUNG

Anhang B

Die SuperDTD-Instanz 'SDTDi_PLAY', erstellt von der DTD 'shaksper.dtd' aus
Anhang A

<!DOCTYPE SUPERDTD SYSTEM "superDtd.dtd">
<SUPERDTD version=2 rootElemName=PLAY>
<DOCTYPE docName=PLAY TABLES=NONE>
<ELEM id=e0 elemName=PLAY tagOmmission=NO
contentModel='(PLAYTITLE,FM,PERSONAE,SCNDESCR,PLAYSUBT,INDUCT?,
ACT+)'
containedTypes='e1 e2 e4 e9 e10 e11 e22 e24 e26'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e1 elemName=PLAYTITLE tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>
<ELEM id=e2 elemName=FM tagOmmission=NO
contentModel='P+'
containedTypes='e3'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e3 elemName=P tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e4 elemName=PERSONAE tagOmmission=NO
contentModel='(PERSONAETITLE,(PERSONA,PGROUP)+)'
containedTypes='e5 e6 e7'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e5 elemName=PERSONAETITLE tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e6 elemName=PERSONA tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e7 elemName=PGROUP tagOmmission=NO
contentModel='(PERSONA+,GRPDESCR)'
containedTypes='e6 e8'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e8 elemName=GRPDESCR tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e9 elemName=SCNDESCR tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e10 elemName=PLAYSUBT tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>
<ELEM id=e11 elemName=INDUCT tagOmmission=NO
contentModel='(INDUCTTITLE,(SCENE+,
(SPEECH,STAGEDIR,SUBHEAD)+))'
containedTypes='e12 e13 e14 e16 e21 e20'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e12 elemName=INDUCTTITLE tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>
<ELEM id=e13 elemName=SCENE tagOmmission=NO
contentModel='(SCENETITLE,(SPEECH,STAGEDIR,SUBHEAD)+)'
containedTypes='e15 e13 e16 e21 e20'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX='SCENETITLE'>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e14 elemName=SCENETITLE tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e15 elemName=SPEECH tagOmmission=NO
contentModel='(SPEAKER+,(LINE,LSTAGEDIR,SUBHEAD)+)'
containedTypes='e17 e18 e19 e20'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e16 elemName=SPEAKER tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>
<ELEM id=e17 elemName=LINE tagOmmission=NO
contentModel='(LSTAGEDIR|(#PCDATA))+'
containedTypes='e19 '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e18 elemName=LSTAGEDIR tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e19 elemName=SUBHEAD tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>
<ELEM id=e20 elemName=STAGEDIR tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=N STRUCTINDEX=' '>
</ELEM>

KAPITEL 8 SCHLUSSBEMERKUNG

<ELEM id=e21 elemName=ACT tagOmmission=NO
contentModel='(ACTTITLE,SCENE+)'
containedTypes='e25 e13 e22 e14 e26'
includedTypes=' '
excludedTypes=' '
FLAT=NOT ELEMINDEX=N STRUCTINDEX='ACTTITLE'>
</ELEM>
<ELEM id=e22 elemName=ACTTITLE tagOmmission=NO
contentModel='(#PCDATA)'
containedTypes=' '
includedTypes=' '
excludedTypes=' '
FLAT=YES ELEMINDEX=Y STRUCTINDEX=' '>
</ELEM>
</SUPERDTD>

KAPITEL 8 SCHLUSSBEMERKUNG

Anhang C

Das SQL-Script 'create.sql' zum Erstellen der Datenbank-Typen und -Tabellen.

-------------------------------------------------------------- Erstellen von Typen und Tabellen für die SGML-Datenbank --------------------------------------------------------------- Ref-Typ benennen: zur besseren Lesbarkeit
create distinct type id_type as integer;
---

Erweiterungen der Spezifikation: own_id' s in:
etype, dtd, docElem, document

-------------------------------------------------------- Attribut-Paarung
-- Die Instanz dieses Typs enthält das Attribut des DokumentElements mit der
-- Referenz auf das entsprechende nonflatElem mit der own_id
'element'
create row type attrRec
(
element
id_type,
name
varchar(128),
value
varchar(128)
);

KAPITEL 8 SCHLUSSBEMERKUNG

-------------------------------------------------------- Elementtypen
-- Für jeden Elementtyp, welcher in einer von der Datenbank
unterstützten
-- DTD enthalten ist, gibt es eine entsprechende Instanz von
'etype'
create row type etype
(
own_id
id_type,
name
varchar(128),
dtdref
id_type,
contentModel
lvarchar,
pcdataIndexed boolean, -- "f" oder "t"
structIndexed
set(varchar(128) not null)
);
-------------------------------------------------------- Dokument Typ Definitionen
-- Jeder Dokumenttyp hat eine entsprechende Instanz dieses Typs
create row type dtd
(
own_id id_type,
name
varchar(128),
etypes
set(id_type not null),
config
clob
);
-------------------------------------------------------- Dokumente
-- Die Instanz dieses Typs ist die Repräsentation eines
Dokuments
create row type document
(
own_id id_type,
name
varchar(128),
dtdref
id_type,
root
id_type
);
-------------------------------------------------------- Dokument- Elemente
-- Das ist die generische Repräsentation eines DokumentFragmentes

KAPITEL 8 SCHLUSSBEMERKUNG

create row type docElem
(
own_id
id_type,
doc
id_type, --ref(document)
up
id_type, --ref(docElem)
succ
id_type, --ref(docElem)
pred
id_type --ref(docElem)
);
-------------------------------------------------------- Strukturierte Dokument- Elemente
-- Das ist die Repräsentation von Dokument- Elementen mit einer
expliziten
-- Datenbank- Repräsentation
create row type nonflatElem
(
down
id_type,
etName
varchar(128)
) under docElem;
-------------------------------------------------------- Flache Dokument Elemente
-- Das ist die Repräsentation von Dokument-Fragmenten, die aus
Dokument- Elementen
-- bestehen, deren Repräsentation unstrukturiert ist.
create row type flatElem
(
flat clob
) under docElem;
-------------------------------------------------------- PCDATA- Index
-- Eine Instanz dieses Typs identifiziert das Vorkommen eines
Text-Inhalts innerhalb
-- eines Dokuments.
create row type pcdataIndex
(
elementType
id_type,
content
varchar(128),
positions
set(varchar(128) not null)
);
-- Jeder Wert von 'content' ist der Textinhalt des Elements vom
Elementtyp 'elementType'
-- 'positions' ist dann die Menge alle Index- Einträge in der
Form : "oid|occurrence"
-- 'oid' ist die own_id des Elementes, in dem der Inhalt
vorkommt

KAPITEL 8 SCHLUSSBEMERKUNG

-- und 'occurrence' gibt die Anzahl an, wie oft 'content' in
dem Dokument-Fragment
-- vorkommt. Ist das betroffene Dokument- Element strukturiert,
ist 'occurrence'=-1 .
-------------------------------------------------------- Attribut- Index
-- Eine Instanz dieses Typs identifiziert das Vorkommen eines
Attributwertes
create row type attrIndex
(
elementType
id_type,
attrName
varchar(128),
attrValue
varchar(128),
positions
set(varchar(128) not null)
);
-- Jedes Attribut-Paar ('attrName','attValue') des Elements ist
vom Elementtyp 'elementType'
-- 'positions' -> siehe PCDATAIndex.
-------------------------------------------------------- Structurierter Index
-- Eine Instanz dieses Typs identifiziert das Vorkommen eines
Textinhalts in einem
-- verschachtelten Paar von bestimmten Elementtypen,
-- bei denen der 2. Elementtyp in dem 1. Elementyp enthalten
ist
create row type structIndex
(
extElemType id_type,
intElemType id_type,
content
varchar(128),
positions
set(varchar(128) not null)
);
-------------------------------------------------------- create Tables (etype, dtd, document, docElem)
------------------------------------------------------create table etypeTable of type etype
(
PRIMARY KEY (own_id)
);
------------------------------------------------------create table dtdTable of type dtd
(
PRIMARY KEY (own_id),
UNIQUE(name)
);
------------------------------------------------------create table documentTable of type document
(
PRIMARY KEY (own_id),

KAPITEL 8 SCHLUSSBEMERKUNG

UNIQUE(name)
);

KAPITEL 8 SCHLUSSBEMERKUNG

------------------------------------------------------create table docElemTable of type docElem
(
PRIMARY KEY (own_id)
);
------------------------------------------------------create table nonflatElemTable of type nonflatElem
UNDER docElemTable;
------------------------------------------------------create table flatElemTable of type flatElem
UNDER docElemTable;
------------------------------------------------------create table attrRecTable of type attrRec
(
PRIMARY KEY (element , name , value)
);
------------------------------------------------------create table attrIndexTable of type attrIndex
(
PRIMARY KEY (elementType , attrName , attrValue)
);
------------------------------------------------------create table structIndexTable of type structIndex
(
PRIMARY KEY (extElemType,intElemType,content)
);
------------------------------------------------------create table PCDATAIndexTable of type pcdataIndex
(
PRIMARY KEY (elementType,content)
);
-------------------------------------------------------

KAPITEL 8 SCHLUSSBEMERKUNG

Anhang D

Das SQL-Skript 'inits.sql' zum Initialisieren der Datenbanktabellen

-- make casts implicit to avoid 0::id_type to get id_typenumbers...
drop cast (integer as id_type);
create implicit cast (integer as id_type);
delete
delete
delete
delete
delete
delete
delete
delete
delete
delete

from
from
from
from
from
from
from
from
from
from

documentTable;
docElemTable;
nonflatElemTable;
flatElemTable;
dtdTable;
etypeTable;
PCDATAIndexTable;
attrIndexTable;
structIndexTable;
attrRecTable;

-----------------------------------------------------------------Initialisieren aller Tabellen mit mindestens einem LeerDatensatz----------------------------------------------------------------- the ETypes for the DTD "SUPERDTD"
insert into etypeTable values(0, "SUPERDTD",4,"(DOCTYPE,
(ENTITY|ELEM|
NOTATION|SHORTREF|USEMAP)*,(COMBI)*)","f",Null);
insert into etypeTable values(1, "DOCTYPE",4,"EMPTY","f",Null);
insert into etypeTable values(2,
"ENTITY",4,"(#PCDATA)","f",Null);
insert into etypeTable values(3,
"ELEM",4,"(ATTRIBUTE*)","f",Null);

KAPITEL 8 SCHLUSSBEMERKUNG

insert into etypeTable values(4,
"ATTRIBUTE",4,"EMPTY","f",Null);
insert into etypeTable values(5, "COMBI",4,"EMPTY","f",Null);
insert into etypeTable values(6,
"NOTATION",4,"EMPTY","f",Null);
insert into etypeTable values(7,
"SHORTREF",4,"(REFLIST*)","f",Null);
insert into etypeTable values(8, "REFLIST",4,"EMPTY","f",Null);
insert into etypeTable values(9, "USEMAP",4,"EMPTY","f",Null);
-- the ETypes for the DTD "VORLESUNGSVERZEICHNIS"
insert into etypeTable
values(10,"VORLESUNGSVERZEICHNIS",2,"((Termine),
(Legende), (Fachbereich)+)","t",Null);
insert into etypeTable values(11 , "TERMINE",2,"(Termin &
Datum)*","t",Null);
insert into etypeTable values(12 , "TERMIN",2,"(#PCDATA),"
"t","SET{'String1','String2'}");
insert into etypeTable values(13 ,
"DATUM",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(14 , "LEGENDE",2,"(Alias &
Erklaerung)*","t",Null);
insert into etypeTable values(15 ,
"ALIAS",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(16 ,
"ERKLAERUNG",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(17 , "FACHBEREICH",2,"(Name ,
(Richtung?,Lehrveranst?, Eintrag+)+ )" ,"t",Null);
insert into etypeTable values(18 , "NAME",2,
"(#PCDATA)","t",Null);
insert into etypeTable values(19 ,
"RICHTUNG",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(20 ,
"LEHRVERANST",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(21 , "EINTRAG",2,"(Kz?,Bezeich,
Art, Tag,
Zeit, Raum, Beginn, Prof, Fn?)" ,"t",Null);
insert into etypeTable values(22 ,
"FN",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(23 ,
"KZ",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(24 ,
"BEZEICH",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(25 ,
"ART",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(26 ,
"TAG",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(27 ,
"ZEIT",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(28 ,
"RAUM",2,"(#PCDATA)" ,"t",Null);

KAPITEL 8 SCHLUSSBEMERKUNG

insert into etypeTable values(29 ,
"BEGINN",2,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(30 ,
"PROF",2,"(#PCDATA)" ,"t",Null);
-- the ETypes for the DTD "PLAY"
insert into etypeTable values(31 , "PLAY",3,"(playtitle, fm,
personae, scndescr, playsubt, induct , act+))" ,"t",Null);
insert into etypeTable values(32 , "FM",3,"(p+)" ,"t",Null);
insert into etypeTable values(33 ,
"PERSONAE",3,"(personaetitle, (persona |pgroup)+)" ,"t",Null);
insert into etypeTable values(34 , "PGROUP",3,"(persona+,
grpdescr),"t",Null);
insert into etypeTable values(35 , "INDUCT",3,"(inducttitle,
(scene+|(speech|stagedir|subhead)+)" ,"t",Null);
insert into etypeTable values(36 , "ACT",3,"(acttitle,scene+),"
"t",Null);
insert into etypeTable values(37 , "SCENE",3,"(scenetitle,
(speech | stagedir | subhead)+)" ,"t",Null);
insert into etypeTable values(38 , "PROLOGUE",3,"((stagedir |
speech)+)" ,"t",Null);
insert into etypeTable values(39 , "EPILOGUE",3,"((stagedir |
speech)+)" ,"t",Null);
insert into etypeTable values(40 , "SPEECH",3,"(speaker+,
line | lstagedir | subhead)+)" ,"t",Null);
insert into etypeTable values(41 , "LINE",3,"(lstagedir
|#PCDATA)+","t",Null);
insert into etypeTable values(42 , "PLAYTITLE",3,
"(#PCDATA)","t",Null);
insert into etypeTable values(43 ,"PERSONAETITLE",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(44 , "ACTTITLE",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(45 , "SCENETITLE",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(46 , "INDUCTTITLE",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(47 , "P",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(48 , "PERSONA",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(49 , "GRPDESCR",3,"(#PCDATA)"
,"t",Null);
insert into etypeTable values(50 ,
"SCNDESCR",3,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(51 ,
"PLAYSUBT",3,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(52 ,
"SPEAKER",3,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(53 ,
"STAGEDIR",3,"(#PCDATA)" ,"t",Null);

KAPITEL 8 SCHLUSSBEMERKUNG

insert into etypeTable values(54 ,
"LSTAGEDIR",3,"(#PCDATA)" ,"t",Null);
insert into etypeTable values(55 ,
"SUBHEAD",3,"(#PCDATA)" ,"t",Null);

KAPITEL 8 SCHLUSSBEMERKUNG

insert into documentTable values(0,"Test-DocumentName",0,Null);
insert into docElemTable values(0,Null,Null,Null,Null);
insert into nonFlatElemTable
values(1,0,Null,Null,Null,2,"initName");
insert into attrRecTable values(1,"AName","AValue");
insert into flatElemTable values(2,0,1,Null,Null,Null);
insert into dtdTable values(0,"INIT",Null,Null);
insert into dtdTable values(1,"LIED",Null,Null);
insert into dtdtable
values(2,"VORLESUNGSVERZEICHNIS",Null,Null);
insert into dtdtable values(3,"PLAY",Null,Null);
insert into dtdtable values(4,"SUPERDTD",Null,Null);
insert into dtdtable values(5,"MMFDOC",Null,Null);
insert into dtdtable values(6,"VZ",Null,Null);
insert into PCDATAIndexTable
values(0,"PCDATAIndexInit","SET{'0|1'}");
insert into attrIndexTable
values(0,"attrInitName","attrInitValue","SET{'0|1'}");
insert into structIndexTable
values(0,1,"structIndexInit","SET{'0|1'}");

KAPITEL 8 SCHLUSSBEMERKUNG

Abbildungsverzeichnis
Abbildung 3.1-1: Eine Beispiel-Dokumnet vom Dokumenttyp 'article'
.................................................................................................................................
13
Abbildung 3.1-2: Eine Beispiel-DTD vom Dokumenttyp 'article'
.................................................................................................................................
14
Abbildung 3.2-1: Repräsentation des Beispieldokuments – Dokumentelement = Knoten
.................................................................................................................................
15
Abbildung 3.2-2: Repräsentation des Beispieldokuments - zusammengefaßte Elemente
.................................................................................................................................
16
Abbildung 4.1-1: Architektur des Gesamtsystems
.................................................................................................................................
18
Abbildung 4.4-1 : Das Vererbungsverhältnis zwischen docElem, nonFlatElem und flatElem.
.................................................................................................................................
20
Abbildung 4.4-1: Zusammenspiel der Tabellen, die zur Speicherung der Dokumente beteiligt sind.
.................................................................................................................................
22
Abbildung 4.6-1: Ablaufdiagramm - Einfügen eines SGML-Dokuments in die Datenbank.
.................................................................................................................................
26
Abbildung 6.3-1: Algorithmus getAllContained in einem Struktogramm mit grafischer Erklärung
.................................................................................................................................
51
Abbildung 6.3-2: Sonderfall, beim Weiterleiten der included Types des Vaters an seine Söhne
.................................................................................................................................
52
Abbildung 6.4-1: Der Baum vor und nach dem Induktionsschritt
.................................................................................................................................
55
Abbildung 6.4-2: Die Auswirkungen im DTD-Baum , wenn I(n+1) Sohn eines included Types ist.
.................................................................................................................................
57

KAPITEL 8 SCHLUSSBEMERKUNG

KAPITEL 8 SCHLUSSBEMERKUNG

Tabellenverzeichnis
Tabelle 4.2-1:

Datentypen von den verschiedenen Schnittstellen
.................................................................................................................................
18

Tabelle 4.3-1:

Selbsterstellte Datentypen und ihre Abstammung
.................................................................................................................................
19

Tabelle 6.2-1:

Illustration des benutzten Datentyps für den Algorithmus
.................................................................................................................................
49

Tabelle 6.3-1:

Darstellung der Funktionen down, succ, up links grafisch, rechts als Pseudo-Code
.................................................................................................................................
50

Tabelle 7.2-1:

Experiment (I+II) zum vergleichen von verschiedenen Konfigurationen .
.................................................................................................................................
62

Tabelle 7.3-1:

Ergebniszeiten von speziellen Funktions-Sequenzen
.................................................................................................................................
64

Tabelle 7.4-1:

Ergebniszeiten von Datenbank-Query getObjs mit verschiedenen Konfigurationen
.................................................................................................................................
65

Tabelle 7.5-1:

Ergebnis - Vorausparsen vs. adhoc-Parsen
.................................................................................................................................
67

KAPITEL 8 SCHLUSSBEMERKUNG

Literaturverzeichnis
[Sto96]

M. Stonebraker, D. Moore : OBJECT-RELATIONAL DBMSs, the
next great wave , Morgan Kaufmann Publishers. inc. San Francisco.
Califonia, USA, 1996

[GBS92]

G.H. Gonnet, R. Baeza-Yates, T. Snider: Information Retrieval,
Data Structures & Algorithms, S.66-82 : New Indices for Text: PAT
Trees and PAT Arrays, Prentice Hall, New Jersey, USA 1992

[Bö97]

K. Böhm, Benutzung objektorientierter Datenbank-Technologie für
die Speicherung strukturierter Dokumente, TU-Darmstadt, 1997

[Her94]

E.v.Herwijnen : Practical SGML, Second Edition , Kluwer
Academic Publishers, Dordrecht, Niederlande 1994

[BAK95]

K. Böhm, K. Aberer, W. Klas : Building a Hybrid Database
Application for Structured Documents, GMD Darmstadt,
Deutschland 1995

[AHU72]

Aho, Hopcroft, Ullman : The Design and Analysis of Computer
Algorithms , Addison Wesley Publishing Co., Massachusetts 1972

[BANY95] K. Böhm, K. Aberer, E.J. Neuhold, X. Yang : Structured Document
Storage and Refined Declarative and Navigational Access
Mechanisms in HyperStorM, GMD Darmstadt, Deutschland, 1995
[INF97]

INFORMIX : INFORMIX-Universal Server DataBlade API, User
Manual , INFORMIX Press, CA, USA, 1997

[IPSI95]

IPSI : VODAK V4.0 User Manual , GMD Darmstadt,1995