Hauptseminar
Datenbanksysteme
- Datenbanken und XML Thema: Type-Checking OQL Queries
In The ODMG Type Systems
Angesprochene Punkte
Allgemeines zum Type Checking in
Datenbanksystemen
Kurze Einführung in den ODMG Standard
Formale Definitionen und Regeln
Betrachtung von auftretenden Problemen und
skizzieren von Lösungsvorschlägen
Referenzen
Type Checking (1/2)
Es gibt zwei Möglichkeiten von Type-Checking
Dynamisches type-checking während der
Programmausführung
Statisches type-checking, zur Kompilierzeit
Type Checking (2/2)
Aus folgenden Gründen wird statisches typechecking bei Datenbanken bevorzugt:
Die Effizienz der Datenbank sollte nicht unnötig
belastet werden
Laufzeitfehler sind bei Datenbanken besonders
kritisch
„Message not understood“-Fehler werden durch
statisches type-checking ausgeschlossen
ODMG Standard (1/5)
ODMG steht für Object Data Management
Group (www.odmg.org)
1993 wurde der ODMG 1.0 Standard
veröffentlicht; der aktuelle Stand ist Release 3.0
Dieser Vortrag geht noch auf den ODMG 2.0
Standard ein
ODMG Standard (2/5)
Interface
Literal
Class
Interface: Definiert das abstrakte Verhalten eines Objektes
Class: Ist ein erweitertes Interface mit einem Status
Literal: Definiert nur einen abstrakten Status
ODMG Standard (3/5)
Was ist ein Interface?
Ein Interface definiert das
abstrakte Verhalten von
Objekt-Typen.
Ein Interface beinhaltet
nur Methoden, keine
Attribute.
Beispiel (The top interface)
interface Object {
boolean same_as(in Object
anObject);
Object copy();
void delete();
};
ODMG Standard (4/5)
Was ist eine Klasse?
Eine Klasse ist ein
erweitertes Interface.
Eine Klasse definiert das
abstrakte Verhalten und
den abstrakten Zustand
von Objekt-Typen.
Beispiel (Class with extent)
class Employee (extent employees)
{ attribute string name;
attribute short id;
attribute Department dept;
float salary();
void hire(in Department d);
void fire();
};
class Department (extent departments)
{ attribute string name;
attribute short id;
short NoOfEmployees();
};
ODMG Standard (5/5)
Was ist ein Literal?
Ein Literal definiert nur
den abstrakten Zustand
eines primitiven LiteralTypen.
Es gibt keine
Objektidentitäten für
Literale
Literal-Typen:
-boolean
-char
-short
-long
-float
-double
-octet
-string
-user-defined collection,
union and enumeration
literale
OQL- Queries
Beispiel
select well_paid(emp: x.name,
sal: x.salary())
from employees as x
where x.salary() > 50000
and x.dept.NoOfEmployees()>100
order by emp
Das Resultat ist eine
Menge vom Typ
well_paid
Der Typ well_paid ist
vorher definiert und hat
die Komponenten emp
und sal
Durch order by wird eine
Liste von Objekten
erzeugt
Collection Objects (1/2)
Es gibt verschiedene Typen von „Mengen“
Set<t> : Eine Menge ohne Duplikate
Bag<t> : Eine Menge mit Duplikaten
List<t> : Geordnete Menge
Array<t> : Geordnete Menge mit Indizes
Dictionary<t,v> : Menge aus Schlüsseln denen ein
Wert zugeordnet wird
Collection Objects (2/2)
Interface Collection: Object {
unsigned long cardinality();
boolean is_empty();
void insert_element(in any element);
void remove_element(in any element);
boolean contains_element(in any element);
Iterator create_iterator();
};
Parametric polymorphism im ODMG Objektmodell
any steht für jeden Objekttypen, dadurch ergeben sich auch
weitere Probleme beim type-checking
Die anderen Collection Types werden von diesem
Interface abgeleitet
Java vs. C++
Java unterstützt
keinen
parametrisierten
Polymorphismus
C++ bietet zu
diesem Zweck
Templates an
interface Collection {
int size();
boolean isEmpty();
void add(in Object element);
boolean remove(in Object element);
Iterator iterator();
...
};
interface Collection <T> {
unsigned long cardinality();
boolean is_empty();
void insert_element(T element);
void remove_element(T element);
boolean contains_element(T element);
Iterator <T> create_iterator();
};
Formale Spezifikation (1/2)
Ein Schema ist eine Menge von Verknüpfungen
Es beinhaltet Schlüsselwörter, die mit interfaces,
classes, class extents und objects assoziiert sind
Ein Schema ist wohlgeformt, wenn:
jedes Schlüsselwort nur genau einer Zuordnung
entspricht.
der Typ zu jedem Objekt ebenfalls im Schema
enthalten ist.
bei interfaces und classes die Regeln für die
Vererbung berücksichtigt wurden.
Formale Spezifikation (2/2)
Das Hinzufügen einer class extent zu einem
Schema stellt ebenfalls den Namen des extent
im Schema zur Verfügung.
Ein Schema beinhaltet vordefinierte
Zuordnungen
String, int, boolean…
Collection, Bag, Set, List, Array…
die Datenbank-/Transaktionsklasse
Vererbung (1/5)
Das top interface ist „Object“, alle weiteren
Interfaces werden von diesem abgeleitet
Vererbung (2/5)
Reflexivität
Transitivität
Vererbung (3/5)
Substitution
Ein Objekt vom Typ C2 kann ein Objekt vom Typ C1
ersetzen, falls C2 von C1 abgeleitet wird
Die Regel beschreibt, daß im Ausdruck e ein vorkommendes
y durch ein x ersetzt werden kann.
Vererbung (4/5)
Type casts
Ist ein Ausdruck e vom Typ C1 und es gilt außerdem
noch, dass C2 von C1 abgeleitet ist, ist ein type-cast
möglich
Es wird ein dynamisches type-checking benötigt
Vererbung (5/5)
Beispiel type casts
class Person {
(extent persons)
...
}
class Employee: Person {
(extent employees)
long salary();
...
}
select well_paid(emp: x.name, sal:((Employee)x).salary())
from persons as x
where ((Employee)x).salary() > 50000
Weitere Regeln zusammengefaßt
Auf ähnliche Weise können nun auch
Structures
Interfaces
Classes
Objects and Messages
in das Schema mit aufgenommen werden.
OQL Queries and the ODMG
object model (1/3)
Nun kommen wir zu dem ersten negativen
Beispiel für das type-checking:
select well_paid(emp: x.name, sal: x.salary())
from employees as x
where x.salary() > 50000
Employees ist vom Typ Collection
x ist ein Objekt vom Typ any
OQL Queries and the ODMG
object model (2/3)
Methoden für den Type any sind im ODMG
Standard nicht definiert
Es ist nicht möglich auf die Typkorrektheit von
x.name und x.salary() zu schließen
Theorem: OQL-Queries können nicht auf
Typkorrektheit überprüft werden.
OQL Queries and the ODMG
object model (3/3)
Beweis:
select projection
from e1 as x1, e2 as x2, … ,en as xn
where e
Die Variabel-Typen der xi müssen bestimmt werden
Die Variabel-Typen der ei müssen bestimmt werden
Im besten Fall nehmen wir an, daß die ei vom Typ
Collection sind
Folglich sind die xi vom Typ any
OQL Queries and Java (1/5)
Die bisherigen Probleme beruhen auf dem Type
any im ODMG Type-System
In der Java-Anbindung ist der Type Object das
Wurzel-Objekt
Alle Objekte im Java-Typ-System erben die
Eigenschaften des Wurzel-Objektes
OQL Queries and Java (2/5)
Theorem: Statisches Type-checking ist im JavaType-System nicht möglich
Beweis
Der Typ der Variable x wird nun als Objekt
identifiziert
Nur Methoden aus dem Interface „Object“ können
benutzt werden
Das type-checking schlägt fehl sobald unbekannte
Methoden aufgerufen werden
OQL Queries and Java (2/5)
Beispiel
class Professor {
public float salary() { }
...
}
class Course {
public int enrollment() { }
...
}
Collection professors;
Collection courses;
select x
from professors as x, x.courses() as y
where x.salary() > 70000
and y.enrollment() > 50
OQL Queries and Java (3/5)
x.salary(), x.courses() und y.enrollment() werden
stets als nicht typkorrekt klassifiziert
Hier stellt sich die Frage ob sich Java für die
Datenbankprogrammierung eignet?
Betrachten wir zunächst eine Lösung für dieses
Problem – dynamisches type-checking…
OQL Queries and Java (4/5)
OQL Query with type casts
Theorem: Bei ausdrücklicher Typangabe für jede
Variabel innerhalb der Anfrag im Java-TypSystem ist ein type-checking möglich, allerdings
nur auf Kosten des teuren Checks zur Laufzeit
(ohne Beweis)
OQL Queries and Java (5/5)
Beispiel
Collection professors;
Collection courses;
select x
from professors as (Professor)x,
x.courses() as (Course)y
where x.salary() > 70000
and y.enrollment() > 50
Diese Anfrage ist aufgrund des type-casts möglich
Es wird ein Check zur Laufzeit ausgeführt
OQL Queries and C++ (1/2)
Theorem: Ein Type-System, das parametrisierten
Polymorphismus unterstützt erlaubt statisches typechecking von OQL Queries
Beweis: Dieses Resultat wird erziehlt, da zur
Kompilierzeit jedem Collection-Type ein bestimmter
Type zugeordnet wird. Dadurch wird jeder ElementType eindeutig einer Menge zugeordnet.
Die Variablen einer Anfrage gehören einem
spezifischen Types an
OQL Queries and C++ (2/2)
Beispiel in C++
Collection <Professor> professors;
Collection <Course> courses;
select x
from professors as x, x.courses() as y
where x.salary() > 70000
and y.enrollment > 50
Korrolar: Das Type-System von C++ erlaubt
statisches type-checking von OQL Queries
OQL Queries with Order by (1/2)
Eine Anfrage in allgemeiner Form:
select projection
from e1 as x1, e2 as x2, … ,en as xn
where e
order by e´1, e´2, … , e´m
Auch hier treten die schon bekannten Probleme
auf
Ein Vergleich von zwei Objekten kommt hinzu
OQL Queries with Order by (2/2)
Theorem: Bei expliziter Typangabe für jede
Variabel innerhalb der Anfrage mit Order by
Klausel im Java-Typ-System ist ein type-checking
möglich, allerdings wiederum nur zur Laufzeit
Theorem: Ein Type-System, das parametrisierten
Polymorphismus unterstützt erlaubt statisches
type-checking von OQL Queries mit Order by
Klausel
Java OQL (1/6)
Java OQL ist eine Untersprach von Java und
ermöglicht eine leichtere Anbindung an die
Datenbank
Es gibt zwei Formen dieser Vereinfachung
durch Methoden
durch Klassen
Java OQL (2/6)
Zunächst die Möglichkeit durch Methoden
interface DCollection extends java.util.Collection {
Object selectElement(String predicate)
java.util.Iterator select(String predicate)
DCollection query(String predicate)
boolean existsElement(String predicate)
}
Die anderen Interfaces aus dem ODMG
Standard (DSet, DBag, DList …) werden von
diesem Interface abgeleitet
Java OQL (3/6)
Ein Java OQL Query
DCollection bestPaid;
bestPaid = employees.query(
„for all x in employees: this.salary() >= x.salary()“
);
Das obige Beispiel findet die Menge der
bestbezahltesden Mitarbeiter
Java OQL (4/6)
Die Anfrage wird mittels eines Strings gestellt
Type-checking im Java-Type-System ist stets
möglich, unabhängig vom Stringinhalt
Der String muß während der Laufzeit ausgewertet
werden
Theorem: Das type-system von Java kann mit
Java-OQL-Queries nicht umgehen, so daß ein
type-checking nicht möglich ist
Java OQL (5/6)
Java OQL Queries als Klassen
class OQLQuery {
// Java constructors
OQLQuery create(String query);
void bind(Object parameter);
Object execute();
}
DBag selectedEmployee;
OQLQuery query = new OQLQuery();
query.create(„select well_paid(emp: x.name,
sal: x.salary())
from employees as x
where x.salary() > $1 and
x.dept.NoOfEmployees() > $2“);
query.bind(50000); query.bind(100);
selectedEmployees = (DBag) query.execute();
Java OQL (6/6)
Es werden gut bezahlte Mitarbeiter in großen
Abteilungen gesucht
Bei diesem Beispiel treten mehrere Probleme
auf:
Es kann nur ein Laufzeitcheck ausgeführt werden
Die Übergabeparameter (mittels query.bind())
müssen zu dem Query passen
Der Rückgabewert von query.execute() ist Object,
die Select-Anweisung liefert eine Menge von
Objekten
C++ und OQL-Erweiterung
Auch für C++ gibt es eine Erweiterung für die
vereinfachte Anbindung an die Datenbank
Die in C++ zur Verfügung stehenden Templates
helfen hier auch nicht
Die Queries werden als String gegeben…
Beim type-checking sind Strings stets typkorrekt
C++ unterliegt den selben Problemen, die eben
im Java-Typ-System diskutiert wurden
Geordnete Mengen (1/2)
Weder im ODMG-Standard noch im Java oder
C++ Type-System können geordnete Menge auf
Typkorrektheit geprüft werden
Ein Beispiel im ODMG Object Model
interface Ordered_Collection: Collection {
unsigned long cardinality();
boolean is_empty();
void insert_element(in Ordered element);
void remove_element(in Ordered element);
boolean contains_element(in Ordered element);
Iterator create_iterator();
}
Geordnete Mengen (2/2)
Das Interface Ordered_Collection erbt von
Collection
Die Vererbungsregeln wurden bei den folgenden
Funktionen nicht befolgt
insert_element
remove_element
contains_element
Die Funktionsköpfe (die Aufrufparameter)
dieser Funktionen wurden geändert
Bounded Type Quantification
Theorem: Ein Type-System, das bounded type
quantificatien unterstützt und das top-Object
beinhaltet kann geordnete Mengen auf
Typkorrektheit überprüfen
interface Ordered_Collection <T: Ordered>: Collection <T>{
...
}
Eiffel unterstützt diese Methode, doch C++
benötigt eine klare Vererbungsstruktur
F-Bounded polymorphism (1/3)
Theorem: Wenn die C++-Anbindung an die
Datenbank F-bounded polymorphism
unterstützt ist ein statisches type-checking von
Queries möglich
interface Ordered_Collection <T: Ord_element <T>>
:Collection <T>{
...
}
F-Bounded polymorphism (2/3)
Beispiel
interface Employee {
String name;
short id:
//boolean leq(Employee e);
}
Dieses Interface entspricht nicht den
Vererbungsregeln, da Employee nicht von
Ord_element <Employee> abgeleitet wird
F-Bounded polymorphism (3/3)
interface Ord_element <Employee> {
boolean leq(Employee e);
}
Durch das obige Interface werden die
Vererbungsstrukturen wiederhergestellt
Es wird garantiert, daß die Methoden die
richtige Signatur haben
Statisches Type-checking ist möglich
Zusammenfassung
OQL Queries können im ODMG-Standard
nicht auf Korrektheit geprüft werden
OQL Queries können in der Java-Anbindung
nicht auf Korrektheit überprüft werden
Parameter Polymorphismus sollte von einer
Sprache für die Datenbank unterstüzt werden
Um geordnete Menge korrekt zu überprüfen
wird F-bounded polymorphism benötigt
Referenzen
Type-Checking OQL Queries In The ODMG Type System
Suad Alagic – Wichita State University
ACM Transaction on Database Systems, Vol.24, No. 3
September 1999, Page 319-360
The Object Data Standard ODMG 3.0
R.G.G. Cattell, Douglas Barry, Mark Berler, Jeff Eastman,
David Jordan, Craig Russell, Olaf Schadow, Torsten Stanieda
Fernando Velez
Verlag: Morgan Kaufmann Publishers
ISBN: 1-55860-647-5