Implementierung eines objektorientierten Datenmodells

Werbung
RHEINISCHE FRIEDRICH-WILHELMS-UNIVERSITÄT
BONN
INSTITUT FÜR INFORMATIK III
Diplomarbeit
Implementierung eines objektorientierten
Datenmodells mit deduktiven Regeln in
Oracle8
Andrea Scheuber
Michael Horn
5. November 1999
Erstgutachter: Prof. Dr. Rainer Manthey
Danksagung
An dieser Stelle möchten wir uns bei einigen Menschen bedanken:
Unserem Betreuer, Prof. Dr. Rainer Manthey, danken wir für die vielen Stunden, die er mit
der Betreuung unserer Diplomarbeit verbracht hat.
Andreas Behrend danken wir für die hilfreiche Unterstützung bei der Lösung von Prolog- und
Oracle-Problemen.
Bei Stefan Schubert möchten wir uns für seine hervorragende Installationsanleitung und
FAQ-Seite zum Thema CPT und für die gemeinsame Einarbeitung in den Quellcode des CPT
bedanken.
Für die hilfreichen und prompten Kommentare beim Korrekturlesen dieser Arbeit danken wir
Arno Bücken.
Inhaltsverzeichnis
Inhaltsverzeichnis
1 Einleitung (Andrea Scheuber und Michael Horn) ............................................................... 5
2 Chimera (Michael Horn) .................................................................................................... 7
2.1 Das Datenmodell von Chimera ................................................................................... 8
2.1.1 Konzepte eines Chimera-Schemas ...................................................................... 9
2.1.1.1 Value Types.................................................................................................... 9
2.1.1.2 Value Classes................................................................................................ 10
2.1.1.3 Object Classes............................................................................................... 10
2.1.1.4 Chimera Views ............................................................................................. 12
2.1.1.5 Constraints.................................................................................................... 12
2.1.1.6 Trigger.......................................................................................................... 14
2.1.2 Klassenhierarchien und Vererbung in Chimera ................................................. 15
2.2 Deklarative Ausdrücke von Chimera ........................................................................ 17
2.2.1 Anwendung deklarativer Ausdrücke ................................................................. 19
2.3 Imperative Ausdrücke von Chimera.......................................................................... 22
3 Das Chimera Prototyping Tool (Michael Horn) ................................................................ 26
3.1 Architektur des CPT................................................................................................. 27
3.2 Der Bonner Chimera-Dialekt .................................................................................... 29
3.2.1 Unterschiede zwischen Chimera- und CPT-Datenmodell .................................. 30
3.2.2 Unterschiede bei deklarativen und imperativen Ausdrücken.............................. 31
3.3 Abbildung des objektorientierten Datenmodells nach Phoenix.................................. 31
3.3.1 Werteklassen und -typen................................................................................... 34
3.3.2 Objektklassen und Klassenhierarchien .............................................................. 35
3.3.3 Integritätsbedingungen...................................................................................... 38
4 Oracle8 (Andrea Scheuber) .............................................................................................. 40
4.1 Datenbanksysteme und Datenmodelle....................................................................... 40
4.2 Die relationalen Konzepte von Oracle8..................................................................... 42
4.2.1 Built-in-Datentypen .......................................................................................... 42
4.2.2 Tabellen............................................................................................................ 44
4.2.3 Sichten.............................................................................................................. 44
4.2.4 Integritätsbedingungen...................................................................................... 45
4.2.5 Trigger.............................................................................................................. 46
4.2.6 Interne Prozeduren und Funktionen................................................................... 47
4.2.7 Externe Prozeduren und Funktionen.................................................................. 49
4.3 Die objektorientierten Konzepte von Oracle8 ........................................................... 49
4.3.1 Objekttypen ...................................................................................................... 50
4.3.1.1 Interne Verwaltung eines Objekttyps als Wertebereich eines Attributs .......... 50
4.3.1.2 Methoden...................................................................................................... 52
4.3.1.3 Die Vergleichsfunktionen MAP und ORDER ............................................... 53
4.3.2 Kollektionstypen............................................................................................... 53
4.3.3 Objekttabellen................................................................................................... 55
4.3.4 Referenzierte Spalten........................................................................................ 55
4.3.5 Objektsichten.................................................................................................... 56
4.4 SQL-92-Standard-Erweiterungen von Oracle8.......................................................... 57
3
Inhaltsverzeichnis
4.4.1
4.4.2
4.4.3
4.4.4
4.4.5
Zusätzliche Datentypen unter Oracle8............................................................... 57
Erweiterte und neue Funktionen in Oracle8....................................................... 58
Pseudospalten ................................................................................................... 58
Zusätzliche Operatoren ..................................................................................... 59
Zusätzliche Konzepte........................................................................................ 59
5 Eine Oracle-basierte Implementierung des Chimera Prototyping Tool (Andrea Scheuber
und Michael Horn) ........................................................................................................... 62
5.1 Architektur des CPTOracle .......................................................................................... 62
5.1.1 Einlesen eines Chimera-Schemas (load_schema/1) .................................... 65
5.1.2 Anlegen einer Chimera-Datenbank (chimera_createdb/1) ...................... 66
5.1.3 Öffnen einer Chimera-Datenbank (chimera_opendb/1) ............................. 67
5.1.4 Schließen einer Chimera-Datenbank (chimera_closedb/0) ...................... 67
5.1.5 Löschen einer Chimera-Datenbank (chimera_destroydb/0).................... 68
5.2 Das ECLiPSe-Oracle-Interface .................................................................................. 68
6 Übersetzung von Chimera-Schemata in Oracle8-SQL-Schemata (Andrea Scheuber) ........ 74
6.1 Datentypen ............................................................................................................... 74
6.2 Wertetypen............................................................................................................... 75
6.3 Werteklassen ............................................................................................................ 77
6.4 Objektklassen und Klassenhierarchien...................................................................... 78
6.4.1 Abbildung von Chimera-Objektklassen auf Oracle8-Tabellen........................... 79
6.4.2 Abbildung einer Chimera-Klassenhierarchie auf Oracle8-Sichten ..................... 80
6.4.3 Umsetzung von DML-Operationen auf Sichten................................................. 84
6.4.4 Abgeleitete Objektklassen................................................................................. 88
6.5 Vergleich zum CPTPhx-Ansatz .................................................................................. 91
6.6 Unterschiede zwischen CPTPhx und CPTOracle............................................................ 93
7
Übersetzung deklarativer Ausdrücke (Michael Horn) ................................................... 94
7.1 Konzepte der Übersetzung deklarativer Ausdrücke nach SQL .................................. 94
7.2 Implementierung ...................................................................................................... 98
7.3 Modifikationen und Optimierungen........................................................................ 101
7.4 Unterschiede zwischen CPTPhx und CPTOracle.......................................................... 103
8
Übersetzung imperativer Ausdrücke (Andrea Scheuber)............................................. 104
8.1 Transaktionen......................................................................................................... 104
8.2 Das Transaktionskonzept von Chimera................................................................... 105
8.3 Erzeugung und Verwaltung von Variablenbindungen ............................................. 109
8.4 Übersetzung von Anfragen ..................................................................................... 110
8.5 Übersetzung von DML-Operationen....................................................................... 113
9
Zusammenfassung und Ausblick (Andrea Scheuber und Michael Horn)..................... 119
10 Literaturverzeichnis.................................................................................................... 125
4
Inhaltsverzeichnis
Andrea Scheuber und Michael Horn
1 Einleitung
Heutzutage existieren in der Datenbankforschung eine Vielzahl von unterschiedlichen Datenmodellen, von denen sich das relationale und einige der unterschiedlichen objektorientierten Modelle kommerziell durchgesetzt haben. Da der Ansatz zur Objektorientierung in letzter
Zeit nicht nur bei Programmiersprachen, sondern auch bei Datenbanksystemen zu beobachten
ist, wurde die relationale Datenbanktheorie durch objektorientierte Konzepte erweitert. Das
Ziel dieser Erweiterungen ist es, mächtigere Konzepte für die Datenmodellierung zu erhalten.
Zusätzlich zu objektorientierten Erweiterungen sind aktive und deduktive Regeln als zusätzliche Konzepte eingeführt worden. Die Integration von Regeln in die Datenbankmanagementsysteme soll eine zentrale Verwaltung der "Anwendungslogik" von Applikationen
ermöglichen. Unterschiedliche Anwendungen können dadurch auf identische Funktionalitäten
zurückgreifen und Redundanzen im Quellcode vermieden werden.
Im Rahmen dieser Forschungen ist das Projekt IDEA (Intelligent Database Environment for
advanced Applications) unter der Schirmherrschaft der Europäischen Union entstanden. Ein
Ergebnis dieses Projekts ist das Datenmodell Chimera ([CM93]). Bestandteil von Chimera
sind unter anderem eine Datendefinitions- und Datenmanipulationssprache, die sowohl deduktive als auch objektorientierte Konzepte unterstützt. Zusätzlich ist es in Chimera möglich,
aktive Regeln zu definieren. Aus diesem Grund kann Chimera als ein deduktives objektorientiertes Datenmodell mit aktiven Komponenten bezeichnet werden. Auf der Grundlage dieses
Datenmodells wurde an der Universität Bonn das Chimera Prototyping Tool (CPT) entwickelt
([GL96 und GLM96]). Das CPT ist ein akademisches Datenbankmanagementsystem, welches
die Funktionalitäten des Datenmodells von Chimera umsetzt. Die Implementierung des CPT
basiert auf dem universitären, aktiven, relationalen Datenbankmanagementsystem Phoenix.
Sowohl Phoenix als auch das CPT sind in ECLiPSe-Prolog realisiert worden.
Aufgabe dieser Diplomarbeit ist die Implementierung des Datenmodells von Chimera auf der
Basis von Oracle8. Sie beschäftigt sich mit der Übersetzung von Chimera-Schemata in
Oracle8-Schemata, wobei die interessanten Aspekte in der Übersetzung der ChimeraKlassenhierarchien und der Übersetzung der Chimera-Datenmanipulationssprache liegt.
5
Inhaltsverzeichnis
Oracle8 ist aus mehreren Gründen für diese zweite Implementierung ausgewählt worden. Das
objekt-relationale Datenbanksystem Oracle8 ist eines der am weitesten verbreiteten kommerziellen Datenbanksystem. Des weiteren stellt Oracle8 objektorientierte Konzepte zur Verfügung, die auf den ersten Blick zur Realisierung eines objektorientierten Datenmodells
geeignet erscheinen.
Das Ziel dieser Diplomarbeit ist es, ein leistungsfähigeres System zu entwickeln, welches ein
größeres Datenvolumen unterstützt, als es die bisherigen Implementation basierend auf Phoenix kann. Die neue Implementierung wurde ebenfalls in ECLiPSe-Prolog realisiert und verwendet Teile der bestehenden Implementierung. Die Verbindung zwischen dem ECLiPSeSystem und dem Oracle8-Datenbankserver wird durch die ECLiPSe-Oracle Schnittstelle von
Thomas Kolbe ([Kol95]) hergestellt. Basierend auf den wenigen bisherigen Tests, erfüllt die
neue Implementierung des CPT die gewünschten Anforderungen nicht vollständig, da die
verwendete Schnittstelle zwischen Prolog und Oracle8 nicht die benötigte Leistungsfähigkeit
besitzt.
Die vorliegende Arbeit ist wie folgt strukturiert worden: Die Kapitel 2-4 führen die Grundlagen ein, die zum Verständnis der Arbeit notwendig sind. Kapitel 2 stellt das Datenmodell von
Chimera vor. Kapitel 3 geht auf die IDEA-Methodologie ein. Kapitel 4 stellt das objektrelationale Datenbanksystem Oracle 8 vor. Die Kapitel 5-8 beschäftigen sich mit der Oracle8basierten Umsetzung des Chimera-Datenmodells, wobei Kapitel 5 auf dessen Architektur eingeht. In Kapitel 6 beschäftigt sich mit der Abbildung einer Chimera-Schemadefinition in eine
Oracle8-Schemadefinition. Kapitel 7 beschäftigt sich mit der Übersetzung von deklarativen
Ausdrücken. Kapitel 8 geht auf die Übersetzung der Operationen zur Datenmanipulation ein.
6
Inhaltsverzeichnis
Michael Horn
2 Chimera
Das Ziel des IDEA-Projektes (http://www.txt.it/idea/idea.html) war die Schaffung einer intelligenten Datenbankumgebung für erweiterte Applikationen ("Intelligent Database Environment for Advanced Applications"). Die Arbeiten im Rahmen dieses Projektes fanden
zwischen Juni 1992 und März 1997 statt. Die Mitglieder des IDEA Projektes stammten aus
der Industrie und der Forschung; darunter befanden sich auch das Politecnico di Milano und
die Rheinische Friedrich-Wilhelms-Universität Bonn.
Im Rahmen dieses Projektes wurde Chimera entwickelt, ein objektorientiertes Datenmodell
mit einer dazugehörigen Datendefinitionssprache (DDL) und einer Datenmanipulationssprache (DML). In der griechischen Mythologie ist eine Chimäre ein Monster mit drei Köpfen:
einem Löwenkopf, einem Ziegenkopf und einem Schlangenkopf. Die drei verschiedenen
Köpfe dieses Fabelwesens symbolisieren die drei verschiedenen Konzepte von Chimera:
•
Objektorientierung: Das Datenmodell von Chimera unterstützt alle wesentlichen Konzepte der Objektorientierung. Daten werden in Klassen organisiert, die wiederum in Klassenhierarchien strukturiert werden können. In Klassenhierarchien sind Vererbung und
Redefinition zugelassen.
•
Deduktive Regeln: Deduktive Regeln werden zur Datengewinnung eingesetzt. Eine einfache Variante von deduktiven Regeln sind Sichten im relationalen Datenmodell. Mit Hilfe von deduktiven Regeln können aber auch Integritätsbedingungen und
Populationsregeln definiert werden. Das Datenmodell von Chimera unterstützt sowohl
Klassenpopulationsregeln als auch Attributdefinitionsregeln. Aufgrund ihrer Verwendung
werden deduktive Regeln auch als passive Regeln bezeichnet.
•
Aktive Regeln: Aktive Regeln reagieren auf Zustandsveränderungen der Datenbank. Zustandsveränderungen können hierbei Anfragen oder Änderungen des Datenbestandes,
Zeitereignisse oder beliebige externe Ereignisse sein. Das Chimera-Modell unterstützt nur
7
Inhaltsverzeichnis
Reaktionen auf Zustandsveränderungen des Datenbestandes und Aufrufe von Operationen. Aktive Regeln werden auch Trigger genannt.
Die folgenden Abschnitte beschreiben den Funktionsumfang des "reinen" Chimera-Modells
und basieren auf dem Buch von Stefano Ceri und Piero Fraternali ([CF97]). Im Zuge der
Weiterentwicklung und der Implementierung lauffähiger Systeme sind einige Veränderungen
vorgenommen worden. Die Unterschiede und Einschränkungen der Bonner Implementation
werden in Kapitel 3 vorgestellt.
2.1 Das Datenmodell von Chimera
Chimera basiert auf einem objektorientierten Datenmodell. Zur Definition eines ChimeraSchemas können folgende Konzepte verwendet werden:
•
Wertetyp ("value type")
•
Werteklasse ("value class")
•
Objektklasse ("object class")
•
Sicht ("view")
•
Integritätsbedingung ("constraint")
•
aktive Regeln ("trigger")
Bei Schemakonzepten unterscheidet man zwischen extensionalen und abgeleiteten Konzepten. Unter extensionalen Konzepten versteht man Konzepte, deren Daten in einer Datenbank
physikalisch abgespeichert werden. Die Daten werden materialisiert. Abgeleitete Konzepte
kombinieren bereits vorhandene Daten zu neuen Daten, die allerdings nicht abgespeichert
werden: Daten abgeleiteter Konzepte werden erst auf Anfrage hin berechnet bzw. hergeleitet.
Hierbei ist zu beachten, daß dies in der Art der relationalen Sichten geschehen kann oder aber
auch durch Berechnungsformeln, die aus bestehenden Daten, neue ableiten.
"Value types" und "value classes" gehören hierbei zu den extensionalen Konzepten. "Object
classes" gibt es sowohl als extensionale also auch abgeleitete Konzepte. Das Chimera-Modell
erlaubt bei "object classes" auch Mischformen (siehe Abschnitt 2.1.1.3). "Views" und "constraints" gehören nur zu den abgeleiteten Konzepten. "Trigger" gehören weder zu den extensionalen noch zu den abgeleiteten Konzepten, da sie auf Ereignisse, z.B. Veränderungen im
Datenbestand einer Datenbank, reagieren. Jeder "value type", "value class" usw. muß mit einem identifizierenden Namen ausgestattet werden. Chimera erlaubt hierbei nur Namen, die
mit einem kleinen Buchstaben beginnen.
8
Inhaltsverzeichnis
2.1.1 Konzepte eines Chimera-Schemas
2.1.1.1 Value Types
Unter einem "value type", zu deutsch einem Wertetyp, versteht man einen Datentyp, der zur
Definition von Parametern für Operationen und Attribute benutzt werden kann. Der große
Vorteil der Wertetypen ist die flexible Definition. Jeder Entwickler einer Chimera-Datenbank
kann zwischen den klassischen atomaren Datentypen und selbstdefinierten Wertetypen wählen. Auch die internen Basisdatentypen sind als "value type" definiert worden. Folgende homogenen Datentypen stehen einen Entwickler zur Verfügung:
•
integer
•
boolean
•
real
•
string
Wertetypen bieten die Möglichkeit, obige Basisdatentypen zu verfeinern und neu zu strukturieren. Chimera bietet drei Konzepte, mit deren Hilfe eigenständige, komplexe Datentypen
strukturiert werden können:
•
Liste ("list-of"): Mit Hilfe dieses Konstruktes können Attribute Listen beliebiger Länge
beinhalten. Listen dürfen dabei durchaus auch doppelt vorhandene Elemente beinhalten.
•
Menge ("set-of"): Im Gegensatz zu Listen, dürfen Mengen keine Duplikate enthalten und
die Elemente sind untereinander nicht geordnet.
•
Tupel ("record-of"): Mit Hilfe eines Tupeldatentyps können Attribute eine feste Struktur
bekommen. Die Struktur des Datentyps wird bei der Definition fest vorgegeben.
Chimera besitzt eine offene Architektur für "value types". Wertetypen können beliebig ineinander verschachtelt und rekursiv miteinander verbunden werden. Zu jedem Datentyp können
Integritätsbedingungen definiert werden. Integritätsbedingungen bieten in diesem Zusammenhang die Möglichkeit, den Wertebereich eines Datentyps einzuschränken. Sie bieten zum Beispiel die Möglichkeit, einen Datentyp für gerade Zahlen zu definieren indem man über eine
Integritätsbedingung alle ungeraden Zahlen als Wert für diesen Datentyp ausschließt.
Folgendes kleine Beispiel zeigt einen selbstdefinierten Datentyp um ein Datum abzuspeichern:
define value type datum:
record-of(tag:integer, monat:integer, jahr:integer)
end;
Über Integritätsbedingungen könnte man den Wertebereich der obigen Struktur so einschränken, daß es nur vierstellige Jahresangaben mit maximal zwölf Monaten mit jeweils maximal
31 Tagen gibt. Die Sonderregeln für jeden einzelnen Monat inklusive der Schaltjahre können
ebenfalls für jeden Monat gesondert definiert werden.
9
Inhaltsverzeichnis
2.1.1.2 Value Classes
Auch eine "value class" ist ein Datentyp. Der Unterschied zwischen einer Werteklasse und
einem Wertetyp ist die Art und Weise der Definition der zulässigen Werte. In einem Wertetyp
wird nur die Struktur des Datentyps festgelegt, der Wertebereich eines Wertetypen ist also
(unendlich) groß und nicht veränderbar (z.B. ganze Zahlen, beliebige Zeichenketten beliebiger Länge). Eine Werteklasse hingegen legt zusätzlich zur Struktur des Datentyps die endliche
Anzahl der Elemente der Klasse explizit fest. Eine Werteklasse entspricht also einem Aufzählungsdatentyp:
define value class geschlecht: string
end;
Für Werteklassen existieren zwei besondere Datenmanipulationsbefehle "add" und
"drop":
add (geschlecht, "maennlich");
add (geschlecht, "weiblich");
add (geschlecht, "male");
drop(geschlecht, "male");
"add" fügt einen neuen Wert in die Werteklasse ein, "drop" löscht einen vorhandenen
Wert aus einer bestehenden Klasse.
2.1.1.3 Object Classes
Die Objektklasse ist das zentrale Konzept des Chimera-Modells. Die Definition einer Objektklasse legt die Struktur (Attribute) und die Ausprägungen (Integritätsbedingungen, Trigger
und Operationen) der zu speichernden Objekte fest. Jede Instanz einer Objektklasse wird
durch einen systemweit eindeutigen Objektidentifikator (OID) bezeichnet. Ein Objekt in
Chimera ist eine Instanz einer Objektklasse. Ein Objekt muß alle Integritätsbedingungen der
Objektklasse und der dazugehörigen Datenbank erfüllen. Durch die Zugehörigkeit eines Objektes zu einer Objektklasse können alle zur jeweiligen Klasse gehörenden Operationen auf
dieses Objekt angewendet werden.
Objektklassen können mit Hilfe folgender Klassenkonzepte definiert werden. Für die Definition einer Objektklasse ist zu beachten, daß die Konzeptnamen immer im Plural verwendet
werden müssen:
•
"superclasses": Das erste Konzept, das bei einer Klassendefinition verwendet werden
kann dient dazu, Klassenhierarchien abzubilden. Die Möglichkeiten von Klassenhierarchien werden in Abschnitt 2.1.2 erläutert.
•
"attributes": Jede Objektklasse benötigt Attribute. Attribute können entweder in einer
Klasse lokal definiert werden oder aber von einer Oberklasse vererbt werden. Das Thema
der Vererbung wird ebenfalls in Abschnitt 2.1.2 erläutert. Ein Attribut besteht aus einem
Namen und einem Wertebereich. Als Datentyp sind hierbei alle Wertetypen und Werteklassen zulässig. Des weiteren besteht die Möglichkeit, einem Attribut als Wertebereich
eine Objektklasse zuzuweisen.
10
Inhaltsverzeichnis
•
"constraints": Constraints, zu deutsch Integritätsbedingungen, definieren illegale Zustände der Datenbank. Jede Objektklasse kann eigene Integritätsbedingungen festlegen, die
illegale Zustände innerhalb der Population einer Klasse ausschließen. Weitere Erläuterungen und Beispiele für Integritätsbedingungen stehen in Abschnitt 2.1.1.5.
In Chimera existieren zusätzlich zu den frei definierbaren Integritätsbedingungen noch
drei grundlegende Integritätsbedingungen: key, unique und notnull. Die ersten beiden Arten von Integritätsbedingungen werden durch ein separates Schlüsselwort in der
Definition einer Objektklasse ausgedrückt. Mit Hilfe dieser beiden Schlüsselworte können
sowohl Primär- als auch Sekundärschlüssel für eine Objektklasse definiert werden. Die
dritte Integritätsbedingung kann während der Definition eines Attributes verwendet werden: notnull legt fest, daß dieses Attribut in jedem Objekt mit einem Wert belegt werden muß.
•
"operations": Operationen können für Attribute definiert werden. Operationen führen
Manipulationen an einzelnen Attributwerten durch. Operationen ermöglichen zum Beispiel das Alter einer Person jederzeit basierend auf dem aktuellen und dem Geburtsdatum
zu berechnen.
Für jede Objektklasse werden automatisch die Operationen für Datenmanipulation
(create, delete und modify) und Anfragen (select und display) erstellt. Die
Anwendung dieser automatisch erzeugten Operationen wird in Abschnitt 2.2.1 erläutert.
•
"triggers": Trigger definieren Aktionen, die in einer bestimmten Situation ausgeführt
werden sollen. Die Trigger einer Objektklasse können nur dann ausgelöst werden, wenn
Veränderungen im Datenbestand der jeweiligen Klasse geschehen. Genauere Erläuterungen bzgl. Trigger werden in Kapitel 2.1.1.6 gegeben.
Folgendes kleine Beispiel soll die Syntax der Definition einer Objektklasse verdeutlichen:
define object class adresse
attributes
strasse:
string,
plz:
number,
wohnort:
string
end;
define object class person
attributes
name:
string notnull,
vorname:
string notnull,
geschlecht:
geschlecht,
adresse:
adresse
key
(name, vorname)
end;
Neben den bisher vorgestellten extensionalen Objektklassen und Attributen existieren in
Chimera noch abgeleitete Objektklassen ("derived object classes") und Attribute ("derived
attributes"). Abgeleitete Objektklassen entsprechen eingeschränkten Sichten des relationalen
Datenmodells. Die Definition von abgeleiteten Objektklassen ist auf Attribute der Oberklas11
Inhaltsverzeichnis
sen der jeweiligen Klassenhierarchie beschränkt. Im Gegensatz zu relationalen Sichten können also nicht beliebige Kollektionen und Kombinationen von Werten zusammengestellt werden (vgl. Chimera Sichten in Abschnitt 2.1.1.4).
Daten einer abgeleiteten Klasse werden über Populationsregeln aus extensionalen oder abgeleiteten Klassen und Attributen hergeleitet. In abgeleiteten Klassen dürfen keine zusätzlichen
extensionalen Attribute definiert werden, da abgeleitete Klassen ansonsten materialisiert, also
permanent gespeichert werden müßten.
Abgeleitete Attribute werden mit Hilfe von Regeln definiert. Definitionsregeln werden mit
Hilfe beliebiger deklarativer Ausdrücke formuliert. Im Gegensatz zu Populationsregeln für
abgeleitete Objektklassen, müssen Attributdefinitionsregeln nicht ausschließlich auf Attributen der jeweiligen Klassenhierarchie basieren. Bei der Definition von Klassenhierarchien
werden abgeleitete Attribute genauso wie extensionale Attribute an alle Unterklassen vererbt.
Die Definition von abgeleiteten Attributen kann im Rahmen einer Klassenhierarchie verändert
werden.
Das Aussehen und die Möglichkeiten von Populationsregeln für abgeleitete Klassen und Definitionsregeln für abgeleitete Attribute, sowie der Redefinition von Regeln für abgeleitete
Attribute wird in Abschnitt 2.2 erläutert.
2.1.1.4 Chimera Views
Sichten (engl. view) in Chimera stellen ein Nischenkonzept dar. Die Elemente von Chimera
Sichten sind keine Objekte mehr, da sie die Eigenschaften von unterschiedlichen Klassen, die
nicht zu einer Klassenhierarchie gehören müssen, vereinigen können. Da die Datensätze einer
Sicht keine Objekte darstellen, besitzen sie auch keinen Objektidentifikator (OID). Bei der
Definition einer Sicht können Attribute aller im Schema vorhandenen Objektklassen verwendet werden: Sichten stehen immer außerhalb einer Klassenhierarchie.
Chimera Sichten übernehmen die Funktion von vordefinierten Anfragen an den Datenbestand
einer Chimera Datenbank. Die Verwendung von Sichten ist besonders interessant in Verbindung mit der Negation innerhalb deklarativer Ausdrücke. Deklarative Ausdrücke (siehe Abschnitt 2.2) bestehen aus Konjunktionen. Mit Hilfe von Sichten und Negationen können nun
aber auch Disjunktionen ausgedrückt werden.
Um die Definition von Chimera-Sichten zu vereinfachen, wurden die möglichen Wertebereiche eingeschränkt: Attribute von Sichten dürfen nur mit Hilfe atomarer und Tupeldatentypen
definiert werden. Die Definition von Sichten in Chimera basiert auf deduktiven Regeln, die
mit Hilfe deklarative Ausdrücke formuliert werden können (siehe Abschnitt 2.2).
2.1.1.5 Constraints
Jeder Datenbankzustand muß alle Integritätsbedingungen erfüllen. Eine Integritätsbedingung
entspricht einer Bedingung, die nur im Fehlerfalle erfüllt werden darf. Im Chimera-Modell
werden "constraints" als Sichten angesehen. Falls eine Integritätsbedingung durch einen Da12
Inhaltsverzeichnis
tenbankzustand verletzt wird, kann mindestens ein Datensatz für eine solche Sicht hergeleitet
werden. Mit Hilfe des Trigger-Konzeptes (siehe Abschnitt 2.1.1.6) von Chimera ist es möglich, benutzerdefinierte Aktionen mit der Verletzung einer Integritätsbedingung zu verknüpfen. Es gibt zwei unterschiedliche Arten von Integritätsbedingungen, die sich nur durch den
Zeitpunkt der Überprüfung einer Integritätsbedingung unterscheiden:
•
"immediate constraints"
•
"deferred constraints"
Um die genaue Bedeutung der beiden Arten zu verstehen, sind einige Informationen aus Kapitel 2.3 nötig. Anfragen und Datenmanipulationen werden in sogenannten Transaktionen
zusammengefaßt. Eine Transaktion besteht aus mehreren Transaktionszeilen und wird durch
den "commit"-Befehl beendet.
"Immediate constraints" werden nach jeder einzelnen Transaktionszeile überprüft. Im folgenden Beispiel wird also nach jeder Datenmanipulation, sei es nun das Einfügen, Löschen oder
Verändern eines oder mehrerer Datensätze geprüft, ob jeder Kunde eine Kontonummer besitzt:
define object class kunde
attributes
name
:
string,
konto_nr:
integer
constraint
immediate hat_keine_kontonummer
end;
define object class konto
attributes
konto_nr:
integer,
guthaben:
real
key
(konto_nr)
end;
"Deferred constraints" werden am Ende einer Transaktion, also nach erst nach dem Befehl
"commit" überprüft. Dieses Vorgehen hat den Vorteil, daß mehrere Aktionen ausgeführt
werden können, bevor eine Überprüfung der Integritätsbedingung am Ende einer Transaktion
geschieht. Dieses Vorgehen wird durch folgendes Beispiel motiviert; die Problemstellung ist
identisch zur obigen, bis auf die Forderung, daß jedes Konto einen Kontoinhaber besitzen
muß. Dadurch werden die veränderten Integritätsbedingungen erforderlich:
define object class kunde
attributes
name
:
string,
konto_nr:
integer
constraints
deferred hat_keine_kontonummer
end;
13
Inhaltsverzeichnis
define object class konto
attributes
konto_nr:
integer,
inhaber:
string,
guthaben:
real
constraints
deferred hat_keinen_inhaber
key
(konto_nr)
end;
Falls beide Integritätsbedingungen sofort nach Einfügen eines Datensatzes überprüft würden,
könnte kein Datensatz für einen neuen Kunden oder ein neues Konto angelegt werden. Erst
durch Überprüfung der beiden Integritätsbedingungen am Ende einer Transaktion ist es möglich, sowohl einen neuen Kunden in die Datenbank einzufügen, als auch ein neues Konto zu
eröffnen.
Die bisher vorgestellten Integritätsbedingungen nennt man auch "targeted constraints". Dieser
Name beruht auf der Tatsache, daß jede Integritätsbedingung eindeutig einer Objektklasse
zugeordnet werden kann. Im Gegensatz dazu werden "untargeted constraints" einer ganzen
Datenbank zugeordnet. Auch bei diesen freien Integritätsbedingungen gibt es die Unterscheidung zwischen solchen, die sofort überprüft werden, und solchen, die erst am Ende einer
Transaktion ausgewertet werden. Die Art und Weise wie eine Integritätsbedingung definiert
werden kann wird in Abschnitt 2.2 erläutert.
Integritätsbedingungen können auch ohne die Angabe des Bearbeitungsmodus definiert werden. Diese Integritätsbedingungen werden dann automatisch als "deferred constraints" umgesetzt.
Bei der Auswertung von Integritätsbedingungen und Trigger ist eine feste Reihenfolge vorgesehen: Zuerst werden alle Trigger ausgewertet und deren Aktionen ausgeführt. Anschließend
werden alle Integritätsbedingungen überprüft.
2.1.1.6 Trigger
Ein Trigger reagiert auf Veränderungen des Datenbestandes oder auf Aufrufe von Operationen. Im Gegensatz zu Integritätsbedingungen kann der Entwickler allerdings zusätzlich zur
Ursache die Folgen frei definieren. Trigger bestehen immer aus drei Teilen:
•
Event
•
Condition
•
Action
Ein Trigger feuert bei einem bestimmten Ereignis (engl. event), wertet eine Bedingung (engl.
condition) aus und führt im Anschluß eine Aktion (engl. action) aus. Dieses dreistufige Konzept wird in der Datenbanktheorie als ECA-Paradigma bezeichnet.
14
Inhaltsverzeichnis
Um einen Chimera-Trigger definieren zu können benötigt der Entwickler Wissen über deklarative Ausdrücke in Chimera (siehe Abschnitt 2.2).
Ähnlich wie bei Integritätsbedingungen unterscheidet man auch bei Triggern zwischen "immediate" und "deferred" Triggern. Wie bei Integritätsbedingungen, wird bei Triggern dadurch
der Zeitpunkt der Auswertung der Bedingung und die Ausführung der Aktion beeinträchtigt.
2.1.2 Klassenhierarchien und Vererbung in Chimera
Eines der Hauptkonzepte der Objektorientierung ist die Vererbung. Vererbung findet immer
in einer festgelegten Richtung statt: Eine Oberklasse, vererbt prinzipiell alle extensionalen
und abgeleiteten Attribute, Integritätsbedingungen, Trigger und Operationen an alle Unterklassen. Dies bedeutet, daß alle Instanzen einer Unterklasse alle Attribute der Oberklassen
besitzt und alle Integritätsbedingungen ihrer Oberklassen erfüllen muß. Zusätzlich stehen alle
Operationen der Oberklassen und alle Trigger der Oberklassen zur Verfügung. Ein Trigger
reagiert auf alle Änderungen innerhalb der Klassenhierarchie, die durch die den Trigger definierende Objektklasse, als Oberklasse definiert wird. Jede Unterklasse kann zusätzliche Integritätsbedingungen, Trigger und Operationen definieren. Die Definitionsregeln von
abgeleiteten Attributen können für eine Unterklasse neu definiert werden.
Hinter dem objektorientierten Konzept der Vererbung steht folgende Idee: "Besitzen mehrere
Datentypen (Objektklassen) gemeinsame Eigenschaften, so faßt man die Gemeinsamkeiten in
einer Klasse zusammen. Die für jeden Datentyp (Objektklasse) spezifischen Eigenschaften
definiert man jeweils in einer eigenen Klasse, die man zur Unterklasse der Klasse der Gemeinsamkeiten macht. Alle Deklarationen der Oberklasse vererben sich dann an die Unterklassen" [Inf93].
Das folgende Beispiel definiert in Verbindung mit dem Beispiel aus Abschnitt 2.1.1.3 eine
kleine Klassenhierarchie:
define object class schueler
superclasses
person
attributes
schule:
string notnull,
klasse:
integer notnull,
faecher:
list-of(string)
end;
Ein "schueler" ist eine "person", der zusätzliche Merkmale besitzt: Jeder Schüler muß
Schüler einer Schule sein und besucht eine bestimmte Klasse. Zusätzlich besucht ein
"schueler" den Unterricht in einer Reihe von Fächern. Die Objektklasse "schueler"
erbt die Attribute "name", "vorname", "geschlecht" und "adresse" aus der Klasse
"person". Dies bedeutet, daß z.B. bei Anfrage an den Namen und Vornamen von einer
"person" ebenfalls die Objekte der Klasse "schueler" ausgewertet werden müssen.
Abbildung 2.1 erweitertet die obigen Klassenhierarchie um zwei extensionale Objektklassen
und eine abgeleitete Objektklasse.
15
Inhaltsverzeichnis
Eine Anmerkung zur grafischen Notation im folgenden Beispiel: Es gibt verschiedene grafische Notationen um objektorientierte Klassenhierarchien darzustellen. Folgende Abbildung
basiert auf der Darstellung der Bonner Implementation von Chimera ("Chimera Prototyping
Tool (CPT)", siehe Kapitel 3):
•
Vererbungspfeile verweisen immer von der Unterklasse auf die Oberklasse.
•
Extensionale Objektklassen werden durch einen durchgezogen Rahmen und abgeleitete
Objektklassen durch einen gestrichelten Rahmen repräsentiert.
person
schueler
oberstufe
student
abitur
Abbildung 2.1: Klassenhierarchie mit abgeleitete Objektklasse
Durch die Verwendung von abgeleiteten Objektklassen wird die Definition von Unterklassen
in einer Chimera-Klassenhierarchie eingeschränkt: Abgeleitete Objektklassen dürfen nur abgeleitete Unterklassen besitzen. Diese Einschränkung basiert auf folgendem Problem: Die
Objekte extensionaler Unterklassen einer abgeleiteten Oberklasse müssen weiterhin die Bedingungen der Populationsregeln der abgeleiteten Objektklasse erfüllen. Diese Forderung
kann zwar durch die Definition einer entsprechenden Integritätsbedingungen umgangen werden, dieses Vorgehen ist allerdings nicht in jedem Fall möglich. Für obiges Beispiel bedeutet
dies, daß die abgeleitete Objektklasse "abitur" nur abgeleitete Unterklassen besitzen darf.
Klassenhierarchien müssen, wie im obigen Beispiel, eine eindeutige Oberklasse besitzen. Es
ist allerdings auf jeder Unterebene einer Klassenhierarchie möglich, Mehrfachvererbungen
durchzuführen. Dies bedeutet, daß eine Unterklasse, ob nun extensional oder abgeleitet, die
Attribute, Integritätsbedingungen, Trigger und Operationen von zwei oder mehr Oberklassen
erbt. Bei Mehrfachvererbungen ist allerdings zu beachten, daß die vererbenden Oberklassen
keine zusätzlichen Attribute definieren dürfen, da ansonsten die Ausprägung eines Objektes
für jede direkte Oberklasse verschieden sein könnte.
16
Inhaltsverzeichnis
2.2 Deklarative Ausdrücke von Chimera
Im vorhergehenden Kapitel wurden die Konzepte eines Chimera-Schemas erläutert. Bei der
Behandlung der Schemakonzepte wurde häufig auf die deklarativen Ausdrücke von Chimera
verwiesen. Dieser Abschnitt wird nun die Möglichkeiten deklarativer Ausdrücke erläutern.
Die Beispiele, die in diesem Abschnitt vorgestellt werden, basieren auf der obigen Klassenhierarchie mit abgeleiteten Objektklassen (siehe Abbildung 2.1).
Deklarative Ausdrücke werden mit Hilfe von Termen und Formeln definiert: In deklarativen
Ausdrücken repräsentieren Terme Objekte oder einzelne Werte. Terme können atomar oder
komplex sein. Atomare Terme bestehen aus Variablen und Konstanten, komplexe Terme aus
Listen, Mengen und Tupeln. Formeln bestehen aus Operatoren und Parametern. Man unterscheidet ebenfalls zwischen atomaren und komplexen Formeln. Komplexe Formeln bestehen
aus mehreren atomaren Formeln, die mit Hilfe von Konjunktion und Negation kombiniert
werden.
Ein deklarativer Ausdruck kann aus mehreren Termen und Formeln bestehen. Die einzelnen
Bestandteile eines Ausdrucks können mittels Konjunktion zu einem Ausdruck kombiniert
werden. Die Konjunktion wird durch ein Komma (",") dargestellt. Um einen deklarativen
Ausdruck in Chimera zu definieren, stehen folgende Konzepte zur Verfügung:
•
Klassenformeln
•
arithmetische Funktionen
•
Vergleichsformeln
•
Aggregatsfunktionen
•
Mitgliedsformeln
•
Listenfunktionen
•
Mengenfunktionen
Die obigen Konzepte benötigen Konstanten und Variablen um korrekt angewendet zu werden.
Konstanten und Variablen müssen folgende Regeln einhalten:
• Zeichenketten müssen in doppelten Anführungszeichen (") stehen.
• Variablennamen müssen mit einem großgeschriebenen Buchstaben beginnen und dürfen keine Sonderzeichen (z.B. "ä", "ö", "ü" und "ß") enthalten.
Durch eine Klassenformel (engl. class formula) wird der Typ einer Variable festgelegt. Als
Typ einer Variable können Wertetypen, Werteklassen und Objektklassen verwendet werden.
Die Bedeutung der Variable unterscheidet sich zwischen Wertetypen und -klassen sowie Objektklassen. Wird eine Variable an eine Wertetyp oder eine Werteklasse gebunden, so repräsentiert sie einen Wert des jeweiligen Typs oder der jeweiligen Klasse. Im Falle einer
Zuordnung zu einer Objektklasse, repräsentiert die Variable die Objektidentifikatoren der
einzelnen Objekte:
person(X)
integer(I)
geschlecht(G)
Durch obige Klassenformeln wird die Variable X an die Objektklasse "person" gebunden.
Über die Variable X sind nun also alle Objekte der Klassen "person" ansprechbar. Die Va17
Inhaltsverzeichnis
riable I hingegen repräsentiert eine ganze Zahl. Der Wertebereich der Variable G ist auf die
Werte der Werteklasse "geschlecht" eingeschränkt.
Auf die Attribute einer Objektklasse kann mit dem Punkt-Operator (".") zugegriffen werden.
Die Attributfunktion selektiert das entsprechende Attribut der Objektklasse:
X.name
X.vorname
Z.klasse
Ein wichtiges Konzept deklarativer Ausdrücke sind Vergleichsformeln. Zur Definition von
Vergleichsformeln innerhalb deklarativer Ausdrücke können folgende Operatoren verwendet
werden:
•
=
•
\=
•
<
•
<=
•
>
•
>=
Mit Hilfe dieser Vergleichsoperatoren lassen sich folgende Vergleichsformeln bilden:
X.name = "Horn"
X.name != Z.name
Z.klasse <= 9
Z.adresse.wohnort = "Meckenheim"
Das letzte Beispiel zeigt einen Pfadausdruck. Pfadausdrücke erlauben einen gezielten Zugriff auf einzelne Komponenten eines strukturierten Attributes. Basierend auf einer Schemadefinition unterstützt Chimera beliebige lange Pfadausdrücke in deklarativen Ausdrücken. Die
Pfadausdrücke können sowohl auf der linken als auch auf der rechten Seite von Operatoren
stehen.
Die obigen Beispiele für Vergleichsformeln sind nicht vollständig, da die Variablen X und Z
sind nicht an eine Objektklasse gebunden wurden. Daher können obige Beispiele nicht korrekt ausgewertet werden. Jede Variable, die innerhalb eines deklarativen Ausdrucks verwendet wird, muß mittels einer Klassenformel an einen Wertetyp, eine Werteklasse oder eine
Objektklasse gebunden werden. Durch die Konjunktion von Klassen- und Vergleichsformeln
entstehen vollständige deklarative Ausdrücke:
person(X), X.name = "Horn"
person(X), student(Z), X.name != Z.name
Ein weiteres Konzept zur Definition deklarativer Ausdrücke sind Mitgliedsformeln (engl.
membership formula). Nachdem eine Variable durch eine Klassenformel einem Wertebereich
zugeordnet wurde, kann mit Hilfe einer Mitgliedsformel der Wertebereich der Variable zusätzlich eingeschränkt werden. Mitgliedsformeln können für die Zugehörigkeit zu Objektklassen, Wertetypen und Werteklassen definiert werden:
person(X), X in abitur
Durch obigen deklarativen Ausdruck wird die Variable X an alle Objektidentifikatoren der
Objektklasse "person" gebunden, die gleichzeitig Mitglied der abgeleiteten Objektklasse
"abitur" sind.
18
Inhaltsverzeichnis
Das letzte Konzept zur Definition deklarativer Ausdrücke sind Funktionen und Operatoren,
die dazu dienen Terme zu definieren, die Werte, Listen und Mengen bearbeiten. Zur Definition deklarative Ausdrücke in Chimera können folgende Funktionen und Operatoren verwendet
werden:
Arithmetische Fkt.
Aggregatfunktionen
Listenoperatoren
Mengenoperatoren
Addition:
+
Maximum:
max
Konkatenation: //
Vereinigung: +
Subtraktion:
-
Minimum:
min
Kopf der Liste: hd
Differenz:
-
Multiplikation: *
Summe:
sum
Rest der Liste: tl
Aufspalten:
*
Division:
/
Durchschnitt: avg
Modulo:
mod
Kardinalität: card
Zuweisung:
=
2.2.1 Anwendung deklarativer Ausdrücke
Im letzten Abschnitt wurden die Möglichkeiten und Konzepte deklarativer Ausdrücke vorgestellt. Die folgende Abschnitte befassen sich mit der Anwendung deklarativer Ausdrücke.
Deklarative Ausdrücke werden zur Formulierung von Anfragen benötigt (siehe Kapitel 2.3)
und zur Definition der Ausprägung von Schemakomponenten angewendet werden. Deklarative Ausdrücke müssen zur Definition folgender Konzepte verwendet werden:
•
Klassenpopulationsregeln
•
Attributdefinitionsregeln
•
Definition von Triggern
•
Definition von Integritätsbedingungen
Die Ausprägung von Schemaobjekten wird in der Implementation des Objektes definiert. Die
Ausprägungen können mittels verschiedener Schlüsselworte zu einer Implementation einer
Objektklasse zusammengefaßt werden. Alle Konzepte, die im Implementationsteil einer Objektklassendefinition definiert werden, können durch mehrere Regeln definiert wenden.
Daten von abgeleiteten Objektklassen müssen via Populationsregeln definiert werden. Bei
der Definition einer solchen Regel dürfen nur Informationen von Oberklassen der zu definierenden Klasse verwendet werden. Populationsregeln einer abgeleiteten Klasse werden nach
dem Schlüsselwort "population" definiert:
19
Inhaltsverzeichnis
define object class oberstufe
superclasses
schueler
attributes
note_leistungskurs1:
note_leistungskurs2:
note_grundkurs1:
note_grundkurs2:
durchschnitt:
constraints
illegale_note
end;
define object class abitur
derived superclass
oberstufe
attributes
durchschnitt:
trigger
abitur_bestanden
end;
integer,
integer,
integer,
integer,
integer derived
integer redefined
define implementation for abitur
population
abitur(X) <oberstufe(X),
X.klasse = 13,
X.durchschnitt <= 4
end;
Obige Populationsregel definiert die Ausprägung der abgeleiteten Klasse "abitur". Alle
Schüler der dreizehnten Klasse mit einem Notendurchschnitt von 4 oder besser gehören zur
Population der Klasse. Die Definition der Populationsregel der Klasse "abitur" basiert auf
dem abgeleiteten Attribut "durchschnitt" der Objektklasse "oberstufe". Attributdefinitionsregeln für abgeleitete Attribute werden innerhalb der Implementation einer Objektklasse nach dem Schlüsselwort "attributes" definiert. Folgende Definition berechnet
den Notendurchschnitt eines Schülers der Oberstufe:
define implementation for oberstufe
attributes
Self.durchschnitt <avg(
Self.note_leistungskurs1,
Self.note_leistungskurs2,
Self.note_grundkurs1,
Self.note_grundkurs2
)
end;
Obige Attributdefinitionsregel definiert die Berechnung des Attributes "durchschnitt"
der Objektklasse "oberstufe". Das Beispiel benutzt eine in der Regel nicht eingeführt
Variable "Self". Bei der Definition von Attributdefinitionsregeln kann die vom System
20
Inhaltsverzeichnis
vordefinierte Variable "Self" verwendet werden um Objekte der aktuellen Klasse direkt
anzusprechen. In der Definition der abgeleiteten Klasse "abitur" wird das Attribut
"durchschnitt" erneut definiert. Dies bedeutet, daß die Berechnungsregel der Objektklasse "oberstufe" nicht für Objekte der Klasse "abitur" gelten soll. Der Durchschnitt
eines Abiturienten soll auf einer anderen Berechnungsregel basieren als der eines Oberstufenschülers:
redefine implementation for abitur
attributes
Self.durchschnitt <avg(
Self.note_leistungskurs1,
Self.note_leistungskurs1,
Self.note_leistungskurs2,
Self.note_leistungskurs2,
Self.note_grundkurs1,
Self.note_grundkurs2
)
end;
Die obige Redefinition der Berechnungsregel für die abgeleitete Objektklasse "abitur"
hat keinen Einfluß auf die Populationsregel der Objektklasse. Durch Redefinition können Attributdefinitionsregeln und die Definitionen von Integritätsbedingungen und Triggern verändert werden. Ab einer Redefinition wird jeweils die redefinierte Regel oder Definition an alle
Unterklassen vererbt.
Integritätsbedingungen werden im Implementationsteil einer Objektklasse formuliert. Die
Signatur einer Integritätsbedingung wird in der Definition der dazugehörigen Objektklasse
festgelegt. Die obige Definition der Objektklasse "oberstufe" definiert die Integritätsbedingung "illegale_note". Die Objekte, die die Integritätsbedingung verletzen, werden
durch folgende deduktive Regel hergeleitet:
define implementation for oberstufe
constraints
illegale_note(Self) <Self.note_leistungskurs1 <
Self.note_leistungskurs1 >
illegale_note(Self) <Self.note_leistungskurs2 <
Self.note_leistungskurs2 >
illegale_note(Self) <Self.note_grundkurs1 < 0,
Self.note_grundkurs1 > 6
illegale_note(Self) <Self.note_grundkurs2 < 0,
Self.note_grundkurs2 > 6
0,
6
0,
6
end;
Obige Integritätsbedingung wird verletzt, sobald für einen Schüler der Oberstufe eine illegale
Note für einen der vier Kurse eingegeben wird. Sobald eine Note schlechter als 6 und besser
21
Inhaltsverzeichnis
als 1 eingegeben wird, verletzt die Modifikation des Objektes die Integritätsbedingung. Der
Wert 0 für Noten wird zusätzlich noch zugelassen, um einen Wert für Noten eingeben zu
können, die noch nicht vergeben wurden. Obige Bedingung ist ein Beispiel dafür, daß Integritätsbedingungen durch mehrere Regeln definiert werden können. Entscheidend für die
Verletzung einer Integritätsbedingungen ist hierbei, daß mindesten eine der Regeln verletzt
wird.
Die Definition eines Triggers ist der letzte Verwendungszweck von deklarativen Ausdrücken
bei der Definition eines Chimera-Schemas. Die Definition eines Triggers besteht aus drei Abschnitten:
•
Ereignis: Ein Trigger ist in der Lage auf mehrere Ereignisse innerhalb der Population
einer Objektklasse zu reagieren. Die einzelnen Elemente der Liste von Ereignissen werden
durch ein Semikolon (";") voneinander getrennt.
•
Bedingung: Zur Definition des Bedingungsteils eines Triggers können beliebige deklarative Ausdrücke verwendet werden.
•
Aktion: Aktionen bestehen aus DML-Operationen von Chimera
Folgendes Beispiel definiert den Trigger "abitur_bestanden" der Objektklasse
"abitur":
define trigger abitur_bestanden for abitur
events
modify(durchschnitt)
condition
Self.durchschnitt <= 4,
Self.note_leistungskurs1 \= 0,
Self.note_leistungskurs2 \= 0,
Self.note_grundkurs1 \= 0,
Self.note_grundkurs2 \= 0
action
generalize(abitur, schueler, Self)
Obiger Trigger verallgemeinert ein Objekt der Objektklasse "abitur", sobald der berechnete Notendurchschnitt besser als 4 ist und alle Noten eingeben wurden. Das Objekt wird daraufhin in die Oberklasse "schueler" verschoben. Die zusätzlichen Informationen eines
Objektes der Klasse "oberstufe" gehen in diesem Beispiel allerdings durch die Verallgemeinerung verloren.
2.3 Imperative Ausdrücke von Chimera
Vor der Vorstellung der imperativen Ausdrücke von Chimera, muß noch das Transaktionskonzept von Chimera erläutert werden: Anfragen und Datenmanipulationen werden in Transaktionen zusammengefaßt. Eine Transaktion wird mit dem Befehl "commit" oder
"rollback" beendet. Der "commit"-Befehl schreibt alle Änderungen der Transaktion
endgültig in die Datenbank. "rollback" macht alle Änderungen der Transaktion rückgängig und beläßt die Datenbank in dem Zustand, der vor Beginn der Transaktion existierte. Am
Ende einer Transaktion werden alle "deferred"-Trigger und -Integritätsbedingungen ausgewertet. Chimera benötigt keinen expliziten Befehl, um eine Transaktion zu beginnen. Der
22
Inhaltsverzeichnis
erste imperative Ausdruck nach einem "commit" oder "rollback" startet eine neue
Transaktion.
Eine Transaktion kann aus einer oder mehreren Transaktionszeilen bestehen. Eine Transaktionszeile wird durch ein Semikolon (";") abgeschlossen. Alle Variablenbindungen gelten
immer nur in einer Transaktionszeile. In einer Transaktionszeile können mehrere Befehle
durch den Sequenzoperator Komma (",") oder durch den Pipeoperator ("|") zusammengefaßt werden. Die Unterschiede zwischen den beiden Operatoren besteht in der Abarbeitungsreihenfolge der einzelnen Befehle: In einer Sequenz wird jeder Befehl komplett ausgeführt,
bevor der nächste Befehl abgearbeitet wird. Durch diese Abarbeitung der Befehle können
Mengen von Variablenbindungen entstehen, die dann von nächsten Befehl komplett bearbeitet werden müssen. Durch den Pipeoperator wird ein Befehl immer einmal abgearbeitet, danach eine eventuelle Bindung einer Variable an den nächsten Befehl weitergeben, dieser
abgearbeitet und danach erst der erste Befehl wieder ausgeführt.
Anfragen können in Chimera mit Hilfe zweier unterschiedlicher Operationen gestellt werden:
select und display
Der Unterschied zwischen beiden Operationen ist der Umgang mit dem Ergebnis der Anfrage:
"display" zeigt das Ergebnis auf dem Bildschirm an, "select" bindet Objektidentifikatoren an eine Variable. Die allgemeine Syntax von "select"- und "display"Befehlen lautet
select(V where B)
display(A where B)
wobei V eine Liste von Objektvariablen, A eine Liste von Attributen, und B die selektierende
Bedingung ist, die alle in V bzw. A auftretenden Variablen an jeweils eine Objektklasse bindet
und die Auswahl zusätzlich beliebig einschränkt. Die Bedingung kann ein beliebiger deklarativer Ausdruck sein:
select(X, Y where
person(X), adresse(Y) X.adresse = Y)
display(Z.name, Z.adresse.wohnort where
schueler(Z), Z in oberstufe, Z.klasse = 12)
Die Bindungen der Variablen X und Y im obigen "select"-Beispiel können in einer Transaktionszeile zur Datenmanipulationen eingesetzt werden. Die selektierten Attribute des
"display"-Befehls werden auf dem Bildschirm ausgegeben und können nicht weiterverwendet werden.
Imperative Ausdrücke von Chimera können zusätzlich zu den obigen Anfrageoperationen
durch fünf Datenmanipulations- und Objektmigrationsoperationen formuliert werden. Mit
Hilfe der Operationen können Objekte erzeugt, gelöscht oder die Ausprägung von Objekten
verändert werden. Folgende Operationen stehen zur Verfügung:
23
Inhaltsverzeichnis
Objektmigration
Datenmanipulation
•
generalize
•
create
•
specialize
•
delete
•
modify
Die beiden Objektmigrationsoperationen verändern die Klasse, zu der ein Objekt gehört.
Mittels der "generalize"-Operation kann ein Objekt von einer Unterklasse in eine Oberklasse migrieren. Durch diesen Operation verliert das Objekt zusätzliche, in der Unterklasse
definierte, Attribute. Die Operation benötigt drei Parameter, um die Aktion ausführen zu können: den Namen der Unterklasse, den Namen der Oberklasse und die Objektidentifikatoren
der Objekte:
select(Z, where student(Z), Z.semester > 20),
generalize(student, person, Z);
Obiges Beispiel selektiert zuerst alle Studenten, die länger als 20 Semester studieren und exmatrikuliert sie anschließend indem die Objekte in die Objektklasse "person" verschoben
werden. Die selektierten Objekte der Klasse "student" sind nach dieser Operation nur
noch Objekte der Klasse "person". Die Objekte der Klasse "student" verlieren durch
diese Operation alle Attribute, die in den Klassen "schueler" und "student" definiert
wurden.
"specialize" verschiebt ein Objekt von einer Oberklasse in eine Unterklasse. Das verschobene Objekt erhält dadurch die in der Unterklasse definierten neuen Attribute. Die
"specialize"-Operation benötigt dafür vier Parameter: den Namen der Oberklasse, den
Namen der Unterklasse, die Objektidentifikatoren und die Werte der zusätzlichen Attribute:
select(X where person(X), X.name = "Horn"),
specialize(person, schueler, X, [schule: "Konrad-AdenauerGymnasium", klasse: 10, faecher: <"Deutsch">]);
Obiges Beispiel selektiert alle Objekte der Klasse "person", deren Attribut Name den Wert
"Horn" hat und verschiebt sie in die Unterklasse "schueler". Die Werte der in der Unterklasse "schueler" definierten Attribute werden in Form eines Tupels definiert.
Der Unterschied zwischen den beiden Objektmigrationsoperationen und einer Kombination
aus den noch vorzustellenden "create"- und "delete"-Operationen liegt in dem Wert
des Objektidentifikators: Durch die Migration wird die OID eines Objektes nicht verändert.
Ein Löschen und erneutes Einfügen eines neuen Objektes mit identischen Werten hingegen,
verändert den Wert des Objektidentifikators. Im objektorientierten Kontext sind die beiden
Objekte dadurch nicht identisch.
Die drei Datenmanipulationsoperationen erzeugen oder löschen Objekte bzw. manipulieren
die Werte der jeweiligen Attribute. Die "create"-Operation benötigt folgende drei Parameter:
24
Inhaltsverzeichnis
•
den Namen der Objektklasse, in die ein neues Objekt eingefügt werden soll
•
die Werte aller Attribute des zu erzeugenden Objektes
•
eine Variable für den erzeugten Objektidentifikator
Das folgendes Beispiel zeigt die Kombination zweier "create"-Befehle in einer Transaktionszeile:
create(adresse, (strasse: "Lueftelberger Str. 9",
plz: 53340, wohnort: "Meckenheim"), A),
create(person, (name: "Horn", vorname: "Michael",
geschlecht: "maennlich", adresse: A), P);
Der erste "create"-Befehl im obigen Beispiel gibt als Ergebnis seiner Aktion die OID des
erzeugten Objektes zurück. In einer Transaktionszeile kann diese OID beliebig weiterverwendet werden. Im Beispiel bedeutet dies, daß nach der Erzeugung einer neuen "adresse", der
Wert des Objektidentifikators im zweiten "create"-Befehl als Wert des Attributes
"adresse" eingesetzt wird. Der Wert der Variable A ist allerdings für den Rest der Transaktionszeile nicht veränderbar!
Die "modify"-Operation ändert den Wert eines Attributes. Die Operation benötigt drei Parameter: den Klassenname mit dem dazugehörigen Attribut, die Objektidentifikatoren und die
neuen Werte:
select(X where student X ),
modify(student.semester, X, X.semester+1);
Im obigen Beispiel wird der Wert des Attributes "semester" von allen Objekten der Klasse "student" um eins erhöht. Die durch den "select"-Befehl gebundene Variable X
wird zur Selektion der betroffenen Objekte verwendet.
Die letzte Operation zur Datenmanipulation löscht ein vorhandenes Objekt aus einer Objektklasse. Die "delete"-Operation benötigt für das Löschen von Objekten den Namen der
entsprechenden Objektklasse und die entsprechenden Objektidentifikatoren:
select(X where student(X), X.name = "Horn"),
delete(student, X);
Obiges Beispiel löscht alle Objekte der Klasse "student", deren Namensattribut den Wert
"Horn" hat. Aufgrund von Vererbung innerhalb von Klassenhierarchien ist die Verwendung
der "delete"-Operation mit Bedacht einzusetzen: Die Operation löscht das Objekt in allen
Klassen der Hierarchie. Nach der Ausführung der obigen Aktion werden auch keine Objekte
der Klasse "person" existieren, deren Namensattribut den Wert "Horn" hat. Die
"delete"-Operation löscht das komplette Objekt, ohne Rücksicht auf den Menge der Klassen, in denen es enthalten ist. In den meisten Fällen wird die "generalize"-Operation
eher den gewünschten Effekt erzielen, da dadurch diese Operation das Objekt nur aus der
Klasse "student" und allen Unterklassen entfernt wird.
25
Inhaltsverzeichnis
Michael Horn
3 Das Chimera Prototyping Tool
Das Chimera Prototyping Tool (CPT) ist eine Implementierung von Chimera an der Bonner
Universität (http://www.informatik.uni-bonn.de/~idea). Die Bonner Umsetzung von Chimera
basiert auf dem in Prolog realisierten relationalen Datenbankmanagementsystem Phoenix.
Das Phoenix-System ist in ECLiPSe-Prolog realisierte Implementierung der aktive und deduktive Datenbankprogrammiersprache (engl. database programming language DBPL) Phoenix, die auf dem relationalen Datenmodell basiert. Die Daten werden dabei entweder im
Hauptspeicher des Computers gehalten oder persistent auf einem Datenträger gespeichert. Bei
der persistenten Speicherung wird auf das MegaLog-Untersystem von ECLiPSe zurückgegriffen.
Die graphische Benutzeroberfläche des CPT (CPT/GUI) unterstützt den Benutzer bei dem
Entwurf von Chimera-Datenbanken. Die CPT/GUI bietet einen Überblick über die Klassenhierarchien eines Chimera-Schemas und die einzelnen Abhängigkeiten zwischen den Objektklassen. Alle Informationen bzgl. einer Objektklasse eines Schemas können mit Hilfe der
graphischen Oberfläche visualisiert werden. Abbildung 3.1 zeigt den Dialog zum Entwurf und
zur Modifikation einer Objektklasse. Der Dialog zur Definition von Objektklassen verteilt die
unterschiedlichen Optionen einer Objektklasse auf mehrere Karteikarten. Die auf der nächsten
Seite abgebildete Karteikarte dient zur Definition von Attributen. Auf den folgenden Seiten
können Integritätsbedingungen, Operationen, Trigger und Populationsregeln definiert und
modifiziert werden. Eine genauere Beschreibung der Funktionen und Möglichkeiten des
Chimera Prototyping Tools befindet sich im CPT-Handbuch ([GLM96]).
26
Inhaltsverzeichnis
Abbildung 3.1: Graphischer Entwurf einer Objektklasse mit Hilfe der graphischen Benutzeroberfläche des Chimera Prototyping Tools (CPT/GUI)
Die folgenden Abschnitte beschäftigen sich mit der Architektur der Bonner Implementierung,
dem Bonner Chimera-Dialekt und den Unterschieden zwischen Chimera und dem Bonner
Chimera-Dialekt. Der letzte Abschnitt dieses Kapitels beschäftigt sich mit der Abbildung des
objektorientierten Datenmodells Chimera auf das relationale Datenmodell von Phoenix.
3.1 Architektur des CPT
Das Chimera Prototyping Tool besteht aus zwei Benutzerschnittstellen, einem ChimeraCompiler, einem Phoenix-Interpreter und dem ECLiPSe-Prolog-System. Bei der Arbeit mit
dem CPT hat der Benutzer die Wahl zwischen einer Kommandoschnittstelle (CPT/CI) und
einer auf Tcl/Tk basierenden grafischen Oberfläche (CPT/GUI).
27
Inhaltsverzeichnis
DDL
DML
CPT/GUI
SEA
PRPT
CPT/CI
PRDT
CARDT
PROP
Chimera-Compiler
Phoenix-DBPL-Interpreter
CDD
ECLiPSe
CPT
MegaLog-DB
Prolog-DB
(persistent)
(temporär)
Abbildung 3.2: Architektur des Chimera Prototyping Tools (CPT) inklusive der zusätzlichen Entwicklungswerkzeuge und -assistenten
28
Inhaltsverzeichnis
Im Rahmen mehrere Diplom- und Forschungsarbeiten sind im Umfeld des CPT weitere Entwicklungswerkzeuge und -Assistenten entwickelt worden:
•
Schema Evolution Assistant (SEA, [Lem94 und LM95])
•
Passive Rule Prototyping Tool (PRPT, [Schu99])
•
Passive Rule Design Tool (PRDT, [Asc96, LM97])
•
Chimera Active Rule Design Tool (CARDT, [Schi98])
•
Propagation Rule Compiler (PROP, [DG94])
Alle Erweiterungen basieren auf dem CPT/GUI. Die Architektur des CPT ist streng hierarchisch geordnet: Alle Datendefinitions- und Datenmanipulationsbefehle werden von den beiden Benutzerschnittstellen an den Chimera-Compiler weitergereicht. Während der
Erstellung oder des Einlesens eines Chimera-Schemas werden die Schemainformationen
durch einen Parser in eine interne Darstellung des Chimera Schemas überführt. Die interne
Schemadarstellung wird im Chimera Data Dictionary (CDD) gespeichert. Das genaue Aussehen des CDD wird in Abschnitt 3.3 erläutert. Basierend auf der internen Repräsentation des
Chimera-Schemas übersetzt der Chimera-Compiler Datendefinitions- und Datenmanipulationsbefehle.
Nach der Übersetzung der Chimera-Befehle in entsprechende Phoenix-Befehle durch den
Compiler, werden die Befehle vom Phoenix-DBPL-Interpreter verarbeitet und an das
ECLiPSe–System weitergereicht. Je nach gewähltem Modus werden die Daten entweder temporär im Arbeitsspeicher (Prolog-Modus) oder persistent auf einem Datenträger (MegaLogModus) gespeichert.
Alle Konfigurationsinformationen werden in einer Datei (".chimerarc") gespeichert. In
dieser Datei muß das CPT-Verzeichnis, ein Datenverzeichnis und der oben beschriebene Datenbankmodus konfiguriert werden. Chimera erwartet die Konfigurationsdatei im HomeVerzeichnis des jeweiligen Benutzers.
3.2 Der Bonner Chimera-Dialekt
Während der Implementation des CPT, sind einige Einschränkungen und Veränderungen an
der Chimera-Sprachdefinition vorgenommen worden. Diese Veränderungen wurden durch die
gewählte Implementationsweise motiviert. Die folgenden Abschnitte basieren auf der Diplomarbeit von Stefan Schubert ([Sch99]), der Implementationsdokumentation des CPT von Ulrike Griefahn und Thomas Lemke ([GL96]) und eigenen Beobachtungen durch den Umgang
mit dem CPT.
29
Inhaltsverzeichnis
3.2.1 Unterschiede zwischen Chimera- und CPT-Datenmodell
Basierend auf der im folgenden Abschnitt vorgestellte relationalen Übersetzung für ChimeraObjektklassen und Klassenhierarchien, existieren einige Einschränkungen für abgeleitete
Objektklassen:
•
Abgeleitete Objektklassen dürfen keine neuen extensionalen Attribute definieren.
•
Abgeleitete Objektklassen dürfen nur genau eine direkte Superklasse besitzen.
•
Abgeleitete Objektklassen dürfen nur abgeleitete Unterklassen besitzen.
Die Forderung, daß abgeleitete Objektklassen keine extensionalen Attribute besitzen dürfen,
wird durch die Tatsache motiviert, daß eine abgeleitete Objektklasse mit extensionalen Attributen materialisiert werden müßte, um die extensionalen Attribute abspeichern zu können.
Die Forderung nach einer eindeutigen direkten Oberklasse basiert auf dem Problem der Ausprägung eines Objektes einer abgeleiteten Klasse bei Mehrfachvererbung. Durch Mehrfachvererbung vererben mehrere Superklassen ihre Attribute, Integritätsbedingungen usw. an die
Unterklasse. Durch die Populationsregeln einer abgeleiteten Klasse werden immer ganze Objekte einer Klasse in die Unterklasse übernommen. Je nach Herkunft der Objekte sind nicht
alle Attribute des Objektes der Unterklasse nach der Population mit Werten belegt. Um eine
komplexe Überprüfung bei Mehrfachvererbung zu umgehen, ist obiges Verbot formuliert
worden. Es ist zu beachten, daß das CPT keinen Fehler meldet, falls eine solche Mehrfachvererbung definiert worden ist.
Die letzte Einschränkung basiert auf dem Problem, daß die Populationsregeln einer abgeleiteten Klasse in Integritätsbedingungen einer extensionalen Unterklasse übersetzt werden
müßten. Dieses Vorgehen ist allerdings nur bei einfachen Populationsregeln möglich. Komplexe Populationsregeln lassen sich nicht ohne beachtlichen Aufwand in entsprechende Integritätsbedingungen übersetzen. Dieses Problem wird durch die aktuelle Implementierung
ebenfalls nicht erkannt.
Für ein CPT-Schema gelten ansonsten noch folgende Einschränkungen:
•
Jede Klassenhierarchie muß auf einer eindeutigen Superklasse basieren.
•
Die Namen von Integritätsbedingungen müssen, bezogen auf das gesamte Schema, eindeutig sein. Chimera fordert nur eine Eindeutigkeit des Namens bezogen auf eine Objektklasse.
•
Das CPT unterstützt in der momentanen Version noch keine Schlüsselattribute.
•
Das Schlüsselwort für Listen, Sätze und Tupel wird im CPT anders geschrieben als durch
die Chimera-Sprachdefinition vorgegeben (list_of anstelle von list-of usw.).
•
Bei der Definition von Wertetypen und –Klassen dürfen keine verschachtelten Listen,
Sätze oder Tupel definiert werden.
30
Inhaltsverzeichnis
3.2.2 Unterschiede bei deklarativen und imperativen Ausdrücken
In der Bonner Chimera-Implementation auch Veränderungen bei deklarativen und imperativen Ausdrücken. Das CPT unterstützt keine "null"-Werte für Attribute, da daß verwendete
Phoenix-System diese Werte nicht unterstützt. Dieses Problem beruht auf der Tatsache, daß
das ECLiPSe-Prolog-System keine "null"-Werte für die bereitgestellten Datentypen unterstützt. Das Phoenix-System benutzt die Datentypen von ECLiPSe ohne den für Datenbanken
erwünschten Wert "null" zusätzlich zu definieren. Der Grund für das Fehlen des Wertes ist
der enorme Aufwand, den eine Implementierung von "null"-Werten mit sich bringt: Alle
Datentypen müssen redefiniert werden, alle Operationen müssen erweitert werden usw. Das
Fehlen von "null"-Werten bedeutet, daß bei jeder Datendefinition alle Attribute eines Objektes mit Werten initialisiert werden müssen. Die "notnull"-Integritätsbedingung, die bei
der Definition von Attributen in Chimera verwendet werden kann, wird nicht unterstützt.
Des weiteren existieren noch zusätzliche Veränderungen:
•
Das CPT unterstützt keine benutzerdefinierte Sortierung für die Rückgabewerte von
select- und display-Kommandos.
•
Durch das Löschen von Objekten können sogenannte hängende Referenzen entstehen.
Das CPT besitzt keinen Mechanismus um diese referentielle Integrität zu überprüfen.
•
Trigger können momentan noch nicht auf Anfragen reagieren.
•
Die Aggregatfunktion von Chimera (card()) wird im CPT durch das Schlüsselwort
count() definiert.
•
Die Klammersymbole für Listen, Sätze und Tupel wurden verändert. Folgende Klammern
müssen verwendet werden:
set_of Hallo
{
}
list_of Hallo
[
]
record_of Hallo (
)
3.3 Abbildung des objektorientierten Datenmodells nach Phoenix
Dieser Abschnitt beschäftigt sich mit der Übersetzung des objektorientierten Datenmodells
von Chimera auf das relationale Modell von Phoenix. Mit Hilfe der graphischen Benutzeroberfläche oder der Kommandoschnittstelle kann ein neues Schema definiert oder ein bestehendes Schema aus einer Datei geladen werden.
Die erste Syntaxanalyse des Schemas liefert eine interne Darstellung des zu übersetzenden
Schemas; diese Darstellung wird in einer Prolog-Datenbank namens Chimera Data Dictionary
(CDD) gespeichert. Der Chimera Compiler übersetzt im Anschluß jeden einzelnen Eintrag
des CDD in entsprechende Phoenix-Befehle. Die Klassenhierarchie von Kapitel 2 bestehend
31
Inhaltsverzeichnis
aus den Objektklassen "adresse", "person", "schueler", "oberstufe" und
"abitur" wird durch folgende Einträge im CDD dargestellt:
********************************************
*** module
********************************************
(1,chimera): chimera
(2,chimera): user
********************************************
*** object_class
********************************************
(4,user): adresse, [extensional]
(8,user): person, [extensional]
(13,user): schueler, [extensional]
(18,user): oberstufe, [extensional]
(25,user): abitur, [derived]
********************************************
*** value_class
********************************************
(3,user): geschlecht, string
********************************************
*** superclass
********************************************
(14,user): person, schueler
(19,user): schueler, oberstufe
(26,user): oberstufe, abitur
********************************************
*** attribute
********************************************
(5,user): adresse, strasse, string, [extensional]
(6,user): adresse, plz, number, [extensional]
(7,user): adresse, wohnort, string, [extensional]
(9,user): person, name, string, [extensional]
(10,user): person, vorname, string, [extensional]
(11,user): person, geschlecht, geschlecht, [extensional]
(12,user): person, adresse, adresse, [extensional]
(15,user): schueler, schule, string, [extensional]
(16,user): schueler, klasse, integer, [extensional]
(17,user): schueler, faecher, list_of(string),[extensional]
(20,user): oberstufe, note_leistungskurs1, integer,[exten.]
...
Abgesehen von den obigen CDD-Kategorien existieren noch folgende zusätzlichen Kategorien im CDD, die die jeweilige Definition und die dazugehörigen Regeln der zusätzlichen
Schemakonzepte von Chimera repräsentieren:
32
Inhaltsverzeichnis
•
Value Classes
•
Attributs- und Klassenpopulationsregeln
•
Trigger
•
Integritätsbedingungen
•
Operationen
•
Sichten
Jeder Eintrag in der CDD-Datenbank besitzt einen Präfix bestehend aus einer fortlaufenden
Nummer und dem Namen des Benutzers. Die Prolog-Prädikate "get_cdd/4",
"put_cdd/4" und "del_cdd/4" dienen zur Manipulation einzelner CDD-Einträge.
"get_cdd/4" ließt Einträge aus dem CDD, "put_cdd/4" schreibt Einträge in das CDD
und "del_cdd/4" löscht bestehende Einträge aus dem CDD. Die Parameter aller drei Operationen ist identisch:
•
ID: Der erste Parameter enthält die ID eines Elementes des CDD.
•
Modul: Der zweite Parameter enthält das Module, zu dem die Elemente gehören. Dies
entspricht in der momentanen Implementation immer dem Module "user".
•
Konzept Name: Der dritte Parameter identifiziert das Konzept, zu dem die Einträge gehören müssen.
•
Konzept: Der letzte Parameter liefert eine Liste der eigentlichen Werte der gewünschten
Einträge.
Jeden der drei obigen Befehle gibt es ebenfalls mit drei oder zwei Parametern. Die dreistellige
Version der Prädikate benötigt keine ID und die zweistellige Version benötigt zusätzlich kein
Modul. Folgendes Beispiel, basierend auf dem zweistelligen Prädikat "get_cdd/2" liefert folgende Ausgabe:
[Chimera] get_cdd(attribute, Werte).
Werte = [adresse, strasse, string, [extensional]]
More?(;)
[Chimera] put_cdd(object_class, [klasse, [extensional]]).
[Chimera] put_cdd(attribute, [klasse, attribut, string,
[extensional]]).
Der erste Befehl des obigen Beispiels liefert alle Attribute, die im CDD eingetragen sind. Das
ECLiPSe-System zeigt allerdings immer nur eine Bindung der Variable "Werte" an, der
Benutzer muß durch die Eingabe eines Semikolons (";") die Ermittlung eines weiteren
Wertes manuell anstoßen. Der Rückgabewert wird in Form einer Liste zurückgegeben. Die
Liste enthält den Klassennamen, Namen, Datentyp und den Modus des Attributes. Der Modus
33
Inhaltsverzeichnis
eines Attributes ist entweder extensional oder abgeleitet. Die letzten beiden Befehle erzeugen
eine neue extensionale Objektklasse mit Namen "klasse" und ein extensionales Attribut
"attribut" mit Datentyp "string".
Auf den folgenden Seiten wird nun das Vorgehendes CPT bei der Schemaübersetzung von
Chimera nach Phoenix aufgezeigt. Jedes der in Kapitel 2 vorgestellten Schemakonzepte wird
hierbei in Kombinationen von Konzepten in Phoenix überführt: Objektklassen, Integritätsbedingungen, Sichten und Werteklassen werden durch Relationen und Trigger durch aktive Regeln in Phoenix realisiert.
Eine kurze Anmerkung zum Sprachgebrauch in den folgenden Abschnitten dieses Kapitels:
Im objektorientierten Datenmodell von Chimera existieren Werteklassen, Wertetypen, abgeleitete und extensionale Objektklassen, Sichten, Integritätsbedingungen und Trigger. Im relationalen Datenmodell von Phoenix existieren dagegen abgeleitete und extensionale
Relationen, aktive und passive Regeln.
3.3.1 Werteklassen und -typen
Werteklassen werden in Phoenix durch extensionale Relationen dargestellt. Dieses Vorgehen
wird durch die endliche Anzahl an zulässigen Werten, die zudem noch explizit mittels add
und drop definiert werden müssen, motiviert. Eine Besonderheit stellt allerdings das Aussehen der Phoenixrelationen dar. Die Chimera Werteklasse "geschlecht"
define value class geschlecht: string
end;
wird durch folgende Phoenixrelation realisiert:
extensional relation geschlecht
(
dummy(integer, 1, +),
geschlecht(term, A, -)
)
Die "dummy"-Spalte der Relation wird benötigt, da Relationen in Phoenix mindestens ein
Nicht-"term"-Attribut besitzen müssen. Diese Einschränkung bzw. Forderung geht auf eine
entsprechende Bedingung für Megalog-Relationen zurück. Die atomaren Datentypen von
Chimera entsprechen weitgehend den Datentypen von Phoenix. Einzige Ausnahme bildet
hierbei der "string"-Datentyp, der in Phoenix durch den Datentyp "atom" repräsentiert
wird.
34
Inhaltsverzeichnis
3.3.2 Objektklassen und Klassenhierarchien
Bei der Übersetzung eines objektorientierten Chimera-Schemas in ein relationales PhoenixSchema werden folgende zwei Fälle unterschieden:
•
extensionale Chimera-Objektklassen inklusive ihrer extensionalen Attribute
•
abgeleitete Attribute extensionaler Objektklassen und abgeleitete Objektklassen
Extensionale Objektklassen inklusive ihrer extensionalen Attribute werden durch eine Kombination aus extensionaler und abgeleiteter Relation realisiert:
define object class person
attributes
name:
string( 30 ),
vorname:
string( 30 )
end;
Obige Objektklasse wird durch den Chimera Compiler in folgende Phoenixrelation übersetzt:
extensional relation ext_person
(
oid( integer, 4, + ),
name( atom, 30, - ),
vorname( atom, 30, - )
)
Alle extensionalen Relationen werden mit dem Namen der entsprechenden ChimeraObjektklasse und dem Präfix "ext_" benannt. Der in objektorientierten Datenbanksystemen
interne Objektidentifikator (OID) wird auf der relationalen Phoenix-Seite durch eine OIDSpalte repräsentiert. Der Wert der OID-Spalte eines Objektes identifiziert das Objekt in der
gesamten Datenbank eindeutig. Die extensionale Relation "ext_person" wird von einer
abgeleiteten Relation überlagert:
derived relation person
(
oid( integer, 4, + ),
name( atom, 30, - ),
vorname( atom, 30, - )
)
person( A, B, C ) <- ext_person( A, B, C )
Alle Anfragen werden nur auf den abgeleiteten Relationen beantwortet. Im Falle einer einzelnen Objektklasse werden die Daten aus der entsprechenden extensionalen Relation komplett
übernommen. Dieses Vorgehen bleibt auch bei Klassenhierarchien erhalten. Die Klassenhierarchie bestehend aus obiger Objektklasse "person" und einer Unterklasse
"angestellter" wird wie folgt unter Phoenix abgebildet:
35
Inhaltsverzeichnis
define object class angestellter
superclasses
person
attributes
beruf:
string( 40 ),
arbeitgeber:
string( 100 )
end;
extensional relation ext_angestellter
(
oid( integer, 4, + ),
name( atom, 30, - ),
vorname( atom, 30, - ),
beruf( atom, 40, - ),
arbeitgeber( atom, 100, - )
)
derived relation angestellter
(
oid( integer, 4, + ),
name( atom, 30, - ),
vorname( atom, 30, - ),
beruf( atom, 40, - ),
arbeitgeber( atom, 100, - )
)
angestellter( A, B, C, D, E ) <ext_angestellter( A, B, C, D, E )
Die Definition der zur "person" gehörenden Sicht wird durch folgende zweite Populationsregel erweitert:
person( A, B, C ) <- ext_angestellter( A, B, C, D, E )
Die zweite Populationsregel stellt alle "personen"-relevanten Daten der Angestellten der
abgeleitete Relation "person" zur Verfügung. Diese zusätzlichen Regeln stellen sicher, daß
alle Anfragen über der vollständigen Menge an Objekten ausgeführt werden.
Das oben beschriebene Vorgehen für extensionale Objektklassen kann also wie folgt zusammengefaßt werden:
1. Übersetze alle Attribute einer Objektklasse, inklusive der von den Superklassen
geerbten Attribute, in eine entsprechende extensionale Phoenix-Relation mit einer
zusätzlichen OID-Spalte. Der Name der extensionalen Relation wird aus dem Präfix "ext_" und dem Namen der Chimera-Objektklasse zusammengesetzt.
2. Erzeuge eine abgeleitete Relation, die alle Attribute der extensionalen Relation besitzt. Der Name der abgeleiteten Relation ist identisch mit dem Namen der Chimera-Objektklasse.
3. Erzeuge eine Populationsregel, die alle Instanzen der extensionalen Relation in die
abgeleitete Relation überführt.
36
Inhaltsverzeichnis
4. Erzeuge gemäß der Chimera-Klassenhierarchie weitere Populationsregeln, die alle
Werte der an die Unterklassen vererbten Attribute der abgeleiteten Relation zur
Verfügung stellen.
Abgeleitete Attribute extensionaler oder abgeleiteter Objektklassen werden in eine binäre,
abgeleitete Phoenixrelation übersetzt. Der Name der Relation setzt sich aus dem Namen der
Objektklasse und dem Namen des abgeleiteten Attributes zusammen. Das erste Attribut der
abgeleiteten Relation verwaltet immer den Objektidentifikator des jeweiligen Objektes der
Klasse. Das zweite Attribut stellt dann das abgeleitete Attribut zur Verfügung.
define object class angestellter
superclasses
person
attributes
beruf:
string( 40 ),
arbeitgeber:
string( 100 ),
einkommen:
integer derived
end;
Das abgeleitete Attribut "einkommen" wird basierend auf obigem Vorgehen in folgende
abgeleiteten Relation übersetzt:
derived relation angestellter_einkommen
(
oid( integer, 4, + ),
einkommen( integer, 8, + )
)
In einer Klassenhierarchie können sowohl für extensionale als auch für abgeleitete Objektklassen abgeleitete Attribute definiert werden. Beide Arten von Klassen können die Berechnungsregeln für bereits definierte Attribute verändern und damit eine Redefinition
durchführen. Entscheidend für die genaue Berechnung eines abgeleiteten Attributes ist also
die Definition, die in der "most specific class" (in der am meisten spezialisierten Klasse) eines
Objektes definiert wurde. Folgendes Beispiel erweitert obige Klassenhierarchie:
define object class professor
superclasses
derived angestellter
attributes
einkommen:
integer redefined
end;
Durch die Redefinition des Attributes "einkommen" in der Objektklasse "professor"
werden die Gehälter für Angestellte und Professoren unterschiedlich berechnet. Die Objekte
der Objektklassen werden zusätzlich nach der am stärksten spezialisierten Klasse geordnet.
Die Objektidentifikatoren der Objekte werden in folgenden abgeleiteten Relationen zusammengefaßt:
37
Inhaltsverzeichnis
derived relation msc_person( oid( integer, 4 + ) )
derived relation msc_angestellter( oid( integer, 4 + ) )
derived relation msc_professor( oid( integer, 4 + ) )
Die abgeleiteten Relationen werden durch folgende Populationsregeln definiert:
msc_person( A ) <- ext_person( A, B, C )
msc_angestellter( A ) <ext_angestellter( A, B, C, D, E ),
not exists [F, G, H, I] : professor( A, F, G, H, I )
msc_professor( A ) <- professor( A, B, C, D, E )
Im obigen Beispiel ist nur die Definition der Populationsregel für die Relation
"msc_angestellter" interessant: In dieser Klasse werden die Objektidentifikatoren für
alle Angestellten gesammelt, die keine Professoren sind, da das Einkommen von Professoren
auf eine andere Art und Weise berechnet wird. Die eigentliche Berechnung des abgeleiteten
Attributs "einkommen" wird durch folgende Regeln erreicht:
angestellter_einkommen( A, B ) <msc_angestellter( A ),
'$berechne_angestellter_einkommen( A, B )'
angestellter_einkommen( A, B ) <professor_einkommen( A, B )
professor_einkommen( A, B ) <msc_professor( A ),
'$berechne_professor_einkommen( A, B )'
Die beiden Funktionen "$berechne_professor_einkommen" und "$berechne_
professor_einkommen" entsprechen der jeweiligen Übersetzung des deklarativen Ausdrucks der Chimera-Attributpopulationsregel und liefern den jeweiligen Wert für das Einkommen des Angestellten oder Professors. Die zweite Regel zur Berechnung des
Einkommens eines Angestellten ist nötig, da Anfragen an die Objektklasse
"angestellte" natürlich auch die Daten von Objekten der Klasse "professoren"
beinhalten können.
3.3.3 Integritätsbedingungen
Integritätsbedingungen werden durch den Chimera Compiler in abgeleitete PhoenixRelationen übersetzt. Dieses Vorgehen wird durch die Tatsache motiviert, daß Integritätsbedingungen in Chimera durch deduktive Regeln definiert werden. Die Idee hinter diesem Vorgehen ist folgende: Falls ein Datenbankzustand eine Integritätsbedingung verletzt, so läßt sich
mindestens ein Datensatz in einer abgeleiteten Relation durch die Populationsregeln erzeugen.
38
Inhaltsverzeichnis
define object class angestellter
superclasses
person
attributes
beruf:
string( 40 ),
arbeitgeber:
string( 100 ),
einkommen:
integer derived
constraints
zu_geringes_einkommen
(
Self : angestelter,
Einkommen : integer
)
end;
Die Integritätsbedingung obiger "angestellten"-Objektklasse wird durch den Chimera
Compiler in eine abgeleitete Relation namens "angestellter$zu_geringes_
einkommen" übersetzt. Die Populationsregel für diese abgeleitete Relation entspricht der
Übersetzung des deklarativen Ausdrucks der Implementation der Chimera-Integritätsbedingung.
Um die Überprüfung aller in der Datenbank definierter Integritätsbedingungen zu vereinfachen, wird bei der Übersetzung eines Chimera-Schemas nach Phoenix eine zentrale, abgeleitete Relation angelegt, die alle Integritätsbedingungen überprüft.
derived relation '$chimera_inconsistent'
(
class( atom ),
constraint( term )
)
Die binäre Relation enthält den Namen der Klasse, deren Instanz eine Integritätsbedingung
verletzt, den Namen der Integritätsbedingung, den Objektidentifikator und den jeweiligen
Wert. Eine Populationsregel zur Überprüfung einer Integritätsbedingung hat folgendes Aussehen:
'$chimera_inconsistent'
(
angestellter,
zu_geringes_einkommen( Oid, Einkommen )
)
<- angestellter$zu_geringes_einkommen( Oid, Einkommen)
Das CPT überprüft am Ende jeder Transaktion, ob mindestens ein Datensatz in obiger Relation hergeleitet werden konnte. Falls dies der Fall ist, wird die gesamte Transaktion entweder
zurückgesetzt, alle Änderungen der Transaktion werden rückgängig gemacht, oder ein entsprechender Trigger wird zur Reparatur des inkonsistenten Datenbestandes ausgeführt. Das
jeweilige Ergebnis der Auswertung der Integritätsbedingungen wird dem Benutzer des CPTs
auf dem Bildschirm ausgegeben.
39
Inhaltsverzeichnis
Andrea Scheuber
4 Oracle8
Dieses Kapitel behandelt das objekt-relationale Datenbanksystem Oracle8. Es werden die
alten relationalen Konzepte von Oracle7 und die neuen relationalen Konzepte von Oracle8
vorgestellt. Des weiteren werden die objektorientierten Konzepte von Oracle8 eingeführt und
erklärt, in welchen Bereichen sie sinnvoll eingesetzt werden können und welchen Einschränkungen sie in dieser Version unterliegen. Des weiteren werden einige der Oracle-spezifischen
Erweiterungen des SQL-92-Standards kurz vorgestellt.
Als Grundlage für den allgemeinen Abschnitt 4.1 diente das Buch "Datenbanksysteme: Eine
Einführung" von Alfons Kemper und André Eickler [KE99]. Für die weiteren Abschnitte, die
das Datenbanksystem Oracle8 vorstellen, wurden hauptsächlich Informationen aus der Online-Dokumentation zu Oracle8 [Ora98] verwendet. Als weitere Informationsquelle diente das
Buch "Oracle8 Design Tips" von Dave Ensor und Ian Stevenson [DS97].
4.1 Datenbanksysteme und Datenmodelle
Ein Datenbanksystem (DBS) besteht aus einer Datenbasis (DB) und einem Datenbankmanagementsystem (DBMS). Die Datenbasis dient zur Speicherung der Daten innerhalb eines Datenbanksystems. Ein Datenbanksystem kann mehrere Datenbasen besitzen, die voneinander
getrennt durch das DBMS verwaltet werden.
Das DBMS eines Datenbanksystems besteht aus Programmen, die Verwaltungsprozesse auf
dem Datenbestand der Datenbasis organisieren. Diese Verwaltungsprozesse dienen dazu, die
Strukturbeschreibung der Datenbasis anzulegen, Manipulationen am Datenbestand durchzuführen, Anfragen über der Datenbasis auszuwerten und dafür zu sorgen, daß die Datenbank
sich immer in einem legalen Zustand befindet. Des weiteren werden vom DBMS Zugriffsrechte, die zur Gewährleistung der Datensicherheit dienen, verwaltet und überprüft.
40
Inhaltsverzeichnis
Ein Datenbankmanagementsystem kann in drei Abstraktionsebenen unterteilt werden. Auf
interner Ebene wird festgelegt, wie die Daten physikalisch gespeichert werden. Auf konzeptioneller Ebene wird durch das Datenbankschema festgelegt, in welchen Strukturen die Daten
in der jeweiligen Datenbasis verwaltet werden. Auf externer Ebene können die Daten durch
die Definition von Sichten in einer anderen Struktur präsentiert werden, die den jeweiligen
Bedürfnissen der Benutzer entspricht.
Die konzeptionelle Ebene eines DBMS wird durch das zugrundeliegende Datenmodell beschrieben. Das Datenmodell liefert die Konstrukte zur Abbildung der realen Welt und stellt
für diesen Zweck sowohl die Datendefinitionssprache (engl. data definition language, DDL),
als auch die Datenmanipulationssprache (engl. data manipulation language, DML) zur Verfügung. Die zwei hauptsächlich verwendeten Klassen von Datenmodelle sind das relationale
Datenmodell und unterschiedliche objektorientierte Datenmodelle. In den folgenden Abschnitten werden die wichtigsten Eigenschaften beider Modelltypen vorgestellt.
Das relationale Datenmodell stellt Gegenstände aus der realen Welt, die auch als Entitäten
bezeichnet werden, in Form von Relationen dar. Eine n-stellige Relation R ist mathematisch
gesehen eine Teilmenge des kartesischen Produktes von Mengen M1, ... Mn:
R ⊆ M1 × M2 × ... × Mn
Eine solche Relation kann auch in Form einer zweidimensionalen Tabelle dargestellt werden,
und als solche wird sie auch im relationalen Datenmodell bezeichnet. Ein Unterschied zwischen einer Tabelle und einer Relation besteht darin, daß durch eine Tabelle eine Multimenge
abgebildet werden kann, da innerhalb einer Tabelle Duplikate zulässig sind, falls nicht ein
eindeutiger Schlüssel (Primärschlüssel) dies verhindert. Im folgenden werden die Begriffe
Tabelle und Relation synonym verwendet, da davon ausgegangen wird, daß eine Tabelle auch
immer einen Primärschlüssel besitzt. Falls dies einmal nicht der Fall sein sollte wird an dieser
Stelle explizit darauf hingewiesen. Eine Zeile in einer Tabelle wird auch als Tupel oder Datensatz bezeichnet, da sie alle Attribute einer Relation zu einer Einheit zusammenfaßt. Die
Spalten einer Tabelle werden durch einen eindeutigen Attributnamen bezeichnet und durch
einen Wertebereich definiert. Als Wertebereich stehen unterschiedliche atomare Datentypen
zur Verfügung. Der zulässige Wertebereich von Attributen kann, durch den Einsatz von Integritätsbedingungen, noch genauer spezifiziert bzw. eingeschränkt werden. Die Aufgabe von
Integritätsbedingungen ist es, zu überprüfen, ob sich die Datenbank in einem legalen Zustand
befindet. Diese Überprüfungen werden durch DML-Anweisungen ausgelöst, die Änderungen
am Datenbestand vornehmen. Verstoßen die Änderungen gegen Integritätsbedingungen, so
werden sie nicht ausgeführt, um den legalen Zustand der Datenbank zu wahren. Mit Hilfe
einer Integritätsbedingung kann zum Beispiel gefordert werden, daß die Schlüsselattribute
zweier Tabellen nur identische Werte enthalten dürfen. Eine solche Integritätsbedingung wird
Fremdschlüsselbedingung (engl. foreign key constraint) genannt. Wird nun eine Anfrage über
diesen beiden Tabellen ausgewertet, können die Werte der Schlüsselattribute dazu benutzt
werden, die Datensätze zueinander in Beziehung zu setzen.
In der Datenbanktheorie existiert nur ein relationales Datenmodell aber mehrere objektorientierte Modelle. Ein objektorientiertes Datenmodell stellt Entitäten aus der realen Welt in Form
von Objekten dar. Ein Objekt ist ein Informationsträger, der alle Eigenschaften eines Gegenstandes aus der realen Welt durch seine Struktur und sein Verhalten repräsentiert. Ein Objekt
besteht aus Attributen, die eine Strukturbeschreibung der Instanzen eines Objektes bilden und
Beziehungen zu anderen Objekten herstellen können, da ein Attribut auch ein beliebiges Ob41
Inhaltsverzeichnis
jekt sein kann und nicht auf atomare Datentypen beschränkt ist. Die Verhaltensbeschreibung
der Instanzen eines Objektes sind innerhalb einer Objektklasse durch eine Menge von Operationen definiert. Eine weitere wichtige Eigenschaft von Objektklassen ist der Vererbungsmechanismus, der dazu dient die Struktur und die Verhaltensweisen zu generalisieren oder zu
spezialisieren.
Die konzeptionelle Ebene des Datenbanksystem Oracle8 beinhaltet sowohl objektorientierte
als auch relationale Konzepte und wird deshalb von Oracle als objekt-relational bezeichnet.
Allerdings ist Oracle8, allein durch seine Entwicklung aus dem relationalen DBMS Oracle7
bedingt, in erster Linie ein relationales System, das durch objektorientierte Modellierungskonzepte erweitert worden ist. Diese Erweiterung beschränkt sich auf grundlegende Konzepte
der Objektorientierung und verzichtet auf wesentliche Eigenschaften wie zum Beispiel den
Vererbungsmechanismus. Des weiteren ist der Einsatz einiger objektorientierten Konstrukte
in Bezug auf ihre Schachtelungstiefe stark eingeschränkt. Das objekt-relationale DBMS
Oracle8 ist als ein erster Versuch zu betrachten, objektorientierte Konzepte in ein relationales
Datenmodell zu integrieren.
4.2 Die relationalen Konzepte von Oracle8
In diesem Abschnitt werden die relationalen Konzepte von Oracle8 vorgestellt, die innerhalb
einer Schemadefinition verwendet werden können. Diese Konzepte werden im folgenden
auch als Schemaelemente bezeichnet. Angefangen wird bei den sogenannten Built-inDatentypen (vom DBS vordefinierte Datentypen), die von Oracle8 zur Verfügung gestellt
werden. Diese Datentypen sind keine Schemaelemente, sondern bilden die Grundlage zur
Definition von Attributen in Schemaelementen, indem sie die vordefinierten Wertebereiche
zur Verfügung stellen. Die eigentlichen relationalen Konzepte sind die Tabellen und Sichten,
die mit Hilfe von Integritätsbedingungen die Struktur einer Entität abbilden. Zur Abbildung
des Verhaltens einer Entität dienen im relationalen Modell Trigger, die an eine Tabelle angehängt werden. Weitere Hilfsmittel sind Prozeduren und Funktionen, die aus Triggern oder
aber aus einer Applikation heraus aufgerufen werden können.
4.2.1 Built-in-Datentypen
Die Built-in-Datentypen von Oracle8 werden zur Definition der Wertebereiche von Attributen
in Schemaelementen benutzt. Des weiteren werden sie zur Definition von Variablen in
PL/SQL benutzt, der internen Programmiersprache von Oracle8. Mit der Hilfe von PL/SQL
können zum Beispiel interne Prozeduren, Funktionen und Trigger definiert werden. Die folgenden Datentypen sind die grundlegenden Datentypen, die sowohl unter Oracle7 als auch
Oracle8 zur Verfügung stehen.
Der Datentyp "character(n)" legt den Wertebereich einer Variablen oder eines Attributes fest, der als Wert eine Zeichenkette akzeptiert, die aus exakt n Zeichen besteht. Wird eine
zu kurze Zeichenkette in die Tabelle eingefügt, werden die fehlenden Stellen durch Leerzeichen aufgefüllt. Ist die Zeichenkette zu lang, wird eine Fehlermeldung ausgegeben. Die maximale Größe für Zeichenketten vom Typ "character" ist 2000. Die vordefinierte
Mindestgröße ist 1, die automatisch vergeben wird, wenn für n kein expliziter Wert spezifi42
Inhaltsverzeichnis
ziert wird. Der Wertebereich des Datentyps "char(n)" ist durch den Datentyp
"character(n)" definiert und besitzt keinerlei Einschränkungen. Beide Datentypen
können synonym verwendet werden.
Der Datentyp "varchar2(n)" legt den Wertebereich einer Variablen oder eines Attributes
fest, der als Wert eine Zeichenkette variabler Länge akzeptiert, die maximal 4000 Zeichen
lang sein kann. Die maximale Länge n muß bei der Definition des Attributes angegeben werden und muß mindestens 1 sein.
Der Datentyp "varchar(n)" ist momentan noch synonym mit dem Datentyp
"varchar2(n)" verwendbar. In der Oracle8-Online Hilfe wird empfohlen den Datentyp
"varchar" nicht zu verwenden, denn in späteren Versionen soll aus "varchar" ein eigener Datentyp mit variabler Länge werden, der anderen Vergleichsoperationen unterliegen soll,
als der Datentyp "varchar2".
Der Datentyp "date" wird benutzt, um Informationen über Datum und Uhrzeit abzuspeichern. Zu diesen Informationen gehören das Jahr, der Monat, der Tag, die Stunde, die Minute
und die Sekunde. Ein gültiges Datum bewegt sich innerhalb der Zeitspanne vom 1. Januar
4712 v. Chr. bis zum 31. Dezember 4712 n. Chr.
Der Datentyp "number(v,n)" wird benutzt, um numerische Werte in der Datenbank abzulegen. Werden die Variablen v und n bei der Definition eines Wertebereichs nicht verwendet, so werden nur natürliche Zahlen als Werte akzeptiert. Soll der Wertebereich auch reelle
Zahlen als Werte zulassen, so muß die Anzahl der Vorkommastellen durch die Variable v und
die Anzahl der Nachkommastellen durch die Variable n spezifiziert werden. Für v können
Werte zwischen 1 und 38 benutzt werden. Der Werte von n darf sich zwischen –84 und 127
bewegen. Eine negative Angabe kann zur Definition sehr großer Zahlen verwendet werden.
Für die interne Programmiersprache PL/SQL stehen zusätzlich die Datentypen "integer"
und "real" zur Verfügung.
Der Datentyp "long" wird dazu benutzt, Zeichenketten variabler Länge zu speichern. Der
Speicherplatz, den die Zeichenkette belegen darf, liegt bei maximal zwei Gigabytes, vorausgesetzt dieser Speicherplatz steht auf dem jeweiligen Datenbankserver zur Verfügung. Die
Nutzung dieses Datentyps unterliegt den folgende Einschränkungen. Eine Tabelle darf nur
eine Spalte des Datentyps "long" beinhalten, über die nur die Integritätsbedingung "not
null" definiert werden kann. Des weiteren kann kein Index über diese Spalte gelegt werden.
Die Datentypen "raw" und "long raw" werden dazu benutzt, binäre Daten zu speichern,
die nicht vom Datenbanksystem interpretiert werden müssen. Bei diesen Daten kann es sich
zum Beispiel um Bilder, Musik oder Dokumente handeln.
Die folgenden Built-in-Datentypen sind neue Datentypen von Oracle8 und werden allgemein
als "lob"s (engl. large objects) bezeichnet. "lob"s sind Datentypen die zur Speicherung
großer und unstrukturierter Datenmengen bis zu einer Größe von vier Gigabytes verwendet
werden. Es ist möglich die Daten von "lob"s durch DML-Operationen zu modifizieren. Es
gibt drei unterschiedliche Typen von "lob"s. Der Datentyp "blob" wird benutzt, um große
Objekte bestehend aus binären Daten zu speichern. Der Datentyp "clob" wird benutzt, um
43
Inhaltsverzeichnis
große Objekte bestehend aus single-byte Zeichen zu speichern. Der Datentyp "nclob" wird
benutzt, um große Objekte bestehend aus multi-byte Zeichen mit fester Länge zu speichern.
Ein weiterer neuer Built-in-Datentyp ist der Datentyp "bfile". Er dient dazu, auf Binärdateien außerhalb des Datenbanksystems zugreifen zu können. Ein Attribut, daß als Wertebereich den Datentyp "bfile" besitzt, speichert einen Zeiger, der die Adresse der Binärdatei
beinhaltet. Der Inhalt der Binärdatei ist nicht durch Oracle-DML-Operationen modifizierbar,
da nur lesender Zugriff auf die Datei erlaubt ist.
Eine Besonderheit der hier vorgestellten Datentypen ist es, daß der Wert "null" für alle
definiert ist. Das heißt, es ist möglich jedem Datentypen einen Nullwert zuzuweisen, der sich
in seiner Bedeutung von Leerstrings für Zeichenketten und dem Wert 0 für numerische Werte
unterscheidet und einen nicht initialisierten Attributwert kennzeichnet.
4.2.2 Tabellen
Die Tabellen sind das grundlegende, relationale Konzept zur Speicherung und Organisation
von Daten. Sie stellen in ihrer Gesamtheit die Datenbasis eines Datenbanksystems dar. Eine
Tabelle besitzt einen Namen, durch den sie innerhalb des Datenbankschemas eindeutig identifiziert werden kann. Die Spalten der Tabelle bestehen aus Attributen, die innerhalb der Tabelle einen eindeutigen Namen besitzen und deren Wertebereich durch einen Datentyp
festgelegt wird. Als Wertebereich stehen die Built-in-Datentypen von Oracle zur Verfügung.
Eine neue Option von Oracle8 ist die Möglichkeit, einen benutzerdefinierten Datentyp (siehe
Abschnitt 4.3.1) zu definieren und als Wertebereich für ein Attribut zu verwenden.
4.2.3 Sichten
Eine Sicht (View) repräsentiert ausgesuchte Daten, die aus Tabellen oder bereits definierten
Sichten zusammengestellt werden. Eine Sicht beinhaltet das Ergebnis einer Anfrage und kann
somit als virtuelle Tabelle bezeichnet werden. Unter bestimmten Voraussetzungen ist es
möglich, Modifikationen an dem Datenbestand einer Sicht (View Update) vorzunehmen. Diese Modifikationen werden nicht an dem virtuellen Datenbestand einer Sicht vorgenommen,
sondern am Datenbestand der Tabellen, aus denen die Attribute der Sicht stammen. Besteht
eine Sicht nur aus Attributen, die aus einer Anfrage an eine einzige Tabelle stammen und ist
auch der Primarschlüssel der Tabelle Bestandteil der Sicht, so werden die Daten automatisch
der richtigen Tabelle zugeordnet und eingefügt, aktualisiert oder gelöscht.
Besitzt eine Sicht Attribute, die aus mehreren Tabellen stammen, so ist Oracle8 nicht mehr in
der Lage, die erforderlichen Modifikationen selbständig an den betroffenen Tabellen durchzuführen, wenn mehrere Attribute aus unterschiedlichen Tabellen gleichzeitig betroffen sind.
Die Attribute, die Schlüsselwerte enthalten und dazu dienen die Beziehungen zwischen den
Tabellen herzustellen (join keys), dürfen auch nicht verändert werden, um die bereits bestehenden Beziehungen zwischen den Daten der Tabellen zu erhalten. Will man trotzdem nicht
darauf verzichten, Modifikationen am Datenbestand von Sichten durchzuführen, so ist man
auf das neue Oracle8-Konzept der Instead-of-Trigger (siehe Abschnitt 4.2.5) angewiesen, die
ausschließlich für Sichten definiert werden können.
44
Inhaltsverzeichnis
4.2.4 Integritätsbedingungen
Integritätsbedingungen (engl. integrity constraints) sorgen dafür, daß sich die Datenbank in
einem legalen Zustand befindet. Es werden fünf verschiedene Arten von Built-inBedingungen zur Verfügung gestellt, die bei der Schemadefinition verwendet werden können.
Wenn es erforderlich ist, speziellere Integritätsbedingungen innerhalb eines Datenbankschemas zu erstellen, die mit den folgenden Built-in-Bedingungen nicht modelliert werden können, so ist man gezwungen auf andere Konzepte, wie Trigger, Prozeduren oder Funktionen
zurückzugreifen.
Die Attribute einer Datenbanktabelle können mit einer Integritätsbedingung vom Typ "not
null" belegt werde, um zu garantieren, daß in jedem Datensatz dieser Tabelle der Wert dieser Attribute einen gültigen Wert, der ungleich dem Wert "null" ist, beim Einfügen zugewiesen bekommt.
Die Attribute einer Datenbanktabelle können mit einer Integritätsbedingung vom Typ
"unique" belegt werden, um zu garantieren, daß dieser Wert für diese Attribute innerhalb
aller Datensätze der Tabelle eindeutig sind.
Eine Integritätsbedingung vom Typ "primary key" definiert den Primärschlüssel, der
einen Datensatz innerhalb einer Tabelle eindeutig identifiziert. Dieser Schlüssel kann auch
aus mehreren Attributen der Tabelle bestehen, die zusammen einen eindeutigen Schlüssel
bilden. Eine Integritätsbedingung vom Typ "primary key" impliziert eine Integritätsbedingung vom Typ "not null" für alle am Primärschlüssel beteiligten Attribute. Das bedeutet, daß alle Attribute eines Primärschlüssels in einem Datensatz einen gültigen Wert
besitzen müssen.
Eine Integritätsbedingung vom Typ "foreign key" definiert einen Fremdschlüssel einer
Tabelle, der benutzt wird, um die Beziehungen zwischen den Tupeln in den Datenbanktabellen zu definieren und zu überprüfen, ob sie eingehalten werden. Es existieren drei unterschiedliche Beziehungstypen, die mit Hilfe der bereits vorgestellten Integritätsbedingungen
realisiert werden können. Mit dem Beziehungstyp 1:1 bezeichnet man eine Verbindung zwischen zwei Tabellen, die einem Datensatz in der ersten Tabelle genau einen Datensatz in der
zweiten Tabelle zuordnet. Der Beziehungstyp 1:n ermöglicht es einem Datensatz in der ersten
Tabelle mehrere Datensätze in der zweiten Tabelle zuzuordnen. Der Beziehungstyp n:m ermöglicht es, daß sowohl ein Datensatz in der ersten Tabelle in Verbindung mit mehrere Datensätzen der zweiten Tabelle steht als auch umgekehrt. Eine n:m-Beziehung ist unter Oracle
nur möglich durch die Simulation einer zusätzlichen Tabelle mit jeweils einer n:1 und einer
1:m Beziehung.
Eine "check"-Bedingung ist ein boolscher Ausdruck, der über dem Wertebereich eines Attributs in einer Datenbanktabelle definiert wird. Dabei kann die Bedingung nur auf die alten
und die neuen Werte eines manipulierten Datensatzes zugreifen. Es dürfen keine Prozeduren
oder Funktionen benutzt oder Anfragen an die Datenbank gestellt werden, um den boolschen
Ausdruck auszuwerten.
In Oracle7 ist es bereits möglich Integritätsbedingungen zu aktivieren und deaktivieren. Dabei
muß allerdings beachtet werden, daß keiner der bereits existierenden Datensätze gegen diese
Integritätsbedingung verstoßen darf, wenn sie aktiviert werden soll. Um diese Problem zu
45
Inhaltsverzeichnis
umgehen, ist es in Oracle8 jetzt möglich durch den folgenden Ausdruck eine Integritätsbedingung zu aktivieren, ohne auf bereits bestehende Datensätze Rücksicht zu nehmen.
ALTER TABLE table_name
ENFORCE CONSTRAINT constraint_name;
Beispiel 4.2.1: Aktivierung einer Integritätsbedingung
Nur neu eingefügte Datensätze unterliegen dieser Integritätsbedingung nach ihrer Aktivierung. Die alten Datensätze, die der Integritätsbedingung nicht entsprechen, werden einfach
ignoriert.
Eine zusätzliche Erweiterung von Oracle8 ist es, daß Integritätsbedingungen verzögert am
Transaktionsende überprüft werden können. Diese Vorgehensweise ist erforderlich, wenn
Integritätsbedingungen fordern, daß zu einem Eintrag in der ersten Tabelle ein Eintrag in der
zweiten Tabelle existieren muß und umgekehrt. Wenn diese Integritätsbedingungen nicht verzögert am Transaktionsende überprüft werden, dann kann in keiner der beiden Tabellen ein
Datensatz eingefügt werden, da immer eine Integritätsbedingung verletzt ist. Durch den folgenden Ausdruck kann eine Integritätsbedingung so definiert werden, daß sie verzögert ausgeführt wird.
SET CONSTRAINTS constraint_name DEFERRED;
Beispiel 4.2.2: Veränderung des Ausführungsmodus einer Integritätsbedingung
Ersetzt man den Namen der Integritätsbedingung durch das Schlüsselwort "all", so werden
alle Integritätsbedingungen des Schemas verzögert (engl. deferred) überprüft. Umgekehrt ist
es auch möglich eine Integritätsbedingung so zu definieren, daß sie sofort (engl. immediate)
überprüft wird. Das Schlüsselwort "deferred" wird in diesem Fall durch das Schlüsselwort "immediate" ersetzt. Standardmäßig sind Integritätsbedingungen so definiert, daß sie
sofort überprüft werden und nicht erst am Ende einer Transaktion.
4.2.5 Trigger
Ein Trigger ist eine aktive Regel, die durch einen spezifizierten Ereignistyp ausgelöst wird. In
Oracle8 wird zwischen den drei Ereignistypen INSERT, UPDATE und DELETE unterschieden, die zur Kategorie der DML-Operationen gehören. Ein Trigger ist in Oracle8 immer an
eine Tabelle oder eine Sicht (siehe Abschnitt 4.2.3) gebunden. Tritt nun der im Trigger spezifizierte Ereignistyp bzgl. der Tabelle auf, so wird der Trigger ausgelöst und führt seine Aktionen aus, die zum Beispiel zur Erhaltung des korrekten Datenbestandes oder zur
Datengewinnung beitragen können.
Innerhalb der Triggerdefinition wird nicht nur durch ein spezifiziertes Ereignis der Typ des
Triggers festgelegt. Hier wird auch zwischen dem sogenannten "row-level"-Trigger und
46
Inhaltsverzeichnis
dem "statement-level"-Trigger unterschieden. Ein "row-level"-Trigger ist ein
Trigger, der für jeden Datensatz, der durch das spezifizierte Ereignis beeinträchtigt wird, ausgelöst wird. Ein "statement-level"-Trigger wird nur einmal pro spezifiziertes Ereignis
ausgeführt. Das bedeutet, daß es egal ist wie viele Datensätze betroffen sind. Im Prinzip sind
die Datenbanktrigger von Oracle8 Prozeduren. Der eigentliche Unterschied zwischen einer
Prozedur und einem Trigger besteht darin, daß ein Trigger implizit vom DBMS Oracle8 ausgeführt wird, während eine Prozedur explizit von den Benutzern, Applikationen oder Triggern
aufgerufen wird. Ein Trigger wird separat von den Tabellen im Schema gespeichert.
Ein neues Konzept von Oracle8 sind die Instead-of-Trigger. Ihre Aufgabe ist es, bei einer
Modifikation am Datenbestand einer Sicht (engl. view update) die Veränderungen der einzelnen Attributwerte in den Sichten auf die Attributwerte der unterschiedlichen Basistabellen zu
übertragen. Die Anwendung der Instead-Of-Trigger ist auf das Konzept der Sichten (views,
object views) beschränkt. Instead-of-Trigger sind immer Row-Level-Trigger und können jeweils für die drei Ereignistypen "insert", "update" und "delete" definiert werden.
Auf diese Weise wird es ermöglicht, das Verhalten eines "view updates" nicht vom
DBMS steuern zu lassen, sondern selbst zu bestimmen, wie der Datenbestand modifiziert
werden soll, um zu garantieren, daß sich die Datenbank auch nach dem View-Update in einem legalen Zustand befindet. Zu beachten ist bei der Definition von Sichten und Instead-ofTriggern, daß für Sichten, die auf Sichten mit Instead-of-Triggern basieren, ebenfalls Insteadof-Trigger definiert werden müssen.
4.2.6 Interne Prozeduren und Funktionen
Benutzerdefinierte interne Prozeduren und Funktionen werden in einem OracleDatenbanksystem in der prozeduralen Spracherweiterung von SQL (PL/SQL) realisiert und
innerhalb der jeweiligen Datenbank gespeichert, in deren Schema sie definiert worden sind.
Sie können aus Triggern, vom SQL-Interface oder aus Applikationen direkt aufgerufen werden. Ein Paket (engl. package) ist eine Kollektion von Prozeduren und Funktionen, die eine
Einheit bildet und auch als solche in der Datenbank gespeichert wird und Applikationen zur
Verfügung gestellt werden kann. Die Definition von Prozeduren, Funktionen und Paketen
erfolgt über einen Spezifikationsteil, der das Interface zwischen den aufrufenden Programmsequenzen und dem Programmcode der Prozeduren bildet. Der sogenannte Body realisiert die
eigentliche Implementierung der Prozeduren und Funktionen.
Bei der Spezifikation von Parametern ist zu beachten, daß Oracle verschiedene Typen von
Parametern zur Verfügung stellt, die sogenannten "in"-, "out"- und "in-out"Parametern. Jeder dieser Typen besitzt unterschiedliche Eigenschaften, die sie für unterschiedliche Aufgabenbereiche qualifizieren. Wird der Parametertyp bei der Spezifikation
nicht mit angegeben, so wird der Parameter automatisch als "in" Parameter klassifiziert.
Ein "in"-Parameter wird verwendet, um einen Wert an Unterprogramme (Funktionen, Prozeduren) zu übergeben. Seine Eigenschaften ähneln innerhalb eines Unterprogramms den Eigenschaften einer Konstante, da der Wert eines "in"-Parameters weder modifiziert noch
nach außen an den Aufruf seines Unterprogramms zurückgegeben werden kann. Der Übergabeparameter eines spezifizierten "in"-Parameters kann eine Konstante, eine initialisierte
Variable oder ein Ausdruck sein.
47
Inhaltsverzeichnis
Ein "out"-Parameter wird verwendet, um einen Wert an den Aufruf des Unterprogramms
zurückzuliefern. Seine Eigenschaften ähneln innerhalb eines Unterprogramms den Eigenschaften einer nicht initialisierten Variablen. Der Übergabeparameter eines spezifizierten
"out"-Parameters muß eine Variable sein. Diese Variable darf durchaus mit einem Wert
initialisiert sein, der allerdings bei dem Aufruf des Unterprogramms verloren geht und durch
den Wert "null" ersetzt wird. Ein "out"-Parameter darf nur einen Wert zugewiesen bekommen und kann innerhalb eines Unterprogramms nicht dazu benutzt werden, einer anderen
Variablen seinen Wert zuzuweisen. Des weiteren darf er auch nicht innerhalb eines Ausdrucks
benutzt werden, um einen Wert zu definieren.
Ein "in-out"-Parameter wird verwendet, um einen Wert an Unterprogramme zu übergeben, ihn innerhalb der Unterprogramme zu aktualisieren und den aktualisierten Wert an den
Aufruf zurückzugeben. Seine Eigenschaften ähneln den Eigenschaften einer initialisierten
Variablen, da es möglich ist den Wert zu modifizieren und man den Parameter auch in Ausdrucken benutzen kann, die neue Werte deklarieren.
Es ist möglich Funktionen und Prozeduren, die zu einem Paket zusammengefaßt sind, zu
überladen. Will man Methoden überladen, so muß man darauf achten, daß sie vom gleichen
Typ sind. Das bedeutet, daß Funktionen nur mit Funktionen und Prozeduren nur mit Prozeduren überladen werden können. Der gleiche Name kann für Funktionen oder Prozeduren mehrfach verwendet werden, wenn sich die spezifizierten Übergabeparameter in Anzahl,
Anordnung oder Datentyp unterscheiden. Datentypen werden nur dann als unterschiedlich
erkannt, wenn ihre Wertebereich grundsätzlich verschieden sind. So gehören beispielsweise
die Datentypen "char", "varchar", "varchar2" und "long" zu einer Familie von
Datentypen, die im Zusammenhang mit Überladen nicht als unterschiedlich erkannt werden,
da sie alle zur Speicherung alphanumerische Daten verwendet werden. Das gleiche Problem
liegt auch bei den Datentypen "number", "integer" und "real" vor.
Wird eine dieser Methoden aufgerufen, wird von PL/SQL die Liste der aktuellen Parameter
mit der spezifizierten Parameterliste in den Methoden verglichen. Auf diese Weise wird die
richtige Funktion oder Prozedur ausgewählt. Es ist nicht möglich eine Methode zu überladen,
deren Parameter sich nur durch ihren Typ ("in" oder "in-out") unterscheiden. Das gleiche gilt auch für Funktionen, die sich nur durch den Datentyp ihres Rückgabewertes unterscheiden. Anhand der folgenden Beispiele wird verdeutlicht, welche Spezifikationen beim
Überladen nicht zulässig sind.
PROCEDURE Lieferdatum( aktDatum IN DATE ) IS ...
PROCEDURE Lieferdatum( aktDatum IN OUT DATE ) IS ...
Beispiel 4.2.1: Problem beim Überladen von Prozeduren mit ungleichem Parametertyp
Die Prozeduren aus dem vorangestellten Beispiel können sich gegenseitig nicht überladen, da
sie sich nur durch den Parametertyp unterscheiden. Dieser Unterschied wird durch das DBMS
nicht überprüft und kann deshalb auch nicht berücksichtigt werden.
48
Inhaltsverzeichnis
PROCEDURE Preisnachlass( Preis INTEGER ) IS ...
PROCEDURE Preisnachlass( Preis REAL ) IS ...
Beispiel 4.2.2: Problem beim Überladen von Prozeduren mit Parametern aus der gleichen Datentypfamilie
Die Prozeduren aus Beispiel 4.2.1 können sich gegenseitig nicht überladen, da die Datentypen
INTEGER und REAL zu der gleichen Datentypfamilie gehören. Das DBMS kann beim Aufruf der Prozedur nicht unterscheiden zur welcher Datentypfamilie der Parameter gehört.
FUNCTION Bezahlt( acct_id INTEGER ) RETURN BOOLEAN IS
FUNCTION Bezahlt( acct_id INTEGER ) RETURN INTEGER IS
Beispiel 4.2.3: Probleme beim Überladen von Funktionen mit Rückgabeparametern
Die Prozeduren aus Beispiel 4.2.3 können sich nicht gegenseitig überladen, da sie sich nur
durch den Datentyp des Rückgabewertes unterscheiden. Ähnliche Beispiele und weitere Informationen zu diesem Thema sind in der Oracle8-Online-Hilfe zu finden.
4.2.7 Externe Prozeduren und Funktionen
Als externe Prozeduren bezeichnet man unter Oracle8 Unterprogramme, die zum Beispiel in
C++ implementiert worden sind und in Windows-Betriebssystemen als "Dynamic Link Libraries" (DLL) der SQL-Schnittstelle zur Verfügung gestellt worden sind. Diese externen Prozeduren werden von PL/SQL behandelt, als ob es sich um PL/SQL Unterprogramme handeln
würde. Dadurch eignen sie sich, um Schnittstellen zwischen Datenbanken und Applikationen
zu gestalten.
4.3 Die objektorientierten Konzepte von Oracle8
In den folgenden Abschnitten werden die neuen Konzepte von Oracle8 vorgestellt, welche die
objektorientierte Komponente des DBMS repräsentieren. Im wesentlichen handelt es sich um
Elemente, die zur Schemadefinition verwendet werden können und im folgenden auch als
Schemaelemente bezeichnet werden. Des weiteren wird erklärt, wie die objektorientierten
Konzepte im Zusammenhang mit den relationalen Konzepten genutzt werden können.
49
Inhaltsverzeichnis
4.3.1 Objekttypen
Das Schemaelement Objekttyp dient zur Abstraktion einer Entität und kann auf vielfältige
Weise bei der Definition eines Datenbankschemas eingesetzt werden. Ein Objekttyp ist ein
benutzerdefinierter Datentyp, dessen Attribute sich aus den atomaren Built-in-Datentypen von
Oracle8 und bereits innerhalb des Schemas definierten Objekttyps zusammensetzen kann. Er
ist als reine Strukturdefinition zu betrachten, die keine Instanzen besitzt.
Ein Objekttyp besitzt einen eindeutigen Namen, um ihn innerhalb eines Schemas zu identifizieren. Seine Attribute sind die Strukturbeschreibung einer Entität. Es ist möglich Methoden
über einem Objekt zu definieren, um auf diese Weise das Verhalten der Entität nachzubilden.
Dieser benutzerdefinierte Datentyp wird je nach Verwendung innerhalb der Definition eines
Schemaelements entweder als Spaltenobjekt oder als Zeilenobjekt klassifiziert und kann innerhalb des Schemas, in dem er definiert worden ist, sowohl als Zeilenobjekt als auch als
Spaltenobjekt verwendet werden.
Der Begriff Spaltenobjekt bezieht sich auf die Attribute eines Schemaelements. Ein Objekttyp, der als Spaltenobjekt bezeichnet wird, definiert die Struktur eines Attributes in einer relationalen Datenbanktabelle oder die Struktur eines Attributes in einem anderen
Schemaelement. Der Begriff Zeilenobjekt bezieht sich auf die Instanzen eines Schemaelements. Ein Zeilenobjekt definiert die Struktur eines kompletten Datensatzes bzw. die Struktur
der Instanz des Schemaelements. Die Verwendung eines Objekttyps als Zeilenobjekt erfolgt
bei der Definition von Objekttabellen auf die im Abschnitt 4.3.3 genauer eingegangen wird.
4.3.1.1 Interne Verwaltung eines Objekttyps als Wertebereich eines Attributs
Wenn eine relationale Datenbanktabelle definiert wird, die einen Objekttyp als Wertebereich
eines Attributes enthält, dann werden vom DBMS Oracle8 zusätzliche Spalten in diese Tabelle eingefügt, die für den Benutzer nicht sichtbar sind und welche die Struktur des Objekttyps repräsentieren. Diese Spalten bilden die einzelnen Grundkomponenten des Objekttyps in
die Tabelle ab. Unter den Grundkomponenten des Objekttyps versteht man die Built-inDatentypen, die Oracle8 zur Verfügung stellt. Eine weitere Spalte wird benötigt, um zu speichern, ob die Instanz des Objekttyps Daten enthält oder nicht. Dies bezeichnet man als die
Null- bzw. Existenzinformation der Instanz. Folgendes Beispiel verdeutlicht, wie der Objekttyp auf relationale Weise innerhalb einer Tabelle umgesetzt wird.
CREATE TYPE ot_adresse AS OBJECT
(
strasse
VARCHAR2( 40 ),
hausnr
NUMBER( 5 ),
plz
NUMBER( 5 ),
land
VARCHAR( 20 )
);
50
Inhaltsverzeichnis
CREATE TYPE ot_person AS OBJECT
(
name
VARCHAR2( 30 ),
vorname
VARCHAR2( 30 ),
geburtstag DATE,
adresse
ot_adresse
);
Beispiel 4.3.1: Definition eines Verschachtelten Objekttyps
Hat man also einen solchen verschachtelten Objekttyp definiert, so kann man ihn in einer
Baumstruktur wie folgt darstellen:
Beispiel 4.3.2: Baumstruktur eines Objekttyps
Diese Baumstruktur wird innerhalb einer Tabelle intern in folgende relationale Darstellung
überführt, wobei die Attribute p.null und a.null die Spalten sind, die festlegen, ob eine Instanz des Objekttyps innerhalb der Tabelle existiert:
p.null p.name
p.vorname
p.geburtstag a.null a.strasse a.hausnr a.plz
a.land
Wie aus diesem Beispiel ersichtlich, werden nur die Blätter der Baumstruktur, die aus den
Built-in-Datentypen von Oracle8 bestehen, in der Tabelle abgelegt. Somit geht die eigentliche
Struktur des Objekttyps in der zweidimensionalen Darstellung verloren, da der Objekttyp in
seine atomaren Komponenten zerlegt wird.
51
Inhaltsverzeichnis
4.3.1.2 Methoden
Wie schon bereits erwähnt, ist es möglich, für einen Objekttyp Methoden zu definieren. Methoden sind Funktionen oder Prozeduren, die an einen Objekttyp gebunden sind. Die Aufgabe
einer Methode ist es, Informationen über die Instanzen der Objekttyps zu beschaffen, indem
sie die Daten einer Instanz analysiert und das Ergebnis außerhalb der Instanz dem DBMS und
dem Benutzer zur Verfügung zu stellt. Die Methoden eines Objekttyps werden innerhalb seiner Spezifikation deklariert und können auch wie die internen Funktionen und Prozeduren
überladen werden (siehe Abschnitt 4.2.6). Der eigentliche Programmcode einer Methode wird
im sogenannten "type body" abgelegt.
CREATE TYPE ot_adresse AS OBJECT
(
strasse
VARCHAR2( 40 ),
hausnr
NUMBER( 5 ),
plz
NUMBER( 5 ),
land
VARCHAR( 20 ),
MEMBER FUNCTION plz2Stadt(PostLeitZahl IN INTEGER)
RETURN VARCHAR2
);
CREATE TYPE BODY ot_adresse IS
MEMBER FUNCTION plz2Stadt(PostLeitZahl IN INTEGER)
RETURN VARCHAR2 IS
StadtName
VARCHAR2(20);
BEGIN
SELECT name
INTO
StadtName
FROM
staedte
WHERE plz = PostLeitZahl;
RETURN StadtName;
END;
Beispiel 4.3.1: Implementierung einer Methode
In diesem Beispiel wird die Funktion "plz2Stadt" benutzt, um zu einer gültigen Postleitzahl den entsprechenden Stadtnamen herauszufinden, der in der Tabelle "staedte" abgelegt ist. Diese Funktion kann z.B. von Applikationen aufgerufen werden, die das Ergebnis
weiter verwenden können.
Bei der allgemeinen Spezifikation von Parametern muß auch, wie bei Funktionen und Prozeduren, auf den Typ des Parameters geachtet werden (siehe Abschnitt 4.2.6). Ein spezieller
Parameter in Methoden ist der Parameter "self", der den direkten Zugriff auf eine Instanz
eines Objekttyps ermöglicht. Dieser Parameter steht in jeder Methode zur Verfügung und
braucht normalerweise nicht explizit spezifiziert zu werden. Bei Funktionen ist der Parameter
"self" automatisch ein "in"-Parameter, bei Prozeduren ein "in-out"-Parameter. Wenn
52
Inhaltsverzeichnis
der Parameter "self" explizit in der Spezifikation der Methode festgelegt werden soll, z.B.
um ihn innerhalb einer Funktion als "in-out"-Parameter zu klassifizieren, so ist zu beachten, daß "self" immer der erste Parameter sein muß, der angegeben wird.
4.3.1.3 Die Vergleichsfunktionen MAP und ORDER
Es existiert unter Oracle8 die Möglichkeit die sogenannten Vergleichsfunktionen "map" und
"order" für Objekttypen zu definieren. Diese werden benutzt, um die Instanzen eines Objekttyps untereinander zu vergleichen. Eine dieser Funktionen sollte vom Benutzer definiert
werden, da ansonsten nur die Möglichkeit besteht, die Instanzen eines Objekttyps auf Gleichheit oder Ungleichheit zu prüfen, indem man alle korrespondierende Attributwerte überprüft.
Sind diese Attributwerte identisch, so werden die Instanzen als gleich interpretiert. Der
Nachteil dieser Vorgehensweise ist es, daß bei Ungleichheit keine Aussage über die Wertigkeit der Instanzen gemacht werden kann.
Die Vergleichsfunktion "map" bildet die Attributwerte einer Instanz auf einen Wert ab, dessen Wertebereich durch einen der atomaren Datentypen "date", "real", "number" oder
"varchar2" definiert ist. Da auf diesen Built-in-Datentypen bereits eine Ordnung vordefiniert ist, können die Werte problemlos miteinander verglichen und eine Ordnung auf den Instanzen definiert werden. Eine "map"-Funktion liefert also die relative Position einer Instanz
innerhalb ihrer Objektklasse. Diese Funktion kann nicht überladen werden, da sie keine Parameter besitzen darf.
Die Vergleichsfunktion "order" vergleicht zwei Instanzen eines Objekttyps miteinander.
Aus diesem Grund hat die "order"-Funktion maximal zwei Parameter. Der erste Parameter
ist der Built-in-Parameter "self". Als zweiter Parameter wird eine Instanz des gleichen
Objekttyps verwendet. Ein Objekttyp darf nur eine "order"-Funktion besitzen, die somit
nicht überladen werden kann. Der Rückgabewert einer "order"-Funktion ist immer ein
numerischer Wert (z.B. –1, 0, 1), der das Ergebnis des Vergleichs repräsentiert.
Innerhalb eines Objekttyps ist es nicht möglich, sowohl eine "map"- als auch eine "order"-Funktion zu definieren, deshalb muß eine Entscheidung getroffen werden, welche Vorgehensweise am besten für den jeweiligen Objekttypen geeignet ist. Wenn es darum geht eine
große Anzahl von Instanzen untereinander zu vergleichen, ist die "map"-Funktion am besten
geeignet, da durch einen Aufruf alle betroffenen Instanzen einen atomaren Wert zugewiesen
bekommen, die dann sortiert werden. Die "order"-Funktion eignet sich nicht für eine große
Anzahl von Instanzen, da sie immer nur zwei Instanzen auf einmal miteinander vergleichen
kann und deshalb wiederholt aufgerufen werden muß, um alle betroffenen Instanzen miteinander zu vergleichen.
4.3.2 Kollektionstypen
Ein Kollektionstyp (engl. collection type) ist eine Strukturbeschreibung, die zur Verwaltung
einer Menge von geordneten Instanzen eines abstrakten Datentyps dient. Alle Instanzen eines
Kollektionstyps sind immer vom gleichem Datentyp. Ein Kollektionstyp besitzt immer nur
53
Inhaltsverzeichnis
ein Attribut, dessen Wertebereich entweder ein Built-in-Datentyp oder ein Objekttyp ist. Im
Prinzip kann man einen Kollektionstyp als ein eindimensionales Array bezeichnen, der durch
numerische Werte indiziert ist. Die Attribute eines Kollektionstyps können sowohl aus atomaren Built-in-Datentypen, als auch aus benutzerdefinierten Objekttypen bestehen. Ein Kollektionstyp kann als Wertebereich eines Attributs innerhalb eines Objekttyps eingesetzt oder aber
in PL/SQL als Variable, Parameter oder Rückgabewert einer Funktion verwendet werden. Es
existieren zwei unterschiedliche Arten von Kollektionstypen, "varrays" und vernestete
Tabellen, die in den folgenden Abschnitten vorgestellt werden.
Ein "varray" (variable size array) ist eine geordnete Menge von Instanzen, die alle durch
den gleichen Datentyp spezifiziert sind und durch einen numerischen Index in ihrer Reihenfolge festgelegt sind. Es ist nicht gestattet "varray"s ineinander zu schachteln. Bei der Definition eines "varray"s wird angegeben, wie viele Instanzen maximal in dem "varray"
gespeichert werden können. Ist eine Instanz erst einmal angelegt, so darf sie nicht mehr aus
dem "varray" gelöscht werden. Die Speicherung der Instanzen eines "varray"s erfolgt
intern innerhalb der Tabelle, in der sie als Wertebereich eingesetzt wird. Die Instanzen sind
durch ihre Position im "varray" eindeutig gekennzeichnet und angeordnet. Das folgende
Beispiel erzeugt einen "varray", in dem die Adressen des ersten bis dritten Wohnsitzes
gespeichert werden können.
CREATE TYPE ot_adresse AS OBJECT
(
strasse
VARCHAR2( 40 ),
hausnr
NUMBER( 5 ),
plz
NUMBER( 5 ),
land
VARCHAR( 20 )
);
CREATE TYPE var_wohnsitze AS VARRAY( 3 ) OF ot_adresse;
Beispiel 4.3.1: Verwendung eines Objekttyps als "varray"
Eine vernestete Tabelle ist eine ungeordnete Menge von Instanzen, die alle durch den gleichen Datentyp spezifiziert sind. Auch bei den vernesteten Tabellen ist es nicht gestattet, sie
ineinander zu verschachteln. Durch den Index, der über die Instanzen einer vernesteten Tabelle gelegt wird, kann der Zugriff auf die Instanzen wie in einem Array vorgenommen werden. Die Anzahl von Instanzen, die eine vernestete Tabelle besitzen darf, ist nicht beschränkt.
Es können dynamisch Instanzen eingefügt und auch gelöscht werden. Zu Anfang sind die
Instanzen einer vernesteten Tabelle dicht organisiert. Durch die erlaubten Löschungen können
Lücken entstehen, da zwar die Instanz an sich gelöscht wird, der Index aber bestehen bleibt.
So bleibt die Eindeutigkeit des Index der Instanzen erhalten. Die Speicherung der Instanzen
einer vernesteten Tabelle erfolgt in einer separaten Tabelle. Auf der separaten Tabelle der ist
keine Ordnung definiert. Jedes Element hat zwar einen eindeutigen Index, der aber nichts mit
der Anordnung der Elemente zu tun hat.
Die folgende Tabelle verdeutlicht noch einmal, welche Unterschiede zwischen den beiden
Kollektionstypen "varray" und vernesteter Tabelle bestehen.
54
Inhaltsverzeichnis
Eigenschaften
"varray"
Vernestete Tabelle
Anzahl der Instanzen
Begrenzt
Unbegrenzt
Löschen von Instanzen
Nicht erlaubt
Erlaubt
Anordnung der Instanzen
Dicht (keine Lücken)
Dicht und Licht (Lücken durch
Löschungen)
Speicherung der Daten
Intern in der Tabelle (in-line)
Extern in einer separaten Tabelle (out-of-line)
Aufgabe des Index
Eindeutige Kennzeichnung der
Instanz, erstellt Ordnung.
Eindeutige Kennzeichnung der
Instanz
Tabelle 4.3.1: Vergleich von Kollektionstypen
4.3.3 Objekttabellen
Ein Objekttabelle (engl. object table) ist ein Spezialtyp einer Tabelle, da bei der Definition der
Attribute nur Objekttypen verwendet werden dürfen oder aber die Objekttabelle aus einem
einzigen Objekttypen besteht, wodurch die Attribute der Objekttabelle den Attributen des
Objekttyps entsprechen. Objekttabellen dienen also dazu, Instanzen von Objekttypen anzulegen, sie zu speichern und zu verwalten. Jeder Instanz in einer Objekttabelle wird mit einem
Objektidenfikator (OID) versehen, die sie eindeutig innerhalb der Tabelle identifiziert. Diese
OID wird benötigt, um auf die Instanzen einer Objekttabelle zu referenzieren. Des weiteren
ermöglicht es eine Objekttabelle, Sichten zu definieren, die gleichzeitig auf Instanzen relationaler und objektorientierter Konzepte basieren.
4.3.4 Referenzierte Spalten
Der Datentyp "ref" definiert einen Wertebereich für Attribute, der nur einen Objektidentifikator des spezifizierten Types als gültigen Wert akzeptiert. Somit verbirgt sich hinter dem
Datentyp "ref" ein objektwertiges Attribut, welches immer auf einen Instanz in einer Objekttabelle (siehe Abschnitt 4.3.3) verweist, da nur die Instanzen einer Objekttabelle einen
Objektidentifikator besitzen. Der Einsatz von referenzierten Spalten muß gut überlegt sein, da
zwar zum Zeitpunkt des Speicherns überprüft wird, ob die referenzierte Instanz existiert, aber
beim Löschen einer Instanz in der Objekttabelle wird nicht überprüft, ob noch Referenzen auf
diese existieren. So kann es zu Referenzen auf nicht mehr existente Instanzen kommen, die
als hängende Referenzen (engl. dangling references) bezeichnet werden. Durch den Einsatz
von benutzerdefinierten Triggern kann in den betroffenen Tabellen überprüft werden, ob eine
Instanz noch referenziert wird oder ob sie gelöscht werden darf.
55
Inhaltsverzeichnis
CREATE TYPE ot_adresse AS OBJECT
(
strasse
VARCHAR2( 40 ),
hausnr
NUMBER( 5 ),
plz
NUMBER( 5 ),
land
VARCHAR( 20 )
);
CREATE TABLE adresse OF ot_adresse;
CREATE TABLE person
(
name
VARCHAR2( 30 ),
vorname
VARCHAR2( 30 ),
geburtstag DATE,
adresse
REF adresse
);
Beispiel 4.3.1: Verwendung von objekt-wertigen Attributen
So kann es innerhalb dieses Beispiels zu der Situation kommen, daß die Adresse einer Person
in der Objekttabelle "adresse" gelöscht wird, die Referenz in der Tabelle "person"
weiterhin auf die gelöschte Instanz verweist.
4.3.5 Objektsichten
Eine Objektsicht (engl. object view) ist eine virtuelle Tabelle, die ihre Instanzen aus den Attributwerten einer Anfrage an relationale und/oder objektorientierte Konzepte (Tabellen und
Sichten) zusammenstellt. Durch die Definition von Instead-of-Triggern ist es möglich, wie
auch bei rein relationalen Sichten, View-Updates zu steuern. Die Objektsicht dient als
Schnittstelle für objektorientierte Entwicklungstools, um relationale Daten als Einheit zu repräsentieren und auf sie zugreifen zu können. Wie bei den Objekttabellen wird auch bei den
Objektsichten eine OID benötigt, damit Referenzen auf die Instanzen ermöglicht werden. Um
zu gewährleisten, daß diese OID immer eindeutig ist, wird einer der selektierten Attributwerte
als OID der Objektsicht deklariert.
CREATE TABLE person
(
id
NUMBER (5),
name
VARCHAR2 (20),
vorname
VARCHAR2 (20),
wohnort
VARCHAR2 (20) );
56
Inhaltsverzeichnis
CREATE TYPE ot_person AS OBJECT
(
id
NUMBER (5),
name
VARCHAR2 (20),
vorname
VARCHAR2 (20) );
CREATE VIEW einwohner_von_bonn OF ot_person
WITH OBJECT OID ( id ) AS
SELECT
p.id, p.name, p.vorname
FROM
person p
WHERE
wohnort = 'Bonn';
Beispiel 4.3.1: Definition einer Objektsicht
In diesem Beispiel wird eine Objektsicht generiert, deren Struktur durch den Objekttyp
"ot_person" festgelegt ist. Die Tupel dieser Sicht werden aus den Tupeln der Tabelle
"person" aufgebaut, deren Attribut "wohnort" den Wert "Bonn" besitzt. Die OID der
Instanzen der Objekttabelle wird durch den Wert "id" aus der Tabelle "person" initialisiert.
4.4 SQL-92-Standard-Erweiterungen von Oracle8
Die Sprache SQL (structured query language) ist entwickelt worden, um Anfragen an relationale Datenbanken zu stellen und auszuwerten. Da es mittlerweile eine Vielzahl von relationalen Datenbanksystemen gibt, ist die Anfragesprache genormt worden, um die Syntax von
Standardoperationen festzulegen und dadurch die Benutzung der unterschiedlichen Systeme
zu vereinfachen. Die zur Zeit aktuelle Norm von SQL ist der SQL-92-Standard, der auch als
SQL-2-Standard bezeichnet wird. Die Konzepte von Oracle orientieren sich im wesentlichen
am SQL-92-Standard, bieten aber Erweiterungen, da sie zusätzliche Konzepte wie zum Beispiel Objekttypen unterstützen, die im SQL-92-Standard nicht vorgesehen sind. Dieser Abschnitt beschreibt die vom SQL-92-Standard abweichenden Eigenschaften von Oracle8.
4.4.1 Zusätzliche Datentypen unter Oracle8
Die folgenden Datentypen sind Built-in-Datentypen (siehe Abschnitt 4.2.1), die von Oracle8
zur Verfügung gestellt werden und nicht Bestandteil des SQL-92-Standards sind, bzw. einem
anderen Standard-SQL-Datentyp entsprechen.
Oracle8
SQL-92
number(x,y)
numeric(x,y)
varchar(x), varchar2(x)
character varying(x)
57
Inhaltsverzeichnis
Oracle8
SQL-92
long
---
raw
---
long raw
---
rowid
---
blob
---
clob
---
nclob
---
bfile
--Tabelle 4.4.1: Zusätzliche Built-in-Datentypen von Oracle8
Zusätzlich zu diesen Built-in-Datentypen ist es in Oracle8 möglich die benutzerdefinierten
Objekttypen (siehe Abschnitt 4.3.1), referenzierte Spalten (siehe Abschnitt 4.3.4), und Kollektionstypen (siehe Abschnitt 4.3.2) zu erstellen und zu benutzen, die im SQL-92-Standard
nicht vorgesehen sind. Weitere Informationen zum Thema Datentypen sind in der Oracle8Online-Hilfe zu finden ([Ora98]).
4.4.2 Erweiterte und neue Funktionen in Oracle8
Die einzigen Funktionen die laut SQL-92-Standard zur Verfügung stehen, sind die internen
Built-in-Funktionen "avg", "count", "max", "min" und "sum". Unter Oracle ist es
möglich maximal zwei unterschiedliche Funktionen ineinander zu verschachteln, was laut
SQL-92-Standard nicht zulässig ist. Des weiteren stellt Oracle zusätzlich eine Vielzahl von
weiteren numerischen Funktionen, Funktionen zur Manipulation und Analyse von Zeichenketten und Datumsfunktionen zur Verfügung, deren Beschreibung an dieser Stelle zu weit
führen würde und zum Beispiel in der Oracle8-Online-Hilfe nachgelesen werden kann. Zusätzlich zu den Built-in-Funktionen von Oracle8, besteht auch noch die Möglichkeit interne
benutzerdefinierte Funktionen und Prozeduren zu definieren und sie in Paketen zusammengefaßt als Bestandteil eines Datenbankschemas zu speichern.
4.4.3 Pseudospalten
Hinter dem Begriff der Pseudospalten verbergen sich Funktionen, die in DML-Operationen
wie Attribute einer Tabelle angesprochen werden können, deren Werte aber nicht innerhalb
einer Tabelle gespeichert sind. Der Wert einer Pseudospalte kann durch eine Anfrage an die
Datenbasis selektiert, aber nicht durch die Standardoperationen "insert", "update" und
58
Inhaltsverzeichnis
"delete" verändert werden. Auf zwei dieser Funktionen wird im folgenden genauer eingegangen, da sie im Rahmen dieser Diplomarbeit benutzt werden.
Die beiden Funktionen "currval" und "nextval" werden dazu benutzt, den Wert einer
"sequence" zu extrahieren und manipulieren. Eine "sequence" ist ein Schemaelement,
welches zur Generierung von eindeutigen und fortlaufenden Werten eingesetzt wird. Diese
Werte können benutzt werden, um eindeutige Werte für Primärschlüssel zu erzeugen. Die
Funktion "currval" liefert den aktuellen Wert einer Sequenz. Durch die Funktion
"nextval" wird der numerische Wert der Sequenz durch die Addition eines numerischen
Wertes, der bei der Definition einer Sequenz festgelegt wird, modifiziert und der neue aktuelle Wert zurückgeliefert. Diese beiden Funktionen können innerhalb der Attributliste einer
"select"-Operation verwendet werden, wenn dieser nicht Bestandteil einer Unteranfrage
ist oder zur Definition einer Sicht verwendet wird. Des weiteren können sie als Attributwerte
in einer "insert" oder "update"-Operation verwendet werden.
4.4.4 Zusätzliche Operatoren
Die folgenden zusätzlichen Operatoren werden von Oracle8 unterstützt, obwohl sie nicht Bestandteil des SQL-92-Standards sind.
Operator
||
!=, ^=, ¬=
Funktion
Konkatenation von Zeichenketten
Vergleichsoperatoren auf Ungleichheit
intersect
Mengenoperator, der zwei Anfragen miteinander verbindet und der alle Datensätze liefert, die sowohl Ergebnis der zweiten als auch der ersten Anfrage
sind.
minus
Mengenoperator, der zwei Anfragen miteinander verbindet und der alle Datensätze der ersten Anfrage liefert, die nicht auch Datensätze der zweiten Anfrage sind.
Tabelle 4.4.1: Zusätzliche Operatoren von Oracle8
4.4.5 Zusätzliche Konzepte
Die Syntax einiger Operationen des SQL-92-Standards, ist unter Oracle8 erweitert worden
und neue Operationen sind dazugekommen. Dies ist durch die Einführung von neuen Konzepten motiviert worden. In der folgenden Tabelle wird ein Überblick über die Oracle8Konzepte gegeben, die im SQL-92-Standard nicht enthalten sind.
59
Inhaltsverzeichnis
KONZEPTE
CLUSTER
ALTER
CREATE
DROP
X
X
X
CONTROLFILE
DATABASE
X
X
X
DATABASE LINK
X
X
DIRECTORY
X
X
FUNCTION
X
X
X
INDEX
X
X
X
X
X
X
X
LIBRARY
PACKAGE
X
PACKAGE BODY
X
PROCEDURE
X
X
X
PROFILE
X
X
X
RESOURCE COST
X
ROLLBACK SEGMENT
X
X
X
ROLE
X
X
X
SEQUENCE
X
X
X
SESSION
X
SNAPSHOT
X
X
X
SNAPSHOT LOG
X
X
X
X
X
SYNONYM
SYSTEM
X
TABLE
X
X
X
TABLESPACE
X
X
X
TRIGGER
X
X
TYPE
X
X
X
X
X
TYPE BODY
USER
X
X
VIEW
X
X
Tabelle 4.4.1: Erweiterte und neue Konzepte von Oracle8
60
Inhaltsverzeichnis
Die DDL- und DML-Operationen von Oracle8 sind in ihrer Funktion erweitert worden, damit
sie auch auf diese neuen Konzepte angewendet werden können. Auf die genaue Syntax der
erweiternden Klauseln und Parametern wird an dieser Stelle nicht eingegangen, da dies den
Rahmen dieses Abschnitts sprengen würde. Weitere Informationen zu diesen Konzepten und
ihren Einsatzgebieten, sind in der Oracle8-Online-Hilfe im Abschnitt „SQL-Reference“ zu
finden.
61
Inhaltsverzeichnis
Andrea Scheuber und Michael Horn
5 Eine Oracle-basierte Implementierung
des Chimera Prototyping Tool
Dieses und die folgenden Kapitel gehen auf die Architektur des Chimera Prototyping Tools
für Oracle und auf die unterschiedlichen Aspekte der Übersetzung von Kommandos der Datendefinitionssprache (DDL) und der Datenmanipulationssprache (DML) von Chimera ein.
Eine kurze Anmerkung zum Sprachgebrauch in den folgenden Kapiteln: Bisher gab es nur
eine Implementierung des Chimera Prototyping Tools (CPT) basierend auf Phoenix. Im Rahmen dieser beiden Diplomarbeiten ist eine zweite Implementation entstanden, die ebenfalls
Chimera Prototyping Tool heißt. Im folgenden wird deshalb die auf Phoenix basierende Implementierung mit CPTPhx und die neue Implementierung mit CPTOracle bezeichnet.
5.1 Architektur des CPTOracle
Die neue Implementation des Chimera Prototyping Tools basiert sehr stark auf der bisherigen
Implementation. Der Chimera-Compiler wurde um drei Komponenten erweitert: Jeweils eine
Komponente übernimmt die Übersetzung eines Chimera-Schemas in ein Oracle-SQL-Schema
(siehe Kapitel 6) und eine Komponente übersetzt die Datenmanipulationssprache von Chimera nach SQL (siehe Kapitel 8). Beide Komponenten benötigen die Komponente zur Übersetzung deklarativer Ausdrücke (siehe Kapitel 7). Der Phoenix-DBPL-Interpretierer der
bestehenden Implementation ist durch das ECLiPSe-Oracle-Interface von Thomas Kolbe (siehe Abschnitt 5.2 und [Kol95]) ersetzt worden. Abschließend wurde das Phoenix-System
durch einen Oracle-Datenbankserver ersetzt. Der Oracle-Datenbankserver übernimmt im
Rahmen des CPTOracle noch eine weitere, wichtige Aufgabe: Sämtliche Typüberprüfungen
werden durch den Server durchgeführt. Durch dieses Vorgehen mußte keinerlei Typüberprüfung innerhalb des CPTOracle implementiert werden.
62
Inhaltsverzeichnis
DDL
DML
CPT/CI
CPT/GUI
Chimera Compiler
load_schema
chimera_closedb
chimera_createdb
chimera_destroydb
chimera_opendb
dml
CDD
InfoDB1
ECLiPSe-Oracle-Interface
CPTOracle
DB
Oracle8 DBMS
InfoDB2
Abbildung 5.1: Architektur des Chimera Prototyping Tools für Oracle (CPTOracle)
63
Inhaltsverzeichnis
Die auffälligsten Unterschiede zwischen den Architekturen der beiden Implementationen sind
die zwei zusätzlichen Datenbanken InfoDB1 und InfoDB2. Erläuterungen des Aussehens
und der Funktionen der einzelnen Komponenten werden in den entsprechenden Kapiteln gegeben. Die beiden zusätzlichen Datenbanken werden für folgende Aufgaben benötigt:
•
Speicherung zusätzlicher Informationen für die Implementierungen von Schemaobjekten (siehe Kapitel 6)
•
Speicherung temporärer Daten, die bei der Übersetzung deklarativer Ausdrükke anfallen (siehe Kapitel 7)
•
Informationen für die Transaktionsverwaltung (siehe Kapitel 8)
Ebenso wie das CPTPhx, wird die Konfiguration des CPTOracle durch die Konfigurationsdatei
".chimerarc" festgelegt. Die neue Implementierung benötigt folgende Parameter:
•
CPT-Verzeichnis
•
Datenverzeichnis
•
Oracle Benutzerkennung
•
Oracle Paßwort
•
Oracle Service ID (SID)
Die Konfiguration des CPT- und Datenverzeichnisses ist aus dem CPTPhx übernommen worden. Die weiteren Information beziehen sich auf den Oracle-Datenbankserver. In der Datei
muß sowohl der Benutzerkennung als auch das Oracle Paßwort eingegeben werden. CPTOracle
meldet sich automatisch unter Verwendung der Benutzerkennung und des Paßwortes am Server an. Die Oracle Service ID (SID) wird momentan nicht benötigt, da die verwendete
ECLiPSe-Oracle-Schnittstelle diese nicht unterstützt. Andere Schnittstellen wie z.B. die
Oracle Schnittstelle SQL+ benötigen allerdings diese Information für eine korrekte Anmeldung am Datenbankserver.
Beide Implementierung von Chimera sind nicht kommerzielle Systeme. Daher ist das Sicherheitsmanko einer unverschlüsselten Speicherung der Benutzerkennung und des dazugehörigen
Paßwortes zu verschmerzen. Durch dieses Vorgehen ist eine Verwendung der graphischen
Oberfläche des CPT sichergestellt, ohne das daran Veränderungen vorgenommen werden
mußten.
Zusätzlich zu den neuen Komponenten und Datenbanken mußten die Aufgaben der sechs
Hauptfunktionen des Chimera Prototyping Tools teilweise verändert oder neu definiert werden. Die Funktionen werden im folgenden durch die entsprechenden Prolog-Prädikate repräsentiert:
•
load_schema/1
•
chimera_createdb/1
64
Inhaltsverzeichnis
•
chimera_opendb/1
•
chimera_closedb/0
•
chimera_destroydb/0
•
dml/0 und dml/1
Die Schnittstelle für die Datenmanipulation (dml/0 und dml/1) des CPT mußte nur geringfügig verändert werden. Die beiden Prädikate unterscheiden sich nur dadurch, daß das erste
Prädikat (dml/0) einen interaktiven Datenmanipulationsmodus aktiviert, während das zweite
Prädikat (dml/1) eine Stapelverarbeitung für ein Skript mit mehreren Befehlen aktiviert.
Jede Transaktion wird an das Modul zur Übersetzung imperativer Ausdrücke weitergeleitet
(siehe Kapitel 8).
5.1.1 Einlesen eines Chimera-Schemas (load_schema/1)
Das Prolog-Prädikat "load_ schema/1" lädt eine Schemadatei und übersetzt den Inhalt
der Datei in die interne Darstellung des Chimera Data Dictionary (CDD). Zusätzlich zur bestehenden Funktionalität des CPTPhx muß dieses Prädikat noch weitere Aufgaben übernehmen. Die interne Darstellung des CDD kann aufgrund der Implementierung der Übersetzung
deklarativer Ausdrücke nicht für die Übersetzung der Implementationen der verwendeten
Schemaobjekte eingesetzt werden. Die Implementation der abgeleiteten Objektklasse
"abitur" aus Kapitel 2
define implementation for abitur
population
abitur(X) <oberstufe(X),
X.klasse = 13,
X.durchschnitt <= 4
end;
wird durch das Prädikat "load_schema/1" in folgende interne Darstellung übersetzt:
...
********************************************
*** population_rule
********************************************
(21,user): abitur,
ctvc(abitur, [var(X)]),
[ctvc(oberstufe, [var(X)]), comp(identity,
dot(var(X), klasse), const(13, integer)),
comp(less_equal, dot(var(X), durchschnitt),
const(4, integer))]
...
Obiger Eintrag des CDD entspricht dem Ergebnis der Syntaxüberprüfung durch den ChimeraParser. Jede Regel wird im CDD durch ein 3-Tupel repräsentiert: Name der Klasse, linke
Seite der Regel (Kopf der Regel) und rechte Seite der Regel (Rumpf der Regel).Der Rumpf
65
Inhaltsverzeichnis
der Regel besteht aus einer Liste, die das Ergebnis der Syntax- und Typanalyse des deklarativen Ausdrucks repräsentiert. Die in Kapitel 7 vorgestellte Übersetzung deklarativer Ausdrükke benötigt für die Übersetzung eine Liste von Zeichenketten. Die obige Repräsentation des
Rumpfes der Regel entspricht daher nicht dem erforderlichen Format. Während des Lesevorgangs eines Chimera-Schemas wird deshalb eine zusätzliche Version der im Schema verwendeten Regeln in der "InfoDB1" abgespeichert. Das Prädikat "implementation/3"
speichert die benötigten Zeichenketten. Es benötigt folgende drei Parameter:
•
Name der zur Implementation gehörenden Klasse
•
Art des implementierten Schemaobjektes
•
Definition der Regel in Form einer Liste von Zeichenketten
Durch das Design des Prädikates können alle möglichen Implementationen für abgeleitete
Klassen und Attribute, Sichten, Integritätsbedingungen und Trigger abgespeichert werden.
Die Implementation der abgeleiteten Objektklasse "abitur" wird wie folgt durch das Prolog-Prädikat abgespeichert:
implementation( abitur,
population,
[abitur, "(", var(X), ")", <-, oberstufe,
"(", var(X), ")", ",", var(X), ., klasse,
=, 13, ",", var(...), ...])
Aus dem Fakt der Prolog-Datenbank können anschließend alle benötigten Informationen ausgelesen werden. Obiges Fakt repräsentiert die Implementation der Klasse "abitur". Es
wird die "population" für die abgeleitete Klasse definiert. Das dritte Attribut entspricht
der Definition der Populationsregel.
5.1.2 Anlegen einer Chimera-Datenbank (chimera_createdb/1)
Das Prolog-Prädikat "chimera_createdb/1" startet die Übersetzung eines ChimeraSchemas in ein Oracle8-SQL-Schema und erzeugt eine auf dem SQL-Schema basierende
Oracle8-Datenbank. Als Parameter benötigt dieses Prädikat den Namen der zu erzeugenden
Datenbank.
Das weitere Vorgehen entspricht dem des bestehenden CPTPhx. Im Datenverzeichnis des CPT
wird ein Unterverzeichnis angelegt, in dem alle zur Datenbank gehörenden Informationen
gespeichert werden. Folgende Dateien werden automatisch erzeugt:
•
Datei für die Informationen des CDD (Dateiname: dbname.cdd)
•
Skript der Schemaübersetzung (Dateiname: dbname.sql)
Das komplette CDD wird ausgelesen und in einer Datei gespeichert. Jeder Eintrag wird durch
eine Liste repräsentiert. Die Liste umfaßt drei Werte: das Chimera-Modul, den Konzeptname
und die Konzeptdefinition. Die Konzeptdefinition entspricht einer Liste von Zeichenketten.
Das CDD-Beispiel aus Kapitel 3 wird wie folgt bei der Erzeugung der Datenbank gesichert:
66
Inhaltsverzeichnis
[chimera, module, [chimera]].
[chimera, module, [user]].
[user, object_class, [adresse, [extensional]]].
[user, object_class, [person, [extensional]]].
[user, object_class, [schueler, [extensional]]].
[user, object_class, [oberstufe, [extensional]]].
[user, object_class, [abitur, [derived]]].
[user, value_class, [geschlecht, string]].
[user, superclass, [person, schueler]].
[user, superclass, [schueler, oberstufe]].
[user, superclass, [oberstufe, abitur]].
...
[user, population_rule, [abitur, ctvc(abitur, [var(X)]),
[ctvc(oberstufe, [var(X)]), comp(identity, dot(var(X),
klasse), const(13, integer)), comp(less_equal, dot(var(X),
durchschnitt), const(4, integer))]]].
Die zweite Datei enthält das Ergebnis der im Kapitel 6 vorgestellten Schemaübersetzung eines Chimera-Schemas in ein Oracle8-SQL-Schema. Das resultierende SQL-Skript kann zur
Erzeugung der Datenbank mit Hilfe einer beliebigen Oracle-Schnittstelle (z.B.
SQL+)eingespielt werden. Das genaue Aussehen der Datei wird durch die Beispiele in Kapitel 6 erläutert.
5.1.3 Öffnen einer Chimera-Datenbank (chimera_opendb/1)
Das Prädikat "chimera_opendb/1" öffnet eine bestehende Datenbank für die Benutzung
durch das CPTOracle. Hierbei wird der Inhalt der CDD-Datei zurück in das CDD geschrieben.
Nachdem die Datei komplett gelesen wurde, ist das CPTOracle bereit, weitere Aufgaben zu erfüllen.
Die momentane Implementation des CPTOracle überprüft nicht, ob die Tabellen, Sichten, Integritätsbedingungen und Trigger den Information des CDD entsprechen. Eine Überprüfung auf
Korrektheit der bestehenden Datenbank ist selbst mit sehr großem Aufwand nicht möglich.
Oracle-SQL bietet nur die Möglichkeit, das Vorhandensein einer Tabelle zu überprüfen, die
genaue Definition der Tabelle läßt sich nicht überprüfen. In SQL existieren keinerlei Mechanismen die Definition von Integritätsbedingungen, Triggern und Sichten mit einer Schemadefinition zu überprüfen. Die einzige, umständliche Möglichkeit Integritätsbedingungen,
Trigger und Sichten zu überprüfen wäre das Löschen der bestehenden und eine erneute Übersetzung der Informationen des CDD. Ein Abgleich der Informationen des geladenen CDD
und der bestehenden Datenbank ist demnach nicht effizient möglich.
5.1.4 Schließen einer Chimera-Datenbank (chimera_closedb/0)
Durch das Schließen einer Chimera-Datenbank werden alle internen Informationen bzgl. der
Datenbank gelöscht. Alle Einträge im CDD und der internen Datenbank "infoDB1" werden
entfernt. Obwohl die bisherige Implementierung des CPTOracle noch keine Schemaevolution
67
Inhaltsverzeichnis
unterstützt, werden die Informationen des CDD vor dem Löschen noch einmal ausgelesen und
in der entsprechenden Datei gespeichert.
Das CPT führt keinerlei Datenbankbefehle beim Schließen einer Chimera Datenbank durch.
Die bedeutet, daß eventuelle Daten, die noch nicht mit einem "commit" bestätigt wurden,
verloren gehen. Der Benutzer ist in diesem Falle selbst verantwortlich, ob die gemachten Änderungen im Datenbestand erhalten bleiben sollen oder nicht.
Die Abmeldung des CPTOracle am Oracle-Server geschieht ebenfalls erst nach Beendigung der
Applikation. Es ist momentan nicht vorgesehen, die Verbindung zu Server während einer Sitzung zu verändern oder zu verlassen. Das Programm meldet sich automatisch während des
Beendens am Datenbankserver ab.
5.1.5 Löschen einer Chimera-Datenbank (chimera_destroydb/0)
Nur eine geöffnete Chimera-Datenbank kann gelöscht werden. Der Löschvorgang basiert auf
den gespeicherten Informationen des CDD. Zuerst werden alle ChimeraIntegritätsbedingungen, -Trigger und -Sichten gelöscht. Anschließend werden alle OracleTabellen, -Trigger und -Sichten gelöscht, die eine Chimera-Klassenhierarchie repräsentieren.
Elemente einer Oracle-Datenbank können mit Hilfe der SQL-Operation "drop" gelöscht
werden. Die "drop"-Operation erwartet folgende zwei Parameter:
•
Schemakonzept
•
Name des Konzeptes
Folgende Beispiele löschen z.B. einen Oracle-Trigger namens "abitur_bestanden" und
eine Oracle-Sicht namens "abitur":
drop trigger abitur_bestanden;
drop view abitur;
Nachdem alle Tabellen, Integritätsbedingungen usw. gelöscht wurden, werden alle Dateien
und Verzeichnisse zur bestehenden Datenbank gelöscht. Abschließend werden alle Informationen aus den internen Prolog-Datenbanken gelöscht.
5.2 Das ECLiPSe-Oracle-Interface
Dieses Kapitel stellt das ECLiPSe-Oracle-Interface vor, das zur Anbindung des CPTOracle an
eine Oracle-Datenbank benutzt wird. Der Inhalt basiert hauptsächlich auf der Dokumentation
"Anbindung des RDBMS Oracle an ECLiPSe" von Thomas Kolbe [Kol95]. Das ECLiPSeOracle-Interface stellt mehrere Prädikate zur Verfügung, die einen Verbindungsaufbau und
die Kommunikation zwischen dem Prolog-System ECLiPSe und einem Datenbanksystem von
Oracle ermöglichen. Diese Schnittstelle wird benutzt, um aus ECLiPSe sowohl DDL- als auch
68
Inhaltsverzeichnis
DML-Operationen an das Datenbanksystem zu schicken. Die wichtigsten Prädikate dieser
Schnittstelle werden im folgenden vorgestellt.
Das Prädikat "sql_login" ist für den Aufbau der Verbindung zwischen ECLiPSe und der
Datenbank zuständig. Es benötigt dazu zwei Parameter, nämlich den Namen eines Datenbankbenutzers und das dazugehörige Paßwort, die als Prolog-Atom oder Prolog-String sein
müssen. Durch das Setzen der Umgebungsvariablen ORACLE_SID wird festgelegt, an welche Datenbank sich der Verbindungsaufbau richten soll. Das Prädikat "sql_logout" beendet die Verbindung zwischen ECLiPSe und Datenbanksystem. Falls Änderungen am
Datenbestand noch nicht durch den Befehl "commit" bestätigt worden sind, wird dies vor
dem Auflösen der Verbindung noch nachgeholt.
Das Prädikat "sql_commit" wird benutzt, um eine Transaktion abzuschließen und die
vorgenommenen Änderungen in der Datenbank permanent verfügbar zu machen, indem es
den Befehl "commit" an die Datenbank schickt. Das Prädikat "sql_rollback" setzt
sämtliche Änderungen einer Transaktion, die noch nicht mit dem Befehl "commit" abgeschlossen worden ist zurück, indem es den Befehl "rollback" an die Datenbank schickt.
Die Prädikate "sql_insert" und "sql_delete" dienen dazu, die SQL-DMLOperationen "insert" und "delete" an eine Oracle-Datenbank zu richten und auszuführen. Das Prädikat "sql_insert" benötigt drei Parameter, um eine syntaktisch korrekte
"insert"-Operation an eine Oracle-Datenbank zu schicken. Der erste Parameter enthält
den Tabellennamen, der einen gültigen Tabellennamen der Oracle-Datenbank als Wert besitzen und als Prolog-String oder Prolog-Atom vorliegen muß. Der zweite Parameter ist eine
Attributliste, die alle Namen der Attribute beinhaltet, denen durch die "insert"-Operation
ein Wert zugewiesen wird. Der zweite Parameter besteht aus einer Werteliste, die genauso
lang sein muß, wie die Liste der Attributnamen, da sie die dazugehörigen Attributwerte beinhaltet.
Prädikat
sql_insert('person',
['Name','Vorname','P_Alter'],
['Scheuber','Andrea', 26 ])
SQL-Operation
INSERT INTO person
( Name, Vorname, P_Alter )
VALUES('Scheuber',Andrea',26);
Beispiel 5.2.1: Verwendung des Prolog-Prädikats "sql_insert"
In dem Beispiel 5.2.1 werden die Parameter des Prolog-Prädikats "sql_insert" in eine
SQL-Insert-Operation umgesetzt. Dabei legt der erste Parameter "person" fest, daß die
"insert"-Operation an die Relation "person" gerichtet wird. Durch die Liste der Attributnamen "Name", "Vorname" und "p_Alter" wird bestimmt, welche Attribute der
Relation einen Attributwert zugewiesen bekommen. Die Liste der Attributwerte beinhaltet die
Werte, die den Attributen zugewiesen werden. Durch die Reihenfolge der Attributnamen und
–werte ist automatisch festgelegt, daß das Attribut "Name" den Wert 'Scheuber', das
Attribut "Vorname" den Wert 'Andrea' und das Attribut "p_Alter" den Wert 26 zugewiesen bekommt.
69
Inhaltsverzeichnis
Das Prädikat "sql_delete" benötigt fünf Parameter, um eine syntaktische korrekte
"delete"-Operation an eine Oracle-Datenbank zu schicken. Der erste Parameter beinhaltet,
wie auch bei dem Prädikat "sql_insert", einen gültigen Tabellennamen. Der zweite Parameter ist ein String, der eine "where"-Bedingung formuliert, aber nicht selbst das Schlüsselwort "where" beinhaltet. Handelt es sich bei diesem Parameter um einen Leerstring, so
wird keine "where"-Bedingung erzeugt, wenn es sich bei dem dritten und vierten Parameter, um leere Listen handelt. Bei diesen beiden Parametern handelt es sich wieder, um Listen,
die Attributnamen und Attributwerte beinhalten. Sind diese beiden Listen nicht leer, so wird
eine "where"-Bedingung aus ihnen formuliert, die zur Folge hat, daß nur Datensätze aus der
festgelegten Tabelle gelöscht werden, deren Attribute aus der Attributliste als Wert die dazugehörigen aufgelisteten Werte beinhalten. Der fünfte und letzte Parameter ist ein Rückgabeparameter, der die Anzahl der gelöschten Datensätze in der Oracle-Datenbank zurück liefert.
Prädikat
SQL-Operation
sql_delete
(
'person',
'p_alter < 30'
['Name'],['Scheuber'],
Rows ).
DELETE
FROM
WHERE
AND
Rows = 1
1 Row(s) affected
person
p_alter < 30
Name = 'Scheuber';
Beispiel 5.2.2: Verwendung des Prolog-Prädikats "sql_delete"
Das Beispiel 5.2.2 zeigt, wie aus den Parametern des Prolog-Prädikats "sql_delete" eine
SQL-Delete-Operation aufgebaut wird. Der erste Parameter 'person' legt fest, daß die
"delete"-Operation an die Relation "person" gerichtet wird. Der zweite Parameter wird
als "where"-Klausel in die "delete"-Operation übernommen. An diese "where"Klausel wird die zusätzliche Bedingung, die sich aus den Listen mit dem Attributnamen und –
wert ergeben angehängt.
Das Prädikat "sql_exec" wird dazu benutzt, um eine beliebige SQL-Operation zu formulieren, die an eine Oracle-Datenbank geschickt wird. Da keine speziellen Prädikate existieren,
um DDL-Operationen auszuführen, ist dies die bisher einzige Möglichkeit via ECLiPSeTabellen und andere Elemente einer Schemadefinition in einer Oracle-Datenbank anzulegen.
Des weiteren ist es auch die einzige Möglichkeit, eine Update-Operation zu formulieren und
an eine Datenbank zu schicken, da für diese Operation auch kein spezielles Prädikat existiert.
Das Prädikat "sql_exec" benötigt vier Parameter, von denen der erste Parameter eine beliebige SQL-Operation beinhalten kann. Bei der Formulierung der SQL-Operation sollte folgendes beachtet werden: Da Werte in Form von Zeichenketten innerhalb einer SQL-Operation
durch einfache Hochkommata eingeschlossen werden müssen, empfiehlt es sich die gesamte
SQL-Operation als Prolog-String in doppelten Hochkommata zu formulieren, da innerhalb
eines Prolog-Strings einfache Hochkommata ohne Probleme verwendet werden können. Dies
ist bei der Definition der SQL-Operation als Prolog-Atom nicht der Fall, da ein Prolog-Atom
durch einfache Hochkommata eingeschlossen wird, und deshalb innerhalb des Atoms keine
einfachen Hochkommata verwendet werden dürfen. Die drei weitere Parameter des Prädikats
70
Inhaltsverzeichnis
"sql_exec" sind Rückgabeparameter, die bei Auftreten eines Fehlers den entsprechenden
Oracle-Fehlercode und den dazugehörigen Fehlertext oder bei fehlerfreier Ausführung der
Operation die Anzahl der bearbeiteten Datensätze zurückliefern.
Prädikat
SQL-Operation
sql_exec(
CREATE TABLE person
"CREATE TABLE person
(
name
VARCHAR( 30 ),
( Name
VARCHAR( 30 ),
vorname
VARCHAR( 30 ),
Vorname VARCHAR( 30 ),
p_alter
NUMBER( 3 )
P_Alter NUMBER( 3 ) )", );
ReturnCode,
ReturnMsg,
Rows).
ReturnCode = 0
ReturnMsg = ""
Rows = 0
Beispiel 5.2.3: Verwendung des Prolog-Prädikats "sql_exec"
Das Beispiel 5.2.3 zeigt die Umsetzung einer DDL-Operation, die zur Erstellung einer Relation dient. Der erste Parameter beinhaltet die gesamte DDL-Operation, die ohne Veränderungen an die Oracle-Datenbank weitergeleitet wird. Da diese Operation durchgeführt werden
konnte, sind die Rückgabeparameter "ReturnCode" und "ReturnMsg" mit der Zahl 0,
bzw. mit einem Leerstring unifiziert worden, da kein Fehler aufgetreten ist und somit auch
kein Fehlercode und somit auch keine Fehlermeldung existiert. Da auch keine Datensätze
durch eine DDL-Operation beeinflußt werden, wird die Variable "Rows" mit der Zahl 0 unifiziert.
Die folgenden Prädikate werden dazu benutzt, selektierte Tupel aus den Relationen einer
Oracle-Datenbank mit einer Variablenliste zu unifizieren und innerhalb eines PrologPrädikats weiter zu verwenden. Bei der Verwendung dieser Prädikate muß auf folgendes geachtet werden: Jedes der folgenden Prädikate legt einen Cursor in der Oracle-Datenbank an,
der zur Selektion von Tupelmengen benutzt wird. Ein Cursor ist eine Datenstruktur vom Typ
"record". Die Attribute eines Cursors bekommen durch eine "select"-Operation die entsprechenden Werte zugewiesen. Da die Anzahl der gleichzeitig geöffneten Cursor in einem
Oracle-Datenbanksystem per Default auf 10 beschränkt ist, muß entweder der Wert des entsprechenden Systemparameters verändert werden oder es muß immer erst die Selektion einer
Tupelmenge abgeschlossen und der verwendete Cursor geschlossen sein, bevor ein weiteres
selektierendes Prädikat benutzt wird. Auf diese Weise ist immer nur maximal ein Cursor geöffnet.
Das Prädikat "sql_query" wird verwendet, um eine "select"-Operation zu konstruieren, die einen oder mehrere Tupel aus einer oder mehreren Relationen selektiert. Dieses Prolog-Prädikat benötigt fünf Parameter. Der erste Parameter besteht aus einer Liste von
Attributnamen, die alle Attribute beinhaltet, deren Werte selektiert werden sollen. Der zweite
Parameter ist entweder ein Prolog-String oder Prolog-Atom, der die Namen der Relationen
71
Inhaltsverzeichnis
beinhaltet, aus denen die Daten selektiert werden sollen. Die einzelnen Relationsnamen werden durch ein Komma voneinander getrennt. Der dritte Parameter beinhaltet die "where"Klausel der "select"-Operation in Form eines Prolog-Strings oder –Atoms, die nicht das
Schlüsselwort "where" beinhaltet. Der vierte Parameter dient dazu, beliebige SQLKlauseln, wie zum Beispiel "order by", hinter der "where"-Klausel der "select"Operation anzuhängen. Der fünfte Parameter ist eine Liste von Variablen, die genau so viele
Variablen besitzen muß, wie die Attributliste des ersten Parameters, da die selektierten Attributwerte mit den Variablen aus der Variablenliste unifiziert werden. Dies geschieht solange,
wie eine neue passende Variablenbelegung gefunden wird. Sind alle Variablenbelegungen
gefunden worden, so schlägt das Prädikat fehl.
Prolog-Prädikat
SQL-Operation
sql_query(
['Name','Vorname','p_Alter'],
'Person',
"Name = 'Scheuber'",
"ORDER BY p_alter",
[Name, Vorname, Alter] ).
SELECT
FROM
WHERE
ORDER BY
Name,Vorname,p_Alter
person
Name = 'Scheuber'
p_Alter;
Name = 'Scheuber'
Vorname = 'Margret'
Alter = 56
More?(;)
Name
Scheuber
Scheuber
Vorname
Margret
Berthold
p_Alter
56
60
Name = 'Scheuber'
Vorname = 'Berthold'
Alter = 60
More?(;)
no (more) solution.
Beispiel 5.2.4: Verwendung des Prolog-Prädikats "sql_query"
In dem Beispiel 5.2.4 wird die Konstruktion einer SQL-Select-Operation durch das PrologPrädikat "sql_query" beschrieben. Der erste Parameter des Prädikats besteht aus einer
Liste, welche die Attribute "Name", "Vorname" und "p_Alter" beinhaltet. Die Werte
dieser Attribute sollen aus der Relation "person" selektiert werden, die durch den zweiten
Parameter des Prädikats festgelegt wird. Der dritte Parameter des Prädikats beinhaltet die
"where"-Klausel, durch welche die Anzahl der zu selektierenden Datensätze der Relation
"person" auf diejenigen beschränkt wird, deren Attribut "name" als Wert die Zeichenkette 'Scheuber' besitzt. Als zusätzliche Klausel wird in diesem Beispiel die "order
by"-Klausel verwendet, durch welche die Reihenfolge, in der die Tupel selektiert werden,
beeinflußt wird. Die "order by"-Klausel wird über das Attribut "p_Alter" definiert,
was zur Folge hat, daß die Tupel in der Reihenfolge des aufsteigenden Alters sortiert werden.
Das Prädikat "sql_querydistinct" unterscheidet sich von dem Prädikat
"sql_query" nur durch die zusätzliche Verwendung des Schlüsselworts "distinct"
72
Inhaltsverzeichnis
bei der Konstruktion der SQL-Select-Operation. Dieses Schlüsselwort hat zur Folge, daß keine Tupel mehrfach selektiert werden, deren Attributwerte alle identisch sind.
Prolog-Prädikat
SQL-Operation
sql_querydistinct
(
['Name'],
'Person',
"",
"ORDER BY Name",
[Name] ).
SELECT
FROM
ORDER BY
Name = 'Horn'
More?(;)
Name = 'Scheuber'
More?(;)
Name
Horn
Scheuber
Schmitz
Name = 'Schmitz'
More?(;)
DISTINCT( Name )
Person
Name;
no (more) solution.
Beispiel 5.2.5 Verwendung des Prolog-Prädikats "sql_querydistinct"
In dem Beispiel 5.2.5 wird die Konstruktion einer SQL-Select-Operation durch das PrologPrädikat "sql_querydistinct" beschrieben. Angenommen es existieren mehrere Datensätze in der Tabelle "person", deren Attribut "name" als Wert die Zeichenkette
'Scheuber' besitzt, so wird dieser Name nur einmal selektiert, da es ansonsten zu Duplikaten in den selektierten Datensätzen kommen würde. Wird das Prädikat
"sql_querydistinct" über mehrere Attribute, wie zum Beispiel Name und Vorname
definiert, so müssen sowohl das Attribute Name als auch Vorname in ihren Werten übereinstimmen, damit der Datensatz nicht zweimal selektiert wird.
Durch das Prädikat "sql_lastmsg" kann ermittelt werden, ob die letzte SQL-Operation
erfolgreich durchgeführt werden konnte. Dieses Prädikat ist erforderlich, da Oracle zwischen
einem lokalen und einem globalen Rollback unterscheidet (siehe Kapitel 8 Abschnitt 8.2). Es
stellt die einzige Möglichkeit dar, zu überprüfen, ob ein lokales Rollback stattgefunden hat.
Die zwei ersten Rückgabeparameter des Prädikats beinhalten den Oracle-Fehlercode und die
dazugehörige Fehlermeldung, falls die SQL-Operation fehlgeschlagen ist. Der dritte
Rückgabeparameter beinhaltet die Anzahl der manipulierten Tupel, falls die SQL-Operation
erfolgreich war, und wird ansonsten mit dem Wert "0" unifiziert.
73
Inhaltsverzeichnis
Andrea Scheuber
6 Übersetzung von Chimera-Schemata in
Oracle8-SQL-Schemata
In diesem Kapitel wird eine Methode vorgestellt, wie die grundlegenden Konzepte des Chimera Data Dictionary (CDD), die aus einer Schemadefinition in der Chimera-Sprache extrahiert werden, in eine Schemadefinition des Datenbanksystems Oracle8 abgebildet werden
können. Dabei wird der Schwerpunkt auf Wertetypen, Werteklassen, Objektklassen und die
Umsetzung von Klassenhierarchien eingegangen. Die interessanten Aspekte dieser Übersetzung liegen insbesondere in der Realisierung der Klassenhierarchien, da Oracle8 zur Zeit keinerlei Vererbungsmechanismen bietet. Die Übersetzung der Integritätsbedingungen und
Trigger stellt einen weiteren interessanten Aspekt dar, da diese Chimera-Konzepte in ihrer
Semantik mächtiger sind, als die Konzepte, die Oracle8 zu bieten hat. Auf die Übersetzung
von Integritätsbedingungen und Triggern wird in Kapitel 9 eingegangen.
6.1 Datentypen
Eine grundlegende Voraussetzung für die Übersetzung eines Chimera-Schemas in ein Oracleoder Phoenix-Schema, ist die Abbildung der Built-in-Datentypen von Chimera auf die Builtin-Datentypen der beiden Datenbanksysteme, da die Konzepte zur Abbildung von Wertetypen, Werteklassen und Objektklassen auf diesen basieren. Bei der Abbildung nach Oracle
tauchen Probleme auf, da kein in einigen Fällen kein äquivalenter Datentyp oder kein äquivalentes Konzept existiert.
Eines dieser Probleme ist die Realisierung des Datentyps "string" ohne Längenbeschränkung, da diese von Oracle bei der Definition einer Zeichenkette von variabler Länge gefordert
wird. Um dieses Problem zu umgehen, wurden die folgenden Überlegungen angestellt. Der
erste Lösungsansatz war, eine Standardlänge von 100 Zeichen bei der Übersetzung des Da74
Inhaltsverzeichnis
tentyps "string" einzuführen. Da dieser Ansatz jedoch ineffizient im Speicherplatzverbrauch ist und auch nicht garantiert werden kann, daß dieser Wertebereich für alle Attribute
ausreichend ist, haben wir in unserer Implementation festgelegt, daß eine Maximallänge bei
Verwendung des Datentyps "string" vom Benutzer festgelegt werden muß. Dies ist die
beste Lösung, da der Platzbedarf am besten von jemanden abgeschätzt werden kann, der das
Datenbankschema erstellt und die Aufgaben kennt, die es erfüllen muß.
Ein weiteres Problem ist die Realisierung des Datentyps "real". Dieser Datentyp existiert
zwar zur Definition von PL/SQL-Variablen, kann aber nicht als Wertebereich eines Attributes
in einer Oracle8-SQL-Schemadefinition dienen. Diesen Zweck erfüllt der Oracle-Datentyp
"number(m,n)", durch den Wertebereiche definiert werden können, die dem Datentyp
"real" entsprechen. Der große Nachteil ist, daß auch hier wieder Maximallängen angegeben werden müssen, die den Vor- und Nachkommabereich des Wertebereichs einschränken.
Dadurch wurden wir gezwungen, bei der Übersetzung des Datentyps "real" Standardwerte
für Vor- und Nachkommastellen zu definieren, die daraufhin mit m=10 und n=10 festgelegt
worden sind.
Da es in Oracle auch keinen äquivalenten Datentyp für den Datentyp "boolean" gibt, muß
dieser ebenfalls auf andere Weise umgesetzt werden. Zur Auswahl stehen die Datentypen
"char(1)" und "number(1)" mit den Werten "Y" bzw. "1" für wahr und den Werten
"N" und "0" für falsch. Da keiner der Datentypen einen Vorteil gegenüber dem anderen
bietet, ist der Datentyp "char(1)" ohne besonderen Grund ausgewählt worden.
Die folgende Tabelle stellt die Built-in-Datentypen von Chimera den Typen der Datenbanksysteme zu besseren Übersicht noch einmal gegenüber.
ChimeraBonn
Phoenix
Oracle
boolean
boolean
char(1)
character
character
char
string
atom
---
string(n)
atom(n)
varchar2(n)
integer
integer
number
real
real
number(X,Y)
Tabelle 6.1.1: Übersetzung der Chimera Datentypen
6.2 Wertetypen
In diesem Kapitel wird die Übersetzung des Chimera-Konzepts Wertetyp vorgestellt. Um das
Chimera-Konzept Wertetyp umzusetzen, ist das Oracle-Konzept Objekttyp ausgewählt wor75
Inhaltsverzeichnis
den. Die Gemeinsamkeiten beider Konzepte bestehen darin, daß sie beide zur Definition eines
benutzerdefinierten, abstrakten Datentyps dienen, der selbst keine Instanzen besitzt, sondern
nur eine Strukturbeschreibung darstellt. Sowohl der Wertetyp als auch der Objekttyp kann bei
der Definition des Wertebereichs von Attributen in Objektklassen, bzw. in Relationen, eingesetzt werden. Ein gravierender Unterschied zwischen dem Chimera-Konzept Wertetyp und
dem Oracle-Konzept Objekttyp besteht in der Definition von Integritätsbedingungen. Die Integritätsbedingungen eines Wertetypen werden direkt an seine Definition gekoppelt und können über einzelne Attribute definiert werden. Das Konzept Objekttyp unterstützt
Integritätsbedingungen nur indirekt, da diese erst bei Einsatz eines Objekttyps als Wertebereich eines Attributs definiert werden können und auch nur über den gesamten Objekttypen
und nicht über einzelne Attribute. So ist es zum Beispiel nicht möglich bei einem Objekttypen
mit mehreren Attributen über nur ein Attribut eine Integritätsbedingung vom Typ "unique"
oder "not null" zu definieren. Der einzige Integritätsbedingungstyp, den Oracle8 zur
Verfügung stellt und der auf einzelne Attribute eines Objekttyps zugreifen kann, ist die Bedingung "check", da sie in der Lage ist, auf alle Werte der aktuellen Instanz zuzugreifen.
Durch die Definition eines boolschen Ausdrucks in Form einer "check"-Bedingung über
den zulässigen Attributwerten eines Objekttyps, kann die Bereichsbeschränkung eines Wertetypen aus einem Chimera-Schema umgesetzt werden. Allerdings muß die "check"Bedingung bei jedem Einsatz des Objekttyps als Wertebereich eines Attributes erneut definiert werden.
Ein weiterer Unterschied zwischen Wertetyp und Objekttyp besteht durch Einschränkungen
im Konzept Objekttyp in Bezug auf zulässige Verschachtelungen der Objekttypen. Das Datenmodell von Chimera erlaubt, daß ein Wertetyp sich selbst als Wertebereich eines Attributes besitzen darf. Es liegt dann eine rekursive Definition eines Wertetyps vor, die in Oracle8
nicht zulässig ist. Solange man diese Einschränkung beachtet, ist es erlaubt Objekttypen beliebig ineinander zu schachteln. Anhand des folgenden Beispiels wird die Vorgehensweise zur
Übersetzung eines Objekttyps noch einmal verdeutlicht.
Chimera-Wertetyp
define value type vt_adresse:
record_of
(
strasse: string(30),
hausnr:
integer,
plz:
integer
)
end;
Oracle8-Objekttyp
CREATE TYPE vt_adresse
AS OBJECT
(
strasse
varchar2(30),
hausnr
number,
plz
number
);
Beispiel 6.2.1: Übersetzung eines Wertetyps in einen Objekttyp
Im oben angegebenen Beispiel wird der Wertetyp "adresse" definiert. Er besteht aus drei
Attributwerten, die seine Strukturbeschreibung darstellen. Der dazugehörige Objekttyp wird
unter dem Namen des Wertetyps definiert und beinhaltet als Strukturbeschreibung die gleiche
Anzahl von Attributen, die auch mit den gleichen Attributnamen des Wertetyps bezeichnet
werden. Die Übersetzung der Attributwertebereiche des Wertetyps in Oracle-Datentypen erfolgt wie schon in Kapitel 6.1 beschrieben.
76
Inhaltsverzeichnis
6.3 Werteklassen
Die Umsetzung des Chimera-Konzepts Werteklasse erfolgt sowohl in Phoenix als auch in
Oracle durch extensionale Relationen bzw. Tabellen. Die Gemeinsamkeiten zwischen Werteklassen und Tabellen besteht darin, daß sowohl Werteklassen als auch Tabellen aus Attributen
bestehen und Instanzen besitzen. Die Instanzen einer Werteklasse werden durch die Operationen "add" und "drop" erzeugt und gelöscht. Die Datensätze einer Tabelle können durch
die Standard DML-Operationen "insert", "delete" und "update" erzeugt, gelöscht
und modifiziert werden. Es ist offensichtlich, daß die Operation "add" der Operation
"insert" entspricht und die Operation "drop" durch die Operation "delete" realisiert
werden kann. Des weiteren ist es möglich, sowohl über Werteklassen als auch Tabellen Integritätsbedingungen zu definieren.
Der Unterschied zwischen Werteklassen und Tabellen besteht darin, daß eine Werteklasse ein
Datentyp mit fest definierten Werten ist, also eine Art Aufzählungstyp, der als Wertebereich
für ein Attribut in einer Objektklasse benutzt werden kann. Eine Tabelle, die eine Werteklasse
realisiert, ist kein Datentyp, sondern eine Struktur, in der Daten abgelegt werden. Um eine
Verbindung zwischen den Tabelle herzustellen, die Objektklassen und Werteklassen realisieren, wird in der Tabelle der Werteklasse ein zusätzliches Attribut eingeführt. Dieses Attribut
wird als Primärschlüssel definiert. Das Attribut in der Tabelle der Objektklasse, welches eine
Werteklasse als Wertebereich besitzt, bekommt als Attributbereich den Datentyp des Primärschlüssels aus der Tabelle der Werteklasse zugewiesen. Über diese gleichwertigen Attribute
kann nun eine Verbindung zwischen den beiden Tabellen in Form eines Fremdschlüssels hergestellt werden. Diese Vorgehensweise wird unbedingt benötigt, wenn eine Werteklasse mehr
als ein Attribut besitzt. Ansonsten kann kein Fremdschlüssel definiert werden, der die Instanzen der Tabelle der Werteklasse korrekt mit den Instanzen der Tabelle der Objektklasse in
Verbindung setzt. Besteht eine Werteklasse nur aus einem Attribut, wird die gleiche Vorgehensweise gewählt, um ein einheitliches Übersetzungsverfahren zu haben. In diesem Fall wäre es von Vorteil direkt über das einzelne Attribut zu referenzieren, da dessen Werte eindeutig
sein müssen und sich dadurch als Fremdschlüssel eignen. Das folgende Beispiel verdeutlicht
die Vorgehensweise zur Übersetzung einer Chimera-Werteklasse in eine Oracle-Tabelle.
Chimera-Werteklasse
define value class vc_abteilung:
record_of
(
bereich:
string(30),
leiter:
string(30)
)
end;
Oracle-Tabelle
CREATE TABLE vc_abteilung
(
vid
NUMBER PRIMARY KEY,
bereich
VARCHAR2(30),
leiter
VARCHAR2(30)
);
Beispiel 6.3.1: Übersetzung einer Chimera-Werteklasse in eine Oracle-Relation
Die Übersetzung der Werteklasse "abteilung" erfolgt durch die Definition einer Tabelle
des selben Namens. Die beiden Attribute der Werteklasse, "bereich" und "leiter"
werden durch Attribute in der Tabelle realisiert, die den gleichen Namen tragen. Die Wertebereiche der Attribute werden wie in Kapitel 6.1 beschrieben übersetzt. Das zusätzliche Attribut
77
Inhaltsverzeichnis
in der Tabellendefinition wird unter dem Attributnamen "vid" (value identificator) und als
Primärschlüssel eingeführt.
Eine Alternative zu dieser Vorgehensweise wäre es, die Struktur einer Werteklasse in Form
eines Objekttyps abzubilden und über eine Objekttabelle zu realisieren, deren Struktur durch
den Objekttyp vorgegeben ist. In dieser Objekttabelle könnten dann die Instanzen der Werteklasse verwaltet werden. Der Vorteil dieser Vorgehensweise wäre, daß keine "vid" eingeführt werden müßte, da die Instanzen der Objekttabelle bereits einen Objektidentifikator
besitzen, über den die Verbindung zwischen Tabelle und Objekttabelle hergestellt werden
könnte. Der Nachteil dieser Vorgehensweise ist wieder das Problem, daß Integritätsbedingungen nicht über Objekttypen und ihren einzelnen Attributen definiert werden können, sondern
nur über den gesamten Objekttypen, wenn er als Wertebereich eines Attributs eingesetzt wird.
Um diese Einschränkung zu vermeiden, ist dieser Ansatz wieder verworfen worden.
Eine weitere Alternative wäre es gewesen, die Umsetzung von Werteklassen über "check"Bedingungen auf der Oracle-Seite zu implementieren. Da allerdings der Wertebereich einer
Werteklasse durch die Operationen "add" und "drop" nicht nur bei der Erstellung des
Datenbankschemas festgelegt, sondern auch noch danach manipuliert werden kann, wurde die
Übersetzung durch eine Tabelle und Integritätsbedingungen vorgezogen, da sonst eine Änderung in einer Werteklasse mindestens eine oder mehrere Modifikationen an der Definition des
Datenbankschemas nach sich ziehen kann. Des weiteren ist es einfacher, einen neuen Datensatz in eine Tabelle abzulegen, als alle "check"-Bedingungen, die auf einer Werteklasse
basieren, zu modifizieren. Ein weiteres Problem taucht bei dieser Vorgehensweise bei der
Definition von Integritätsbedingungen auf, da sowohl die Daten der Werteklasse als auch ihrer Integritätsbedingungen bei der Implementation einer "CHECK"-Bedingung berücksichtigt
werden müssen. Aus diesen Gründen wurde die Idee der Implementation von Werteklassen
durch "check"-Bedingungen wieder verworfen.
6.4 Objektklassen und Klassenhierarchien
Das Chimera-Konzept der Objektklasse wird in Oracle durch die Kombination von Tabellen
und Sichten umgesetzt. Die Gemeinsamkeiten von Objektklassen und Tabellen besteht darin,
daß beide Konzepte zur Speicherung und Verwaltung von Daten dienen. Der Bezeichner einer
Tabelle, die eine Objektklasse repräsentiert, setzt sich aus dem Präfix "oc_" und dem Namen der Objektklasse zusammen, um sie von den Bezeichnern der dazugehörigen Sichten zu
unterscheiden. Sowohl Objektklassen als auch Tabellen bestehen aus Attributen, deren Wertebereiche entweder durch Built-in-Datentypen oder benutzerdefinierte Datentypen definiert
werden können. Für jede Objektklasse wird genau eine Tabelle und eine Sicht erstellt. Die
Tabellen enthalten bis auf eine Ausnahme nur die Attribute, die innerhalb der Objektklassen
auch definiert worden sind. Zusätzlich zu den im Chimera-Schema definierten Attributen erhält eine Tabelle, die eine Objektklasse repräsentiert, ein zusätzliches Attribut in dem der
Objektidentifikator (OID) gespeichert wird. Dieser Objektidentifikator stellt bei der Definition einer Sicht die Verbindung zwischen den Instanzen der Tabellen her, um sie der Klassenhierarchie entsprechend zusammenzuführen. Der eindeutige Wert eines Objektidentifikators
wird durch das Oracle-Konzept "sequence" erzeugt. Auf eine "sequence" kann durch
die Funktionen "currval" und "nextval" zugegriffen werden, wobei die Funktion
78
Inhaltsverzeichnis
"currval" den aktuellen Wert der angegebenen "sequence" zurück liefert und die
Funktion "nextval" den aktuellen Wert um einen festgelegten Wert inkrementiert und das
Ergebnis als neuen Wert zurück liefert.
6.4.1 Abbildung von Chimera-Objektklassen auf Oracle8-Tabellen
Die benutzerdefinierten Wertebereiche der Attribute einer Objektklasse können durch Wertetypen, Werteklassen und andere Objektklassen repräsentiert werden. Ist der Wertebereich
eines Attributs durch einen Wertetypen festgelegt worden, so kann einfach der Bezeichner des
Wertetyps als Wertebereich benutzt werden, da ein entsprechender Objekttyp mit dem gleichen Bezeichner auf der Oracle-Seite bereits definiert worden ist (siehe Kapitel 6.2). Das folgende Beispiel zeigt die Umsetzung einer Objektklasse, in der ein Attribut einen Wertetyp als
Wertebereich besitzt.
Chimera-Objektklasse
define object class
person
attributes
name:
string(30),
vorname:
string(30),
adresse:
vt_adresse
end;
Oracle-Tabelle
CREATE TABLE oc_person
(
oid
NUMBER PRIMARY KEY,
name
VARCHAR2(30),
vorname
VARCHAR2(30),
adresse
vt_adresse
);
Beispiel 6.4.1: Übersetzung eines Wertetyps als Wertebereich eines Attributs
In diesem Beispiel ist der in Kapitel 6.1 definierte Objekttyp "vt_adresse" als Wertebereich des Attributs "adresse" verwendet worden. Dieser Wertebereich umfaßt die zusätzlichen Attribute "strasse", "hausnr" und "plz", auf die nur zugegriffen werden kann,
wenn eine Tupelvariable innerhalb einer DML-Operation oder Anfrage definiert worden ist.
Der Ausdruck, mit dem ein Attribut eines Objekttyps angesprochen werden kann, besteht aus
den Komponenten Tupelvariable, Name des Objekttyps und Name des Attributs. Auf das
vorangestellte Beispiel bezogen, wird auf die Werte des Attributs "strasse" aus der
Tabelle "oc_person" wie folgt zugegriffen:
SELECT V.adresse.strasse FROM oc_person V;
Ist der Wertebereich eines Attributs durch eine Werteklasse festgelegt worden, so wird dem
entsprechenden Attribut in der Tabelle, welche die Objektklasse abbildet, der Wertebereich
"number" zugewiesen. Dies ist eine Voraussetzung, um einen Fremdschlüssel zwischen
dem Attribut, welches als Wertebereich eine Werteklasse besitzt, und dem Primärschlüssel
der Tabelle, welche die Werteklasse repräsentiert, definieren zu können, da beide Attribute
den gleichen Datentyp als Wertebereich besitzen müssen (siehe Kapitel 6.3).
79
Inhaltsverzeichnis
Chimera-Objektklasse
define object class
angestellter
superclasses
person
attributes
abteilung: vc_abteilung,
gehalt:
integer
end;
Oracle-Tabelle
CREATE TABLE oc_angestellter
(
oid
NUMBER PRIMARY KEY,
abteilung
INTEGER REFERENCES
vc_abteilung,
gehalt
NUMBER
);
Beispiel 6.4.2: Übersetzung einer Werteklasse als Wertebereich eines Attributs
In diesem Beispiel ist in der Chimera-Objektklasse "angestellter" der Wertebereich des
Attributs "abteilung" durch die Werteklasse "vc_abteilung" festgelegt worden. Das
Attribut "abteilung" in der Oracle-Tabelle "angestellter" bekommt als Wertebereich den Datentyp "number" zugewiesen. Die Verbindung zwischen der Tabelle
"angestellter" und der Tabelle "vc_abteilung" wird durch die Definition eines
Fremdschlüssels zwischen dem Attribut "abteilung" und dem Primärschlüssel der Werteklasse hergestellt. Die genaue Übersetzung dieser Werteklasse in eine Oracle-Tabelle ist in
dem Kapitel 6.3 zu finden.
6.4.2 Abbildung einer Chimera-Klassenhierarchie auf Oracle8-Sichten
Durch die Definition von Oberklassen innerhalb der Definition einer Objektklasse wird die
eigentliche Hierarchie eines Chimera-Datenbankschemas aufgebaut, welche durch die Vererbung von Attributen organisiert wird. Da ein solcher Mechanismus für Oracle8 nicht existiert,
werden Sichten benutzt, um diesen Mechanismus zu implementieren. Eine Sicht, die eine
Objektklasse abbildet, enthält sowohl die Attribute der Objektklasse als auch alle Attribute
ihrer Oberklassen. Auf diese Weise wird die Struktur der Klassenhierarchie umgesetzt. Der
Bezeichner einer Sicht ist der Name der Objektklasse, die durch sie repräsentiert wird. Besitzt
eine Objektklasse keine Oberklassen, so wird trotzdem ein Sicht über ihren Attributen erstellt,
um das Übersetzungsverfahren zu vereinfachen.
person
angestellter
student
Beispiel 6.4.1: Klassenhierarchie
80
Inhaltsverzeichnis
So werden für die Abbildung der Klassenhierarchie in Beispiel 6.4.1 sowohl die drei Tabellen
"oc_person", "oc_angestellter" und "oc_student", als auch die drei Sichten
"person", "angesteller" und "student" benötigt.
Bei der Abbildung einer Klassenhierarchie gibt es zwei alternative Vorgehensweisen. Die
erste besteht darin, die Definition der Sicht auf den bereits existierenden Sichten aufbauen zu
lassen. Diese Vorgehensweise hätte den Vorteil, daß man nur die direkten Oberklassen bei der
Definition der Sicht beachten muß, da diese bereits alle Attribute ihrer Oberklassen besitzt.
Der Nachteil dieser Vorgehensweise ist, daß Modifikationen am Datenbestand einer Sicht, die
auf anderen Sichten basiert, wesentlich ineffizienter zur Laufzeit sind als Modifikationen am
Datenbestand einer Sicht, die nur auf Tabellen basiert. Basiert eine Sicht auf anderen Sichten,
so müssen die modifizierten Daten erst alle anderen beteiligten Sichten passieren, bevor sie in
den Basistabellen ankommen. Dadurch ergeben sich in Abhängigkeit von der Länge dieser
Kette von Sichten die schlechten Laufzeiten.
Aus diesem Grund ist die zweite Vorgehensweise gewählt worden, in der alle Sichten des
Datenbankschemas ausschließlich auf Tabellen basieren. Diese Vorgehensweise ist zwar aufwendiger bei der Übersetzung des Datenbankschemas, da erst alle beteiligten Oberklassen
einer Objektklasse und ihre Attribute zusammengestellt werden müssen, um eine Sicht zu
definieren, aber dafür verbessert sich die Laufzeit der DML-Operationen. Da die Definition
des Datenbankschemas nur einmal zur Erstellung der Datenbank übersetzt wird, die DMLOperationen hingegen laufend benutzt werden, liegt der Vorteil dieser Lösung auf der Hand.
Anhand der folgenden Beispiele, die sich auf die vorangestellte Klassenhierarchie aus
Beispiel 6.2.1 bezieht, wird die Umsetzung einer Klassenhierarchie durch den Einsatz von
Sichten genauer erläutert.
Chimera-Objektklasse
Oracle-Tabelle
Oracle-Sicht
CREATE VIEW person AS
CREATE TABLE oc_person
define object class
( oid, name, vorname,
(
person
strasse, hausnr, plz )
oid NUMBER PRIMARY KEY,
attributes
SELECT
name
VARCHAR2(30),
name:
string(30),
P.oid,
vorname
VARCHAR2(30),
vorname:
string(30),
P.name,
adresse
vt_adresse
adresse:
vt_adresse
P.vorname,
);
end;
P.adresse.strasse,
P.adresse.hausnr,
P.adresse.plz
FROM oc_person P;
Beispiel 6.4.2: Übersetzung der Objektklasse Person
In dem Beispiel 6.4.2 wird beschrieben, wie die Objektklasse "person" umgesetzt wird, die
keine Oberklasse besitzt und somit auch keine Attribute aus anderen Klassen erbt. Die Sicht,
die eine solche Objektklasse repräsentiert, basiert ausschließlich auf den Attributen ihrer Basistabelle, die alle explizit zur Erstellung der Sicht selektiert werden. In diesem Beispiel werden aus der Tabelle "oc_person" die Attribute "oid", "name" und "vorname"
selektiert. Da das Attribut "adresse" durch den Wertebereich des Objekttyps
"vt_adresse" festgelegt wird, müssen alle Attribute des Objekttyps explizit mit selektiert
81
Inhaltsverzeichnis
werden, damit die Attribute und nicht der Objektidentifikator des Objekttyps Bestandteil der
Sicht sind.
Chimera-Objektklasse
Oracle-Tabelle
CREATE TABLE
define object class
oc_angestellter
angestellter
(
superclasses
oid NUMBER PRIMARY KEY,
person
abteilung INTEGER
attributes
REFERENCES
abteilung:vc_abteilung,
vc_abteilung,
gehalt: integer
gehalt
NUMBER
end;
);
Oracle-Sicht
CREATE VIEW angestellter
AS ( oid, name, vorname,
strasse, hausnr,
plz, bereich,
leiter, gehalt )
SELECT
P.oid,
P.name,
P.vorname,
P.adresse.strasse,
P.adresse.hausnr
P.adresse.plz,
V.bereich,
V.leiter,
A.gehalt
FROM
oc_person P,
oc_angestellter A,
vc_abteilung V
WHERE
P.oid = A.oid AND
A.abteilung = V.vid
Beispiel 6.4.3: Übersetzung der Objektklasse Angestellter
In dem Beispiel 6.4.3 wird beschrieben, wie eine Objektklasse umgesetzt wird, die eine andere Objektklasse als Oberklasse besitzt. In diesem Fall besitzt die Objektklasse
"angestellter" die Objektklasse "person" als Oberklasse. Das hat für die Definition
der Sicht "angestellter" zur Folge, daß nicht nur alle Attribute der Tabelle
"oc_angestellter" zur Definition der Sicht selektiert werden müssen, sondern auch alle
Attribute der Tabelle "oc_person", um auf diese Weise die Attribute der übergeordneten
Klasse zu vererben. Die einzige Ausnahme bei der Selektion der Attribute bildet das Attribute
"oid". Da durch dieses Attribut die Verbindung zwischen den Datensätzen der Basistabellen
hergestellt wird, wenn der Wert der beiden "oid"s in den unterschiedlichen Tabellen identisch ist, wäre es nicht sinnvoll dieselbe "oid" mehrfach anzuzeigen. Da in unserer Implementation grundsätzlich die Spalten, der Objektklassen zuerst selektiert werden, die keine
anderen Objektklassen als Oberklassen besitzen, wird auch immer die "oid" dieser
Objektklasse als erstes Attribut mit selektiert. In diesem Beispiel werden deshalb die Attribute
"oid", "name", "vorname", die Attribute des Objekttyps "vt_adresse" aus der Basistabelle "oc_person" und das Attribut "gehalt" aus der Basistabelle
"oc_angestellter" selektiert. Die Verbindung zwischen den Attributen aus den beiden
Basistabellen wird über die Bedingungsklausel, die zur Definition der Sicht benötigt wird
erstellt. In dieser wird gefordert, daß die "oid" eines Tupels aus der Basistabelle
"oc_person" identisch zu der "oid" eines Tupels aus der Basistabelle
82
Inhaltsverzeichnis
"oc_angestellter" sein muß, damit ein Tupel aus der Kollektion dieser Attribute in der
Sicht zusammengestellt werden kann.
Ein weiterer interessanter Aspekt des Beispiel 6.4.3 besteht in der Verwendung einer Werteklasse als Wertebereich eines Attributes in einer Objektklasse. In einem solchen Fall werden
nicht nur die Attribute der Objektklasse und ihrer Oberklassen selektiert, sondern auch alle
Attribute der beteiligten Werteklasse mit Ausnahme der "vid" werden als Attribute in die
Definition der Sicht mit eingebunden. Die Verbindung der Tupel der beiden Tabellen, welche
die Objektklasse und die Werteklasse darstellen, erfolgt über eine zusätzliche Bedingung in
der Bedingungsklausel der SQL-"select"-Operation, durch welche die Daten einer Sicht
selektiert werden. Diese zusätzliche Bedingung legt fest, daß die "vid" aus der Tabelle,
welche die Werteklasse repräsentiert, identisch zu dem Wert des Attributes sein muß, dessen
Wertebereich in der Objektklasse durch die Werteklasse festgelegt ist. Für das konkrete
Beispiel 6.4.3 bedeutet dieses, daß die beiden Attribute "bereich" und "leiter" aus der
Tabelle "vc_abteilung" zusätzlich in die Definition der Sicht "angestellter" mit
einfließen. Die zusätzliche Bedingung in der Bedingungsklausel fordert die Gleichheit der
Attributwerte "vid" und "abteilung", um die konkreten Daten der Werteklasse
"vc_abteilung" in die Sicht mit einzubinden.
Chimera-Objektklasse
define object class
student
superclasses
angestellter
attributes
matrikel_nr: integer
end;
Oracle-Tabelle
Oracle-Sicht
CREATE VIEW student AS
CREATE TABLE oc_student
( oid, name, vorname,
(
strasse, hausnr, plz,
oid NUMBER PRIMARY KEY,
bereich, leiter,
matrikel_nr NUMBER
gehalt, matrikel_nr )
);
SELECT
P.oid,
P.name,
P.vorname,
P.adresse.strasse,
P.adresse.hausnr
P.adresse.plz,
V.bereich,
V.leiter,
A.gehalt,
S.matrikel_nr
FROM
oc_person P,
oc_angestellter A,
vc_abteilung V,
oc_student S
WHERE
P.oid = A.oid AND
P.oid = S.oid AND
A.abteilung = V.vid;
Beispiel 6.4.4: Übersetzung der Objektklasse Student
In dem Beispiel 6.4.4 wird beschrieben, wie eine Objektklasse umgesetzt wird, deren Oberklasse wiederum eine andere Objektklasse als Oberklasse besitzt. Dadurch ergibt sich eine
Kette von Objektklassen. Die Objektklasse "student" besitzt sowohl die Objektklasse
83
Inhaltsverzeichnis
"angestellter" als direkte Oberklasse, als auch die Objektklasse "person" als indirekte Oberklasse, da diese eine direkte Oberklasse der Objektklasse "angestellter" ist.
Das hat für die Definition der Sicht "student" zur Folge, daß die Attribute der Tabellen
"oc_student", "oc_angestellter" und "oc_person" selektiert werden müssen.
Daraus ergibt sich, daß die Attribute "oid", "name", "vorname" und die Attribute des
Attributs "adresse" aus der Basistabelle "oc_person" selektiert werden müssen. Hinzu
kommen die Attribute "bereich" und "leiter" aus der Tabelle "vc_abteilung".
Das Attribut "gehalt" aus der Basistabelle "oc_angestellter" und das Attribut
"matrikel_nr" aus der Basistabelle "student" werden auch noch in die Definition der
Sicht mit eingebunden. In der Bedingungsklausel der "select"-Operation, durch welche
die Sicht definiert wird, werden die Datensätze der einzelnen Basistabellen durch die Forderung nach der Gleichheit der "oid"s in allen beteiligten Tabellen miteinander verbunden.
6.4.3 Umsetzung von DML-Operationen auf Sichten
Die Chimera DML-Operationen "create", "modify" und "delete", werden in die
SQL-Operationen "insert", "update" und "delete" übersetzt. Eine SQL-Operation
wird immer an die entsprechende Sicht und nicht an die Basistabellen gerichtet, da die Sicht
alle Attribute der Objektklasse, inklusive der geerbten Attribute der Oberklassen, enthält. Die
hier vorgestellte Vorgehensweise ist nur durch das neue Oracle8-Konzept der Instead-ofTrigger möglich. Diese Trigger sind dafür zuständig, die einzelnen Attributwerte einer Sicht
den richtigen Attributen der Basistabellen zuzuordnen. Dies kann nicht automatisch von
Oracle übernommen werden, da in der Regel mehr als eine Basistabelle zur Definition der
Sicht benutzt wird und auch nicht alle Primärschlüssel der Basistabellen beteiligt sind. Für
jede DML-Operation wird ein entsprechender Instead-of-Trigger bei der Übersetzung eines
Chimera-Schemas in ein Oracle8-Schema automatisch erzeugt. Die Instead-of-Trigger einer
Sicht überladen die rudimentären "view-update"-Funktionen, die von Oracle selbst zur
Verfügung gestellt werden und nur unter den oben bereits genannten Bedingungen funktionieren.
Die Konstruktion eines Instead-of-Insert-Triggers wird wie folgt umgesetzt. Der Bezeichner
des Instead-of-Triggers setzt sich aus dem Bezeichner der Sicht und dem Typ der DMLOperation, die durch den Trigger implementiert wird, zusammen. Diese Konvention zur Erstellung eines Triggerbezeichners wurde festgelegt, da ein eindeutiger Bezeichner für jeden
Trigger innerhalb des Datenbankschemas vergeben werden muß. Ein Instead-of-InsertTrigger verteilt die Attributwerte der Sicht, über der er definiert worden ist, an die entsprechenden Basistabellen. Dementsprechend muß der Trigger genau so viele "Insert"Operationen beinhalten, wie auch Basistabellen betroffen sind. Das folgende Beispiel zur Definition eines Instead-of-Insert-Triggers verdeutlicht, wie die Verteilung der Werte in die entsprechenden Basistabellen umgesetzt wird.
84
Inhaltsverzeichnis
CREATE OR REPLACE TRIGGER student_insert
INSTEAD OF INSERT ON student
vid_abteilung
NUMBER;
BEGIN
INSERT
INTO
oc_person
VALUES( new.oid, :new.name,
:new.vorname, vt_adresse( :new.adresse.strasse,
:new.adresse.hausnr, :new.addresse.plz) );
SELECT
INTO
FROM
WHERE
AND
V.vid
vid_abteilung
vc_abteilung V
V.bereich = :new.bereich
V.leiter = :new.leiter;
INSERT INTO oc_angestellter
VALUES( new.oid,
vid_abteilung, :new.gehalt );
INSERT INTO oc_student
VALUES( new.oid, :new.matrikel_nr );
END;
Beispiel 6.4.1: Instead-of-Insert-Trigger der Sicht Student
Der Trigger "student_insert" beinhaltet drei "Insert"-Operationen, welche die
neuen Daten der Sicht im Falle einer "Insert"-Operation auf die drei beteiligten Basistabellen "oc_person", "oc_angestellter" und "oc_student" verteilt. Generell
wird der neue Wert des Attributes "oid" in der Sicht an alle Basistabellen weitergegeben
und die anderen Attribute werden an die einzelnen Basistabellen verteilt. Die erste
"Insert"-Operation des Triggers richtet sich an die Tabelle "oc_person". Dabei ist zu
beachten ist, daß die drei Attribute "strasse", "hausnr" und "plz" dem Attribut
"adresse" zugeordnet werden müssen, dessen Wertebereich durch den Objekttypen
"vt_adresse" festgelegt ist. Die zweite Operation des Triggers besteht in einer Anfrage
an die Tabelle "vc_abteilung", die eine Werteklasse repräsentiert. Die Aufgabe dieser
Anfrage ist es, die entsprechende "vid" zu den Werten der Sichtattribute "bereich" und
"leiter" herauszufinden, um diese als Wert dem Attribut "abteilung" in der Basistabelle "oc_person" zuzuordnen. Dieser Vorgang ist erforderlich, damit der Wert des
Fremdschlüssels, der die Verbindung zwischen den Tabellen "oc_person" und
"vc_abteilung" herstellt, nicht gegen Integritätsbedingungen verstößt. Die dritte Operation des Triggers ist eine "insert"-Operation, die sich an die Tabelle
"oc_angestellter"
richtet.
In
dieser
Operation
wird
die
Variable
"vid_abteilung", die in der vorangestellten "select"-Operation mit der selektierten
85
Inhaltsverzeichnis
"vid" initialisiert wird, als Wert des Attributs "abteilung" verwendet. Die letzte
"insert"-Operation verteilt zusammen mit der neuen "oid" das Attribut
"matrikel_nr" an die Basistabelle "oc_student".
Ein Instead-of-Update-Trigger wird durch eine "update"-Operation an eine Sicht ausgelöst.
Da es sich bei Instead-of-Triggern generell um "row-level"-Trigger handelt, wird dieser
Trigger nicht nur einmal pro aufgerufene Operation, sondern pro Tupel ausgelöst, welches in
der Sicht von der "update"-Operation betroffen ist. Innerhalb eines Instead-of-UpdateTriggers wird jeder einzelne Wert eines modifizierten Tupels daraufhin überprüft, ob er durch
eine "update"-Operation modifiziert worden ist. Dies wird durch die Funktionen "old"
und "new" ermöglicht, die den alten Wert des jeweiligen Attributs bei Beginn der aktuellen
Transaktion und den aktuellen Wert des Attributs nach der "Update"-Operation liefern.
Diese Werte werden miteinander verglichen und falls sie unterschiedlich sind, wird eine
"update"-Operation an die entsprechende Basistabelle gerichtet, damit die Modifikationen
am Datenbestand der Sicht auf die Basistabellen übertragen werden. Dabei wird der Wert der
"oid" benutzt, um eine Verbindung zwischen den Tupeln der Sicht und den Tupeln der Basistabellen herzustellen. Aus diesem Grund bildet das Attribut "oid" eine Ausnahme bei den
zu überprüfenden Attributwerten. Die "oid" wird automatisch über eine "sequence" generiert, und darf nicht modifiziert werden. Deshalb wird eine Modifikation dieses Attributwerts nicht überprüft und somit auch nicht umgesetzt. In dem folgenden Beispiel wird ein
Ausschnitt aus der Definition des Instead-of-Update-Triggers der Sicht Student dargestellt.
Der Trigger wird nicht vollständig vorgestellt, da ansonsten die Übersicht innerhalb des Beispiels verloren geht. Deshalb wurde das Beispiel auf die interessanten Aspekte beschränkt.
CREATE OR REPLACE TRIGGER student_update
INSTEAD OF UPDATE ON student
BEGIN
IF :new.name != :old.name THEN
UPDATE oc_person
SET
name = :new.name
WHERE
oid = :old.oid;
END IF;
...
IF :new.vt_adresse.strasse != :old.vt_adresse.strasse
THEN
UPDATE oc_person P
SET
P.vt_adresse.strasse = :new.adresse.strasse
WHERE
P.oid = :old.oid;
END IF;
...
86
Inhaltsverzeichnis
IF :new.bereich != :old.bereich
THEN
UPDATE oc_angestellter A
SET
abteilung =
( SELECT
vid
FROM
vc_abteilung V
WHERE
V.bereich = :new.bereich
AND
V.leiter = :new.leiter )
WHERE
A.oid = :old.oid;
END IF;
...
IF :new.matrikel_nr != :old.matrikel_nr THEN
UPDATE oc_student
SET
matrikel_nr = :new.matrikel_nr
WHERE
oid = :old.oid;
END IF;
END;
Beispiel 6.4.2: Ausschnitt des Instead-of-Update-Trigger der Sicht "student"
Die erste und die letzte "update"-Operation des Beispiel 6.4.2 sind einfach zu realisieren,
da die Wertebereiche der beteiligten Attribute durch einen Built-in-Datentyp von Oracle festgelegt sind. Ihre Werte können einfach an die entsprechenden Attribute in den Basistabellen
weitergereicht werden, deren Wertebereiche durch die gleichen Built-in-Datentypen festgelegt
sind. Die interessanten Aspekte des Instead-of-Update-Trigger der Sicht "student" bestehen in den "update"-Operationen, die für Werte von benutzerdefinierten Attributen zuständig sind, wie in der zweiten und dritten Operation des vorangestellten Beispiels.
Bei der zweiten "update"-Operation handelt es sich, um eine Modifikation an einem Attribut, dessen Wertebereich in der Basistabelle durch einen Objekttypen festgelegt ist und nur
das Unterattribute "strasse" modifiziert. Die Unterattribute müssen aufgrund der Struktur
der Sicht alle einzeln modifiziert werden, da sie auch als einzelne Attribute und nicht als gesamtes Attribut selektiert worden sind. Deshalb muß bei der Konstruktion dieser "update"Operation darauf geachtet werden, daß der Pfad, durch den das Unterattribut in der Tabelle
identifiziert wird, korrekt aus den Komponenten Tupelvariable, Objekttypname und Unterattributname zusammengesetzt wird.
Bei der dritten "update"-Operation handelt es sich, um eine Modifikation an einem Attribut, dessen Wertebereich durch einen Fremdschlüssel auf eine Tabelle festgelegt ist, die eine
Werteklasse repräsentiert. Hier besteht wieder das Problem, daß eine gültige "vid" aus der
Tabelle "vc_abteilung" selektiert werden muß, um die "Update"-Operation korrekt
durchführen zu können. Ansonsten wird gegen die Integritätsbedingungen des Fremdschlüssels verstoßen. Dieses Problem wird durch die Formulierung einer "Select"-Operation
gelöst, welche die benötigte "vid" aus der Tabelle selektiert und dem Attribut
87
Inhaltsverzeichnis
"abteilung" in der Tabelle "oc_angestellter" als Wert in dem Tupel zugewiesen
wird, welches durch die "oid" des Tupels in der Sicht "angestellter" eindeutig identifiziert wird.
Die Konstruktion des Instead-of-Delete-Triggers ist im Vergleich zu den bereits vorgestellten
Instead-of-Triggern relativ einfach. Da auch dieser Triggertyp ein "row-level"-Trigger
ist, wird er für jedes Tupel, das von der "delete"-Operation in der Sicht betroffen ist, einmal ausgelöst. Der Instead-of-Delete-Trigger enthält genauso viele "delete"-Operationen,
wie Basistabellen an der Konstruktion seiner Sicht beteiligt sind. Die einzige Bedingung in
der Bedingungsklausel der "delete"-Operation, besteht darin, daß der Wert des Attributs
"oid" in den Basistabellen identisch zu dem Wert des Attributs "oid" in der Sicht sein.
CREATE OR REPLACE TRIGGER student_delete
INSTEAD OF DELETE ON student
BEGIN
DELETE FROM oc_person WHERE oid = :old.oid;
DELETE FROM oc_angestellter WHERE oid = :old.oid;
DELETE FROM oc_student WHERE oid = :old.oid;
END;
Beispiel 6.4.3: Instead-of-Delete-Trigger der Sicht Student
An der Definition der Sicht Student sind die drei Basistabellen "oc_person",
"oc_angestellter" und "oc_student" mit ihren Attributen beteiligt. Aus diesem
Grund wird in dem Trigger "student_delete" im Beispiel 6.4.3 jeweils eine "delete"-Operation an diese Tabellen gerichtet, um alle Daten zu löschen, die einer Instanz der
Objektklasse "student" entsprechen.
Michael Horn
6.4.4 Abgeleitete Objektklassen
Abgeleitete Objektklassen werden durch eine Klassendefinition definiert und durch eine Populationsregel mit Daten gefüllt. Es ist nicht möglich neue Objekte für eine abgeleitete Klasse
direkt zu erzeugen oder bereits bestehende Objekte zu verändern. Daher werden durch die
Übersetzung abgeleiteter Chimera-Objektklassen nach Oracle-SQL keinerlei Trigger zur Datenmanipulation erzeugt.
Wie in Kapitel 2 bereits erläutert, entsprechen abgeleitete Objektklassen in Chimera den
Sichten der relationalen Datenmodells. Sichten im relationalen Modell werden durch Anfragen an die Datenbank definiert. Dieses Vorgehen entspricht der Kombination aus Klassendefinition und Populationsregeln. Die Klassendefinition legt die zu selektierenden Spalten und
die Populationsregel die Datenherkunft und die Bedingungen fest.
Durch folgende Definition
"abgestellter" definiert:
wird
eine
abgeleitete
Unterklasse
der
Objektklasse
88
Inhaltsverzeichnis
define object class edv
derived superclasses
angestellter
end;
define implementation for edv
population
edv(E) <angestellter(E),
E.abteilung.bereich = "EDV"
end;
Basierend auf der in Kapitel 7 beschriebenen Übersetzung deklarativer Ausdrücke, würde
obiges Beispiel in folgende relationale Sicht übersetzt:
CREATE VIEW edv AS
SELECT *
FROM
angestellter E, abteilung abteilung_1
WHERE E.abteilung = abteilung_1.vid
AND abteilung_1.bereich = 'EDV'
Durch den verwendeten Pfadausdruck in der Definition der Populationsregel der abgeleiteten
Objektklasse "edv" muß der View basierend auf zwei Tabellen definiert werden. Obiger
View würde alle Objekte der Klasse "angestellter" beinhalten, deren Abteilung dem
Bereich "EDV" zugeordnet wurde.
Abgeleitete Objektklassen dürfen nur abgeleitete Unterklassen besitzen. Das einfachste Vorgehen für die Übersetzung abgeleiteter Klassenhierarchien besteht darin, die Sicht der Oberklasse als Basis für die Definition einer neuen Sicht zu verwenden und die Populationsregel
als Bedingung für die neue Sicht zu übernehmen. Folgendes Beispiel definiert eine abgeleitete
Unterklasse für die Klasse "EDV".
define object class teure_edv
derived superclasses
edv
end;
define implementation for teure_edv
population
teure_edv(T) <- edv(T), T.gehalt > 200000
end;
89
Inhaltsverzeichnis
Basierend auf obigen Vorgehen, würde die abgeleitete Unterklasse wie folgt nach SQL übersetzt:
CREATE VIEW teure_edv AS
SELECT *
FROM
edv T
WHERE T.gehalt > 200000
Die momentane Implementierung basiert auf obigem Verfahren. Dieses Verfahren ist allerdings nicht sehr effizient, sobald Anfragen an eine Sicht formuliert werden müssen. Zur Beantwortung einer Anfrage auf einer Unterklasse einer abgeleiteten Klasse muß zuerst die
Population der Oberklasse berechnet werden um im Nachhinein die Population der benötigten
Unterklasse zu berechnen. Dieses Art der Definition von Sichten basierend auf anderen Sichten kann vom SQL-Optimierer des Oracle-Datenbankservers nicht effizient ausgewertet werden, da der Optimierer davon ausgeht, das Sichten nur basierend auf Tabellen definiert
werden. Daher werden bei der Optimierung die zusätzlichen Informationen der verwendeten
Sichten nicht mit verarbeitet.
Durch eine Analyse aller Populationsregeln der abgeleiteten Klassenhierarchie kann dieses
ineffiziente Vorgehen optimiert werden. Bei genauerer Untersuchung der beiden obigen Populationsregeln stellt man fest, daß die Populationsregel der abgeleiteten Klasse
"teure_edv" die Population der abgeleiteten Objektklasse "edv" weiter einschränkt. Die
deklarativen Ausdrücke, die innerhalb einer Populationsregel verwendet werden, können in
zwei unterschiedliche Gruppen unterteilt werden:
1. deklarative Ausdrücke, die die Objektherkunft beschreiben
2. deklarative Ausdrücke, die Bedingungen für die Objekte formulieren
Werden nun die Populationsregeln der zu definierenden Klasse mit denen aller abgeleiteten
Oberklassen kombiniert, so entsteht eine einzige Regel, die nur auf extensionalen Objektklassen basiert. Bei der Kombination der Regeln können die Klassenformeln, die die Daten der
jeweiligen Oberklasse selektieren, gelöscht werden. Die durch die gelöschten Klassenformeln
definierten Variablen werden durch die entsprechenden Variablen der Populationsregel der
Oberklasse ersetzt. Für obiges Beispiel bedeutet dies, daß die Populationsregel für die abgeleitete Unterklasse "teure_edv" wie folgt aussehen könnte:
define implementation for teure_edv
population
teure_edv(E) <- angestellter(E),
E.abteilung.bereich = "EDV",
E.gehalt > 200000
end;
90
Inhaltsverzeichnis
Die Übersetzung obiger Regel nach Oracle-SQL würde folgende Sicht definieren
CREATE VIEW teure_edv AS
SELECT *
FROM
angestellter E, abteilung abteilung_1
WHERE E.abteilung = abteilung_1.vid
AND abteilung_1.bereich = 'EDV'
AND E.gehalt > 200000
Die Definition der obigen Sicht kann effizienter abgearbeitet werden, da sie nur auf Tabellen
basiert. Die durch die Klassenformel "edv(T)" definierte Variable "T" ist durch die entsprechende Variable "E" aus der Definition der Populationsregel der Klasse "edv" ersetzt
worden.
Andrea Scheuber
6.5 Vergleich zum CPTPhx-Ansatz
Bei der Übersetzung eines Chimera-Schemas nach Phönix wird für jede Objektklasse des
Schemas eine extensionale Relation und eine dazugehörige abgeleitete Relation angelegt. Jede
Phoenix-Relation besitzt eine OID-Spalte, in welcher der Objektidentifikator des jeweiligen
Datensatzes gespeichert wird. In jeder Relation werden Spalten für jedes Attribut eines Chimera-Objektes angelegt. Dies bedeutet, daß im folgenden Beispiel die Relation Student, zusätzlich zu ihren eigenen Attributen, auch noch alle Attribute ihrer Oberklasse Person
bekommt. Dadurch wird ein einfacher Zugriff auf jeden Datensatz einer Relation gewährleistet.
Wird nun eine Anfrage an die Oberklasse "person" gestellt, werden die Daten aus der Relation "person" und die Daten aus der Relation "student" in einer Sicht zusammengeführt und repräsentieren somit die gesamten Daten der Objektklasse "person". Auf diese
Weise müssen die Daten nicht doppelt in den Relationen abgelegt werden, was in Bezug auf
den Verbrauch des Speicherplatzes ineffizient wäre. Die Daten einer Oberklasse müssen also
erst in Form von Sichten berechnet werden, bevor sie weiter verwendet werden können. Dafür
kann auf die Daten der am meisten spezifizierten Klassen direkt zugegriffen werden.
91
Inhaltsverzeichnis
Chimera
Person
Phönix
Person
Name
String
OID
Integer
Vorname
String
Name
String
Vorname
String
Ï
Student
Matrikel_nr
Ï
Student
Integer
OID
Integer
Name
String
Vorname
String
Matrikel_nr
Integer
Abbildung 6.1: Übersetzung einer Chimera-Klassenhierarchie nach Phönix
Auf den ersten Blick ähneln sich die beiden Ansätze zur Implementation von Chimera auf der
Basis der beiden Datenbanksystem Phoenix (CPTPhx) und Oracle (CPTOracle) einander. Beide
Ansätze benutzen die Konzepte von extensionalen Relationen (Tabellen) in Kombination mit
abgeleiteten Relationen (Sichten). Tatsächlich aber unterscheiden sie sich in wesentlichen
Punkten voneinander, was die Organisation von Daten und ihrer Berechnung anbelangt.
Das CPTPhx ist so realisiert, daß ein direkter und effizienter Zugriff auf die Attribute der am
meisten spezialisierte Klasse (most specific class) ermöglicht wird. Dieser Ansatz führt dazu,
daß die Daten aller übergeordneten Oberklassen über Sichten berechnet werden müssen, um
die kompletten Daten einer Oberklasse zu erhalten. Dieser Ansatz wurde gewählt, um effizient die Daten einer spezialisierten Klasse zu bearbeiten, da man davon ausgeht, daß mit diesen auch hauptsächlich gearbeitet wird. Ein große Nachteil dieser Vorgehensweise ist, daß bei
der Berechnung der Daten der am wenigsten spezialisierten Klassen (least specific class) einer
Klassenhierarchie eine ganze Kette von Berechnungen der Sichten aller spezialisierteren
Klassen, die untereinander in Verbindung stehen, ausgelöst wird.
Die Implementation von CPTOracle bietet durch das gewählte Konzept einen direkten und effizienten Zugriff auf die Attribute der am wenigsten spezialisierte Klasse. Die Daten aller Anfragen an spezialisiertere Klassen werden über die Spezifikation der jeweiligen Sicht
berechnet. Da die Sichten immer auf Tabellen und nicht, wie im CPTPhx, auch auf anderen
Sichten aufbauen, muß nur eine Sicht berechnet werden. Der Ansatz dieser Übersetzung geht
von folgender Annahme über das Datenaufkommen in den Relationen aus: Die größte Datenmenge ist für die am wenigsten spezialisierte Klasse einer Klassenhierarchie zu erwarten,
da alle Instanzen einer spezialisierten Klasse ebenfalls Instanzen ihrer Oberklassen sind. Daher haben wir uns für einen schnelleren Zugriff auf die größere Datenmenge entschieden.
92
Inhaltsverzeichnis
Einen großen Vorteil bietet Oracle gegenüber Phoenix im Zusammenhang mit Attributen und
Nullwerten. Unter Phoenix ist es nicht möglich, einem Attribut keinen Wert bzw. den Wert
"null" zuzuweisen. Das bedeutet, daß allen Attribute immer ein gültiger Wert zugewiesen
werden muß. Dadurch ist die Integritätsbedingung "notnull", die Bestandteil der Sprachspezifikation von Chimera ist, nicht in CPTPhx realisiert, da Phoenix grundsätzlich keine
Nullwerte bei Built-in-Datentypen unterstützt. Damit ist die Umsetzung dieses Integritätsbedingungstyps überflüssig. In Oracle ist es möglich, jedem beliebigen Built-in-Datentyp den
Wert "null" zuzuweisen. Dies ist nützlich, wenn im ersten Schritt ein Datensatz mit nur
teilweise bekannten Daten generiert werden soll. Im zweiten Schritt kann dieser Datensatz mit
neuen Daten vervollständigt werden. Diese Vorgehensweise ist benutzerfreundlicher, da nicht
unbedingt alle erforderlichen Daten auf einmal zur Verfügung stehen können. Aus diesem
Grund ist die Übersetzung der Bedingung "notnull" nach Oracle erforderlich, die durch
die Built-in-Bedingung "not null" von Oracle einfach realisiert werden kann.
Der große Vorteil von Phoenix liegt in der Vereinigung der imperativen, deduktiven und aktiven Elementen einer Programmiersprache. Dadurch ist es in Phoenix wesentlich einfacher,
die Chimera-Konzepte der Integritätsbedingungen und Trigger umzusetzen, da Oracle deduktive und aktive Konzepte nur stark eingeschränkt in Form von Sichten und Triggern zur Verfügung stellt. Die Umsetzung von Triggern und Integritätsbedingungen erfolgt durch die
Spezifikation von aktiven Regeln, die durch spezifizierte Ereignisse implizit ausgelöst werden.
Beide Ansätze zur Implementierung von Chimera haben je nach Schemadefinition und Datenaufkommen Vor- und Nachteile. Eine optimale Lösung kann es bei beiden nicht geben, da
sowohl Phoenix als auch Oracle hauptsächlich relationale Datenbanksysteme sind, welche die
objektorientierten Konzepte von Chimera nicht eins zu eins umsetzen können, sondern sie
durch relationale Konzepte simulieren müssen und dadurch keine optimale und vollständige
Umsetzung erreichen können.
6.6 Unterschiede zwischen CPTPhx und CPTOracle
Basierend auf dem momentanen Stand der Implementation, existieren folgende zusätzliche
Einschränkungen:
•
Der Chimera-Datentyp "string" wird nur mit Längenbeschränkungen bei der Übersetzung eines Schemas akzeptiert.
•
Der Chimera-Datentyp "real" wird durch den Wertebereich "number(10,10)" umgesetzt. Dies bedeutet, daß nur ein Ausschnitt des Wertebereichs von "real" unterstützt
wird.
93
Inhaltsverzeichnis
Michael Horn
7 Übersetzung deklarativer Ausdrücke
Dieses Kapitel behandelt die Übersetzung deklarativer Chimera-Ausdrücke nach Oracle-SQL.
Deklarative Ausdrücke finden Verwendung bei der Definition von Klassenpopulationsregeln
und Attributherleitungsregeln, bei der Definition von Sichten, Integritätsbedingungen, Triggern und Operationen und bei der Formulierung von Anfragen an die Datenbank (siehe Kapitel 2). Trotz der unterschiedlichen Anwendung deklarativer Ausdrücke werden die
einzelnen Konzepte immer auf die gleiche Art und Weise übersetzt.
Der folgende Abschnitt beschäftigt sich mit der Übersetzung der einzelnen Konzepte deklarativer Ausdrücke. Abschnitt 7.2 wird auf besondere Aspekte der Implementierung eingehen.
Der vorletzte Abschnitt dieses Kapitels wird angedachte Modifikationen und Optimierungen
der Übersetzung vorstellen. Im letzten Abschnitt werden die Einschränkungen bzw. die Erweiterungen der Implementation basierend auf Oracle zur bisher bestehenden Implementierung des CPT zusammengefaßt.
Alle Beispiele im folgenden Kapitel basieren auf der Klassenhierarchie, die in Kapitel 2 während der Vorstellung der Schemakonzepte eines Chimera-Schemas definiert wurde.
7.1 Konzepte der Übersetzung deklarativer Ausdrücke nach SQL
Deklarative Ausdrücke werden zur Definition von Bedingungen einer Selektion benutzt. Die
Verwendung der Ergebnisse einer Anfrage an eine Chimera-Datenbank wird durch den Kontext der Anfrage definiert. SQL bietet nur eine Möglichkeit, Selektionen zu formulieren:
"select"-Anweisungen. Eine SQL-"select"-Anweisung besteht aus drei unterschiedlichen Hauptteilen:
94
Inhaltsverzeichnis
•
"select": In diesem Teil werden die Spalten definiert, die durch diese Operation angezeigt werden sollen.
•
"from": Dieser Teil legt die Tabellen und Sichten fest, aus den die Daten selektiert werden sollen.
•
"where": In diesem Teil können beliebige Bedingungen formuliert werden, die die anzuzeigenden Daten erfüllen müssen, u. a. können auch Tabellen über sogenannte "join"Bedingungen miteinander verknüpft werden.
Die weiteren Optionen und Möglichkeiten der "select"-Operation werden für die Übersetzung deklarativer Ausdrücke nicht benötigt. Die einzelnen Konzepte deklarativer Ausdrücke
werden auf die "from"- und "where"-Teile der "select"-Anweisung übersetzt. Die
genaue Auswahl der zu selektierenden Spalten hängt vom Kontext des deklarativen Ausdrucks ab und ist Thema der Schemaübersetzung (Kapitel 6) und der Übersetzung imperativer
Ausdrücke (Kapitel 8).
Deklarative Ausdrücke in Chimera können Kombinationen von mehreren Ausdrücken sein,
die mittels Konjunktion zu einem Ausdruck zusammengefaßt werden. Innerhalb einer
"select"-Anweisung lassen sich Konjunktionen auf zwei unterschiedliche Arten ausdrükken. Mehrere Bedingungen innerhalb eines "where"-Teils einer "select"-Anweisung
können durch das Schlüsselwort "AND" (Konjunktion) zusammengefaßt werden. Die Verwendung mehrere Tabellen oder Sichten innerhalb eines "from"-Abschnittes einer
"select"-Anweisung werden durch ein Komma (",") voneinander getrennt. Die Verwendung des Kommas bewirkt, daß über alle verwendeten Tabellen und Sichten das kartesische
Produkt gebildet wird. Das kartesische Produkt ist in diesem Fall ein Spezialfall der Konjunktion. Bei der Berechnung des kartesischen Produktes werden eventuelle Einschränkungen
des "where"-Teils einer Anfrage beachtet. Durch diese Optimierung wird der Berechnungsaufwand stark reduziert.
Der "from"-Abschnitt einer Anfrage legt alle Tabellen und Sichten fest, aus denen die gewünschten Daten stammen sollen. Es ist nicht möglich mittels Negation das Gegenteil zu fordern, daß die Daten nicht aus dieser Tabelle oder Sicht stammen dürfen. Negation kann nur in
"where"-Teil einer Anfrage verwendet werden. Das Vorgehen in SQL ist also, eine Tabelle
im "from"-Abschnitt einer Anweisung zu verwenden und die Werte dann durch entsprechende Bedingungen im "where"-Teil auszuschließen. Eine zweite Möglichkeit besteht
darin, im "where"-Teil einer Anfrage eine Unteranfrage zu formulieren und deren Werte
dann anschließend Mittels Negation auszuschließen (siehe Übersetzungen von Mitgliedsformeln).
Die in Kapitel 2.3 eingeführten Klassenformeln legen den Wertebereich für die an die jeweilige Objektklasse gebundene Variable fest. Der "from"-Teil einer SQL "select"Anweisung erfüllt eine ähnliche Aufgabe: Er bietet die Möglichkeit, eine selbstdefinierte Variable für eine verwendete Tabelle oder Sicht zu definieren. Diese Variable entspricht einer
Tupelvariable. Jedes Tupel einer relationalen Datenbank wird durch einen eindeutigen Tupelidentifikator bezeichnet. Im Kontext von Oracle heißt der Tupelidentifikator "row number".
Die Bedeutung einer Chimera-Objektvariable und einer SQL-Tupelvariable entsprechen sich
weitgehend. Da im Falle der Übersetzung eines Chimera-Schemas in ein Oracle-SQL-Schema
nur Sichten durch deklarative Ausdrücke selektiert werden, ist die Bedeutung der Tupelvaria95
Inhaltsverzeichnis
ble einer Sicht identisch zu Bedeutung einer Objektvariable in Chimera. Ein Datensatz einer
Sicht entspricht immer einem kompletten Chimera-Objekt.
deklarativer Ausdruck in Chimera
Übersetzung nach Oracle-SQL
person(X), student(Y)
select ...
from
person X, student Y
where ...
Obiges Beispiel verdeutlicht, wie Klassenformeln in den "from"-Teil einer "select"Anweisung übersetzt werden. Würde obiger deklarativer Ausdruck in einem Chimera
"select"- oder "display"-Befehl verwendet um Attribute der beiden Klassen zu selektieren, so würde ebenfalls das kartesische Produkt gebildet werden.
Vergleichsformeln von Chimera und SQL unterscheiden sich nur in einem kleinen Detail:
Die Zeichenkette für Ungleichheit in Chimera ("\=") entspricht der "!="-Zeichenkette von
Oracle SQL. Alle anderen Vergleichsoperatoren werden ohne Veränderung übernommen.
Vergleichsformeln deklarativer Ausdrücke definieren Bedingungen, die in den "where"Teil einer "select"-Anweisung überführt werden.
deklarativer Ausdruck in Chimera
Übersetzung nach Oracle-SQL
person(X),
X.name = "Horn"
select ...
from
person X
where X.name = 'Horn'
Obiges Beispiel zeigt eine weitere Besonderheit der Übersetzung auf. Zeichenketten werden
in Chimera durch doppelte Anführungszeichen (") gekennzeichnet. Der SQL-Dialekt von
Oracle fordert dagegen ein einfaches Anführungszeichen (') zur Kennzeichnung von Zeichenketten. Obiges Beispiel zeigt, daß die Tupelvariablen einer Oracle-Tabelle die gleiche Funktionalität bzgl. des Zugriffs auf Attribute, wie die Objektvariablen von Chimera besitzen.
Vergleichsformeln können auch Pfadausdrücke verwenden. Diese Ausdrücke können schon
auf der Seite von Chimera in eine Kombination aus Klassen- und Vergleichsformeln aufgespalten werden.
person(X),
X.adresse.ort = "Meckenheim"
Î
person(X), adresse(Y),
X.adresse = Y,
Y.ort = "Meckenheim"
Das obige Beispiel zeigt den Vorgang der Normalisierung deklarativer Ausdrücke. Der normalisierte Ausdruck wird anschließend in die entsprechende Kombination der "from"- und
"where"- Teile einer "select"-Anweisung übersetzt:
96
Inhaltsverzeichnis
deklarativer Ausdruck in Chimera
Übersetzung nach Oracle-SQL
person(X), adresse(Y),
X.adresse = Y,
Y.ort = "Meckenheim"
select
from
where
and
...
person X, adresse Y
X.adresse = Y.oid
Y.ort = "Meckenheim"
Obiges Beispiel zeigt noch eine Besonderheit der Übersetzung: Das Attribut "adresse" der
Objektklasse "person" ist ein objektwertiges Attribut. Die Objektidentifikatoren werden in
den durch die Schemaübersetzung generierten "oid"-Spalten gespeichert. Daher muß im
obigen Vergleich, das Attribut "adresse" mit der "oid"-Spalte der Sicht "adresse"
gleichgesetzt werden.
Das letzte Basiskonzept deklarativer Ausdrücke in Chimera sind die Mitgliedsformeln. Mitgliedsformeln können in drei unterschiedliche Klassen unterteilt werden:
•
Mitgliedsformeln für Objektklassen
•
Mitgliedsformeln für Wertetypen und –klassen
•
Mitgliedsformeln für Listen und Mengen
Alle drei Arten überprüfen, ob der Wert einer Chimera-Variable oder eines Attributes in einem Wertebereich liegt. Im ersten Fall entspricht der Wertebereich der Menge der Objektidentifikatoren der Objektklasse, im zweiten Fall dem Wertebereich der Datentypen und im
dritten Fall den Elementen der Liste oder Menge.
deklarativer Ausdruck in Chimera
Übersetzung nach Oracle-SQL
person(X),
X in student
select ...
from
person X
where X.oid IN
select oid
from oc_student
Mitgliedsformeln für Objektklassen werden durch eine Unteranfrage an die zur Mitgliedsformel gehörende Objektklasse übersetzt. Der Objektidentifikator der Objektklasse wird selektiert und mit dem Wert der Variable verglichen. Durch diese Übersetzung werden im obigen
Beispiel nur Objekte von "person" selektiert, die ebenfalls Studenten sind.
Bei obiger Übersetzung ist zu beachten, daß hier von der Tabelle "oc_student" die Objektidentifikatoren selektiert werden (siehe Kapitel 6). Alle bisher vorgestellten Übersetzungen basierten immer auf den Oracle-Sichten, die die Chimera-Klassenhierarchie
repräsentieren. In diesem Fall kann allerdings der Zugriff auf die Sicht "student" umgangen werden, da nur die Objektidentifikatoren der Studenten interessant sind. Die Objektidentifikatoren werden in der "oid"-Spalte der Tabelle "oc_student" verwaltet. Durch dieses
Wissen werden die zur Berechnung der Sicht "student" benötigten Joins eingespart und
die Anfrage kann effizienter ausgewertet werden.
97
Inhaltsverzeichnis
7.2 Implementierung
Der folgende Abschnitt dokumentiert das implementierte Verfahren zur Übersetzung von deklarativen Ausdrücken nach Oracle SQL. Es werden dabei einige Besonderheiten aufgezeigt,
die Aufgrund von Problemen während der Implementation gelöst werden mußten. Alle Prolog-Prädikate, die zur Vorbereitung der Übersetzung und zur Übersetzung von deklarativen
Ausdrücken benötigt werden, sind im Modul dec2oracle definiert.
Jede Übersetzung eines deklarativen Ausdrucks läßt sich in folgende Phasen unterteilen:
1. alle Chimera-Variablen werden durch generierte Platzhalter ersetzt
2. alle Pfadausdrücke werden aufgelöst
3. der resultierende deklarative Ausdruck wird übersetzt
4. interne Informationen bzgl. der verwendeten Variablen werden gelöscht
Als Ergebnis der Übersetzung wird der generierte "from"- und "where"-Ausdruck in
Form einer Zeichenkette an den Aufrufer zurückgegeben. Die Schlüsselworte "from" und
"where" sind in den Rückgabewerten noch nicht enthalten, da bei der Übersetzung des
Kontextes eines deklarativen Ausdrucks weitere Bedingungen entstehen können (siehe Kapitel 8).
Jede Stelle, die mit deklarativen Ausdrücken umgehen muß, muß obige vier Schritte separat
durchführen. Dieses Vorgehen ist nötig, da z.B. Variablen, die in einem deklarativen Ausdruck definiert werden, in einer kompletten Transaktionszeile verwendet werden können.
Die Auflösung der Pfadausdrücke wird ebenfalls sowohl innerhalb von deklarativen Ausdrükken aber auch zur Übersetzung von Anfragen an die Datenbank benötigt. Die Funktionsweise
der Übersetzung wird anhand folgender Anfrage erläutert:
display( X.name, X.adresse.ort where person(X),
X in student, X.name = "Horn" );
Alle Prädikate der Übersetzung deklarativer Ausdrücke erwarten als Eingabe eine Listen von
Zeichenketten. Alle DDL- und DML-Befehle an eine Chimera-Datenbank werden durch die
bestehenden Prädikate des CPTPhx in die benötigte Liste überführt. Die DML-Schnittstelle des
CPT übersetzt obige Anfrage in folgende Liste:
[
display, "(", var(X), ".", name, ",", var(X), ".",
adresse, ".", ort, where, person, "(", var(X), ")", ",",
var(X), in, student, ",", var(X), ".", name, "=", "Horn",
")"
]
Der erste Schritt der Übersetzung deklarativer Ausdrücke ist die Generierung von Platzhaltern
für verwendete Variablen. Dieses Vorgehen ist nötig, da es während der Implementation nicht
gelungen ist, an den Namen einer verwendeten Variable zu gelangen. Variablen, im obigen
Beispiel das X, werden durch die DDL- und DML-Schnittstelle des CPT in PrologCompounds übersetzt. ECLiPSe stellt für die Extraktion einer Variable aus einem Compound
98
Inhaltsverzeichnis
die Operation "::-" zur Verfügung. Anschließend kann mit Hilfe des Prädikates
"get_var_info/3" der Name einer Variable ermittelt werden. Der Name wird in Form
einer Zeichenkette ausgegeben. Das Vorgehen scheitert allerdings aus nicht ermittelbaren
Gründen, wenn die entsprechenden Prädikate in einem laufenden CPT-System verwendet
werden; ein laufendes ECLiPSe ohne das CPT liefert dagegen immer den gewünschten Namen
der verwendeten Variable.
Obiges Problem wurde durch die automatische Generierung von Platzhaltern gelöst. Alle in
der Liste auftauchenden Compounds werden durch eine fortlaufende Nummer mit Präfix
"var_" ersetzt. Die Ersetzungen werden durch ein Prädikat in der Prolog-Datenbank protokolliert: Das Prolog-Prädikat "varName/2" speichert sowohl die verwendete ChimeraVariable als auch den generierten Platzhalter. Für jede Klassenformel wird zusätzlich der
Platzhalter sowie der Klassenname durch das Prädikat "varInfo/2" gespeichert. Jedes
Auftreten einer Variable wird durch den identischen Platzhalter ersetzt. Das Ergebnis der Variablenersetzung für obiges Beispiel sieht wie folgt aus:
[
display, "(", var_1, ".", name, ",", var_1, ".",
adresse, ".", ort, where, person, "(", var_1, ")", ",",
var_1, in, student, ",", var_1, ".", name, "=", "Horn",
")"
]
In den beiden Prolog-Relationen "varName/2" und "varInfo/2" werden demnach folgende Fakten gespeichert:
varName/2
varInfo/2
varName( var(X), var_1 )
varInfo( person, var_1 )
Der zweite Schritt während der Übersetzung ist die Eliminierung sämtlicher Pfadausdrücke
eines Chimera-Befehls. Da Oracle-SQL nicht in der Lage ist, Pfade automatisch zu verarbeiten, müssen Pfadausdrücke aus den Chimera-Befehlen entfernt werden. Das Prädikat
"expandPath/2" durchläuft eine Liste von Zeichenketten und entfernt alle Pfadausdrücke.
Dabei werden zwei aufeinanderfolgende Anwendungen der Attributfunktion durch eine ersetzt. Die entfernte Anwendung der Attributfunktion wird durch eine neue Variable, eine
Klassenformel und eine Gleichung ersetzt. Obiger Pfadausdruck wird demnach wie folgt ersetzt:
var_1.adresse.ort
Î
adresse_1.ort
where
adresse( adresse_1 ),
var_1.ort = adresse_1.oid
Die neue Variable wird durch den Namen der dazugehörigen Klasse und einer fortlaufenden
Nummer benannt. Die betroffene Klasse kann basierend auf den Informationen für den Platzhalter "var_1" und den Informationen des Chimera Data Dictionary (CDD) ermittelt werden. Die zusätzlichen Bedingungen werden nach Durchlaufen der kompletten Liste am Ende
der Liste angehängt:
99
Inhaltsverzeichnis
[ display, "(", var_1, ".", name, ",", adresse_1, ".", ort,
where, person, "(", var_1, ")", ",", var_1, in, student,
",", var_1, ".", name, "=", "Horn", ",", adresse, "(",
adresse_1, ")", ",", var_1, ".", ort, "=", adresse_1,")"]
Durch die neue Variable ergibt sich folgende Veränderung in den beiden Relationen:
varName/2
varInfo/2
varName( var(X), var_1 )
varInfo( person, var_1 )
varInfo( adresse, adresse_1 )
Im obigen Beispiel wird nun die Liste der Zeichenketten geteilt. Alle Elemente der Liste, die
auf der linken Seite des Schlüsselwortes "where" stehen werden durch die Übersetzung der
Datenmanipulationsbefehle bearbeitet (siehe Kapitel 8). Alle Elemente auf der rechten Seite
des Schlüsselwortes stellen einen deklarativen Ausdruck dar und werden durch das Prädikat
"translateDecExp/3" in den "from"- und "where"-Teil einer SQL-Anweisung
übersetzt.
Das Vorgehen der eigentlichen Übersetzung ist folgendes: Die Liste der Zeichenketten wird
von links nach rechts abgearbeitet. Jedes Konzept eines deklarativen Ausdrucks hat eine eindeutige Signatur Anhand deren man das entsprechende Konzept eindeutig identifizieren kann.
Zur Identifikation eines Konzeptes müssen nur unterschiedlich viele Elemente der Liste der
Zeichenkette im voraus gelesen werden:
•
Klassenformeln bestehen immer aus vier Teilen: einer Zeichenkette, einer geöffneten,
runden Klammer, einer Variablen und einer geschlossenen, runden Klammer.
•
Mitgliedsformeln bestehen aus unterschiedlich vielen Teilen, in denen aber immer das
Schlüsselwort "in" auftauchen muß.
•
Vergleichsformeln bestehen ebenfalls aus unterschiedlich vielen Teilen, in denen aber
immer genau ein Vergleichssymbol verwendet werden muß.
Anhand der jeweilige eindeutigen Signatur können die entsprechenden Konzepte dann Schritt
für Schritt in entsprechende Teile einer SQL-"select"-Anweisung übersetzt werden. Obiges Beispiel wird durch das Prolog-Prädikat in folgende "from"- und "where"-Teile übersetzt. Das Prädikat wird folgende beiden Zeichenketten als Rückgabewert liefern.
Eingabe:
[ person, "(", var_1, ")", ",", var_1, in,
student, ",", var_1, ".", name, "=", "Horn",
",", adresse, "(", adresse_1, ")", ",", var_1,
".", ort, "=", adresse_1, ")" ]
Ausgabe FROM:
person var_1, adresse adresse_1
Ausgabe WHERE:
var_1.name = "Horn" AND
var_1.ort = adresse_1.oid AND
var_1.oid IN (SELECT oid FROM oc_student)
100
Inhaltsverzeichnis
7.3 Modifikationen und Optimierungen
Die bisherige Implementation ist in keiner Weise optimiert, sie basiert auf der einfachsten Art
und Weise für die Übersetzung. Sie könnte durch folgende Modifikationen und Optimierungen erweitert werden:
•
Das Entfernen von Pfadausdrücken und die eigentliche Übersetzung können parallel
durchgeführt werden.
•
Durch die Analyse der verwendeten Klassen- und Mitgliedsformeln kann die am meisten
spezialisierende Objektklasse ermittelt werden. Durch diese Analyse können Joins verhindert werden.
•
Bisher basieren die Anfragen auf den Sichten, die die Chimera-Klassenhierarchie repräsentieren. Es ist möglich, die Anfragen direkt auf den Tabellen zu beantworten und die
Joins manuell durchzuführen.
•
Durch eine Analyse der selektierten Attribute der Anfragen und in der Definition von abgeleiteten Objektklassen, Sichten, Integritätsbedingungen und Trigger können überflüssige Joins vermieden werden.
Die erste Optimierung der Übersetzung ist leicht einzusehen. Das Entfernen von Pfadausdrücken ersetzt Elemente der Liste durch andere Elemente und fügt neue Elemente der Liste
hinzu. Den Vorgang des Ersetzens muß nicht verändert wer, die hinzugefügten Elemente der
Liste können allerdings direkt in die entsprechenden "from"- und "where"-Teile eines
"select"-Befehls übersetzt werden. Der erste Schritt der Analyse der vorhanden ChimeraVariablen und deren Ersetzung durch Platzhalter könnte ebenfalls parallel ausgeführt werden.
Während der Ersetzung der Variablen durch Platzhalter werden allerdings die Informationen
der verwendeten Klassenformeln gesammelt und in dem Prädikat "varInfo/2" gespeichert. Da diese Informationen während des Entfernens von Pfaden innerhalb des Ausdrucks
benötigt werden, muß dieser Schritt separat ausgeführt werden.
Die Zeit, die zur Beantwortung einer Anfrage an eine Datenbank benötigt wird, hängt sehr
stark von der Anzahl der zu bildenden kartesischen Produkte ab. Die Anzahl der kartesischen
Produkte wiederum hängt von der Anzahl der Joins und der Anzahl der dadurch betroffenen
Datensätze ab. Das Ziel einer Anfrageoptimierung sollte also die Reduzierung von Joins im
Bedingungsteil einer Anfrage sein. Alle drei weiteren Optimierungen der bisherigen Übersetzung zielen auf die Reduzierung von Joins ab.
Die erste Möglichkeit, die Anzahl der Joins zu vermindern liegt in der Analyse der verwendeten Klassen- und Mitgliedsformeln eines deklarativen Ausdrucks. Wie in Kapitel 2 beschrieben, definiert eine Klassenformel den Wertebereich einer Chimera-Variable, eine
Mitgliedsformel schränkt den Wertebereich einer Variable zusätzlich ein. Basierend auf der in
Kapitel 6 vorgestellten Übersetzung eines Chimera-Schemas in ein Oracle-SQL-Schema und
der damit verbunden Übersetzung deklarativer Ausdrücke nach SQL können Anfragen immer, basierend auf der am meisten spezialisierten Objektklasse, beantwortet werden. Basierend auf dem Beispiel aus dem vorherigen Abschnitt bedeutet dies: Die Unteranfrage
innerhalb des "where"-Abschnittes der Anweisung entfällt; die Anfrage würde nur über der
Objektklasse "student", also nur indirekt über der Objektklasse "person", beantwortet
101
Inhaltsverzeichnis
werden. Die Verbindung zwischen der Objektklasse "person" und der Objektklasse
"student" wird durch die Oracle-Sicht "student" hergestellt:
Eingabe:
[ person, "(", var_1, ")", ",", var_1, in,
student, ",", var_1, ".", name, "=", "Horn",
",", adresse, "(", adresse_1, ")", ",", var_1,
".", ort, "=", adresse_1, ")" ]
Ausgabe FROM:
student student_1, adresse adresse_1
Ausgabe WHERE:
student_1.name = "Horn" AND
student_1.ort = adresse_1.oid
Jedes DBMS besitzt einen Optimierer für Anfragen an die Datenbanken. Der Optimierer definiert eine Abarbeitungsreihenfolge, in der die einzelnen Bedingungen einer Anfrage abgearbeitet werden sollen. Dies bedeutet, daß Joins z.B. nach der geschätzten Anzahl der zu
erwartenden Datensätze sortiert werden. Bezogen auf Joins bedeutet dies, daß zuerst "billige"
Joins abgearbeitet und erst gegen Ende der Anfragebeantwortung die "teuren" Joins durchgeführt werden. (Die Klassifizierung von Join-Operationen in "billige" und "teure" Joins, basiert
auf der Abschätzung der zu erwartenden Datensätze in der Resultatmenge.) Die Ergebnisse
des Oracle-Optimierers sind allerdings nicht immer optimal: Wie in Kapitel 6 vorgestellt, verzögert sich die Anfragebeantwortung rapide, sobald eine Oracle-Sicht basierend auf einer
anderen Oracle-Sicht definiert wurde. Die Lösung der Schemaübersetzung ist, daß Sichten
immer nur auf Tabellen basieren. Dieses Vorgehen kann auf die Übersetzung deklarativer
Ausdrücke übertragen werden: Anstelle die Anfragen an die Sichten zu richten, wird die Anfrage basierend auf den Tabellen formuliert. Dies bedeutet das die Joins, die sonst durch die
Sicht automatisch realisiert wurden, nun manuell in jedem Ausdruck durchgeführt werden
müssen. Diese Verlängerung der Anfragedefinition führt zu einer vereinfachten Analyse der
Anfrage, die zu besseren Laufzeitergebnissen führt. Obiges Beispiel würde nach dieser Optimierung wie folgt übersetzt:
Eingabe:
[ person, "(", var_1, ")", ",", var_1, in,
student, ",", var_1, ".", name, "=", "Horn",
",", adresse, "(", adresse_1, ")", ",", var_1,
".", ort, "=", adresse_1, ")" ]
Ausgabe FROM:
oc_person oc_person_1,
oc_student oc_student_1,
oc_adresse oc_adresse_1
Ausgabe WHERE:
oc_person_1.name = "Horn" AND
oc_person_1.ort = oc_adresse_1.oid AND
oc_person_1.oid = oc_student_1.oid
102
Inhaltsverzeichnis
7.4 Unterschiede zwischen CPTPhx und CPTOracle
Basierend auf dem momentanen Stand der Implementation existieren folgende zusätzliche
Einschränkungen:
•
Klassenformeln für Datentypen werden nicht unterstützt: Dies bedeutet, daß es momentan
nicht möglich ist, neue Variablen innerhalb eines deklarativen Ausdrucks zu definieren
und durch eine Klassenformel den Wertebereich der Variable auf den Wertebereich eines
Wertetyps oder einer Werteklasse einzuschränken. Dieses Problem wird für alle DMLOperationen und bei der Definition von Sichten auch weiterhin bestehen bleiben, da Standard-SQL keinerlei Möglichkeit bietet, Variablen zu definieren. Oracle bietet allerdings in
der Definition von Operationen, Triggern und Integritätsbedingungen die Möglichkeit,
neue Variablen zu definieren, da die Implementation dieser Konzepte auf Oracle PL/SQL
basiert.
•
Mitgliedsformeln für Wertetypen und –klassen werden noch nicht unterstützt: Es ist momentan leider nicht möglich, die Zugehörigkeit des Wertes eines Attributes zu einem
selbstdefinierten Wertetyp oder einer Werteklasse zu überprüfen, da diese Option noch
nicht implementiert wurde.
•
Aggregats-, Mengen- und Listenfunktionen werden nicht unterstützt: Da die Implementierung des CPTOracle zum jetzigen Zeitpunkt noch keine Listen und Mengen unterstützt,
werden die entsprechenden Funktionen für diese Konzepte auch noch nicht nach SQL
übertragen. In späteren Erweiterungen müssen diese Funktionen deklarativer Ausdrücke
noch nach SQL übersetzt werden. Die Implementierung dieser Funktionen wird stark von
der gewählten Übersetzung der entsprechenden Schemakonzepte abhängen.
103
Inhaltsverzeichnis
Andrea Scheuber
8 Übersetzung imperativer Ausdrücke
Hinter dem Begriff der imperativen Ausdrücke (siehe Kapitel 2) verbergen sich zwei unterschiedliche Typen von Operationen, die über der Datenbasis des Datenbanksystems ausgeführt werden. Der erste Operationstyp sind die DML-Operationen, die für die Generierung
und Pflege des Datenbestandes eingesetzt werden. Der zweite Operationstyp besteht aus den
Anfragen, die an die Datenbank gestellt werden. Anfragen werden benutzt, um Daten zu selektieren, die entweder zur Formulierung von Bedingungen in DML-Operationen eingesetzt
werden oder einfach nur ausgegeben werden. Die Reihenfolge der unterschiedlichen Operationen innerhalb einer Transaktion beeinflußt das Ergebnis einzelner Operationen, durch die
am Ende einer Transaktion der neue Zustand der Datenbank bestimmt wird. Im Abschnitt 8.2
wird das Transaktionskonzept von Chimera vorgestellt und mit dem Transaktionskonzept von
Oracle verglichen, bevor in den folgenden Abschnitten die Vorgehensweise zur Übersetzung
der imperativen Ausdrücke von Chimera in imperative Ausdrücke von Oracle8-SQL vorgestellt wird.
8.1 Transaktionen
Eine Transaktion ist eine Folge von Anfragen und DML-Operationen auf Datenbankobjekten.
Die Reihenfolge, in der die einzelnen Operationen abgearbeitet werden, wird durch ihre Reihenfolge in der Transaktion bestimmt. Eine Transaktion wird als eine Einheit behandelt. Das
bedeutet, wenn nur eine Operation einer Transaktion fehlschlägt, weil sie nicht zulässig ist, so
werden die gesamten Änderungen, die innerhalb der Transaktion schon ausgeführt worden
sind, zurückgesetzt und die Transaktion wird abgebrochen. Auf diese Weise wird die Erhaltung eines korrekten Datenbestandes gewährleistet. Die Überprüfungen, ob eine Operation
zulässig ist, wird durch das DBMS des jeweiligen Datenbanksystems durchgeführt. Bei diesen Überprüfungen wird festgestellt, ob die Syntax der Operation korrekt ist und ob die Operationen gegen Integritätsbedingungen der Datenbank verstößt. Die Überprüfung von
104
Inhaltsverzeichnis
Integritätsbedingungen ist immer an eine Transaktion gebunden, da sich die Datenbank spätestens nach Abschluß der Transaktion wieder in einem korrekten Zustand befinden muß.
Die Überprüfung der Integritätsbedingungen kann zu zwei unterschiedlichen Zeitpunkten erfolgen. Entweder werden sie sofort nach der Ausführung der jeweiligen DML-Operation
überprüft (engl. immediate constraint checking) oder aber erst am Ende der Transaktion,
wenn alle Anfragen und Operationen abgearbeitet worden sind (engl. deferred constraint
checking). Erst nachdem alle betroffenen Integritätsbedingungen überprüft worden sind und
gewährleistet ist, daß sie nicht verletzt worden sind, kann eine Transaktion mit der Operation
"commit" terminiert und die Änderungen in der Datenbank permanent verfügbar gemacht
werden. Sobald festgestellt wird, daß eine Integritätsbedingung durch eine DML-Operation
verletzt worden ist, wird die gesamte Transaktion durch die Operation "rollback" automatisch abgebrochen und alle schon durchgeführten, vorläufigen Änderungen am Datenbestand werden wieder zurückgesetzt.
Eine Transaktion muß die folgenden vier Eigenschaften besitzen, damit sie zur Erhaltung eines korrekten Datenbestands beiträgt. Eine Transaktion ist atomar, da sie entweder als Einheit ausgeführt wird oder aber als Einheit fehlschlägt. Eine Transaktion führt ihre Operationen
isoliert von anderen Transaktionen aus. Es darf keinerlei Verbindung mit anderen Transaktionen und deren Operationen bestehen. Eine Transaktion ist in sich konsistent. Das bedeutet,
daß jeder Datenbankbestand, der durch eine korrekt abgeschlossene Transaktion zustande
gekommen ist, auch ein gültiger Zustand ist. Die Änderungen, die durch eine abgeschlossene
Transaktion zustande kommen, werden permanent im Datenbestand verfügbar gemacht, das
bedeutet, daß keine dieser Änderungen verloren gehen darf. Sind diese Eigenschaften durch
ein Transaktionskonzept umgesetzt, so ist auch die Korrektheit des Datenbestandes nach jeder
Transaktion gewährleistet.
8.2 Das Transaktionskonzept von Chimera
Ein Transaktion in Chimera beginnt immer mit dem Ausdruck "begin transaction",
durch den der Anfang einer Transaktion gekennzeichnet wird. Wird dieser Ausdruck nicht
explizit vor einer Folge von Operationen eingegeben, so wird implizit vor der erste Operation
der Transaktion der Transaktionsanfang von Chimera markiert. Eine Transaktion wird in
Chimera entweder mit dem Befehl "commit" abgeschlossen oder mit dem Befehl
"rollback" zurückgesetzt, was bedeutet, daß alle Modifikationen, die innerhalb der aktuellen Transaktion vorgenommen worden sind, wieder rückgängig gemacht werden. Der Befehl "rollback" kann sowohl innerhalb der Transaktion explizit aufgerufen werden, als
auch implizit durch Chimera ausgeführt werden. Die explizite Verwendung des Befehls
"rollback" wird durch den Benutzer gesteuert, damit die Möglichkeit besteht, syntaktisch
korrekte Operationen, die inkorrekte Daten enthalten, aber nicht von Chimera als solche
erkannt werden können, zurückzusetzen. Die implizite Verwendung des Befehls
"rollback" wird von Chimera im Zusammenhang mit der Überprüfung von
Integritätsbedingungen gesteuert. Wird die Verletzung einer Integritätsbedingung vom Typ
"immediate" festgestellt, so wird die gesamte Transaktion sofort nach der auslösenden
Operation durch ein implizites "rollback" zurückgesetzt. Die Verletzung einer
Integritätsbedingung vom Typ "deferred" wird erst am Ende einer Transaktion
105
Inhaltsverzeichnis
festgestellt und deshalb kann erst dann von Chimera ein implizites "rollback" ausgelöst
werden.
Das Transaktionskonzept von Chimera sieht eine Unterteilung einer Transaktion in sogenannte Transaktionszeilen vor. Eine Transaktionszeile ist eine Folge von Operationen, die in
direktem Zusammenhang zueinander stehen. Um eine Transaktion zu unterteilen, wird als
Trennungszeichen zwischen zwei Transaktionszeilen ein Semikolon verwendet. Einzelne
Operationen innerhalb einer Transaktionszeile werden jeweils durch ein Komma voneinander
getrennt, um auf diese Weise zu kennzeichnen, daß sie Bestandteil der aktuellen Transaktionszeile sind. Der Sinn dieser Unterteilung einer Transaktion in logische Untereinheiten besteht darin, die Verwaltung von Variablenbindungen, die durch Anfragen an die Datenbank
generiert und in DML-Operationen weiter verwendet werden, zu optimieren. Variablenbindungen existieren immer nur innerhalb der Transaktionszeile, in der sie auch erzeugt werden.
Dadurch wird die Anzahl der Variablen und ihre assoziierten Werte möglichst gering gehalten. Wenn eine Transaktionszeile durch ein Semikolon abgeschlossen wird, hat dies die Löschung aller erzeugten Variablenbindungen zur Folge, die dann nicht mehr benötigt werden.
Eine weitere Aufgabe von Transaktionszeilen besteht in der Festlegung des Ausführungszeitpunkts von Triggern. Im Chimera werden Trigger, wie auch Integritätsbedingungen, in zwei
Typen unterschieden. Der erste Triggertyp beinhaltet die Trigger, welche sofort nach dem
spezifizierten, auslösenden Ereignis ausgeführt werden müssen ("immediate"-Trigger).
Der zweite Triggertyp umfaßt alle Trigger, die verzögert nach dem spezifizierten, auslösenden
Ereignis am Ende einer Transaktion auszuführen sind ("deferred"-Trigger). Der Abschluß einer Transaktionszeile durch ein Semikolon definiert den Ausführungszeitpunkt der
"immediate"-Trigger, die durch Operationen innerhalb der Transaktionszeile ausgelöst
worden sind. Durch den Abschluß der gesamten Transaktion mit dem Befehl "commit",
wird der Ausführungszeitpunkt, der "deferred"-Trigger definiert, die alle abgearbeitet
werden, bevor das Datenbanksystem die Modifikationen am Datenbestand permanent übernimmt.
Die Implementation von Chimera durch das CPTPhx setzt das Chimera-Transaktionskonzept
um. Dazu werden in Phoenix internen Prozeduren benötigt, die den Ablauf einer PhoenixTransaktion steuern. Wenn der Beginn einer Transaktion mit dem Ausdruck "begin
transaction" markiert wird, hat das den Aufruf der internen Phoenix-Prozedur
"chimera_start_transaction" zur Folge. Diese Prozedur überprüft, ob eine nicht
abgeschlossene Transaktion existiert. Ist das nicht der Fall wird eine neue PhoenixTransaktion durch den Phoenix-Befehl "start_transaction" gestartet. Danach kann
mit der Abarbeitung einer Folge von Operationen begonnen werden, aus denen die Transaktion sich zusammensetzt. Existiert bereits eine offene Phoenix-Transaktion, so wird nichts unternommen, da eine neue Transaktion nicht innerhalb einer offenen Transaktion geöffnet
werden kann und dies auch nicht erforderlich ist, da alle folgenden Operationen innerhalb der
offenen Transaktion abgearbeitet werden können. Durch diese Operationen werden administrative Daten erzeugt, die für die Überprüfung von Integritätsbedingungen und zur Auslösung von Triggern erforderlich sind. Jede Operation wird als Ereignis registriert und zu
diesem Zweck in die Phoenix-Relation "$chimera_event" eingetragen, die aus drei Attributen besteht. Das erste Attribut beinhaltet den Ereignisidentifikator (EID), durch den ein
Ereignis innerhalb einer Transaktion eindeutig identifiziert wird. Das zweite Attribut spezifiziert die Operation, durch die das Ereignis ausgelöst worden ist. Das dritte Attribut beinhaltet
die "oid", des betroffenen Tupels. Falls mehrere Tupel von einer Operation betroffen sind,
106
Inhaltsverzeichnis
erfolgt pro Tupel ein Eintrag in die Phoenix-Relation "$chimera_event". Diese Einträge
unterscheiden sich voneinander durch die "oid" des betroffenen Tupels.
Der Abschluß einer Transaktion mit dem Befehl "commit" löst den Aufruf der internen
Phoenix-Prozedur "chimera_commit" aus. Diese Prozedur überprüft zuerst, ob eine geöffnete Transaktion existiert, da nur in diesem Fall Modifikationen am Datenbestand noch
nicht permanent durchgeführt worden sind. Existiert eine offene Phoenix-Transaktion, so wird
das Ereignis "chimera_transaktion_end" explizit durch die Phoenix-Operation
"raise" ausgelöst. Durch dieses Ereignis wird die Abarbeitung der Integritätsbedingungen
und Trigger vom Typ "deferred" angestoßen. Nachdem alle Integritätsbedingungen und
Trigger erfolgreich überprüft und ausgeführt worden sind, wird in der Phoenix-Prozedur
"chimera_commit" dafür gesorgt, daß alle administrativen Daten, die zur Verwaltung
von Ereignissen und der Ausführung und Überprüfung von Triggern und Integritätsbedingungen benötigt werden und die innerhalb der aktuellen Transaktion angefallen sind, explizit gelöscht werden. Anschließend wird die aktuelle Phoenix-Transaktion mit dem Phoenix-Befehl
"commit" abgeschlossen und alle Modifikationen am Datenbestand permanent übernommen.
Die explizite Verwendung des Ausdrucks "rollback" zur Markierung des Endes einer
Transaktion löst im CPTPhx den Aufruf der Phoenix-Prozedur "chimera_rollback" aus.
Diese Prozedur überprüft, ob eine offene Phoenix-Transaktion existiert. Nur wenn dies der
Fall ist, wird durch den Phoenix-Befehl "rollback" die offen Phoenix-Transaktion zurücksetzt und auf diese Weise beendet. Da durch das Zurücksetzen einer Transaktion automatisch auch alle administrativen Daten gelöscht werden, die innerhalb der Transaktion
angefallen sind, brauchen diese nicht wie bei einem "commit" explizit gelöscht zu werden.
Die implizite Verwendung des Befehls "rollback" wird von Phoenix selbst gesteuert.
Dieser Fall tritt ein, wenn eine Integritätsbedingung verletzt wird, und hat das Zurücksetzen
der kompletten Transaktion zur Folge.
Die Implementation von Chimera durch das CPTOracle muß das Chimera-Transaktionskonzept
auf ähnliche Weise umsetzen. Um das Chimera-Transaktionskonzept zu realisieren, muß auch
in einem Oracle-Datenbanksystem auf das Konzept der internen Prozeduren und Funktionen
zurückgegriffen werden. Die Implementierung der internen Oracle-Prozedur (Oracle: stored
procedure) "chimera_start_transaction" kann nicht überprüfen, ob eine offene
Transaktion bereits existiert. Da aber der Beginn einer Oracle-Transaktion immer implizit
vom Datenbankmanagementsystem markiert wird, sobald die erste Operation einer Transaktion an die Datenbank gerichtet wird, ist dies auch nicht erforderlich. Eine explizite Markierung
des Beginns einer Oracle-Transaktion könnte durch die Verwendung des Ausdrucks "set
transaction" umgesetzt werden. Da aber durch das DBMS bereits die implizite
Markierung des Transaktionsanfangs vorgenommen wird, ist die explizite Markierung durch
die Oracle-Prozedur "chimera_start_transaction" überflüssig.
Die Implementation der Oracle-Prozedur "chimera_commit" muß den Oracle-Befehl
"commit" aufrufen, um die Modifikationen, die innerhalb der Transaktion angefallen sind,
permanent zur Verfügung gestellt werden und um die Transaktion zu beenden. Da das
Triggerkonzept und Integritätsbedingungskonzept von Chimera im derzeitigen Stand der
Implementierung noch nicht realisiert worden ist, kann an dieser Stelle nur gesagt werden,
daß die organisatorischen Operationen zur Umsetzung dieser Konzepte vor dem Oracle107
Inhaltsverzeichnis
Befehl "commit"
müssen.
in der Oracle-Prozedur "chimera_commit" aufgerufen werden
Bei der Implementation der Oracle-Prozedur "chimera_rollback" tauchen keine
Probleme im Zusammenhang mit Integritätsbedingungen und Triggern auf, da ein explizites
Rollback die komplette Transaktion zurücksetzen muß und weder Integritätsbedingungen
überprüft noch Trigger ausgelöst werden müssen. Um dies zu erreichen muß nur der OracleBefehl "rollback" aufgerufen werden. Ein Problem stellt die Behandlung eines impliziten
Rollbacks dar. Ein implizites Rollback wird durch das DBMS von Oracle ausgelöst, sobald
eine Transaktion gegen Integritätsbedingungen verstößt. Das Problem bei dem
Transaktionskonzept von Oracle besteht darin, daß es sowohl ein globales als auch lokales
implizites Rollback unterstützt. Ein globales, implizites Rollback wird immer am Ende einer
Transaktion ausgelöst, wenn festgestellt wird, daß eine Integritätsbedingung vom Typ
"deferred" durch eine Operation innerhalb der Transaktion verletzt worden ist. Es setzt
die komplette Transaktion zurück, wie es auch laut Transaktionskonzept von Chimera sein
soll. Ein lokales, implizites Rollback tritt direkt nach einer Operation auf, die eine
Integritätsbedingung vom Typ "immediate" verletzt. Durch ein lokales Rollback wird nur
die Operation zurückgesetzt, die auch die Verletzung der Integritätsbedingung verursacht hat.
Es sind weder früher ausgeführte Operationen durch dieses lokale Rollback betroffen noch
wird die Transaktion abgebrochen oder beendet. Diese Vorgehensweise entspricht nicht dem
Transaktionskonzept von Chimera. Aus diesem Grund muß nach jeder Oracle-DMLOperation überprüft werden, ob ein lokales implizites Rollback stattgefunden hat. Diese
Information kann über das Prolog-Prädikat "sql_lastmsg" zur Verfügung gestellt werden
(siehe Kapitel 5). Im Falle eines lokalen, impliziten Rollbacks muß vom CPTOracle aus ein
globales Rollback explizit angestoßen werden. Ein globales Rollback kann entweder durch
den Aufruf der Oracle-Prozedur "chimera_rollback" durch das Prolog-Prädikat
"sql_exec" oder aber durch das Prolog-Prädikat "sql_rollback" durchgeführt
werden, die beide Bestandteil des Eclipse-Oracle-Interfaces sind.
Um eine komplette Chimera-Transaktion übersetzen zu können, muß diese erst in Transaktionszeilen aufgeteilt werden. Eine Transaktion liegt sowohl im CPTPhx als auch im CPTOracle in
Form einer Tokenliste vor. Diese Tokenliste wird in mehrere Tokenlisten aufgeteilt, wobei ein
Semikolon innerhalb der Tokenliste bestimmt, an welcher Stelle die Liste geteilt werden soll.
Auf diese Weise erhält man mehrere Tokenlisten, die jeweils eine Transaktionszeile beinhalten. Um nun eine Transaktionszeile zu übersetzen, muß sie in ihre einzelnen Operationen
zerlegt und diese einzeln übersetzt werden. Die Aufteilung einer Transaktionszeile in ihre
einzelnen Operationen übernimmt das Prolog-Prädikat "splitTransactionLine", welches die einzelnen Operationen extrahiert und in eine Liste von Operationen überführt. Im
CPTOracle wird diese Liste von Operationen an das Prolog-Prädikat "translateDML" übergeben, durch welches die Übersetzung der einzelnen Operationen in SQL-Ausdrücke gesteuert wird. Anhand der Schlüsselwörter "add", "drop", "create", "modify",
"delete", "select", "display", "generalize" und "specialize", mit denen
eine Operation beginnen muß, wird festgestellt, um welchen Operationstyp es sich handelt,
und der Aufruf des entsprechenden Prolog-Prädikats gesteuert, welches die eigentliche Übersetzung durchführt. Die Übersetzung der einzelnen Operationstypen wird in den Abschnitten
8.4 und 8.5 genauer erläutert. Vorher wird in Abschnitt 8.3 die Erzeugung und Verwaltung
von Variablenbindungen erläutert, welche eine Voraussetzung zur Übersetzung von ChimeraOperationen ist.
108
Inhaltsverzeichnis
8.3 Erzeugung und Verwaltung von Variablenbindungen
Ein Problem bei der Übersetzung von Chimera-Operationen in SQL-Operationen stellt die
Erzeugung von Variablenbindungen und ihre Verwaltung dar. Da Phoenix ein auf Prolog basierendes DBMS ist, existiert dieses Problem dort nicht. Durch deklarative Ausdrücke werden
in Phoenix Variablenbindungen erzeugt und durch das Prolog-System Eclipse verwaltet. Innerhalb einer SQL-DML-Operation können auch Variablenbindungen in Form einer Unteranfrage erzeugt werden. Diese gelten aber nur innerhalb dieser einen SQL-DML-Operation und
können nicht in den folgenden Operationen weiter verwendet werden. Aus diesem Grund
mußte eine Möglichkeit gefunden werden, durch SQL-DML-Operationen Variablenbindungen zu erzeugen und diese zu verwalten.
Es existieren in Chimera die zwei folgenden DML-Operationen, die verwendet werden können, um Variablenbindungen zu erzeugen. Eine Anfrageoperation vom Typ "select" kann
eine oder mehrere Instanzen einer Objektklasse an eine Variable binden. Eine DMLOperation vom Typ "create" bindet eine Variable an die in der "create"-Operation
erzeugten Instanz. Die Instanz einer Chimera-Objektklasse wird im CPTPhx und im CPTOracle
durch den Wert des Attributs "oid" repräsentiert. Jede Relation, die eine Objektklasse
abbildet, besitzt dieses Attribut als Primärschlüssel. Ist nun eine Chimera-"select"Operation in eine SQL-"select"-Operation übersetzt worden, so wird sie mit Hilfe des
Prolog-Prädikats "sql_query" aus dem Eclipse-Oracle-Interface an die Datenbank
geschickt. Dieses Prädikat unifiziert eine Liste von Variablen mit den selektierten "oid"s
(siehe Kapitel 5). In Kombination mit dem Prolog-Prädikat "findall" wird eine Liste aus
den selektierten Tupeln erzeugt, die dann weiter verwendet wird, um die Daten
abzuspeichern. Die Variablennamen in der Variablenliste ensprechen den Variablennamen
aus der DML-Operation. Auf diese Weise werden die selektierten Werte der "oid"s den
entsprechenden Variablen zugeordnet.
Um nun eine Variable und ihre gebundenen "oid"s zu verwalten, wird eine Tabelle
benötigt. Die Tabelle muß zwei Attribute besitzen. Das erste Attribut besitzt als Wert den
Namen einer Variablen und wird deshalb mit dem Bezeichner "varname" versehen. Das
zweite Attribut besitzt als Wert eine "oid", welche an die Variable gebunden worden ist.
Der Bezeichner dieser Tabelle ist durch den Namen "chi_boundVar" festgelegt worden.
VARNAME
OID
var_1
90
var_1
105
Die Tabelle "chi_boundVar"
Diese Tabelle kann entweder als Prolog-Prädikat oder als Oracle-Tabelle realisiert werden.
Der wesentliche Unterschied dieser beiden Ansätze liegt in der Formulierung der DMLOperationen, die auf gebundene Variablen zurückgreifen. Generell müssen die gebundenen
Variablen im Bedingungsteil einer SQL-DML-Operation berücksichtigt werden. Dies erfolgt
durch eine oder mehrere zusätzliche Bedingungen in der Bedingungsklausel. Wird nun die
Tabelle durch ein Prolog-Prädikat realisiert, so müssen alle "oid"s der betroffenen
109
Inhaltsverzeichnis
Variablen aus der Tabelle extrahiert und explizit in die Bedingungsklausel einer SQLOperation mit eingebaut werden. Das bedeutet auf das obige Beispiel bezogen, daß die
Variablenbindungen der Variable "var_1" durch die beiden zusätzlichen Bedingungen
"var_1.oid = 90 OR var_1.oid = 105"
realisiert werden. Wird hingegen die Tabelle als Oracle-Tabelle realisiert, so brauchen die
Werte der "oid"s nicht explizit in die Bedingungsklausel mit eingebunden zu werden,
sondern sie werden implizit durch eine Unteranfrage aus der Tabelle "chi_boundVar"
eingebunden. Die entsprechende Bedingung sieht auf das obige Beispiel bezogen wie folgt
aus:
var_1.oid = (
SELECT oid FROM chi_boundVar
WHERE varname = 'var_1' )
Wir haben uns für die Lösung des Problems durch eine Oracle-Tabelle entschieden, da dies
die Formulierung der zusätzlichen Bedingungen in der SQL-Operation vereinfacht. Es
braucht dadurch nur noch eine Bedingung formuliert zu werden, die den explizit formulierten
Bedingungen in ihrer Bedeutung entspricht. Auf diese Weise wird die Generierung der
erforderlichen Bedingungen aus dem Prolog-Programm herausgenommen und durch das
DBMS von Oracle durchgeführt.
8.4 Übersetzung von Anfragen
In Chimera existieren die zwei Anfragetypen "select" und "display", die unterschiedliche Aufgabenbereiche abdecken. In Oracle existiert hingegen nur die Anfrageoperation
"select", die zur Umsetzung beider Chimera-Anfragetypen verwendet wird. Der ChimeraAnfragetyp "select" wird ausschließlich benutzt, um Variablenbindungen zu erzeugen, die
in anderen Operationen weiter verwendet werden können. Durch diese Eigenschaft ist der
Chimera-"select"-Operation vergleichbar mit dem Konzept der Unteranfrage in einer
SQL-DML-Operation. Der Operationstyp "select" wird im CPTOracle durch das PrologPrädikat "translateSelect" analysiert. Es liefert die Parameter, die von dem PrologPrädikat "sql_query" benötigt werden, um die entsprechende SQL-Operation aufzubauen
und an die Datenbank zu schicken. Der erste Parameter des Prädikats "sql_query" besteht
aus der Liste von Attributen, die selektiert werden sollen. Da Variablenbindungen erzeugt
werden, muß immer nur die "oid" eines Tupels aus einer Tabelle selektiert werden. Deshalb
wird für jede Variable vor dem Bedingungsteil einer "select"-Operation in ChimeraSyntax, eine "oid" aus einer Tabelle selektiert, die eine Objektklasse des ChimeraDatenbankschemas repräsentiert. Die Variablennamen einer Chimera-"select"-Operation
werden in der "from"-Klausel einer SQL-Operation als Tupelvariable für die Tabellen verwendet, aus denen die "oid"s selektiert werden. Durch diese Vorgehensweise kann das Attribut "oid" durch den Ausdruck "variablen_name.oid" angesprochen werden. Die
Verbindung zwischen Tupelvariable und Tabelle wird im Bedingungsteil der "select"Operation
in
Chimera-Syntax
festgelegt,
der
durch
das
Prolog-Prädikat
"translateDecExp" in eine SQL-"from"- und einer SQL-"where"-Klausel übersetzt
wird. Die "from"-Klausel wird aus den Klassenformeln im Bedingungsteil der Chimera"select"-Operation zusammengesetzt. Dabei wird der Klassenname in die SQL-"from"Klausel übernommen und der Variablenname der Klassenformel als Tupelvariable vereinbart.
110
Inhaltsverzeichnis
Die "from"-Klausel entspricht dem zweiten Parameter des Prolog-Prädikats
"sql_query". Die "where"-Klausel, die dem dritten Parameter des verwendeten PrologPrädikats entspricht, wird aus den Bedingungen zusammengesetzt, die keine Klassenformeln
sind. Die Übersetzung dieser deklarativen Ausdrücke ist im Kapitel 7 bereits beschrieben
worden. Das folgende Beispiel verdeutlicht noch einmal die Vorgehensweise bei der Übersetzung einer "select"-Operation.
Chimera-DML
select( X,Y where person(X),
person(Y),
X.name = Y.name,
X.name = 'Scheuber')
Oracle-DML
SELECT
FROM
WHERE
AND
X.oid,
person
X.name
X.name
Y.oid
X, person Y
= Y.name
= 'Scheuber';
sql_query( ['X.oid', 'Y.oid'],"person X, person Y",
"X.name = Y.name AND X.name = 'Scheuber'",
"",[X,Y] )
Beispiel 8.4.1 Übersetzung des Anfragetyps "select"
In dem Beispiel 8.4.1 werden die Variablen "X" und "Y" der Klassenformeln
"person(X)" und "person(Y)" als Tupelvariablen in der SQL-"from"-Klausel verwendet. Der deklarative Ausdruck "person(X)" entspricht in seiner Bedeutung dem Ausdruck "person X". Dadurch ist es möglich die Attribute in den beiden Operationen durch
den identischen Ausdruck anzusprechen. Die selektierten "oid"s werden durch das PrologPrädikat "sql_query" mit den Variablen der Liste " [X,Y]" unifiziert. Die Variablennamen und die dazugehörigen Werte werden durch SQL-"insert"-Operationen in die
Oracle-Tabelle "chi_boundVar" übertragen, wodurch Variablenbindungen erzeugt werden, die in anderen Operationen weiter verwendet werden können. Pro selektierten Tupel wird
eine "insert"-Operation erzeugt.
Der Operationstyp "display" wird im CPTOracle durch das Prolog-Prädikat
"translateDisplay" analysiert, um die benötigten Parameter für das Prolog-Prädikat
"sql_querydistinct" zu konstruieren. Dieses Prädikat wird verwendet, da in Chimera
durch die "display"-Operation keine Duplikate angezeigt werden. Der Anfragetyp
"display" wird ausschließlich dazu verwendet, Daten aus der Datenbank zu extrahieren
und auszugeben. Es existieren zwei unterschiedliche Möglichkeiten eine "display"Operation zu formulieren. Entweder wird in einer "display"-Operation auf bereits erzeugte Variablenbindungen zurückgegriffen oder aber es muß ein Bedingungsteil innerhalb
der "display"-Operation formuliert werden. Allerdings ist es zur Zeit nicht möglich, beide
Alternativen innerhalb einer "display"-Operation zu kombinieren, da dieser Fall bisher
nicht in der Implementation berücksichtigt worden ist. Um nun eine "display"-Operation
in eine SQL-Operation zu übersetzen, wird als erstes die Liste von Attributen benötigt, die
angezeigt werden sollen. Diese werden durch das Prolog-Prädikat "getSelAttributes"
aus der Tokenliste extrahiert, welche die Chimera-"display"-Operation enthält. Da wieder
111
Inhaltsverzeichnis
die verwendeten Variablennamen als Tupelvariable für die Tabellen in der entsprechenden
SQL-Operation eingesetzt werden, ist es möglich, die Attributnamen eins zu eins zu übernehmen. Wird nun ein Bedingungsteil in einer "display"-Operation formuliert, so wird er
genauso übersetzt, wie schon bei den Chimera-"select"-Operationen beschrieben.
Chimera-DML
display(
X.name,
where person(X),
X.name = 'Horn' )
sql_querydistinct(
Oracle-DML
SELECT
FROM
WHERE
X.name,
X.vorname
person X
X.name = 'Horn';
['X.name','X.vorname'],
"person X",
" X.name = 'Horn'", "", [Name,Vorname])
Beispiel 8.4.2 Übersetzung einer "display"-Operation mit Bedingungen
Existiert nun innerhalb der "display"-Operation kein Bedingungsteil, so wird über die
verwendeten Variablennamen im Pfadausdruck der Attribute, die "from"- und "where"Klausel der SQL-Operation aufgebaut. Die dazu benötigten Variablenbindungen werden über
das Prolog-Prädikat "varInfo" und die Oracle-Tabelle "chi_boundVar" zur Verfügung gestellt. Das Prolog-Prädikat "varInfo" liefert zu einem Variablennamen den Namen
der Objekttklasse, an dessen Instanzen die Variable gebunden ist. Durch diese Informationen
kann die "from"-Klausel der SQL-"select"-Operation aufgebaut werden, indem für jede
Variable der zugehörige Objektklassenname selektiert wird. Die Variable wird wieder als
Tupelvariable für die entsprechende Sicht verwendet. Die "where"-Klausel wird dadurch
aufgebaut, daß für jede in der "display"-Operation verwendete Variable eine Bedingung
formuliert wird. Diese Bedingung stellt die Verbindung zwischen der Variable und den gebundenen "oid"s her.
Chimera-DML
select( X where person(X),
X.name = 'Horn' ),
display(X.name, X.vorname).
Oracle-DML
SELECT X.name,X.vorname
FROM
person X
WHERE
X.oid =
( SELECT
X.oid
FROM
chi_boundVar
WHERE
varname = X );
sql_query( ['X.name','X.vorname'], "person X",
"X.oid = ( SELECT X.oid FROM chi_boundVar
WHERE varname = X )", "", [X,Y] )
Beispiel 8.4.3: Übersetzung einer "display"-Operation ohne Bedingungen
112
Inhaltsverzeichnis
In dem Beispiel 8.4.3 werden die Werte der selektierten Attribute "name" und "vorname"
durch das Prolog-Prädikat "sql_querydistinct" mit den Variablen der Liste
"[Name,Vorname]" unifiziert. Durch die Verwendung des Prolog-Prädikats "findall"
werden alle Tupel in Form einer Liste zurückgegeben. Danach erfolgt pro selektierten Tupel
die Ausgabe der Variablennamen und ihrer dazugehörigen Werte.
8.5 Übersetzung von DML-Operationen
Zu den DML-Operationen gehören in der Sprachspezifikation von Chimera die Operationstypen "create", "delete" und "modify". Diese werden verwendet, um Instanzen
von Objektklassen zu generieren, zu löschen oder zu modifizieren. Die weiteren DMLOperationstypen "add" und "drop" dienen dazu, Werteklassen mit den erforderlichen Daten zu füllen. Im folgenden wird die Vorgehensweise zur Übersetzung dieser DMLOperationen beschrieben.
Der Operationstyp "add" wird im CPTOracle durch das Prolog-Prädikat "translateAdd"
analysiert, um eine SQL-"insert"-Operation zu konstruieren. Diese "insert"-Operation
legt eine neue Instanz in der Tabelle an, welche die Werteklasse repräsentiert. Bei der Formulierung der Operation muß darauf geachtet werden, daß jede Tabelle, die eine Werteklasse
repräsentiert, zusätzlich zu ihren in Chimera definierten Attributen, ein weiteres Attribut
besitzt. Dieses Attribut, welches unter dem Namen "vid" angelegt wird, ist der
Primärschlüssel der Tabelle. Durch ihn wird ein Tupel in der Tabelle eindeutig identifiziert.
Um einen eindeutigen Wert für dieses Attribut generieren zu können, wird das OracleKonzept der "sequence" verwendet. Eine "sequence" ist eine Pseudospalte (siehe
Kapitel 4), deren Wertebereich durch den Datentyp "number" festgelegt ist. Durch die
Funktion "nextval" wird der Wert einer "sequence" sukzessiv um einen festgelegten
Wert erhöht. Dadurch ist garantiert, daß immer ein eindeutiger Wert für das Attribut "vid"
innerhalb des Datenbankschemas zur Verfügung steht. Die "sequence" für "vid"s wird
wie folgt definiert:
CREATE SEQUENCE chi_vid_seq;
Da kein spezieller Wert definiert worden ist, um den die "sequence" bei Aufruf der
Funktion "nextval" erhöht werden soll, wird sie standartmäßig durch die Addition des
Wertes 1 inkrementiert. Ein fester Wert zur Addition kann durch die Klausel "increment
by" spezifiziert werden.
Die komplette SQL-Operation wird durch das Prolog-Prädikat "sql_exec" und nicht durch
"sql_insert" an die Datenbank geschickt, da bei "sql_insert" eine Liste von
Attributnamen als Parameter benötigt wird. Da die gesamte Definition einer Werteklasse
analysiert werden muß, um festzustellen, wieviele Attribute sie besitzt und wie deren
Bezeichner lauten, wird die komplette SQL-Operation in Form einer Zeichenkette an das
Prolog-Prädikat "sql_exec" übergeben. Dies hat den Vorteil, daß keine Attributnamen in
der Operation spezifiziert werden müssen, da die "insert"-Operation allen Attributen der
Tabelle einen Wert zuweist. Die Zuordnung zwischen Werten und Attributen erfolgt in Abhängigkeit der Reihenfolge der übergebenen Werte und der Reihenfolge, in der die Attribute
der Tabelle definiert worden sind. Das erste Attribut einer Tabelle, die eine Werteklasse ab113
Inhaltsverzeichnis
bildet, ist immer die "vid". Danach werden die eigentlichen Attribute definiert, welche die
Werteklasse beinhaltet. Diese Attribute werden in der gleichen Reihenfolge angelegt, wie sie
auch in der Chimera-Werteklasse spezifiziert worden sind. Aus diesem Grund ist auch die
Reihenfolge der Werte aus der "add"-Operation einfach auf die Reihenfolge der Werte in
der "insert"-Operation übertragbar.
Chimera-DML
add( vc_abteilung,
['EDV','Schmitz'] )
Oracle-DML
INSERT INTO vc_abteilung
VALUES( chi_vid_seq.nextval,
'EDV','Schmitz');
sql_exec( "INSERT INTO vc_abteilung
VALUES( chi_vid_seq.nextval, 'EDV', 'Schmitz' )",
Fehlercode, Fehlermeldung, _ )
Beispiel 8.5.1: Übersetzung einer Chimera-"add"-Operation
Im Beispiel 8.5.1 wird in die Tabelle "vc_abteilung", die im Kapitel 6 als Beispiel zur
Übersetzung einer Werteklasse eingeführt worden ist, ein neuer Datensatz eingefügt. Die
Werte, die den Attributen der Tabelle zugewiesen werden, setzen sich aus einer eindeutigen
"vid", und den Werten "EDV" und "Schmitz" zusammen. Der Wert der "vid" wird
durch den Ausdruck "chi_vid_seq.nextval" generiert, wobei "chi_vid_seq" der
Name der benutzten Sequenz und "nextval" die Funktion ist, die auf sie angewendet wird.
Die beiden anderen Werte werden aus der Liste des zweiten Parameters der "add"-Operation
extrahiert und als Werte für die Attribute "bereich" und "leiter" verwendet.
Der Operationstyp "drop" wird im CPTOracle durch das Prolog-Prädikat
"translateDrop" analysiert, um die erforderlichen Parameter für das Prädikat
"sql_delete" zu konstruieren, durch welches die entsprechende SQL-"delete"Operation erzeugt wird. Als erster Schritt müssen die Attributnamen der Werteklasse aus dem
CDD extrahiert werden, da sie zur Umsetzung der "drop"-Operation explizit in der Bedingungsklausel der SQL-Operation benötigt werden. Da Informationen über die Attribute einer
Werteklasse nicht getrennt im CDD verwaltet werden, muß ihre komplette Definition analysiert werden, um herauszufinden, ob der Wertetyp nur ein einziges Attribut besitzt oder aber
sich aus mehreren Attributen in Form eines benutzerdefinierten Datentyps zusammensetzt.
Besitzt die Chimera-Werteklasse nur ein Attribut, so wird dieses Attribut in der entsprechenden Oracle-Tabelle standardmäßig mit dem Namen der Werteklasse bezeichnet, da kein expliziter Name in der Chimera-Werteklasse für ein einzelnes Attribut vorgesehen ist.
114
Inhaltsverzeichnis
Chimera-DML
drop( vc_abteilung,
['EDV','Schmitz'] )
Oracle-DML
DELETE FROM vc_abteilung
WHERE bereich = 'EDV'
AND
leiter = 'Schmitz';
sql_delete( "vc_abteilung", "",
['bereich','leiter'],
['EDV','Schmitz'],
_ )
Beispiel 8.5.2: Übersetzung einer Chimera-"drop"-Operation
Um die "drop"-Operation aus dem Beispiel 8.5.2 umsetzen zu können, müssen zuerst die
Attributnamen "bereich" und "leiter" aus der Definition der Werteklasse
"vc_abteilung", die im CDD gespeichert vorliegt, extrahiert werden. Die beiden Attributnamen werden in Form einer Liste als dritter Parameter in dem Prolog-Prädikat
"sql_delete" verwendet. Die Liste aus der "drop"-Operation, welche die beiden Werte
enthält, durch die eine Instanz der Tabelle "vc_abteilung" eindeutig identifiziert werden
kann, wird eins zu eins als vierter Parameter des Prolog-Prädikats "sql_delete" verwendet. Aus diesen beiden Listen, die als Parameter verwendet werden, wird durch
"sql_delete" die Bedingungsklausel für die SQL-"delete"-Operation zusammengesetzt (siehe Kapitel 5) und die komplette Operation an die Oracle-Datenbank geschickt.
Der Operationstyp "create" wird im CPTOracle durch das Prolog-Prädikat
"translateCreate" analysiert, um die erforderlichen Parameter für das Prädikat
"sql_insert" zur Verfügung zu stellen. Aus diesem Grund werden mit Hilfe des PrologPrädikats "getAttributeValue" zwei Listen aus der Tokenliste der "create"Operation generiert. In der ersten Liste sind alle Attributnamen und in der zweiten Liste die
dazugehörigen Attributwerte enthalten. Zusätzlich zu den Attributnamen aus der
"create"-Operation wird noch die "oid" an erster Stelle der Liste mit aufgenommen.
Der Wert des Attributs "oid" wird durch die Verwendung der folgenden Oracle"sequence" erzeugt, um einen eindeutigen Wert zu garantieren:
CREATE SEQUENZ chi_oid_seq;
Der Ausdruck "chi_oid_seq.nextval" wird als erster Wert in der Werteliste verwendet und erzeugt die eindeutige "oid" für den neu angelegten Datensatz. Diese beiden Listen
werden zusammen mit dem Namen der betroffenen Objektklasse an das Prolog-Prädikat
"sql_insert" (siehe Kapitel 5) übergeben, welches aus diesen drei Parametern die SQL"insert"-Operation aufbaut und ihn an die entsprechende Sicht in der Oracle-Datenbank
schickt. Durch die Instead-of-Trigger der Sicht, werden die Daten aus der "insert"Operation an die entsprechenden Basistabellen der Sicht verteilt.
Ein weiteres Problem bei der Übersetzung einer Chimera-"create"-Operation besteht in
der Generierung der erforderlichen Variablenbindung. Eine Chimera-"create"-Operation
115
Inhaltsverzeichnis
bindet die in ihr verwendete Variable an die von ihr neu erzeugte Instanz einer Objektklasse.
Um eine äquivalente Variablenbindung im CPTOracle zu erzeugen, wird zusätzlich zu der übersetzten "create"-Operation eine weitere SQL-"insert"-Operation an die Tabelle
"chi_boundVar" gerichtet. Diese Operation fügt einen zweistelligen Tupel ein, dessen
Werte sich aus dem Variablennamen aus der "create"-Operation und der "oid" der neu
erzeugten Instanz zusammensetzen. Auf die "oid" der neu erzeugten Instanz kann ganz einfach zugegriffen werden, da sie dem aktuellen Wert der Sequenz "chi_oid_seq"
entspricht. Auf diesen Wert kann man mit Hilfe der Funktion "currval" zugreifen.
Chimera-DML
Oracle-DML
create( person,
INSERT INTO person
( name:
'Scheuber', ( oid, name, vorname )
vorname: 'Andrea'
VALUES( chi_oid_seq.nextval,
), X );
'Scheuber',
'Andrea' );
INSERT INTO chi_boundVar
( varname, oid )
VALUES
('X',chi_oid_seq.nextval);
sql_insert("person",['oid','name','vorname'],
[chi_oid_seq.nextval,'Scheuber','Andrea'])
sql_insert("chi_boundVar",['varname','oid'],
['X',chi_oid_seq.nextval] )
Beispiel 8.5.3: Übersetzung einer Chimera-"create"-Operation
Im Beispiel 8.5.3 wird in der Objektklasse "person" durch eine "create"-Operation
eine neue Instanz angelegt. Um nun eine äquivalente "insert"-Operation zu generieren
wird das Prolog-Prädikat "sql_insert" verwendet, welches drei Parameter dazu benötigt.
Diese Parameter erhält man durch die Analyse der Tokenliste, welche die "create"Operation enthält. Der erste Parameter besteht aus dem Namen der Objektklasse "person".
Der zweite Parameter beinhaltet eine Liste der Attribute, welche zu der Objektklasse gehören.
An erster Stelle dieser Liste, wird zusätzlich das Attribut "oid" eingefügt, da jede OracleSicht, die eine Objektklasse repräsentiert zusätzlich das Attribut "oid" als Objektidentifikator besitzt. Auf diese Weise ergibt sich die Attributliste "['name','vorname']" der
als zweiter Parameter des Prädikats "sql_insert" verwendet wird. Der dritte Parameter
beinhaltet die Liste der entsprechenden Attributwerte. An erster Stelle dieser Liste wird der
Wert der neuen "oid" durch die Funktion "chi_oid_seq.nextval" beschrieben.
Daraus ergibt sich die Liste "[chi_oid_seq.nextval,'Scheuber','Andrea']".
Aus diesen drei Parametern wird die erste "insert"-Operation konstruiert und an die
entsprechende Sicht in der Oracle-Datenbank geschickt. Diese insert-Operation löst den
116
Inhaltsverzeichnis
Instead-of-Insert-Trigger der Sicht "person" aus, der dafür zuständig ist, die neue Instanz
an die entsprechende Basistabelle weiterzuleiten. Die Werteliste der zweiten "insert"Operation setzt sich aus dem Namen der Variablen "X" und der Funktion
"chi_oid_seq.nextval" zusammen. Durch diese "insert"-Operation wird die
Variablenbindung für die Variable "X" erzeugt.
Der Operationstyp "delete" wird im CPTOracle durch das Prolog-Prädikat
"translateDelete" in den SQL-Operationstyp "delete" überführt. Um eine Chimera"delete"-Operation korrekt formulieren zu können, muß an die Variable, die in der
"delete"-Operation benutzt wird, durch vorher durchgeführte Anfragen vom Operationstyp "select" Instanzen der Objektklasse gebunden werden. Diese gebundenen Variablen werden in der Oracle-Tabelle "chi_boundVar" gespeichert und eine Unteranfrage in
die SQL-Operation integriert. Der Name, der betroffenen Objektklasse und der Bedingungsteil, der SQL-"delete"-Operation werden an das Prädikat "sql_delete" des EclipseOracle-Interfaces übergeben, durch das die SQL-Operation generiert und an die entsprechende Sicht in der Datenbank geschickt wird.
Chimera-DML
select( X where person(X),
X.name = 'Scheuber'),
delete( person, X );
Oracle-DML
DELETE
WHERE
( SELECT
FROM
WHERE
FROM person
oid =
oid
chi_boundVar
varname = X );
sql_delete("person",
"oid=(SELECT oid FROM chi_boundVar WHERE varname=X",
[],[], RowsDeleted )
Beispiel 8.5.4: Übersetzung einer Chimera-"delete"-Operation
Dadurch, daß nur die gebundenen Variablen aus der Tabelle "chi_boundVar" ausschlaggebend dafür sind, welche Instanzen durch eine "delete"-Operation gelöscht werden, ist es
nur erforderlich den Bedingungsteil der SQL-Operation so zu spezifizieren, daß alle Datensätze aus der Sicht "person", deren "oid" in der Tabelle "chi_boundVar" an die Variable "X" gebunden ist, gelöscht werden. Diese "delete"-Operation löst den Instead-ofDelete-Trigger der Sicht "person" aus, durch welchen alle betroffenen Instanzen in der
Basistabelle "oc_person" gelöscht werden.
Der Operationstyp "modify" wird im CPTOracle durch das Prolog-Prädikat
"translateModify" in den SQL-Operationstyp "update" überführt. Auch bei diesem
Ausdruck wird eine vorher gebundene Variable benötigt, durch die der Bedingungsteil der
"update"-Operation aufgebaut wird, wie schon bei der Übersetzung der Chimera"delete"-Operation beschrieben. Da kein Prolog-Prädikat im Eclipse-Oracle-Interface existiert, welches speziell für "update"-Operationen konzipiert worden ist, muß auf das all117
Inhaltsverzeichnis
gemeinere Prädikat "sql_exec" zurück gegriffen werden. Durch dieses Prädikat können
beliebige SQL-Operationen an die Datenbank geschickt werden, die mit dem Oracle-Befehl
"execute" ausgeführt werden.
Chimera-DML
modify( person.name,
X,
'Horn');
Oracle-DML
UPDATE
SET
WHERE
person
name = 'Horn'
oid =
( SELECT oid
FROM
chi_boundVar
WHERE
varname = X);
sql_exec( "UPDATE person SET name = 'Horn'
WHERE oid = ( SELECT oid FROM chi_boundVar
WHERE varname = X)",
Fehlercode, Fehlermeldung, ZeilenAnzahl )
Beispiel 8.5.5: Übersetzung einer Chimera-"modify"-Operation
Im Beispiel 8.5.5 wird gezeigt, wie eine Chimera-"modify"-Operation in eine SQL"update"-Operation überführt wird. Aus der Tokenliste der Chimera-"modify"-Operation
wird der Objektklassenname "person", der Attributname "name", der neue Attributwert
'Horn' und der Variablenname "X", an den Instanzen der Objektklasse gebunden sein müssen extrahiert. Mit Hilfe dieser Daten läßt sich die SQL-"update"-Operation wie folgt formulieren. Der Name der Chimera-Objektklasse "person" entspricht dem Namen der
Oracle-Sicht "person", welche die Objektklasse repräsentiert. Das Attribut "name" der
Sicht wird mit dem neuen Attributwert gleichgesetzt. Dies gilt für alle Instanzen der Sicht
"person", deren "oid" durch einen Tupel in der Tabelle "chi_boundVar" an die
Variable "X" gebunden ist. Diese "update"-Operation auf der Sicht "person" löst den
zur Sicht dazugehörigen Instead-of-Update-Trigger aus, der dafür sorgt, daß die Modifikation
an dem Attribut "name" in die Basistabelle "oc_person" übertragen wird.
118
Inhaltsverzeichnis
Andrea Scheuber und Michael Horn
9 Zusammenfassung und Ausblick
Die bisherige Implementierung des CPTPhx basiert auf dem in ECLiPSe-Prolog realisierten
Datenbankmanagementsystem Phoenix. Phoenix ist eine universitäre Implementierung des
relationalen Datenmodells mit einer Erweiterung für aktive und deduktive Regeln. Das
CPTPhx übernimmt hierbei die Aufgabe, die Konzepte eines Chimera-Schemas, der aktiven
und deduktiven Regeln sowie der Datenmanipulationssprache von Chimera auf das relationale
System Phoenix abzubilden. Im Umfeld des CPTPhx wurde durch mehrerer Forschungs- und
Diplomarbeiten eine Umgebung für den Entwurf und die Analyse von objektorientierten
Chimera-Schemata geschaffen.
Im Rahmen dieser Ausarbeitung wurde die Basis für eine neue, zweite Implementierung gelegt, dem CPTOracle. Das experimentelle Datenbankmanagementsystem Phoenix sollte durch
das kommerzielle objekt-relationale DBMS Oracle8 ersetzt werden. Die Übersetzung des objektorientierten Datenmodells von Chimera auf das objekt-relationale Datenmodell von
Oracle8 stand hierbei im Vordergrund. Basierend auf den unterschiedlichen Fähigkeiten von
Oracle8 und Phoenix wurde ein anderer Weg für die Übersetzung eines Chimera-Schemas
gewählt. Das in Oracle8 neu eingeführte Konzept der "instead-of"-Trigger ermöglichte
dieses unterschiedliche Vorgehen.
Der zweite Aspekt dieser Diplomarbeit lag in der Übersetzung der imperativen Ausdrücke der
in Chimera definierten Datenmanipulationssprache und die Übertragung des Transaktionsmodells von Chimera nach Oracle8. Das Transaktionskonzept von Chimera wurde mit Hilfe interner Prolog-Prädikate und Oracle8-Tabellen auf das Transaktionskonzept von Oracle8
übertragen.
Der dritte Aspekt dieser Arbeit liegt in der Übersetzung deklarativer Ausdrücke von Chimera
nach Oracle8-SQL. Deklarative Ausdrücke werden zur Formulierung von Anfragen und zur
Definition von Klassenpopulations- und Attributdefinitionsregeln, von Integritätsbedingungen, Triggern und Operationen verwendet.
119
Inhaltsverzeichnis
Obige Aspekte der Übersetzung wurden in ECLiPSe-Prolog implementiert. Die Verbindung
zwischen dem Prolog-System und dem DBMS Oracle8 wurde durch die bereits existierende
Schnittstelle zwischen ECLiPSe und Oracle8 von Thomas Kolbe ([Kol95]) realisiert.
Zusätzlich zu den übersetzten Aspekten existieren noch Konzepte, die im Rahmen dieser Diplomarbeit nicht mehr vollständig behandelt werden konnten. Die restlichen Abschnitte dieses
Kapitels erläutern Ideen zur Umsetzung von listen- und mengenwertigen Attributen und
Wertetypen, der Integritätsbedingungen und Trigger von Chimera.
Bisher können Listen und Mengen nicht von der Implementation des CPTOracle verarbeitet
werden. Folgender Abschnitt wird einen Lösungsansatz vorstellen, der dieses Manko entfernen könnte.
Listen sind Ansammlungen von Elementen, die jeweils eindeutig sein müssen und in einer
festen Reihenfolge eingegeben wurden. Diese Bedingungen können durch die Realisierung
einer Liste durch eine Oracle8-Tabelle realisiert werden. Die Tabelle müßte folgende Spalten
besitzen:
•
Spalte für den Objektidentifikator
•
Spalte für eine eindeutigen Reihenfolgenindikator
•
Spalte für den Wert des Listenelements
Durch obige Darstellung könnten die Listeneinträge eines Attributes abgespeichert werden.
Die Eindeutigkeit der Einträge kann durch eine Schlüsselbedingung für die beiden Spalten des
Objektidentifikatoren und des eigentlichen Wertes sichergestellt werden. Zwischen der Objektklasse und der Listen-Tabelle besteht eine 1:n Verbindung. Dies bedeutet, daß ein Objekt
mehrere Listeneinträge in der Tabelle abspeichern darf.
Mengen unterscheiden sich nur durch die nicht vorhandene Reihenfolge innerhalb der Werte
und durch die nicht geforderte Eindeutigkeit der einzelnen Werte. Menge könnten daher auf
die gleiche Art und Weise implementiert werden, wie für Listen empfohlen. Die Tabelle, die
eine Menge repräsentiert kommt allerdings mit nur zwei Spalte aus:
•
Spalte für den Objektidentifikator
•
Spalte für den Wert des Listenelements
Die Spalte zur Speicherung der Reihenfolge wird in den ungeordneten Mengen nicht mehr
benötigt.
Die Ideen zur Übersetzung von Listen und Mengen haben allerdings folgende Auswirkungen
auf die in dieser Diplomarbeit beschriebene Implementierung:
•
Anfragen an eine Chimera-Objektklasse mit einem listen- oder mengenwertigen Attribut
müssen die Liste bzw. die Menge verarbeiten können. Die Oracle8-Sichten, die eine Chimera-Objektklasse repräsentieren, sind nicht in der Lage, mit dieser Art von Attributen
umzugehen. Das Datenmodell von Oracle8 unterstützt keine komplexen Attributdefinitionen, die eine Liste oder Menge repräsentieren.
120
Inhaltsverzeichnis
•
Die Übersetzung der Datenmanipulationsbefehle von Chimera müssen ebenfalls an diese
Darstellung von Listen und Mengen angepaßt werden.
•
Es muß eine Funktionalität entwickelt werden, die es ermöglicht, eine neues Element in
die Mitte einer Liste einzufügen. Diese Operation muß den Reihenfolgenindikator der in
der Liste folgenden Elemente verändern.
Das obig beschriebene Vorgehen kann ebenfalls bei der Übersetzung listen- und mengenwertige Wertetypen angewendet werden. Durch die Realisierung der Listen- und Mengenstruktur
in Form einer Tabelle können Integritätsbedingungen einmal, zentral definiert werden.
Die Implementierung des CPTOracle kann bis jetzt noch keine Integritätsbedingungen von
Chimera nach Oracle übersetzen. Auch wenn es auf den ersten Blick so aussieht, als ob Integritätsbedingungen in Chimera und Oracle doch sehr ähnlich wären, so sieht das bei genauerer Betrachtung doch ganz anders aus: Das Konzept der Integritätsbedingungen ChimeraModells (siehe Kapitel 2) ist sehr viel mächtiger als das Konzept der built-inIntegritätsbedingungen des Oracle8-Datenmodells (siehe Kapitel 4). Ziel einer Übersetzung
von Chimera-Integritätsbedingungen nach Oracle8 muß es also sein, die Einschränkungen auf
Seiten von Oracle8 so weit wie möglich aufzuheben.
Trotz der markanten Unterschiede, existiert dennoch eine kleine Schnittmenge von Klassen
von Integritätsbedingungen, die beide Modelle unterstützen:
•
"notnull"-Bedingungen für ein Attribut
•
Primär- und Sekundärschlüssel für eine Tabelle
Diese beiden Klassen können demnach auf das jeweilige Äquivalent übertragen werden. Bei
den komplexeren, selbstdefinierten Integritätsbedingungen sieht es dagegen vollkommen anders aus: Chimera-Integritätsbedingungen können im Rumpf der Bedingung durch beliebige
deklarative Ausdrücke formuliert werden. Der Umfang der "check"-Bedingungen von
Oracle8 entspricht nicht einmal annähernd dem der deklarativen Ausdrücke von Chimera.
Innerhalb einer "check"-Integritätsbedingung dürfen keine Anfragen auf den Datenbestand
erfolgen. Des weiteren ist es nicht möglich, die Zugehörigkeit eines Wertes zu einer Menge
zu fordern, wenn diese Menge sich während der Laufzeit der Datenbank verändern kann.
Die Lösung für obige Probleme könnte die Übersetzung von Chimera-Integritätsbedingungen
in Oracle8-Trigger sein. Dieser Ansatz der Problemlösung hätte noch einen zusätzlichen
Vorteil: Das Oracle8-Datenmodell erlaubt keine Definition von Integritätsbedingungen für
Sichten. Bei der Übersetzung eines Chimera-Schemas in ein Oracle8-SQL-Schema werden
Sichten allerdings zur Darstellung von Objektklassen verwendet (vergleiche Kapitel 6). Das
Aufspalten der Definition einer Chimera-Integritätsbedingung auf die verschiedenen Oracle8Tabellen ist allerdings nicht möglich.
Die bisherige Implementierung des CPTOracle unterstützt noch keinerlei Schemaevolution.
Daher können Integritätsbedingungen nur zu Beginn der Schemadefinition definiert werden.
Eine Integritätsverletzung kann also nur durch eine Datenmanipulation geschehen, wenn man
einmal davon ausgeht, daß alle bisher eingefügten und veränderten Daten einen konsistenten
Datenbankzustand definieren. Alle DML-Operationen von Chimera werden auf der Seite von
Oracle durch "instead-of"-Trigger realisiert. Innerhalb dieser Trigger kann daher die
121
Inhaltsverzeichnis
komplette Überprüfung aller Integritätsbedingungen einer Chimera-Objektklasse realisiert
werden. Es bietet sich an, eine komplexe Integritätsbedingung von Chimera in eine Oracle8Datenbankfunktion ("stored function") zu übersetzen. Oracle8-Datenbankfunktionen
werden mit Hilfe der Oracle-Programmiersprache PL/SQL formuliert. PL/SQL ist eine Erweiterung von SQL um Kontrollstrukturen u.ä. Jede Integritätsbedingung eines ChimeraSchemas könnte in eine Funktion übersetzt werden. Die Funktion würde von den jeweiligen
"instead-of"-Triggern einer übersetzten Objektklasse aufgerufen werden.
Verletzungen einer Integritätsbedingung müssen zentral für eine Chimera-Datenbank auf einem Oracle8-Server verwaltet werden. Dieses Vorgehen ist nötig, da z.B. Trigger auf Integritätsverletzungen automatisch reagieren können. Die Implementierung des CPTPhx hat das
Problem durch eine extensionale Relation gelöst, in der alle Verletzungen einer Integritätsbedingung protokolliert werden. Dieses Vorgehen läßt sich ohne Probleme für das CPTOracle
übernehmen. Die entsprechende Oracle8-Tabelle sollte mindestens folgende Informationen
einer Integritätsverletzung speichern:
•
Namen der Objektklasse
•
Namen der verletzten Integritätsbedingung
•
Identifikator des inkonsistenten Objektes (OID)
•
Operation, bei der die Verletzung auftrat
Obige Liste erhebt keinen Anspruch auf Vollständigkeit, da eine Implementierung obiger Ideen eventuell noch weitere Informationen benötigt. Es könnte z.B. möglich sein, daß die Werte
der Datenmanipulation zusätzlich interessant sind.
Das bisher vorgestellte Verfahren bezieht sich auf Integritätsbedingungen, die sofort nach
einer Datenmanipulation überprüft werden müssen ("immediate constraints"). Die Integritätsbedingungen, die an Ende einer Transaktion überprüft werden sollen, können allerdings durch
ein ähnliches Verfahren übersetzt werden. Der einzige Unterschied stellt der Aufruf der Integritätsüberprüfung da. Der DML-Befehl "commit" muß durch eine entsprechende Funktion
oder Prozedur eingeschlossen werden. Die Funktion oder Prozedur übernimmt dann zusätzlich die Überprüfung der Integritätsbedingungen.
Das Konzept der Chimera-Trigger ist, wie auch das Konzept der ChimeraIntegritätsbedingungen, wesentlich mächtiger als das Triggerkonzept, welches von Oracle8
zur Verfügung gestellt wird. Dies liegt unter anderem daran, daß in Chimera mehr Ereignistypen zur Verfügung stehen, durch die ein Trigger ausgelöst werden kann. Die Trigger von
Oracle8 können nur durch spezifizierte Ereignisse vom Typ "insert", "delete" und
"update" ausgelöst werden. Da diese Ereignisse auch als Auslöser in Chimera-Triggern
festgelegt werden können, wäre es sinnvoll diese Trigger direkt durch die entsprechenden
Oracle-Trigger zu implementieren. Dadurch würde der Verwaltungsaufwand für diese Trigger
vom DBMS übernommen. Zu beachten ist bei dieser Vorgehensweise, daß in Oracle8 nicht
mehrere Datenbanktrigger des gleichen Typs einer Tabelle zugeordnet werden dürfen. Aus
diesem Grund ist es zu empfehlen diese Trigger als interne Prozedur in Oracle zu implementieren und nur den Aufruf der internen Prozeduren in den entsprechenden Oracle-Trigger zu
verlagern.
122
Inhaltsverzeichnis
Die Umsetzung von Chimera-Triggern, die durch andere Ereignistypen ausgelöst werden,
kann durch den Einsatz von internen Prozeduren und Funktionen in Oracle erfolgen. Im Gegensatz zu den bereits vorgestellten Ereignistypen, existieren keine entsprechenden OracleTrigger die ihren Aufruf automatisch ermöglichen. Deshalb müssen zusätzliche administrative
Konzepte eingeführt werden, um die Umsetzung dieser Trigger zu ermöglichen. Der im folgenden vorgestellte Ansatz zur Übersetzung von Triggern orientiert sich im an der Implementation des CPTPhx, welches ähnliche administrative Konzepte benötigt, um das
Triggerkonzept von Chimera umzusetzen.
Bei der Implementierung durch interne Prozeduren muß in für jeden Trigger eine Prozedur
pro Ereignistyp definiert werden. Die Verwaltung dieser Trigger erfolgt mit Hilfe von mehreren Tabellen. Die erste Tabelle dient dazu, alle Ereignisse zu registrieren, die in der Datenbank eintreten können. Das bedeutet, daß jede Anfrage- und DML-Operation durch einen
Eintrag in dieser Tabelle registriert werden müßte. Dies könnte durch eine zusätzliche
"insert"-Operation in die Ereignistabelle nach der Übersetzung einer Operation erfolgen.
Des weiteren ist das Auslösen eines Triggers auch wieder ein Ereignis, daß in der Ereignistabelle registriert werden muß. Um diese Registrierung durchzuführen, müßte jede OracleProzedur, die einen Trigger realisiert, am Ende ihres Programmcodes eine zusätzliche
"insert"-Operation durchführen, welche die entsprechenden Daten in die Ereignistabelle
einträgt. Diese Ereignistabelle müßte wie folgt aussehen:
Ereignis ID
Ereignistyp
Objektklasse
Das erste Attribut der Ereignistabelle dient dazu, daß Ereignis eindeutig zu identifizieren, da
innerhalb einer Transaktion mehrere Ereignisse des gleichen Typs auftreten können. Das
zweite Attribut wird verwendet, um den Ereignistypen zu speichern, der einen Trigger auslösen kann. Das dritte Attribut beinhaltet den Namen der Tabelle (Objektklasse), in der das Ereignis aufgetreten ist, damit der richtige Trigger zu der entsprechenden Tabelle ausgeführt
werden kann. In einer weiteren Tabelle können die "immediate"- und "deferred"Trigger des Datenbankschemas wie folgt verwaltet werden:
Triggername
Triggertyp
Ereignistyp
Objektklasse
Prozedurname
Das erste Attribut der Tabelle zur Verwaltung von Triggern beinhaltet den Triggernamen, der
den Trigger innerhalb des Datenbankschemas eindeutig identifiziert. Das zweite Attribut beinhaltet den Triggertypen, der entweder "immediate" oder "deferred" sein kann. Das
dritte Attribut beinhaltet das spezifizierte Ereignis, welches den Trigger auslösen soll. Das
vierte Attribut beinhaltet die Objektklasse, zu welcher der Trigger gehört und das fünfte
Attribut beinhaltet den Namen der internen Oracle-Prozedur, die aufgerufen werden soll,
wenn das spezifizierte Ereignis des Triggers eingetreten ist. Diese Daten müssen einmal bei
der Schemaübersetzung mitgeneriert werden und dürfen danach nicht verändert werden, da
ansonsten die Gefahr besteht, daß sie nicht mehr dem Schema entsprechen.
Die Auswertung der Daten, die sich in diesen zwei administrativen Tabellen befinden, erfolgt
zu zwei unterschiedlichen Zeitpunkten. Am Ende einer Transaktionszeile muß überprüft
werden, ob Ereignisse eingetreten sind, die in "immediate"-Triggern als auslösende
123
Inhaltsverzeichnis
Ereignisse spezifiziert worden sind. Dies kann durch den Aufruf einer Oracle-Prozedur
erfolgen, welche die Überprüfung in Form einer "select"-Operation vornimmt und das
Ergebis in einem Cursor verwaltet. Die select-Operation könnten aufgrund der vorgestellten
administrativen Tabellen wie folgt aussehen.
SELECT
FROM
WHERE
AND
AND
T.Prozedurname
Ereignistabelle E, Triggertabelle T
E.Ereignistyp = T.Ereignistyp
E.Objektklasse = T.Objektklasse
T.Triggertyp = 'immediate';
Bestandteil des Ergebnis dieser "select"-Operation müssen auf jeden Fall die Namen der
internen Oracle-Prozeduren sein, durch welche die auszulösenden Trigger implementiert
werden. Alle selektierten Prozeduren werden nacheinander durch den Oracle-Befehl
"EXECUTE" abgearbeitet.
Der zweite Zeitpunkt zur Auswertung der administrativen Tabellen findet am Ende einer
kompletten Transaktion statt. An dieser Stelle müssen alle "deferred"-Trigger auf gleiche
Weise wie die "immediate"-Trigger überprüft werden. Die Daten der administrativen
Tabelle zu Verwaltung von Ereignissen müssen nach jeder Transaktion vollständig gelöscht
werden, damit Trigger innnerhalb der folgenden Transaktion nicht fälschlicher Weise
ausgelöst werden.
124
Inhaltsverzeichnis
Andrea Scheuber und Michael Horn
10 Literaturverzeichnis
[Asc96]
Elmar Ascheid: "Ein Werkzeug zur Unterstützung von Entwurf und Validierung deduktiver Regeln in Chimera". Diplomarbeit am Institut für Informatik
III, Rheinische-Friedrich-Wilhelms-Universität, Dezember 1996
[CF97]
Stefano Ceri und Piero Fraternali: "Designing Database Applications with
Objects and Rules – The IDEA Methodology". Addison-Wesley, 1997
[CM93]
Stefano Ceri und Rainer Manthey: "Consolidated Specification of Chimera
(CM and CL)". ESPRIT Projekt 6333, IDEA.DE.2P.006.01, Oktober 1993
[CM94]
W. F. Clocksin und C. S. Mellish: "Programming in Prolog". 4. Auflage,
Springer-Verlag, 1994
[Dau96]
Ulrich Daugs: "Entwurf und Implementierung einer grafischen Oberfläche zur
Verwaltung objektorientierter Datenbank-Schemata". Diplomarbeit am Institut
für Informatik III, Rheinische-Friedrich-Wilhelms-Universität, August 1996
[DG94]
Susanne Deiters und Ulrike Griefahn: "Propagation Rule Compiler: Tool Specification". ESPRIT Projekt 6333, IDEA.DE.22.O.001, November 1994
[Dra93]
Christof Draxler: "A DCG Implementation of the Full Chimera Language".
ESPRIT Projekt 6333, IDEA.DD.2P.008.01, 1993
[DS97]
Dave Ensor und Ian Stevenson: "Oracle8 Design Tips". O'Reilly, 1997
[ECRC95]
"ECLiPSe 3.5: User Manual". ECRC, Dezember 1995
125
Inhaltsverzeichnis
[GL96]
Ulrike Griefahn, Thomas Lemke: "Implementing Chimera on Top of an Active Relational Database System". ESPRIT Projekt 6333, IDEA.WP22.O.005,
Juli 1996
[GLM96]
Ulrike Griefahn, Thomas Lemke und Rainer Manthey: "Chimera Prototyping
Tool: User Manual". ESPRIT Projekt 6333, IDEA.DE.22.O.006, Mai 1996
[GLM97]
Ulrike Griefahn, Thomas Lemke und Rainer Manthey: "Tools for Chimera:
An Environment for Designing and Prototyping Advanced Applications in an
active DOOD Model". Proc. 1st East-European Symposium on Advances in
Databases and Information Systems (ADBIS97), St. Petersburg, September
1997
[GM95]
Ulrike Griefahn und Rainer Manthey: "Propagation Rule Compiler: Tool Description". ESPRIT Projekt 6333, IDEA.DE.22.O.003, November 1995
[GR96a]
Ulrike Griefahn und Thomas Rath: "Propagation Rule Compiler: Technical
Documentation". ESPRIT Projekt 6333, IDEA.DE.22.O.005, November 1996
[GR96b]
Ulrike Griefahn und Thomas Rath: "Propagation Rule Compiler: User Manual". ESPRIT Projekt 6333, IDEA.WP.22.O.004, November 1996
[Inf93]
"Duden Informatik: Ein Sachlexikon für Studium und Beruf". 2. Auflage, Duden-Verlag, 1993
[KE99]
Alfons Kemper und André Eickler: "Datenbanksysteme: Eine Einführung". 3.
Auflage, Oldenbourg Verlag, 1999
[Kol95]
Thomas H. Kolbe: "Anbindung des RDBMS Oracle an ECLiPSe". Institut für
Informatik III, Rheinische-Friedrich-Wilhelms-Universität, September 1995
[Lem94]
Thomas Lemke: "The Schema Evolution Assistant: Tool Specification".
ESPRIT Projekt 6333, IDEA.DE.22.O.002, November 1994
[LM95]
Thomas Lemke und Rainer Manthey: "The Schema Evolution Assistant: Tool
Description". ESPRIT Projekt 6333, IDEA.DE.22.O.004, November 1995
[LM97]
Thomas Lemke und Rainer Manthey: "The Passive Rule Design Tool: Tool
Documentation" ESPRIT Projekt 6333, IDEA.DE.22.O.010, März 1997
[Ora98]
Online Dokumentation zu Oracle8, Oracle Corporation, 1998
[Schi98]
Michael Schiefer: "CARDT- Ein Tool zur dynamischen Analyse aktiver Regeln". Diplomarbeit am Institut für Informatik III, Rheinische-FriedrichWilhelms-Universität, Oktober 1998
[Schm99]
Thomas Schmitt: "Entwurf und Implementation einer graphischen Schnittstelle zur Datenmanipulation für das objektorientierte Datenmodell Chimera".
Diplomarbeit am Institut für Informatik III, Rheinische-Friedrich-WilhelmsUniversität, Januar 1999
126
Inhaltsverzeichnis
[Schu99]
Stefan Schubert: "Ein Passiv Rule Prototyping Tool für Chimera". Diplomarbeit am Institut für Informatik III, Rheinische-Friedrich-Wilhelms-Universität,
Juli 1999
127
Herunterladen