Upload
hrotger-allaman
View
108
Download
1
Embed Size (px)
Citation preview
1
Teil ITeil IDatenmodelleDatenmodelle
Kapitel 6: Objektorientierte Anfragesprachen
2
Der ODMG-Standard für ODBMS ODMG = Object Database Management Group, gegründet
1991 als Arbeitskreis von ODBMS-Herstellern. Ziel: Entwicklung eines Standards für die objektorientierte
Datenhaltung (ODBMS, ORDBMS, ...). Stand: ODMG-Standard Version 3.0 (2000) definiert:
sprachneutrales Objektmodell, Object Definition Language (ODL), Object Interchange Format
(OIF) und Object Query Language (OQL), Sprachanbindungen des Objektmodells an C++, Java,
SmallTalk. Mehrheit der Produkte unterstützt ODMG, allerdings oft
ohne ODL, OIF, OQL.
3
Object Definition Language (ODL) Im Gegensatz zu SQL sind DML und DDL im ODMG-
Standard getrennt: Schema einer ODMG-Datenbasis wird in ODL spezifiziert. (Interaktive) Datenmanipulation erfolgt in OQL.
ODL ist reine Daten-Definitionssprache, Programmierung von Methoden muss in Wirtssprache Java, C++ oder SmallTalk erfolgen.
Praxisrelevanz von ODL begrenzt, da DB-Schema oft per Schemagenerator direkt aus Applikation gewonnen wird.
4
Kollektionstypen ODMG-Objektmodell definiert folgende Literal- bzw.
Klassenkonstruktoren für Kollektionen (t,v beliebige Typen): set<t>, Set<t>: Ungeordnete Menge ohne
Duplikate bag<t>, Bag<t>: Ungeordnete Menge mit
Duplikaten list<t>, List<t>: Geordnete Menge mit Duplikaten array<t>, Array<t>: Funktion von {1, 2, ..., n} nach t
Alle Kollektionstypen implementieren das Interface Collection mit (u.a.) folgenden Operationen:
insert_element() remove_element() is_empty() cardinality() contains_element() create_iterator()
5
Konsistenz: Schlüssel
class Vielflächner (extent alleVielflächner key vName ){ attribute string vName;
attribute float oberfläche;relationship set<Fläche> flächen
inverse Fläche::körper;void translation(in Punkt p) };
Bedeutung einer key-Spezifikation: ODBMS erzwingt, dass Vielflächner-Instanzen mit
verschiedenen Objekt-Identifikatoren auch verschiedene vname-Werte haben.
Objekt-Identifikator ist dennoch separat von vname-Wert (letzterer kann sich ändern, ersterer nicht).
6
Referenzielle Konsistenz
class Vielflächner (extent alleVielflächner key vName ){ attribute string vName;
attribute float oberfläche;relationship set<Fläche> flächen
inverse Fläche::körper;void translation(in Punkt p) };
class Fläche {relationship set<Vielflächner> körper
inverse Vielflächner::flächen; }
Nur zweistellige Beziehungen können spezifiziert werden. Unterschied zwischen Beziehungen und einfachen
objektwertigen Attributen: ODBMS sorgt bei Beziehungen für Wahrung der referenziellen Konsistenz.
7
Object Query Language (OQL) ODMG-Standard spezifiziert Object Query Language (OQL)
als deklarative Anfragesprache für ODMG-Objektmodell. Entwurfsprinzipien:
Weitgehende Kompatibilität mit SQL-92. Strenge Typisierung: Alle Ausdrücke haben statisch
bestimmbare Typen innerhalb des ODMG-Typsystems. Orthogonalität: Alle Ausdrücke können, soweit ihre Typen
verträglich sind, beliebig kombiniert werden; keine syntaktischen Ausnahmen und Sonderstellungen für spezielle Typen.
Wahrung der Objektkapselung: Objektänderungen nur durch Aufruf entsprechender Methoden.
In existierenden ODBMS allerdings noch nicht sehr verbreitet, daher im Folgenden nur kursorische Präsentation.
8
Beispielschema
class Punkt( extent allePunkte ) { attribute float x; attribute float y; attribute float z; void translation(in Punkt p);};
class Kante {( extent alleKanten ) { attribute Punkt p1; attribute Punkt p2; void translation(in Punkt p); float länge()};
class Fläche {( extent alleFlächen ) { attribute string fName; attribute set<Kante> kanten; relationship Vielflächner körper inverse Vielflächner::flächen; void translation(in Punkt p); float fläche()};
class Vielflächner( extent alleVielflächner key vName ) { attribute string vName; attribute float oberfläche; relationship set<Fläche> flächen inverse Fläche::körper; void translation(in Punkt p);};
class Quader extends Vielflächner( extent alleQuader ) { float volumen();};
9
Einfache OQL-Ausdrücke (1)Literale und Objekte können direkt konstruiert werden; gültige
Ausdrücke und ihre Typen sind z.B.: "Quader77":
string struct(x:1.0, y:2.0, z:0.0)
struct<x: float, y: float, z: float > Punkt(x:1.0, y:2.0, z:0.0)
Punkt Kante(Punkt(x:1.0, y:2.0, z:0.0), Punkt(x:1.0, y:2.0, z: 0.0))
Kante bag(1,1,2,3,3)
bag<unsigned short> set(1,2,3,4,5)
set<unsigned short>
10
Einfache OQL-Ausdrücke (2) Klassen mit Extensionen:
Extensionen für Klassen nur, wenn im Schema vereinbart allePunkte
set<Punkt>
liefert Menge der dauerhaften Instanzen der Klasse Punkt Klassen ohne Extension:
Dann sind alle Instanzen nur indirekt durch Referenzierung zugänglich
Beispiel: Wenn Punkt keine Extension hätte, wären Punkte nur noch z.B. über Kante erreichbar
11
Einfache OQL-Ausdrücke (3) Funktionen über Ausdrücken ergeben wieder Ausdrücke,
z.B. abs, not
t t t numerischer bzw. boolescher Typ +, -, *, /, mod
t t t t numerischer Typ Aggregatfunktionen über Ausdrücken sind auch möglich
count:collection<t> unsigned long t beliebig
min, max, sum, avg:collection<t> t t numerisch
Beachte: collection ist Obertyp von set, bag, list etc. und somit substituierbar
12
OQL-Pfadausdrücke Attribut- und Methodenzugriffe erfolgen mit "."-Operator:
p.xfloat p sei Verweis auf Punktobjekt
Pfadausdrücke können mehrere Stufen aufweisen:k.p1.xfloat k sei Verweis auf Kanteobjekt
Trifft gleichermaßen zu auf tieferes Eindringen in ein komplexes Objekt entlang struct oder auf Fortschreiten über mehrere Objekte entlang der Referenzen (dann automatisches Dereferenzieren).
Bei Methoden können Parameterlisten angegeben werden:
k.translation( Punkt(x:1.0, y:2.0, z:0.0) )void
13
OQL-Bedingungen Elementare Vergleiche (!=, =, <, >, like) und boolesche
Kombinationen wie in SQL. Etwas andere Form der Quantifizierung:
exists x in e : c
for all x in e : c
wobei e Ausdruck mit Kollektionstyp und c Bedingung, z.B. (f Verweis auf Flächenobjekt):exists k in f.kanten : k.p1.x = 0.0
Diverse Kurzformen existieren als Zugeständnis an SQL:x in e als Kurzform für exists y in e : x = y
x all e als Kurzform für for all y in e : x y
x any e als Kurzform für exists y in e : x y
14
Select-Ausdrücke Gegenüber SQL geringfügig andere Syntax:
select [distinct] e from [x1 in] e1, [x2 in] e2, ..., [xn in] en
[where c][order by f1, ..., fm]
e1...en Ausdrücke mit Kollektionstypen,e beliebiger Ausdruck,f1...fm Ausdrücke mit atomaren oder strukturierten Literaltypen,c Bedingung undx1...xn optionale Variablendeklarationen.
Typ eines select-Ausdrucks ist (mit t = Typ von e):list<t> wenn order by angegeben wurde,
set<t> wenn distinct, aber nicht order by angegeben wurde,
bag<t> wenn weder distinct noch order by angegeben wurde.
15
Semantik von Select-Ausdrücken (1) Semantik ist analog zu SQL. Auswertung eines Select-Ausdrucks (vereinfachte Version):
1. Werte Ausdrücke e1...en in from-Klausel aus und konvertiere Ergebnisse in Bags b1...bn.
2. Kartesisches Produkt: Bilde alle Tupel x1...xn mit xi bi.
3. Eliminiere Tupel, die Bedingung c aus where-Klausel nicht erfüllen.
4. Werte auf jedem verbleibenden Tupel Ausdruck e aus select-Klausel aus und füge Resultat in Ergebnis ein.
5. Falls distinct spezifiziert wurde, eliminiere Duplikate6. Falls order by spezifiziert wurde, sortiere Ergebnis nach
Werten der Ausdrücke f1...fm.
16
Semantik von Select-Ausdrücken (2) Gruppierung analog zu SQL:
select … from … where …
[group by y1 : g1, y2 : g2, ..., yn : gn]
[having c]
g1...gn Ausdrücke mit Kollektionstypen, c Bedingung und y1...yn nichtoptionale Bezeichner.
Angabe von group by wird jedoch nicht benötigt, da geschachtelte Ergebnisse direkt spezifiziert werden können
Beispiel: Typset<struct<vName: string, punkte: set<Punkt>>>beschreibt Punkte gruppiert nach Namen von Vielflächnern.
17
Semantik von Select-Ausdrücken (3) Erweiterte Syntax (Ausschnitt):
select e(x1, x2, …, xn , xn+1, …, xn+p)
from x1 in e1(xn+1, …, xn+p),x2 in e2(x1, xn+1, …, xn+p),x3 in e3(x1, x2, xn+1, …, xn+p),…,xn in en(x1, x2, …, xn-1, xn+1, …, xn+p)
Was bei Abhängigkeiten zwischen den xi? Auswertung eines select-Ausdrucks (erweiterte Version):
1. Werte Ausdrücke e1...en in from-Klausel aus und konvertiere Ergebnisse in Bags b1...bn.
2. Bilde alle Tupel x1...xn mit xi bi wobei die Abhängigkeiten zwischen den xi sich nun als Joins auswirken.
Existieren keine Abhängigkeiten, degeneriert dieser Schritt wieder zu einem einfachen kartesischen Produkt.
3.-6. bleiben gleich.
18
OQL-Anfragen (1) Alle Punkte, die auf der Null-Ebene liegen:
select struct (ex : x, ey : y) from allePunkte where z = 0
Rückgabetyp: bag<struct<ex:float, ey:float>> Alle Kanten, die zu Flächen mit mindestens vier Kanten
gehören:select struct (kp1 : k.p1, kp2 : k.p2)from f in alleFlächen, k in f.kanten where count (f.kanten) >= 4
Rückgabetyp: bag<struct<kp1:Punkt, kp2:Punkt>>
Impliziter Join!
19
OQL-Anfragen (2) Dieselbe Anfrage, aber gruppiert nach Flächen:
select struct (fläche: f.fName, punkte:(select struct (kp1 : p1,
kp2 : p2) from f.kanten))
from f in alleFlächenwhere count (f.kanten) >= 4
Rückgabetyp:
bag<struct<fläche:string, punkte:bag<struct<kp1:Punkt,kp2:Punkt>>>>
Beachte: Gruppierung ohne group by
20
OQL-Anfragen (3) Ergebnis kann Resultat von Operatoraufrufen enthalten
z.B.:select volumen()from alleQuader
Länge aller Kanten von großen Flächen:select k.längefrom f in alleFlächen, k in f.kanten where f.fläche > 100.0
Vielflächner mit großen Flächen:select vNamefrom alleVielflächnerwhere for all f in flächen : f.fläche() > 100.0
21
OQL-Anfragen (4) Aggregierung nach Gruppen, z.B. zuerst Gruppierung der
Quader nach Oberfläche, dann Berechnung des mittleren Volumens über alle Quader mit dieser Oberfläche, dies aber nur für Oberflächen über 20:
select struct (ofläche, dvolumen: avg( volumen() )from alleQuadergroup by ofläche : oberflächehaving oberfläche >= 20.0
Rückgabetyp:bag<struct<ofläche:float, dvolumen:float>>
22
OQL-Anfragen (5) Auch die Sortierungsklausel existiert in OQL, z.B.:
select from alleQuaderorder by oberfläche desc, volumen() asc
Es kann nach mehreren Attributen bzw. Methodenresultaten sortiert werden Aufsteigend: asc (Voreinstellung) Absteigend: desc
23
OQL-Anfragen (6) Gesamtzahl aller Kanten, die aus dem Nullpunkt
entspringen:count( select
from alleKantenwhere p1.x = 0.0and p1.y = 0.0 and p1.z = 0.0)
Ergebnistyp:unsigned long
Bemerkung: OQL erlaubt (als Tribut an SQL) auch Syntaxselect count ()from alleKanten where p1.x = 0.0 and p1.y = 0.0 and p1.z = 0.0)
24
OQL-Anfragen (7) Liste aller Flächen mit Umfang über 1000:
select ffrom f in alleFlächenwhere 1000 < sum( select k.länge
from k in f.kanten) Ergebnistyp:
bag<Fläche>
25
Vordefinierte Anfragen Anfragen können in OQL parametrisiert und vordefiniert
werden, z.B.:define oberflächeZuName(x) as
select oberfläche from alleVielflächner
where vName = x
oberflächeZuName(x) kann jetzt in anderen Anfragen wiederverwendet werden.
26
OQL-Anbindung an Java (1) Java als Beispiel für die Einbettung von OQL in eine
Programmiersprache Die OQL-Einbettung in Java ist teilweise mit dynamischem
SQL zu vergleichen OQL-Anfrage wird als Zeichenkette angegeben OQL kann von Java aus auf zwei Wegen angesprochen
werden: Mit einer Methode der Collection-Schnittstelle Über die generische OQLQuery-Klasse
27
OQL-Anbindung an Java (2) Ausschnitt aus der Collection-Schnittstelle:
interface Collection { Collection query(String predicate); ...}
Beispiel (alle Vielflächner, die Fünfecke enthalten):
Set körperMitfünfEck = (Set)meineVielflächner.query(
“exists f in flächen : count(f.kanten) = 5“);
Äquvalente OQL-Query:select from meineVielflächnerwhere exists f in flächen : count(f.kanten) = 5
Diese Form der Anfrage legt den select- und from-Teil der Anfrage bereits durch den Elementtyp der Kollektion fest
28
OQL-Anbindung an Java (3) Die Verwendung der query-Methode ist zwar sehr einfach,
doch hat sie einige Nachteile: Anfragen können nicht parametrisiert werden
Ausnahme: Anfragen über dynamisch zusammengebaute Zeichenketten
DBMS bekommt jedoch immer ihm unbekannte Zeichenketten, die immer neu zu analysieren und optimieren sind!
Anfragen können nicht wiederverwendet werden Auch hier gilt: Wiederverwendung über Zeichenketten ist nur die
halbe Lösung. Das DBMS bekommt davon nichts mit.
Beispiel: Alle Vielflächner, die Sechsecke enthalten ... Alle Vielflächner, die n-Ecke enthalten
29
OQL-Anbindung an Java (4) Diese Nachteile behebt die generische OQLQuery-
Schnittstelle:interface OQLQuery { public create(String query); public bind(Object parameter); public Object execute(); }
Ein OQLQuery-Objekt wird zunächst mittels einer Fabrikmethode des DBMS erzeugt.
create() erzeugt eine Anfrage wie bei der query-Methode, ohne sie jedoch auszuführen, Parameter haben die Syntax $1, $2, $3 etc.
bind() bindet aktuelle Parameter an die formalen, wobei die Reihenfolge eine Rolle spielt: beim ersten Aufruf wird das Parameterobjekt an $1 gebunden, usw.
execute() führt die Anfrage schließlich aus, und liefert eine passende Kollektion in Form eines Objektes zurück.
30
OQL-Anbindung an Java (5)
Beispiel für den Einsatz von OQLQuery: Liefere alle Vielflächner, die n Ecken enthalten und eine gewisse
Mindestoberfläche vorweisen können! // Java// statische (einmalige) InitialisierungOQLQuery query = dbms.newOQLQuery(); query.create(“ select * from alleVielflächner where exists f in flächen : count(kanten) = $1 and oberfläche >= $2“);...
// Methode mit Parameterübergabe und Ausführungpublic Set vielFlächnerMitNEcken(long n, float f) { Long anzahl = new Long(n); Float minOberfläche = new Float(f); query.bind(anzahl); query.bind(minOberfläche); return (Set)query.execute();
};