Automatische Generierung von Update-Masken aus Datenbanksichten Diplomarbeit von Arnim von Helmolt im Rahmen des Studiengangs Mathematik mit der Studienrichtung Informatik an der Universität Hannover Prüfer: Prof. Dr. Udo Lipeck Hannover, den 2. November 1999 ii iii Zusammenfassung Verschiedene Benutzer und Benutzergruppen eines Datenbanksystems erhalten gewöhnlich nur einen Ausschnit der in der Datenbank vorhandenen Informationen, sei es aus Sicherheitsgründen oder zur Ausblendung unwichtiger Daten. Sowohl Masken als auch Sichten haben die Aufgabe, einen bestimmten Ausschnitt der Datenbank an den Benutzer weiterzugeben. In dieser Arbeit wird untersucht, inwieweit durch Spezifikation einer SQL-Sicht eine Maske als Benutzerschnittstelle automatisch generiert werden kann und welche Operationen auf dieser möglich sind. Dazu werden allgemein Änderungsoperationen auf Sichten behandelt und ein eigener Ansatz erarbeitet, der es erlaubt, die Änderungen auf der Sicht eindeutig in Änderungen auf den zugrundeliegenden Relationen zu übersetzen. Davon ausgehend wird ein Konzept vorgestellt, wie ein Maskengenerator zur Spezifikation der Sicht und der Maske beschaffen sein muß, um änderbare Masken erzeugen zu können. iv Inhaltsverzeichnis 1 Einleitung 1 1.1 Gliederung der Arbeit . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.2 Zielsetzung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1.3 Verwendete Werkzeuge . . . . . . . . . . . . . . . . . . . . . . . . . . 3 2 Das View-Update-Problem 2.1 2.2 2.3 2.4 5 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 2.1.1 Grundlegende Definitionen und Notationen . . . . . . . . . . 5 2.1.2 Änderungen auf Relationen . . . . . . . . . . . . . . . . . . . 9 2.1.3 Übersetzungen von Änderungen auf Sichten . . . . . . . . . . 10 2.1.4 Beispiele problematischer Fälle . . . . . . . . . . . . . . . . . 11 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen . . . . . . 14 2.2.1 Grundlagen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14 2.2.2 Sicht-Graphen . . . . . . . . . . . . . . . . . . . . . . . . . . 17 2.2.3 Löschänderungen . . . . . . . . . . . . . . . . . . . . . . . . . 20 2.2.4 Einfügeänderungen . . . . . . . . . . . . . . . . . . . . . . . . 21 2.2.5 Ersetzungsänderungen . . . . . . . . . . . . . . . . . . . . . . 24 Übersicht über weitere Ansätze für die Übersetzung von View-Updates 25 2.3.1 Komplementäre Sichten . . . . . . . . . . . . . . . . . . . . . 25 2.3.2 Der Ansatz der Abstrakten Datentypen . . . . . . . . . . . . 27 2.3.3 Änderung unvollständiger Informationen . . . . . . . . . . . . 28 Bewertung und eigener Ansatz . . . . . . . . . . . . . . . . . . . . . 28 2.4.1 Löschänderungen . . . . . . . . . . . . . . . . . . . . . . . . . 31 2.4.2 Einfügeänderungen . . . . . . . . . . . . . . . . . . . . . . . . 31 vi INHALTSVERZEICHNIS 2.4.3 Ersetzungsänderungen . . . . . . . . . . . . . . . . . . . . . . 32 2.4.4 Eingeschränkte Übersetzungen . . . . . . . . . . . . . . . . . 33 3 Konzeption eines Maskengenerators 37 3.1 Ausgangsidee und Systemumfang . . . . . . . . . . . . . . . . . . . . 37 3.2 Spezifikation der Sicht . . . . . . . . . . . . . . . . . . . . . . . . . . 40 3.2.1 Schemastruktur und Aufbau der Sicht . . . . . . . . . . . . . 40 3.2.2 Modellierung des Spur- und des Abhängigkeits-Graphen . . . 42 Entwurf der Maske . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43 3.3.1 Aufbau einer Maske zu einer Sicht . . . . . . . . . . . . . . . 43 3.3.2 Spezifizierung der Maskenelemente und des Maskenlayouts . 45 3.3.3 Abbildung der Datentypen . . . . . . . . . . . . . . . . . . . 47 3.3.4 Generieren der Maske . . . . . . . . . . . . . . . . . . . . . . 49 Die Ausführung der Maske und die Anbindung an eine Datenbankinstanz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49 3.4.1 Die Datenbankschnittstelle . . . . . . . . . . . . . . . . . . . 49 3.4.2 Interaktion der Maske mit einer Datenbankinstanz . . . . . . 50 3.4.3 Zustände und Operationen einer Maske . . . . . . . . . . . . 51 Der Maskengenerator JForms . . . . . . . . . . . . . . . . . . . . . . 52 3.3 3.4 3.5 4 Die Implementierung eines Gerüsts“ für den Maskengenerator ” JForms 57 4.1 Die Darstellung des Datenbankschemas und des Sichtschemas . . . . 57 4.2 Pfadsuche im Abhängigkeits-Graphen . . . . . . . . . . . . . . . . . 59 4.3 Der Maskeneditor JForms . . . . . . . . . . . . . . . . . . . . . . . . 61 4.3.1 Auswahl und Einstellungen der Sichtelemente . . . . . . . . . 61 4.3.2 Speichern der Einstellungen in Property-Dateien . . . . . . . 63 Der Ablauf der generierten Maske . . . . . . . . . . . . . . . . . . . . 65 4.4 A Abkürzungen 67 B Programmierung 69 B.1 Ausgewählte Klassendiagramme . . . . . . . . . . . . . . . . . . . . . 69 B.2 Sourcecode zur Pfadsuche in Abhängigkeits-Graphen . . . . . . . . . 75 INHALTSVERZEICHNIS vii Abbildungsverzeichnis 78 Literaturverzeichnis 81 viii INHALTSVERZEICHNIS Kapitel 1 Einleitung 1.1 Gliederung der Arbeit In dieser Einleitung wird das Ziel der Arbeit vorgestellt und die verwendeten Werkzeuge kurz beschrieben. Kapitel 2 gibt einen Überblick über die Problematik von Änderungen auf Sichten. Nach einer Einführung grundlegender Notationen werden einige Beispiele erläutert. Anschließend wird der Lösungsansatz von [DB82] vorgestellt, der dieser Arbeit zugrundeliegt. In einer kurzen Übersicht wird auf drei weitere Ansätze hingewiesen, die aber nicht vertieft werden. Das Kapitel schließt mit einer Bewertung und mit einem eigenen Ansatz, der für das folgende Konzept verwendet wird. Die Konzeption in Kapitel 3 steckt den Rahmen der Implementierung eines Maskengenerators ab und zeigt die Struktur einer Realisierung. Es werden die erforderlichen Klassen mit einer Beschreibung ihrer Funktionen und ihren Verbindungen untereinander vorgestellt. In Kapitel 4 wird die Umsetzung einiger Klassen aus Kapitel 3 beschrieben, um exemplarisch die Implementierung des Konzepts vorzuführen. Dabei wurden allerdings nicht alle vorgestellten Klassen realisiert, sondern vielmehr ein Gerüst grundlegender Funktionen angelegt, welches das Konzept berücksichtigt und leicht erweitert werden kann. 1.2 Zielsetzung Der Benutzer einer Datenbankanwendung erhält den Zugriff auf Informationen aus der Datenbank (DB) häufig über Masken oder Tabellen. Während Tabellen gewöhnlich mehrere Tupel darstellen, zeigen Masken in der Regel nur ein Tupel. Zur Bearbeitung der Tupel stehen verschiedene Operationen zur Verfügung, die sich auf ein oder mehrere Tupel beziehen. Eine Maske ist die Darstellung eines Teils oder auch aller Attribute einer oder mehrerer Relationen auf dem Bildschirm in Form von Feldern, die einen Bezeichner (Attributname) und einen Wert (Attributwert) besitzen. 2 Einleitung Eine Sicht ist eine virtuelle Relation, der eine Anfrage zugrundeliegt und damit einen Ausschnitt der DB darstellt. Sowohl Masken als auch Sichten zeigen einen bestimmten Ausschnitt einer DB. Es ist nun naheliegend, Masken mit korrespondierenden Sichten zu verknüpfen, so daß jedes Attribut in der Maske ein korrespondierendes Attribut in der Sicht (Quelle) besitzt. Der Informationsgehalt einer Maske wird demnach durch eine Sicht definiert. Allgemein sind folgende Operationen auf Masken denkbar: • suchen (search), • eingeben (insert), • löschen (delete) und • ändern (modify). Abgesehen von der search Operation können diese zusammenfassend als update bezeichnet werden. Wird ein update auf einer Maske, bzw. auf der korrespondierenden Sicht ausgeführt, so muß dieses in updates auf den der Sicht zugrundeliegenden Basisrelationen übersetzt werden (View-Update-Problem). In der vorliegenden Arbeit werden Möglichkeiten untersucht, wie aus einer vorgegebenen Sicht eine korrespondierende Maske erzeugt werden kann, welche Probleme dabei zu erwarten sind und welche Bearbeitungs-Operationen auf dieser möglich sind. Dazu müssen die sichtdefinierenden Anfragen klassifiziert und unterschiedlichen Mengen von updates auf den Basisrelationen zugewiesen werden, falls updates überhaupt auf der Sicht möglich sind. Dabei ist insbesondere das Ziel zu berücksichtigen, eine große Menge von praktikablen Masken in typischen Anwendungen abzudecken. Das View-Update-Problem braucht hier nur für die praktisch relevanten Fälle betrachtet zu werden. Die dafür benötigten Sichten sollen im Anschluß an die Untersuchung bisheriger Ansätze für das View-Update-Problem vorgestellt werden. Insbesondere soll diese Arbeit keine neuen Lösungsmöglichkeiten des View-Update liefern, sondern vielmehr vom praktischen Blickwinkel beleuchten, wie eine große Klasse von Sichten als Grundlage für Update-Masken“ verwendet werden kann. ” Dadurch soll eine Lösung für einen allgemeinen Ansatz der Maskenimplementierung geliefert werden. Das Konzept beschreibt zwei Teile: das Entwurfswerkzeug zur Spezifizierung einer Maske mit der zugrundeliegenden Sicht und die Ausführungsumgebung der zuvor spezifizierten Maske. Im Implementierungsteil dieser Arbeit wird das zuvor erarbeitete Konzept in der Programmiersprache Java realisiert. Durch die JDBC-Schnittstelle von Java kann die Datenbankunabhängigkeit weitestgehend sichergestellt werden. Zu einer Sicht sollen Klassen für den sichtbaren Teil der Maske und Klassen, welche die Datenstruktur enthalten, in Java generiert werden. Diese generierten Klassen sollen Bestandteil einer in Ansätzen vorbereiteten Klassenstruktur mit den notwendigen BearbeitungsOperationen sein, welche die Ausführungsumgebung darstellt. 1.3 Verwendete Werkzeuge 1.3 Verwendete Werkzeuge Für die Implementierung wurde das Java Development Kit (JDK) 1.2 unter Solaris 2.7 verwendet, beides von Sun Microsystems. Weiterhin wurde die Blackdown Portierung des JDK 1.1.7v3 sowie das Swing 1.1.1 Paket der Java Foundation Classes und der Java Compiler Jikes 1.05 von IBM unter Linux Kernel Version 2.2.10 verwendet. Die Datenbankverbindungen erfolgten mittels der JDBC-Treiber von Oracle an eine Oracle Datenbank 8.0.4 und 8.0.5 sowohl unter Solaris als auch unter Linux. Diese Arbeit wurde mit LATEX 2ε gesetzt, die UML-Diagramme mit Rational Rose 98 für Solaris. 3 4 Einleitung Kapitel 2 Das View-Update-Problem Änderungen auf Sichten werden so realisiert, daß sie in entsprechende Änderungen auf den Relationen einer Datenbank übersetzt werden. Die dabei auftretenden Probleme werden in diesem Kapitel erläutert. Zunächst werden benötigte Notationen eingeführt und die Problematik anhand einiger Beispiele illustriert. In dem folgenden zentralen Abschnitt wird ein Lösungsansatz vorgestellt, der Ausgangspunkt für diese Arbeit ist. Anschließend wird ein kurzer Überblick über weitere Ansätze gegeben und das Kapitel mit einer Bewertung und einer eigenen Lösung abgeschlossen. 2.1 Einführung In den folgenden Abschnitten werden die benötigten Definitionen eingeführt und Begriffe erläutert, auf die später zurückgegriffen wird. 2.1.1 Grundlegende Definitionen und Notationen Definition 2.1 Eine Domäne oder ein Wertebereich ist eine beliebige Menge von Elementen eines bestimmten Datentyps. Ein Wertebereich kann auch Nullwerte enthalten, welche die Bedeutung haben, daß der Wert unbekannt, also nicht spezifiziert ist. Definition 2.2 Eine Relation R ist eine endliche Teilmenge des kartesischen Produkts R ⊆ D1 × . . . × Dn wobei D1 , . . . , Dn beliebige Wertebereiche sind. Definition 2.3 Ein Tupel t ist ein Element einer Relation R, in Zeichen t ∈ R. Wir sagen auch, daß eine Relation R eine endliche Menge von Tupeln ist. 6 Das View-Update-Problem Definition 2.4 Ein Attribut Ai ist eine Projektionsfunktion Ai : R −→ Di , i = 1, . . . , n auf die i-te Komponente eines Tupels t ∈ R. Der Wertebereich Di von Ai wird auch als dom(Ai ) bezeichnet. Wir schreiben auch t.A für die Projektion des Tupels t ∈ R auf das Attribut A, bzw. t.X für die Projektion von t auf die Attribute in X = {A1 , . . . , An }. Mit R[X] bezeichnen wir die Menge der Tupel t.X, also R[X] := {t.X | t ∈ R}. Definition 2.5 Ein Relationenschema R ist die Menge der Attribute A1 , . . . , An zu einer Relation R. Wir schreiben für ein Relationenschema R mit den Attributen A1 , . . . , An auch R[A1 : D1 , . . . , An : Dn ] und abkürzend auch R[A1 , . . . , An ] oder R[X] mit X = {A1 , . . . , An }. Mit dom(R) sei das kartesische Produkt dom(A1 ) × . . . × dom(An ) bezeichnet. Eine Relation R wird auch als Instanz oder Zustand eines Relationenschemas R bezeichnet. Für die Menge der Zustände von R schreiben wir auch inst(R). Definition 2.6 Eine Integritätsbedingung cR zu einer Relation R ist eine logische Funktion cR : R −→ {true, f alse} die jedem Tupel t ∈ R einen Wahrheitswert zuordnet. Definition 2.7 Eine Relation R heißt konsistent bezüglich einer Menge von Integritätsbedingungen CR , falls für alle Tupel t ∈ R und alle Integritätsbedingungen c ∈ CR c(t) = true gilt. Wir sagen auch, daß die Relation R die Integritätsbedingungen CR erfüllt oder R konsistenter Zustand ist. Definition 2.8 Ein relationales Schema oder Datenbankschema S ist eine endliche Menge von Relationenschemata {R1 , . . . , Rn }. Definition 2.9 Ein Datenbankzustand S oder einfach Zustand eines Datenbankschemas S ist eine Funktion s, die jedes Relationenschema R ∈ S auf eine Relation R ∈ inst(R) abbildet, S −→ inst(R) s: R 7−→ R Die Menge der Zustände wird mit inst(S) bezeichnet. Definition 2.10 Ein Datenbankzustand S heißt konsistent bezüglich einer Menge von Integritätsbedingungen CS , falls die Relationen R ∈ S konsistent bezüglich CS sind. 2.1 Einführung 7 Definition 2.11 Seien X, Y ⊆ R Attributmengen von R und R ein Zustand von R. Dann ist Y funktional abhängig von X in R, in Zeichen X →R Y , wenn ∀s, t ∈ R s.X = t.X ⇒ s.Y = t.Y gilt. Wir sagen auch, die Relation R erfüllt die funktionale Abhängigkeit X →R Y . Falls X →R R gilt, wird X auch Superschlüssel genannt. Definition 2.12 Seien X, Y ⊆ R Attribute von R. Dann ist Y voll funktional • abhängig von X in R, in Zeichen X →R Y , wenn 1. X →R Y und 2. ∀A ∈ X X \ {A} 9R Y • gelten. Falls X →R R gilt, wird X auch Schlüsselkandidat genannt. X ist in dem Sinne minimal, daß kein Attribut entfernt werden kann, ohne die funktionale Abhängigkeit zu zerstören. Definition 2.13 Seien Q und R zwei nicht notwendigerweise verschiedene Relationenschemata mit den Attributmengen X = {X1 , . . . , Xk } ⊆ Q und Y = {Y1 , . . . , Yk } ⊆ R. Dann erfüllen die zugehörigen Instanzen Q und R die Inklusionsabhängigkeit X ⊆ Y , wenn ∀q ∈ Q ∃r ∈ R q.X = r.Y gilt. Wir schreiben auch Q[X] ⊆ R[Y ] für die Inklusionsabhängigkeit. Mit den obigen Notationen haben wir die wichtigsten Begriffe zur Beschreibung von Meta-Daten (Datenbank- und Relationenschemata) und den eigentlichen Daten (Datenbankinstanz und Relation) eingeführt. Im folgenden kommen wir zu dem in dieser Arbeit zentralen Begriff der Sicht. Definition 2.14 Eine Sicht oder ein externes Schema V eines Datenbankschemas S ist ein Paar (SV , f ), mit dem Datenbankschema SV und einer Funktion f , die jeden Zustand S ∈ inst(S) auf einen Zustand S 0 ∈ inst(SV ) abbildet: inst(S) −→ inst(SV ) f: S 7−→ S 0 f wird die V definierende Funktion genannt und abkürzend wird die Sicht V auch mit f bezeichnet, wenn die Bedeutung von S und SV bekannt ist. Sichten werden durch Formulierung von Anfragen auf dem zugrundeliegenden Datenbankschema mit Hilfe der Relationen-Algebra (siehe auch [KE96]) beschrieben. Sichten können anhand der verwendeten relationalen Operationen eingeteilt werden in 8 Das View-Update-Problem • Projektionssichten, • Selektionssichten, • Verbundsichten, • berechnete“ Sichten, ” • Sichten auf geschachtelten Relationen, sowie Mischformen von diesen. Definition 2.15 Eine Sicht V heißt triviale Sicht, falls S = SV und f die Identität ist. Definition 2.16 Der Zustand V einer Sicht V ist die Bezeichnung für den Zustand von SV . Für Abschnitt 2.2 wird eine Notation benötigt, in der die Bestandteile“ einer Sicht ” genauer bezeichnet werden. Dafür wird die SQL-Notation zur Definition einer Sicht benutzt, mit der damit verbundenen Einschränkung auf nur eine Sichtrelation, d. h. SV besteht nur aus einer Relation. Entsprechend wird die Schreibweise V[Y ] für eine Sicht verwendet, wobei Y eine Menge von Attributen ist. Eine Sicht V wird durch das vereinfachte SQL-Statement create view V as select <Attribute> from <Relationen> where <Qualifikation> definiert, wobei • <Attribute> := Liste von Attributen, • <Relationen> := Liste von Relationen, • <Qualifikation> := Kombination boolescher Ausdrücke der Form <Term><Op><Term>, • <Term> := Konstante oder Attribut, • <Op> := <, ≤, >, ≥, =, 6= ist. In der folgenden Betrachtung wird von dieser vereinfachten SQL-Syntax ausgegangen, eine Erweiterung auf den vollen Sprachumfang ist jedoch durchaus möglich. Die select-Klausel entspricht in der Relationen-Algebra der Projektion auf die Attribute, die from-Klausel entspricht dem kartesischen Produkt der aufgelisteten Relationen und die where-Klausel der Bedingung in der Selektion. Wir definieren zu einer Sicht V eines Datenbankschemas S die Mengen der Relationenschemata TRels(V) = {R ∈ S | ∃a Attribut in <Attribute> und a ∈ R} und QRels(V) = {R ∈ S | ∃a Attribut in <Qualifikation> und a ∈ R} 2.1 Einführung 9 mit den zugehörigen Attributmengen TAttrs(V) = {A | A Attribut in <Attribute>} und QAttrs(V) = {A | A Attribut in <Qualifikation>} und sagen, V ist über den Relationenschemata Rels(V) = TRels(V) ∪ QRels(V) bzw. <Relationen> definiert. Definition 2.17 I(V) = {i | Ri ist Relation aus <Relationen>} bezeichne eine Indexmenge mit der Mächtigkeit p = |I(V)|, V eine Sicht über S = {Ri [Xi ] | i ∈ I(V)} mit den Attributen Y = {Y1 , . . . , Ym } und dem Zustand V . Sei v ∈ V und ti ∈ Ri , i ∈ I(V). Dann ist (ti1 , . . . , tip ) ein Generator von v, wenn QualV (ti1 , . . . , tip ) = true und TargV (ti1 , . . . , tip ) = v. Dabei ist QualV : dom(X1 ) × . . . × dom(Xp ) −→ {true, f alse} wobei QualV (ti1 , . . . , tip ) = true falls ti1 , . . . , tip der <Qualifikation> genügen und TargV : dom(X1 ) × . . . × dom(Xp ) −→ dom(Y1 ) × . . . × dom(Ym ) wobei TargV (ti1 , . . . , tip ) das Sichttupel nach Berechnung der <Attribute> mit ti1 , . . . , tip ist. 2.1.2 Änderungen auf Relationen Definition 2.18 Eine Änderung auf einer Relation R ist eine Funktion u, die jeder Relation R ∈ inst(R) eine Relation R0 ∈ inst(R) zuordnet: u: inst(R) −→ inst(R) R 7−→ R0 UR ist die Menge der Änderungen auf R. Folgende Typen von Änderungsoperationen auf einzelnen Tupeln werden betrachtet: • Einfügen eines Tupels t in R, u(R) ≡ insR (t) = R ∪ {t}. • Löschen eines Tupels t ∈ R, u(R) ≡ delR (t) = R \ {t}. • Ersetzen eines Tupels t ∈ R durch t0 , u(R) ≡ replR (t → t0 ) = (R \ {t}) ∪ {t0 }. Folgende Mengen von Änderungsoperationen auf Tupelmengen werden betrachtet: • Einfügen der Tupel T in R, u(R) ≡ insR (T ) = R ∪ T . • Löschen der Tupel T ⊆ R, u(R) ≡ delR (T ) = R \ T . • Ersetzen der Tupel T ⊆ R durch T 0 , u(R) ≡ replR (T → T 0 ) = (R \ T ) ∪ T 0 . 10 Das View-Update-Problem Definition 2.19 Eine Änderung auf einer Datenbankinstanz S ist eine Sequenz von Änderungen û = u1 . . . un von der Menge der Zustände inst(S) in sich selbst: inst(S) −→ inst(S) û : S 7−→ S 0 mit ui ∈ URi , i = 1, . . . , n, ui Änderung auf einer Relation Ri ∈ RS , wobei ui die anderen Relation unverändert läßt. Mit US wird die Menge der Änderungen auf S bezeichnet. Definition 2.20 Eine Änderung u heißt konsistent, wenn für jeden konsistenten Zustand S der Zustand u(S) konsistent ist. Definition 2.21 Sei V = (SV , f ) eine Sicht. Dann wird mit der Änderung u auf V die Änderung auf SV bezeichnet. Wir werden im weiteren Verlauf nur konsistente Änderungen betrachten. 2.1.3 Übersetzungen von Änderungen auf Sichten Änderungen auf den Datenbankinstanzen sind eindeutig auf der Sicht, da diese funktional auf den Datenbankinstanzen definiert ist. Wird eine Änderungsoperation auf eine Sicht angewendet, so muß diese in Änderungsoperationen auf den die Sicht definierenden Basisrelationen übersetzt werden. Dabei taucht das Problem auf, daß die Sichtfunktion im allgemeinen nicht bijektiv ist. Bei einer Änderung auf der Sicht muß also ein zugehöriger Datenbankzustand gefunden werden, der der Sicht entspricht. Falls die Sichtfunktion nicht injektiv ist, gibt es unter Umständen mehrere zugehörige Datenbankzustände, die der geänderten Sicht entsprechen (Mehrdeutigkeit), falls sie nicht surjektiv ist, gibt es zu einer Änderung vielleicht keine entsprechende Übersetzung. Es wird also eine Änderung û auf einer Datenbankinstanz gesucht, die eine vorgegebene Änderung u auf einer Sichtinstanz übersetzt. Wir wollen dabei zwischen einfachen Übersetzungen und exakten Übersetzungen unterscheiden. Definition 2.22 Eine Änderung û auf einer Datenbankinstanz S führt eine Änderung u auf einer Sichtinstanz V zur Sicht V = (SV , f ) aus, falls • u(V ) ≡ insV (t) und t ∈ f (û(S)) oder • u(V ) ≡ delV (t) und t 6∈ f (û(S)) oder • u(V ) ≡ replV (t → t0 ) und f (û(S)) ∩ ({t} − {t0 }) = ∅ und t0 ∈ f (û(S)), wobei t, t0 Tupel sind. Eine Änderung auf einer Datenbankinstanz entspricht dann der Einfügung des Tupels in die Sicht, wenn dieses Tupel in der durch f aus der geänderten Datenbankinstanz berechneten Sicht enthalten ist. Ebenso entspricht die Änderung an einer Datenbankinstanz dem Löschen eines Tupels in der Sicht, wenn dieses Tupel in der durch f aus der geänderten Datenbankinstanz berechneten Sicht nicht enthalten ist. Eine Ersetzung liegt dann vor, wenn das zu ersetzende Tupel nicht mehr in der Sicht vorkommt, stattdessen aber das geänderte Tupel. 2.1 Einführung 11 Definition 2.23 Eine Änderung û bezüglich eines Datenbankschemas S führt exakt eine Änderung u bezüglich einer Sicht V = (SV , f ) aus, falls VO f u _ _ S /V0 O û f / S0 für jeden Zustand S kommutiert. Dies ist der Fall, wenn f (û(S)) = u(V ) und V = f (S) für alle S. Definition 2.24 Eine Änderung û ist eine Übersetzung der Änderung u :⇐⇒ û führt u aus und û ist konsistent. Definition 2.25 Eine Änderung û ist eine exakte Übersetzung der Änderung u :⇐⇒ û führt exakt u aus und û ist konsistent. Bei einer exakten Übersetzung werden Seiteneffekte weitestgehend verhindert. Nicht ausgeschlossen werden können z. B. Seiteneffekte auf andere Sichten, da nur der Kontext der betrachteten Sicht bekannt ist.1 Seiteneffekte, die durch die exakte Übersetzung ausgeschlossen werden, können aber in bestimmten Fällen wünschenswert sein. Weitere Klassifizierungen von Änderungsübersetzungen werden hier nicht betrachtet, können aber durchaus auch interessant sein, z. B. eindeutige Übersetzungen, die nicht exakt sind. 2.1.4 Beispiele problematischer Fälle Folgende Beispiele stammen zum großen Teil aus [FC85]. Gegeben sind die Relationenschemata 1. E[EMP,DEP], 2. M[DEP,MGR], 3. S[EMP,SAL,AGE] und 4. E 0 [EMP,DEP] mit den Zuständen E, M, S und E 0 . Als Integritätsbedingungen sollen die funktionalen Abhängigkeiten EMP →E DEP, DEP →M MGR und EMP →S {SAL,AGE} sowie die Inklusionsabhängigkeit E[DEP] ⊆ M [DEP] gelten. Die betrachteten Sichtenzustände werden wie folgt berechnet: 1. V1 = σDEP=’Sales’ (E) 2. V2 = σDEP=’Sales’ (M ) 3. V3 = πEMP (E) 1 siehe auch Beispiel 6 aus Abschnitt 2.1.4 12 Das View-Update-Problem 4. V4 = πDEP (E) 5. V5 = E ∗ M 6. V6 = E nach DEP gruppiert und beschränkt auf count(EMP) > 2 7. V7 = E ∪ E 0 8. V8 = πEMP,MGR (E ∗ M ) 9. V9 = πEMP,DEP,SAL (E ∗ S) 10. V10 = πEMP,DEP (σM.MGR=’Alex’ (E ∗ M )) Der Datenbankzustand sei: E EMP John Peter Alice DEP Sales Finance Sales E0 EMP Joan DEP Toys M DEP Sales Finance MGR Mary Jane S EMP John Peter Alice SAL 100K 130K 100K AGE 35 32 37 mit den resultierenden Sichten V1 EMP John Alice V4 V7 V10 V2 DEP Sales MGR Mary DEP Sales Finance V5 EMP John Peter Alice DEP Sales Finance Sales EMP John Peter Alice Joan V8 EMP John Peter Alice MGR Mary Jane Mary EMP DEP Sales Sales DEP Sales Finance Sales Toys MGR Mary Jane Mary V3 EMP John Peter Alice V6 EMP DEP V9 EMP John Peter Alice DEP Sales Finance Sales DEP 1. Verletzung einer Integritätsbedingung: • insV1 ((Peter,Sales)) Die Übersetzung insE ((Peter,Sales)) verstößt gegen die funktionale Abhängigkeit EMP →E DEP, da E schon (Peter,Finance) enthält. • delV2 ((Sales,Mary)) Die Übersetzung delM ((Sales,Mary)) verstößt gegen die Inklusionsabhängigkeit EMP →E DEP, da E noch (John,Sales) enthält. Eine andere SAL 100K 130K 100K 2.1 Einführung Übersetzung wäre die Änderungssequenz delE ((x,Sales)) und delM ((Sales,Mary)), so daß die Inklusionsabhängigkeit gewahrt bleibt, wobei x Platzhalter für alle Namen ist. Diese Fälle besitzen keine exakte Übersetzung. 2. Es wird ein Ergebnis erzeugt, welches nicht konform mit der Sichtdefinition ist: • insV1 ((Mark,Finance)) Da V1 nur Tupel mit DEP=’Sales’ enthält, würde die Übersetzung insE ((Mark,Finance)) nicht sichtbar in V1 werden. In diesem Fall wird zwar eine Änderung auf der zugrundeliegenden Relation ausgeführt, jedoch führt dies zu keinem Effekt in der Sicht. Bei Beschränkung auf konsistente Änderungen wird dieser Fall ausgeschlossen. 3. Es wird ein anderes Ergebnis erzeugt, als mit der Operation beabsichtigt: • replV1 ((John,Sales) → (John,Finance)) Die Übersetzung replE ((John,Sales) → (John,Finance)) hat ein Löschen“ ” des Tupels aus der Sicht V1 zur Folge. 4. Nullwerte müssen eingefügt werden: • insV3 ((Roger)) Eine sinnvolle Übersetzung könnte insE ((Roger, NULL)) sein, aber es wäre auch eine beliebige Abteilung anstelle eines Nullwertes möglich. Durch Integritätsbedingungen wie das Verbieten von Nullwerten oder Fremdschlüsselbeziehungen können diese Effekte vermieden werden, falls gewünscht. 5. Attribute außerhalb der Sicht werden verändert: • delV4 ((Sales)) Bei der Übersetzung mit delE ((x,Sales)), wobei x Platzhalter für alle Namen ist, würden alle Angestellten der Abteilung ’Sales’ gelöscht werden. Hier sind Effekte außerhalb der Sicht die Folge. 6. Es werden mehrere Tupel auf den zugrundeliegenden Relationen verändert: • replV4 ((Sales) → (Marketing)) Die Ausführung der Übersetzung replE ((x,Sales) → (x,Marketing)), x Platzhalter für alle Namen, hat den Effekt, daß alle Mitarbeiter der Abteilung ’Sales’ in die Abteilung ’Marketing’ wechseln. In diesem Fall wird auch die Sicht V1 beeinflußt. 7. Mehrere in der Sicht befindliche Tupel werden geändert: • replV5 ((John,Sales,Mary) → (John,Sales,Jane)) Die Ersetzung replM ((Sales,Mary) → (Sales,Jane)) hat in der Sicht V5 den Effekt, daß alle Mitarbeiter der Abteilung ’Sales’ eine neue Managerin haben. 8. Eine Menge von Tupeln oder kein Tupel werden geändert: 13 14 Das View-Update-Problem • insV6 ((Roger,Sales)) Die Übersetzung insE ((Roger,Sales)) bewirkt in der Sicht V6 , daß in der vorher leeren Sicht drei Tupel auftauchen. • insV6 ((Roger,Finance)) Hier würde die Übersetzung insE ((Roger,Finance)) keine Auswirkung auf die Sicht V6 haben. 9. Es gibt mehrere Übersetzungen: • insV7 ((Roger,Sales)) Das Einfügen des Tupels in E oder2 in E 0 sind gleichwertige Übersetzungen. • replV8 ((John,Mary) → (John,Jane)) Die Übersetzungen replE ((John,Sales) → (John,Finance)) oder replM ((Sales,Mary) → (Sales,Jane)) haben den gleichen Effekt auf der Sicht V8 . Durch Formulierung der funktionalen Abhängigkeit MGR →M DEP kann diese Mehrdeutigkeit vermieden werden. • delV9 (x,Sales,y) Den gleichen Effekt haben auch die beiden Löschoperationen delE (x,Sales) und {delS (John,y,z), delS (Alice,y,z)}. 2.2 Übersetzungen mit Hilfe von Sicht-AbhängigkeitsGraphen In [DB78] und [DB82] wird ein Ansatz verfolgt, der untersucht, wie durch Kenntnis der Abhängigkeiten des der Sicht zugrundeliegenden Datenbankschemas bestimmte mehrdeutige Übersetzungen vermieden werden können. Dabei braucht nur das Datenbankschema betrachtet werden und die Art Änderung auf der Sicht, sowie die dabei abhängigen“, in der Änderung spezifizierten Attribute. Eine grundsätzliche ” Charakterisierung der änderbaren Sichten erfolgt nicht, da die Einschränkungen zu groß wären. Je nachdem, welche Attribute der Sicht, abhängig vom Änderungstyp, geändert werden, ist eine Übersetzung möglich oder nicht. Die Beweise zu den hier getroffenen Aussagen sind in [DB82] nachzulesen. 2.2.1 Grundlagen Zur Charakterisierung der einem Sichttupel zugrundeliegenden Datenbanktupel werden die Begriffe Quelle und exakte Quelle eingeführt, mit deren Hilfe spezifiziert werden kann, welche Änderungen an welchen Attributen (exakt) übersetzbar sind. Im folgenden sei S = {R1 , . . . , Rn } eine Datenbankinstanz und V = f (R1 , . . . , Rn ) die zugehörige Instanz einer Sicht V. Definition 2.26 Sei v ∈ V und i ∈ I(V). Dann ist ti ∈ Ri , ein Quelltupel von v genau dann, wenn ti Komponente eines Generators von v ist. 2 Kein ausschließendes oder ! 2.2 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen Definition 2.27 Sei V 0 ⊆ V beliebig. Sei G die Menge der Generatoren von V 0 . Für jeden Generator g = (ti1 , . . . , tip ) ∈ G sei A(g) Seine nichtleere Teilmenge von {(ti ; Ri ) | i ∈ I(V)}. Dann ist jede Obermenge von A(g) eine Quelle von V 0 in g∈G S. Falls G = ∅, hat V 0 keine Quelle. Betrachte die Sicht V5 in Abschnitt 2.1.4, dann ist für V 0 = {(John,Sales,Mary), (Peter,Finance,Jane)} die Menge der Generatoren G = {((John,Sales), (Sales,Mary)), ((Peter,Finance), (Finance,Jane))} . Seien nun z. B. A(g1 ) = {((John,Sales);E)} und A(g2 ) = {((Finance,Jane);M)}, dann ist A(g1 ) ∪ A(g2 ) = {((John,Sales);E),((Finance,Jane);M)} eine Quelle von V 0 . Das bedeutet also, daß aus einer Quelle nicht notwendigerweise das Sichttupel berechnet werden kann. Eine Quelle soll vielmehr anzeigen, daß Teile des zugehörigen Tupels in der Sicht auftauchen. Definition 2.28 Sei V 0 ⊆ V beliebig und Q eine Quelle von V 0 , dann sei Qi = {t ∈ Ri | (t; Ri ) ∈ Q} der Teil der Quelle, der von der Relation Ri kommt. Definition 2.29 Sei V 0 ⊆ V beliebig und Q eine Quelle von V 0 in S. Dann ist Q eine exakte Quelle von V 0 , wenn für alle v ∈ V \ V 0 ein Q0 existiert, welches Quelle von {v} in {R1 \ Q1 , . . . , Rn \ Qn } ist. Äquivalent zu dieser Definition ist, daß Q eine exakte Quelle von V 0 in S ist, wenn für alle v ∈ V \ V 0 Q keine Quelle von {v} in S ist. So ist z. B. ((John,Sales);E) exakte Quelle von (John,Sales,Mary) in Sicht V5 , während ((Sales,Mary);M) zwar eine Quelle, aber nicht exakt ist, da für (Alice,Sales,Mary) keine Quelle in M \ {(Sales,Mary)} existiert, bzw. (Sales,Mary) auch Quelle von (Alice,Sales,Mary) ist. Definition 2.30 Sei V 0 ⊆ V beliebig und U eine Änderung auf einem Datenbankschema S mit dem Zustand S = {R1 , . . . , Rn } und U (S) = {R10 , . . . , Rn0 }. Sei S n Ti = Ri \ Ri0 und T = i=1 {(t; Ri ) | t ∈ Ti }, wobei i = 1, . . . , n. 1. U löscht eine (exakte) Quelle gdw. T eine (exakte) Quelle von V 0 in S ist. 2. U fügt ein Quelltupel von v ∈ dom(V) ein gdw. ein i existiert, so daß t ∈ Ri0 \Ri ein Quelltupel von v in U (S) ist. Lemma 2.1 Sei V 0 ⊆ V und f die V definierende Funktion. Dann gilt: 1. Q ist eine Quelle von V 0 in S ⇔ f (R1 \ Q1 , . . . , Rn \ Qn ) ⊆ V \ V 0 2. Q ist eine exakte Quelle von V 0 in S ⇔ f (R1 \ Q1 , . . . , Rn \ Qn ) = V \ V 0 15 16 Das View-Update-Problem Das Lemma macht deutlich, daß aus der Quelle einer Teilsicht ein Quelltupel nicht notwendigerweise berechnet werden kann, daß aber bei Entfernen einer Quelle die Sicht mindestens um die Quelle verringert wird. Bei einer exakten Quelle wird die Sicht genau um die Teilsicht verringert. Lemma 2.2 Sei U eine Änderung auf S und v ∈ V . (Dann löscht U eine Quelle von {v} und U fügt kein Quelltupel von v ein) ⇔ v 6∈ f (U (S)). Lemma 2.3 Sei U wie oben. Sei v ∈ dom(Y ) \ V , Y Menge der Attribute von V. Dann fügt U ein Quelltupel von v ein ⇔ v ∈ f (U (S)). Die beiden Lemmata zeigen die Auswirkungen von Lösch- und Einfügeänderung von Quellen auf die Sicht. Für jeden Typ von Änderungsoperationen stellen die folgenden Theoreme den Zusammenhang zwischen Änderungen auf Sichten und Änderungen auf zugehörigen Quellen dar. Für die Untersuchung, in welchen Fällen (exakte) Übersetzungen von Sichtänderungen vorhanden sind, bilden die Theoreme die Grundlage. Theorem 2.1 Sei u die Löschänderung einer Menge von Sichttupeln V u ⊆ V . Dann ist 1. U eine Übersetzung von u in S ⇔ U löscht eine Quelle von V u , 2. U eine exakte Übersetzung von u in S ⇔ U löscht eine exakte Quelle von V u . Theorem 2.2 Sei u die Einfügeänderung einer Menge von Sichttupeln V u in V . Seien V i = V u \ V und V 0 = V \ V u . Dann ist 1. U eine Übersetzung von u in S ⇔ für alle v ∈ V i fügt U ein Quelltupel ein und 2. U eine exakte Übersetzung von u in S ⇔ (a) für alle v ∈ V i fügt U ein Quelltupel ein und (b) für alle v ∈ dom(V) \ (V 0 ∪ V i ) fügt U kein Quelltupel von v ein. Theorem 2.3 Sei u die Ersetzungsänderung einer Menge von Tupeln V u ⊆ V durch V r . Sei V 0 = V u \ V r . Dann ist 1. U eine Übersetzung von u in S ⇔ (a) für alle v ∈ V 0 löscht U eine Quelle von {v} und fügt kein Quelltupel von v ein und (b) für alle v ∈ V r \ V u fügt U ein Quelltupel von v ein und (c) für alle v ∈ V r ∩ V u löscht U keine Quelle von {v} oder U fügt ein Quelltupel von v ein. 2. U eine exakte Übersetzung von u in S ⇔ (a) für alle v ∈ V 0 löscht U eine Quelle von {v} und fügt kein Quelltupel von v ein und 2.2 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen (b) für alle v ∈ V r \ V u fügt U ein Quelltupel von v ein und (c) für alle v ∈ V \ V 0 löscht U keine Quelle von {v} oder fügt ein Quelltupel von v ein und (d) für alle v ∈ dom(V) \ (V ∪ U r ) fügt U kein Quelltupel von v ein. 2.2.2 Sicht-Graphen Neben den oben beschriebenen semantischen Bedingungen, d. h. den Bedingungen an die Datenbankzustände für die Übersetzung von Änderungsoperationen, werden im folgenden syntaktische Bedingungen angegeben. Diese werden anhand von zwei Graphen formuliert, genauer: zu einer Sicht V wird ein Sicht-Spur-Graph T (V) und ein Sicht-Abhängigkeits-Graph D(V) konstruiert.3 Definition 2.31 Ein Spur-Graph T (V) ist ein gerichteter Graph, der folgendermaßen aufgebaut wird: 1. Für alle i ∈ I(V) und alle A ∈ Ri füge einen ,-Knoten mit der Bezeichnung ’Ri .A’ ein. 2. Für alle A ∈ TAttrs(V) füge einen 4-Knoten mit der Bezeichnung ’V.A’ ein. 3. Für jede Konstante c aus <Qualifikation> füge einen 4-Knoten mit der Bezeichnung ’c’ ein. 4. Für jedes Attribut A ∈ TAttrs(V) füge die Kanten (V.A, Ri .A) und (Ri .A, V.A) ein, wobei Ri .A der Wert aus der Relation Ri ist, aus dem V.A berechnet wird. 5. Für jeden Ausdruck ti .A = tj .B in der <Qualifikation> von V füge die Kanten (Rj .B, Ri .A) und (Ri .A, Rj .B) ein. 6. Für jeden Ausdruck ti .A = c in der <Qualifikation> von V füge die Kanten (c, Ri .A) und (Ri .A, c) ein. E.EMP E.DEP V.EMP V.DEP M.DEP M.MGR V.MGR Abbildung 2.1: Der Spur-Graph für die Sicht V5 aus Abschnitt 2.1.4 Die Kanten stellen eine Verbindung zwischen den Attributen eines Sichttupels und den Attributen einer zugehörigen Quelle dar. Im folgenden wird dies noch genauer dargestellt. 3 Diese werden in [DB82] als view-trace-graph und view-dependency-graph bezeichnet. 17 18 Das View-Update-Problem Definition 2.32 Wenn in T (V) ein Pfad von einem 4-Knoten V.A zu einem ,Knoten Ri .A existiert, dann ist V.A eine V -Spur von Ri .A. Falls eine Kante zwischen V.A und Ri .A existiert, dann ist V.A eine direkte V -Spur von Ri .A. Das wesentliche Merkmal von Spuren ist, daß, wenn V.A eine V -Spur von Ri .A und ti ∈ Ri ein Quelltupel von v ∈ V in S ist, dann ist ti .A = v.A. Um also ein Sichttupel v mit v.A = a einzufügen, muß ein Tupel ti mit ti .A = a in Ri eingefügt werden. Falls V.A ein konstanter Knoten ’c’ ist, dann ist v.A = c für alle v ∈ V . Der Abhängigkeits-Graph D(V ) wird so aufgebaut, daß die Informationen der funktionalen Abhängigkeiten der Integritätsbedingungen CS eines Datenbankschemas in T (V) eingefügt werden. Definition 2.33 Ein Abhängigkeits-Graph D(V ) ist ein Spur-Graph T (V), in welchem Kanten wie folgt eingefügt werden: 1. Für jede funktionale Abhängigkeit {B1 , . . . , Bk } →Ri A, k > 1 füge einen FDKnoten wie in Abbildung 2.2 ein. Für k = 1 füge die Kante (Ri .B, Ri .A) ein. 2. Falls ein konstanter Knoten ’c’ V -Spur von Ri .A ist, dann füge für jedes Attribut B aus jeder Relation R ∈ S eine Kante (R.B, Ri .A) ein. B1 A Bk Abbildung 2.2: Ein FD-Knoten zur funktionalen Abhängigkeit {B1 , . . . , Bk } →R A Die Abbildungen 2.3 und 2.4 zeigen Abhängigkeits-Graphen zu Sicht V5 aus Abschnitt 2.1.4. Dabei sind die gestrichelten Kanten diejenigen, die in den zugehörigen Spur-Graphen eingefügt werden. E.EMP E.DEP V.EMP V.DEP M.DEP M.MGR V.MGR Abbildung 2.3: Der Abhängigkeits-Graph für die Sicht V5 aus Abschnitt 2.1.4 Die zusätzlichen Kanten nach Bedingung 2 in Definition 2.33 von allen Knoten zu dem konstanten Knoten ’Sales’ kennzeichnen quasi eine funktionale Abhängigkeit. Diese wird von der Menge der Sichttupel erfüllt. Denn durch die Selektionsbedingung DEP=’Sales’ ist das Attribut DEP funktional von den anderen Attributen abhängig. Der gebräuchliche Begriff des Pfads in einem Graphen muß noch auf Mengen von Knoten und auf FD-Knoten erweitert werden: 2.2 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen E.EMP E.DEP V.EMP Sales M.DEP 19 M.MGR V.MGR Abbildung 2.4: Der gleiche Graph wie in Abbildung 2.3, jedoch hat die Sicht die zusätzliche Selektionsbedingung DEP=’Sales’ Definition 2.34 Seien A, B, C beliebige Knoten und X, Y, Z beliebige Knotenmengen in einem Graph G, wobei ein Knoten D der Knotenmenge {D} gleichzusetzen ist. Mit Y G Z bezeichnen wir einen Pfad im Graphen G von Y nach Z, wobei Pfad“ folgende Bedeutung hat: ” 1. Von jedem Knoten existiert ein Pfad zu sich selbst. 2. Falls die Kante (A, B) existiert, so gibt es einen Pfad von A nach B. 3. Falls es von einer Teilmenge Y 0 ⊆ Y von Knoten einen Pfad zu A gibt, dann gibt es einen Pfad von Y nach A. 4. Falls es von einer Teilmenge Y 0 ⊆ Y von Knoten einen Pfad zu allen Knoten Zi ∈ Z gibt, dann gibt es einen Pfad von Y nach Z. 5. Falls es einen Pfad von X nach Y gibt und einen Pfad von Y nach Z, dann gibt es einen Pfad von X nach Z. 6. Sei F ein FD-Knoten zur funktionalen Abhängigkeit X →R Z. Falls Y existiert, dann gibt es einen Pfad von Y nach Z. G X Wird der Graph in Abbildung 2.5 betrachtet, so gibt es zwar Pfade {V.D, V.E} S.F V und {V.A, V.B, V.C, V.D} V S.F aber {V.C, V.D} 6 V S.F. Pfade über FD-Knoten müssen alle eingehenden Kanten des FD-Knotens enthalten, während es bei Pfaden von normalen Knotenmengen ausreichend ist, daß zwei Knoten existieren, die durch einen Pfad verbunden sind. Lemma 2.4 Sei S = {Ri [Xi ] | i = 1, . . . , n} ein Datenbankschema, V[Z] eine Sicht über S, L ⊆ {X1 , . . . , Xn } und Y ⊆ Z. Dann gilt für alle Generatoren g, g 0 beliebiger Sichttupel v, v 0 (g.L = g 0 .L ⇒ v.Y = v 0 .Y ) ⇔ (L D(V ) Y ) 20 Das View-Update-Problem R.A R.B R.C R.D R.E V.A V.B V.C V.D V.E S.E S.F V.F Abbildung 2.5: Der Abhängigkeits-Graph für die Sicht V = πY (R o nR.E=S.E S) mit Y = {R.A, R.B, R.C, R.D, R.E, S.F } über den Relationenschemata R[A, B, C, D, E] und S[E, F ] mit den funktionalen Abhängigkeiten {A, B, C} →R E und E →S F . Pfade in D(V ) haben die Eigenschaft, exakte Quellen anzuzeigen. Im Beispiel auf Seite 15 gibt es z. B. einen Pfad E.EM P D(V5 ) V5 .EM P, während {M.DEP, M.M GR} 6 D(V5 ) V5 .EM P. Wie schon auf Seite 15 gesehen ist ((John,Sales);E) exakte Quelle von (John, Sales, Mary), während dies bei ((Sales,Mary);M) nicht der Fall ist. Korollar 2.1 Sei Y ⊆ V eine beliebige Menge von Sichtattributen und A ∈ R ∈ Rels(V) beliebiges Attribut. Es ist dann Y →V A ⇔ Y D(V ) A. Eine funktionale Abhängigkeit zwischen Sichtattributen ist durch das Suchen eines Pfads im Abhängigkeits-Graph zwischen diesen Attributen zu finden, Pfade sind im Abhängigkeits-Graph synonym zu funktionalen Abhängigkeiten in den zugrundeliegenden Relationen. In den folgenden Abschnitten werden Algorithmen für die Übersetzung von Sichtänderungen angegeben und unter welchen Bedingungen die Änderungen exakt sind. 2.2.3 Löschänderungen Sei V[Z] eine Sicht mit den Attributen Z und Y ⊆ Z eine Teilmenge der Attribute. Mit V [Y = y] bezeichnen wir die Menge der Tupel aus V , deren Attribute Y = {Y1 , . . . , Yn } die Werte y = {y1 , . . . , yn } haben. Die Löschänderung wird wie folgt übersetzt, wobei V u = V [Y = y] die Menge der zu löschenden Tupel in V sein soll, Y die Menge der in der Löschbedingung spezifizierten Attribute. Der folgende Algorithmus übersetzt eine Löschänderung auf einer Sicht in eine Löschänderung auf dem zugrundeliegenden Datenbankschema. 2.2 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen Algorithmus 2.1 Für jede Relation R des Schemas R ∈ Rels(V) lösche die Menge {t ∈ R | t ist Quelle eines v ∈ V u }. Theorem 2.4 Eine Änderung delV (t) ist exakt übersetzbar ⇔ Xi D(V ) Y , wobei Y die Attribute der Sicht sind, die in der Löschbedingung auftauchen und Ri [Xi ], i ∈ I(V) die Relationenschemata sind, von denen einige Attribute eine direkte V -Spur in Y haben. Der Algorithmus 2.1 ist eine exakte Übersetzung, wenn die Bedingungen zutreffen. Die Löschoperation auf dem Datenbankschema, die das Theorem 2.4 erfüllt, braucht nur die exakten Quellen von t zu löschen, dies folgt aus Theorem 2.1. So ist das Löschen von (John,Sales,*) aus der Sicht V5 auf der Relation E eine exakte Übersetzung, da ein Pfad {E.EM P, E.DEP } D(V5 ) {V.EM P, V.DEP, V.M GR} existiert, während {M.DEP, M.M GR} 6 D(V5 ) {V.EM P, V.DEP, V.M GR} und somit das Löschen aus der Relation M keine exakte Übersetzung ist. Eine Übersetzung auf der Relation E ist auch dann noch exakt, wenn die funktionale Abhängigkeit DEP →M MGR nicht vorhanden ist. Wenn die Löschbedingung nur für das Attribut EMP formuliert wird, also die Tupel (John,*,*) gelöscht werden, so ist die Übersetzung exakt. Zwar fehlt die Kante von M.DEP nach M.MGR, aber es wird auch nicht verlangt, daß der Pfad {E.EM P, E.DEP } D(V5 ) V.M GR vorhanden ist. 2.2.4 Einfügeänderungen Durch das Einfügen eines Tupels können funktionale Abhängigkeiten verletzt werden. Da durch Projektionen in der Sicht beim Einfügen Attribute auch unspezifiziert sein können, sollen diese Attribute den Wert NULL erhalten. In [DB82] wird die Einfügeoperation explizit beschrieben. Dabei werden die einzufügenden Tupel aus den Werten der Sichtattribute gebildet, soweit diese jeweils eine V -Spur sind. Die verwendete Prozedure reduce dient dazu, daß beim Einfügen eines Sichttupels v weniger definierte Sichttupel w gelöscht werden.4 Die einzufügenden Tupel werden nach folgendem Algorithmus gebildet: Algorithmus 2.2 1. Sei v einzufügendes Tupel in V , für alle Ri [Xi ] ∈ Rels(V) definiere ti ∈ dom(Xi ) für alle A ∈ Xi wie folgt (a) falls V.A V -Spur von Ri .A und v.A 6= N U LL, dann setze ti .A = v.A sonst falls ∃L →Ri A ∃t0i ∈ Ri ti .L = t0i .L und t0i .A 6= N U LL, dann setze ti .A = t0i .A (b) falls ∃Rj .B Rj .B T (V) Ri .A, dann setze ti .A = tj .B, sonst setze ti .A = N U LL 2. für alle i ∈ I(V) führe reduce(Ri ∪ {ti }) aus. Das folgende Theorem gibt die Bedingungen an, unter welchen der Algorithmus eine (exakte) Übersetzung einer Einfügeänderung auf einer Sicht ist: 4 w ist weniger definiert, wenn w.A = v.A für fast alle Attribute A und sonst w.A = N U LL 21 22 Das View-Update-Problem Theorem 2.5 Sei V[Y ] eine Sicht über Ri [Xi ], i = 1, . . . , n. 1. Eine Änderung insV (t) ist genau dann übersetzbar, wenn gilt: (a) falls A1 und A2 V -Spuren des gleichen Attributs Ri .A, v.A1 6= N U LL und v.A2 6= N U LL sind, dann ist v.A1 = v.A2 , und (b) QualV (ti1 , . . . , tip ) = true und ti wie im Algorithmus berechnet. 2. Eine Änderung insV (t) ist dann exakt übersetzbar, wenn sie übersetzbar ist und für alle i ∈ I(V ) Xi D(V ) Y gilt. Der Algorithmus 2.2 ist eine (exakte) Übersetzung, wenn die Bedingungen zutreffen. Damit die Übersetzung einer Einfügeoperation die Konsistenz erhält, müssen alle Primärschlüsselattribute eine V -Spur in der Sicht haben, es muß ein Wert für die Primärschlüsselattribute definiert sein und funktionale Abhängigkeiten müssen berücksichtigt werden. Damit QualV (ti1 , . . . , tip ) = true gilt, muß die Übersetzung also insbesondere für Attribute, die eine V -Spur haben und in der Sichtbedingung verwendet werden einen Wert spezifizieren. Durch Erweiterung der Theorie unter Berücksichtigung von Inklusionsabhängigkeiten können diese Bedingungen abgeschwächt werden. Die Bedingung für die exakte Übersetzbarkeit ist eigentlich zu stark, z. B. ist ein Einfügen in die Sicht aus Abbildung 2.3 nicht möglich, da {M.MGR, M.DEP} 6 D(V5 ) {V.EMP, V.DEP, V.MGR}. Dies sollte jedoch möglich sein. Für die Sicht in Abbildung 2.6 ist eine exakte Übersetzung auf den beiden Relationen E und S möglich, für das Attribut S.EM P wird der Wert von V.EM P genommen, da dies eine V -Spur ist. E.DEP E.EMP V.DEP V.EMP S.EMP S.SAL S.AGE V.SAL Abbildung 2.6: Der Abhängigkeits-Graph für die Sicht V9 aus Abschnitt 2.1.4 Zu der Sicht in Abbildung 2.7 gibt es keine Übersetzung, da es zu den Join-Attributen E.DEP und M.DEP keine V -Spuren gibt, was gegen die Bedingung 1b in Theorem 2.5 verstößt. Im folgenden soll gezeigt werden, wie die Bedingungen in Theorem 2.5 abgeschwächt werden können, wenn Inklusionsabhängigkeiten auf dem Datenbankschema vorhanden sind. Angenommen, die Bedingung E[DEP] ⊆ M [DEP] würde nicht gelten und das Tupel (Joan,Toys) wäre auch in E enthalten. Die Übersetzung von insV5 ((Bill,Toys,Alex)) 2.2 Übersetzungen mit Hilfe von Sicht-Abhängigkeits-Graphen E.EMP E.DEP M.DEP V.EMP M.MGR V.MGR Abbildung 2.7: Der Abhängigkeits-Graph für die Sicht V8 aus Abschnitt 2.1.4 ist {insE ((Bill,Toys)), insM ((Toys,Alex))}. Dies ist aber keine exakte Übersetzung, da nun auch das Tupel (Joan,Toys,Alex) in der Sicht V5 auftaucht. Funktionale und Inklusionsabhängigkeit reichen aber noch nicht aus, um eine exakte Übersetzung zu garantieren. Sei (Toys,NULL) ein Tupel in M und (Chris,Toys) ein Tupel in E. Funktionale und Inklusionsabhängigkeit sind erfüllt. Fügen wir das Tupel (Bill,Toys,Alex) in die Sicht V10 ein, so wird durch die Übersetzung der Einfügeoperation zur Einhaltung der funktionalen Abhängigkeit das Tupel (Toys,NULL) in M durch (Toys,Alex) ersetzt, was dazu führt, daß auch das Tupel (Chris,Toys) in V10 erscheint. Dies kann nur durch eine Existenzabhängigkeit verhindert werden, die garantiert, daß für ein Tupel t ∈ M mit t.DEP 6= N U LL folgt, daß t.M GR 6= N U LL ist. Definition 2.35 Sei R[X] ein Relationenschema und L1 , L2 ⊆ X Teilmengen von Attributen aus R. Dann erfüllt die zugehörige Relation R die Existenzabhängigkeit EXISTR (L1 , L2 ), falls ∀t ∈ R ∀A ∈ L1 t.A 6= N U LL ⇒ ∀B ∈ L2 t.B 6= N U LL Durch diese Bedingung wird ausgeschlossen, daß Tupel wie (Toys,NULL) in der Relation M enthalten sind, die zu den beschriebenen Seiteneffekten führen. Theorem 2.5 kann nun weniger restriktiv formuliert werden, zunächst auf zwei Relationen beschränkt. Theorem 2.6 Sei V[Y ] eine Sicht über zwei Relationen mit den Schemata R1 [X1 ] und R2 [X2 ] und es gelten die Bedingungen 1a und 1b von Theorem 2.5. Eine Änderung insV (t) ist dann exakt übersetzbar, wenn sie übersetzbar ist und für eine Permutation (i,j) von (1,2) gilt 1. Xi D(V) 2. (a) Xj Y und D(V) Y oder (b) ∃A ∈ Ri ∃B ∈ Rj Ri .A und EXISTRj (Lj , B ∗ ). T (V) Rj .B ∧ Ri [Li ] ⊆ Rj [Lj ] ∧ Lj →Rj B ∗ Dabei sind Li = {A ∈ Xi | ∃B ∈ Xj ti .A = tj .B ist in der Sichtbedingung erfüllt}, 23 24 Das View-Update-Problem Lj symmetrisch dazu gebildet und B ∗ = {A ∈ Xj | A ist Attribut in der Sichtbedingung}. Falls nun die Sicht V als Folge von Sichten V1 , . . . , Vk ausgedrückt werden kann, die jeweils die Bedingungen in Theorem 2.6 erfüllen, dann ist insV (t) exakt übersetzbar. Durch die Erweiterung auf Inklusions- und Existenzabhängigkeiten müssen Lösch-, Einfüge- und Änderungsprozeduren angepasst werden, um diese Integritätsbedingungen zu prüfen. Dies wird hier ausgelassen. Auch die folgende Änderungsprozedur berücksichtigt dies nicht. 2.2.5 Ersetzungsänderungen Ähnlich wie beim Einfügen sind beim Ersetzen eines Sichttupels nicht notwendigerweise alle Attribute mit Werten belegt. Die Ersetzungsänderung wird mit folgendem Algorithmus übersetzt, wobei V u die Menge der Tupel in V sein soll, die durch V r ersetzt werden und v r ∈ V r ein geändertes Tupel der Sicht. Sei Y ∗ die Menge der Sichtattribute, die in der Änderungsbedingung spezifiziert sind, W die Menge der Sichtattribute, deren Werte geändert werden und URels = {Ri | ∃A ∈ Ri ∃B ∈ W B ist V -Spur von A}. Algorithmus 2.3 1. für alle Ri ∈ URels(V) setze Ti := {ti ∈ Ri | ti ist Quelltupel eines v ∈ V u } und für alle ti ∈ Ti definiere tri durch r v .A A ist V-Spur von Ri .A r ti .A = ti .A sonst 2. für alle Ri ∈ URels(V) und für alle tri aus Schritt 1 und für alle A ∈ Xi falls ∃L →Ri A ∃t0i ∈ Ri (t0i 6∈ Ti ∧ t0i .L = tri .L) gilt dann setze t0i .A = tri .A 3. für alle Ri ∈ URels(V) setze Ri =reduce({Ri \ Ti } ∪ Tir ), wobei Tir = {tri | ti ∈ Ti } Das folgende Theorem formuliert die Bedingungen, unter denen der Algorithmus eine (exakte) Übersetzung ist: Theorem 2.7 Sei V[Y ] eine Sicht über Ri , i = 1, . . . , n. 1. Eine Änderung replV (t → t0 ) ist dann übersetzbar, wenn gilt: (a) falls V.A1 , V.A2 zwei V -Spuren des gleichen Attributs Ri .A sind, dann ist für alle v ∈ V u v r .A1 = v r .A2 und (b) falls ein Generator g = (ti1 , . . . , tip ) von v ∈ V u existiert, dann ist g r = (tri1 , . . . , trip ) Generator von v r , trij , wobei tr = t für alle Tupel t, die nicht in Algorithmus 2.3 berechnet werden. 2. Eine Änderung replV (t → t0 ) ist dann exakt übersetzbar, wenn sie übersetzbar ist und (a) falls für alle Ri [Xi ] ∈ URels(V) ein Pfad Xi D(V ) Y ∗ existiert, und 2.3 Übersicht über weitere Ansätze für die Übersetzung von View-Updates (b) falls für alle A ∈ V gilt: falls A ∈ W V -Spur einiger Ri .A ist, die in einer join-Klausel in <Qualifikation> vorkommen, dann existiert ein Pfad Xi D(V ) Y . Der Algorithmus 2.3 ist eine (exakte) Übersetzung, wenn die Bedingungen zutreffen. Eine notwendige Bedingung für 1b ist, daß v r einen Generator hat, was genau dann der Fall ist, wenn ti .A<Op>a in der Sichtbedingung vorkommt und Ri .A eine V Spur in W hat. Wenn ti .A<Op>Tj .B in der Sichtbedingung vorkommt, dann hat Ri .A eine V -Spur D ∈ W genau dann, wenn Rj .B eine V -Spur E ∈ W hat und v r .D = v r .E gilt. Zur Erhaltung der Konsistenz müssen wie bei der Einfügeoperation die V -Spuren von Primärschlüsseln ungleich NULL sein und das ersetzende Tupel darf keine funktionalen Abhängigkeiten in der jeweiligen Relation verletzen. Wie bei den anderen Änderungsoperationen wird auch bei der Ersetzungsänderung die exakte Übersetzung im wesentlichen durch die Pfade zwischen den Attributen der beteiligten Relationen zu den Sichtattributen im Spur- und Abhängigkeits-Graph bestimmt. Der hier beschriebene pragmatische Ansatz läßt eine große Anzahl an Sichtänderungen zu, die sehr stark von den Integritätsbedingungen des zugrundeliegenden Datenbankschemas abhängen. Die Menge der änderbaren Sichten ist durch Formulierung zusätzlicher, oben besprochener Abhängigkeiten sehr zu vergrößern. In Abschnitt 2.4 wird der Ansatz von [DB82] verwendet und im Hinblick auf das Ziel dieser Arbeit modifiziert. Durch bestimmte ausgezeichnete Relationen einer Sicht sollen noch zusätzliche, auf diese Relationen beschränkte Änderungen möglich sein. Der Begriff der Änderung muß dafür ebenfalls modifiziert werden. 2.3 2.3.1 Übersicht über weitere Ansätze für die Übersetzung von View-Updates Komplementäre Sichten In [BS81] wird ein aus theoretischer Sicht sehr interessant erscheinender und inspirierender Ansatz vorgestellt, der mit komplementären Sichten arbeitet. Dazu wird zu einer update-Sicht eine konstante komplementäre Sicht festgelegt, die in Komposition mit der update-Sicht den Datenbankzustand vollständig darstellt. In [Lan90] wird allerdings gezeigt, daß der vorgestellte Übersetzer nur auf trivialen Sichten definierbar ist. Im folgenden sei dieser Ansatz informal dargestellt. Definition 2.36 Seien f, g zwei Sichten, dann wird die binäre Relation ≤ wie folgt definiert f ≤ g :⇐⇒ g(S) = g(S 0 ) ⇒ f (S) = f (S 0 ) mit S, S 0 beliebige Datenbankinstanzen von S. Durch ≤ wird eine partielle Ordnung über den Sichten eines Datenbankschemas S eingeführt. g kann als eine Verfeinerung“ angesehen werden, da g zwischen mehr ” Datenbankinstanzen unterscheidet“. ” 25 26 Das View-Update-Problem Definition 2.37 Für eine Sicht f und zwei Datenbankinstanzen S, S 0 ist die Äquivalenzrelation ≡f definiert durch S ≡f S 0 :⇐⇒ f (S) = f (S 0 ) Definition 2.38 Zwei Sichten f und g heißen äquivalent, in Zeichen f ≡ g, wenn f ≤ g und g ≤ f . Wir bezeichnen mit > die Sicht, welche die Identität repräsentiert und mit ⊥ die Sicht, die jede Instanz von S auf ∅ abbildet. Die durch > und ⊥ repräsentierten Äquivalenzklassen bilden gerade das maximale und das minimale Element von ≤. Definition 2.39 Das Kreuzprodukt × auf zwei Sichten f und g ist definiert als (f × g)(S) = (f (S), g(S)) Definition 2.40 Eine Sicht g ist das Komplement einer Sicht f , falls f × g ≡ >. Das heißt, daß eine Datenbankinstanz vollständig mit f und g identifiziert werden kann. Jede Sicht hat trivialerweise > als Komplement, interessant sind daher insbesondere minimale Komplemente. Eine Übersetzung einer Änderung u einer Sicht f kann mit Hilfe eines Komplements g durch die Komposition û = (f × g)−1 ◦ u ◦ (f × g) beschrieben werden. V = (f (S), g(S)) / V 0 = (u(f (S)), g(S)) u O (f ×g)−1 f ×g S û / S 0 = ((f × g)−1 ◦ u ◦ (f × g)) Im folgenden sollen die Voraussetzungen angegeben werden, für die eine gültige Übersetzung einer Änderung gefunden werden kann. Sei UV die Menge aller Änderungen auf der Sicht V und US die Menge aller Änderungen auf dem Datenbankschema S. Sei f die definierende Funktion von V. Definition 2.41 Die Abbildung T : UV → S heißt Übersetzer einer Änderung der Sicht V in eine Änderung des Datenbankschemas S. Die Änderung T (u) auf S ist eine Übersetzung von u und wird auch mit Tu bezeichnet. Definition 2.42 Eine Menge UV von Änderungen auf der Sicht V heißt komplett falls 1. ∀u, v ∈ UV uv ∈ UV und 2. ∀s ∈ S, ∀u ∈ UV ∃v ∈ UV vuf (s) = f (s). Definition 2.43 Sei u ∈ UV eine Änderung auf der Sicht V. Eine Übersetzung Tu ∈ US heißt BS-zulässig, falls 2.3 Übersicht über weitere Ansätze für die Übersetzung von View-Updates 1. f Tu = uf (Konsistenz) und 2. ∀s ∈ S uf (s) = f (s) ⇒ Tu (s) = s. Definition 2.44 Ein Übersetzer T heißt BS-zulässig, falls 1. ∀u ∈ UV ist T (u) BS-zulässig und 2. ∀u, v ∈ UV T (uv) = T (u)T (v) In [BS81] wird gezeigt, daß jeder BS-zulässige Übersetzer mindestens ein Komplement konstant läßt und daß durch Angabe eines konstanten Komplements ein BSzulässiger Übersetzer eindeutig bestimmt ist. Die oben genannten Voraussetzungen sind allerdings sehr restriktiv, so daß z. B. in [Lan90] folgende Aussage gezeigt wird: Theorem 2.8 Sei S ein unabhängiges5 Datenbankschema und V[X] eine Sicht mit der Menge UV aller Einfüge- und Löschänderungen in V . Angenommen, es gibt einen BS-zulässigen Übersetzer für UV , dann sind alle X 0 ∈ X V -Spuren der gleichen Relation R ∈ S. Existiert also ein BS-zulässiger Übersetzer, so ist V eine triviale Sicht und damit aus praktischer Sicht recht uninteressant. Trotzdem kann der Ansatz interessant sein, wenn eventuell die Voraussetzungen gelockert werden können und in der Spezifizierung des konstanten Komplements weitere Informationen festgelegt werden. Dazu gibt es aber zur Zeit keine Untersuchungen. 2.3.2 Der Ansatz der Abstrakten Datentypen Abstrakte Datentypen (ADT) beschreiben Objekte mit den zugehörigen, auf ihnen anwendbaren Operationen, unabhängig von der zugrundeliegenden Implementierung. Stattdessen wird das Verhalten des ADT, also die Wirkung der Operationen beschrieben. Eine Sicht kann ebenso zu einem ADT erweitert werden, in welchem die auf der Sicht definierten Operationen aus dem Anwendungskontext zusammengefaßt werden. Die Semantik der formulierten Sicht führt zur Formulierung der notwendigen Operationen. Änderungen auf der Sicht sind nur über die vorhandenen Operationen möglich. Der Sichtdesigner hat die vollständige Kontrolle über die Effekte einer Änderung, die sich unter Umständen nicht in der Sicht äußern. Unerwünschte Seiteneffekte können ebenfalls besser vermieden werden, indem bestimmte Operationen nicht angeboten werden. Dieser Ansatz hat einige bedeutende Vorteile ([FC85]): 1. Mehrdeutigkeiten der Änderungstranslation werden vermieden, da diese durch die Festlegung der Operation in der Implementierung ausgeschlossen werden können. 2. Es können genau solche Änderungen auf der Sicht angeboten werden, die dem Anwendungskontext entsprechen und dadurch besonders benutzerfreundlich sind. 5 Wird in [Lan90] genauer definiert, besagt, daß S alle funktionalen Abhängigkeiten erfüllt, d. h. konsistent ist. 27 28 Das View-Update-Problem 3. Integritätsbedingungen können gleich in den Operationen geprüft werden, bzw. sind sie den Operationen zum Teil inhärent. Da auf Datenbankobjekte jedoch von verschiedenen Benutzern zugegriffen wird, müssen zusätzlich Vorkehrungen für den konkurrierenden Zugriff bei der Implementierung der Operationen bedacht werden. Auch ist die Formulierung der nötigen Operationen mit einigem Arbeitsaufwand verbunden. Erleichtert wird die Implementation durch Konstrukte wie Spracherweiterungen und die Definition von Objekten als Datenbankobjekte, die das zugehörige DBMS anbietet, z. B. SQL/DS. Dieser Ansatz wird auch in [TFC83] verfolgt. 2.3.3 Änderung unvollständiger Informationen Änderungen auf Sichten sind nicht vollständig spezifizierte Änderungen auf den Basisrelationen des zugrundeliegenden Datenbankschemas. Die auszuführenden Änderungen müssen erst noch spezifiziert werden. Daher gibt es einen allgemeineren (und sehr theoretischen) Ansatz für das View-Update-Problem, der hier nicht weiter verfolgt wird. Es sei auf [AHV95] verwiesen, wo weitere Literaturangaben zu finden sind. Die Verwendung von Tabellen mit Bedingungen (conditional tables, c-tables) stellen Tabellen dar, in denen Bedingungen festgelegt werden, die eine genaue Spezifizierung bestimmter Änderungen ermöglicht. Dabei sind nur Änderungen erlaubt, die den Bedingungen der Tabellen genügen. Wird ein Datenbankschema als die Repräsentierung einer logischen Theorie aufgefaßt, so ergibt sich ein allgemeinerer Ansatz als der der c-tables. Zu einer logischen Theorie T , also eine Menge logischer Aussagen, wird die Menge der Modelle mit M od(T ) bezeichnet. Ist |M od(T )| > 1, dann repräsentiert T unvollständige Informationen. Dieser Ansatz sei hier nur erwähnt, um einen anderen Blickwinkel auf Sichtänderungen zu zeigen, in dem weniger im Vordergrund steht, daß die Sicht eine Funktion auf einem Datenbankschema ist. Im Umfeld relationaler Datenbanken scheint dieser Ansatz jedoch weniger interessante Ergebnisse zu liefern. 2.4 Bewertung und eigener Ansatz Die Betrachtung wesentlicher Lösungsansätze für das View-Update-Problem in den obigen Abschnitten zeigt die eingeschränkten Möglichkeiten für die automatische Übersetzung von Änderungsoperationen auf Sichten in Operationen auf den zugrundeliegenden Relationen. Für das hier verfolgte Ziel, die Generierung von Benutzermasken aus zugehörigen Sichten, bedeutet das, daß entweder die verwendbaren Sichten sehr stark eingeschränkt werden müssen oder die Änderungsfähigkeit auf andere Weise sichergestellt werden muß. Der Ansatz der Sicht-Abhängigkeits-Graphen ist für diese Arbeit am interessantesten. Der Zusammenhang zwischen den Sichtattributen und den zugehörigen Quellen 2.4 Bewertung und eigener Ansatz 29 und damit die Bewertung der Änderungsmöglichkeiten wird algorithmisch zugänglich gemacht. Über die Suche von Pfaden in den beschriebenen Graphen können änderbare Attribute aus der Sichtdefinition identifiziert werden, unabhängig vom aktuellen Datenbankzustand. Für Selektions- und Projektionssichten, die nur auf einer Relation definiert sind, zeigt der Ansatz exakte Übersetzungen für alle betrachteten Änderungsoperationen. Bei Verbundsichten ist aus dem Abhängigkeits-Graphen ablesbar, welche Änderungen übersetzbar sind. Im Hinblick auf das Ziel dieser Arbeit, die Generierung einer Update-Maske zu einer Sicht, sollen einige Einschränkungen vorgenommen werden. Neben der Struktur des Abhängigkeits-Graphen ist auch die Form der Änderung entscheidend für die Übersetzbarkeit, insbesondere, welche Attribute und damit welche Quelltupel betroffen sind. In einer Maske sollen daher schon einige Änderungsmöglichkeiten ausgeschlossen werden. Betrachten wir zunächst als einfaches Beispiel eine Sicht, in der eine Relation R1 eine Fremdschlüsselbeziehung zu einer anderen Relation R2 hat. Gegeben seien die Relationenschemata 1. R[NR,DATUM,NAME] für Rechnungen und 2. P[RECHNUNG,POS,ARTIKEL] für zugehörige Rechnungsposten, die Primärschlüssel 1. NR →R {DATUM,NAME} und 2. {RECHNUNG,POS} →P ARTIKEL, und der Fremdschlüssel P [RECHNUNG] ⊆ R[NR], der gewährleistet, daß ein Rechnungsposten zu einer Rechnung gehört. Die Sicht V sei folgendermaßen definiert: V = πY (R o nNR=RECHNUNG P ) wobei Y = {R.NAME, R.DATUM, R.NR, P.POS, P.ARTIKEL} In der Sicht V werden Rechnungen mit den zugehörigen Rechnungspositionen angezeigt. Der in Abbildung 2.8 gezeigte Abhängigkeits-Graph zu V macht deutlich, welche Änderungsoperationen exakt übersetzbar sind. Werden beim Löschen nur die Attribute Y spezifiziert, die V -Spuren von P sind, dann ist eine Übersetzung möglich, da ein Pfad P D(V) Y existiert. Wird zusätzlich ein Attribut spezifiziert, R.NAME R.DATUM R.NR V.NAME V.DATUM V.NR P.RECHNUNG P.POS P.ARTIKEL V.POS V.ARTIKEL Abbildung 2.8: Abhängigkeits-Graph zur Sicht V = πY (R o nNR=RECHNUNG P ) welches direkte V -Spur eines Attributs von R ist, dann gibt es keinen Pfad von diesem Attribut zu den Sichtattributen V.POS und V.ARTIKEL. Die Integritätsbedingungen ermöglichen die Übersetzung einer Einfügeänderung, da die Bedingungen 30 Das View-Update-Problem in Theorem 2.6 erfüllt sind. Die Ersetzungsänderung ist exakt übersetzbar, falls nur Attribute einer Relation betroffen sind oder keine Join-Attribute geändert werden. Die mit der formulierten Fremdschlüsselbedingung intendierte Abhängigkeit der Relation P von der Relation R soll besonders berücksichtigt werde. Um Änderungen auf der Relation R in der oben beschriebenen Weise zuzulassen, muß diese besondere Bedeutung von R kenntlich gemacht werden, da dies nicht aus der Sichtdefinition und dem Datenbankschema hervorgeht. Diese Relation soll sogenannte Master-Relation der Sicht sein, während P sogenannte Child-Relation ist. Definition 2.45 Sei RM [XM ] eine Relationenschema mit einem Schlüsselkandi• 0 0 daten XM ⊆ XM , so daß eine Instanz RM [XM ] existiert, für die XM →RM XM gilt, und RC1 [X1 ], . . . , RCn [Xn ] Relationenschemata, für welche Instanzen RC1 [X1 ], . . . , RCn [Xn ] existieren, welche die Fremdschlüsselbeziehungen der Form 0 ], . . . , R [X 0 ] ⊆ R [X 0 ] erfüllen, wobei X 0 ⊆ X . Dann heißt RC1 [X10 ] ⊆ RM [XM i Cn M n i M RM Master-Relation und jede Relation RCi Child-Relation. Die in Abschnitt 2.2 vorgestellten Algorithmen und Theoreme werden im folgenden auf Master-Child-Sichten“ angewendet. Dabei interessieren uns nur exakte ” Übersetzungen, einfache Übersetzungen wollen wir nicht zulassen. Im folgenden sei S ein Datenbankschema, bestehend aus den Relationenschemata RM [XM ] und RCi [Xi ], i = 1, . . . , n, zu denen eine Master-Relation RM [XM ] und entsprechende Child-Relationen RCi [Xi ], i = 1, . . . , n gehören, und V[Y ] eine Equijoin-Sicht der Form 0 =X 0 . . . o 0 =X 0 RC ) V = πY (RM o nY 0 =X10 RC1 o nXM nXM n n 2 0 und X 0 wie in Definition 2.45. Abbildung 2.9 zeigt den Abhängigkeitsmit XM i Graphen zu so einer Sicht V. M.Xl V.MXl M.X1 V.MX1 M.Pk V.MPk M.P1 C1.P1 V.C1P1 C1.Pk V.C1Pk C1.X1 V.C1X1 C1.Xm1 V.C1Xm1 Cn.P1 V.CnP1 Cn.Pk V.CnPk Cn.X1 V.CnX1 V.MP1 Cn.Xmn V.CnXmn Abbildung 2.9: Abhängigkeits-Graph zu einer Sicht V über der Master-Relation M mit dem Schlüsselkandidaten X 0 = {P1 , . . . , Pk } und den Child-Relationen Ci . 2.4 Bewertung und eigener Ansatz 2.4.1 31 Löschänderungen Beim Löschen muß die bestehende Fremdschlüsselbeziehung zwischen Master- und Child-Relation beachtet werden, so daß beim Löschen eines Tupels aus der MasterRelation auch die zugehörigen Tupel der Child-Relationen gelöscht werden müssen. Algorithmus 2.4 Für alle R ∈ S, die eine V -Spur in der Menge Y ∗ der Attribute, die in der Löschbedingung spezifiziert sind, definiere T = {t0 ∈ R | t ist Quelltupel eines v ∈ V [Y = y]} und 1. falls R Master-Relation, lösche in allen Child-Relationen RCi die Menge {t | r ∈ T t.Xi0 = r.Y 0 }, 2. lösche die Menge T . Lemma 2.5 Seien S und V[Y ] wie oben. Dann ist Algorithmus 2.4 eine exakte Übersetzung der Löschänderung u(V ), falls für alle X ∈ R gilt X D(V) Y∗ wobei R ∈ S und ∃R Zustand von R, so daß R Quelltupel eines v ∈ V [Y ∗ = y] enthält, und Y ∗ die Menge der Attribute, die in der Löschbedingung spezifiziert sind. Das Lemma 2.5 ist eine Folgerung des Theorems 2.4 aus Abschnitt 2.2 und der Algorithmus berücksichtigt entsprechende Fremdschlüsselbeziehungen. 2.4.2 Einfügeänderungen Der Algorithmus zum Einfügen kann unverändert übernommen werden, da dieser das Einfügen nicht-spezifizierter Attribute beachtet. Die Sicherung der Integritätsbedingung wird vom DBMS sichergestellt. Algorithmus 2.5 1. Sei v einzufügendes Tupel in V , für alle Ri [Xi ] ∈ Rels(V ) definiere ti ∈ dom(Xi ) für alle A ∈ Xi (a) falls V.A V -Spur von Ri .A und v.A 6= N U LL dann setze ti .A = v.A sonst falls ∃L →Ri A ∃t0i ∈ Ri ti .L = t0i .L und t0i .A 6= N U LL dann setze ti .A = t0i .A (b) falls ∃Rj .B Rj .B T (V) Ri .A dann setze ti .A = tj .B sonst setze ti .A = N U LL 2. für alle i ∈ I(V) reduce(Ri ∪ {ti }) Lemma 2.6 Seien S und V[Y ] wie oben. Algorithmus 2.5 ist eine exakte Übersetzung der Einfügeoperation u(V ) falls 32 Das View-Update-Problem 1. falls Y1 und Y2 V -Spuren des gleichen Attributs Ri .X, v.Y1 6= N U LL und v.Y2 6= N U LL, dann ist v.Y1 = v.Y2 , 2. QualV (ti1 , . . . , tip ) = true, 3. ∀Ri ∈ S, Ri 6= RM 0 ] und Ri ∪ {ti } erfüllt Ri [Xi0 ] ⊆ RM [XM 0 , B ∗ ). 4. EXISTRM (XM 0 Schlüsselkandidat von R[M ] und Dabei ist ti wie in Algorithmus 2.5 berechnet, XM ∗ B = {A ∈ RM | A ist Attribut in der Sichtbedingung}. Aus Theorem 2.6 folgt unmittelbar Lemma 2.6, da die Sicht über den MasterChild-Relationen und die Master-Child-Relationen die funktionale und die Inklusionsabhängigkeit in der Bedingung des Theorems erfüllen. 2.4.3 Ersetzungsänderungen Das Ersetzen von Tupeln ist auf Master-Child-Sichten unverändert mit Hilfe des in Abschnitt 2.2 vorgestellten Algorithmus möglich, da die Sicherung der Integritätsbedingungen vom DBMS sichergestellt wird. Da die zu ersetzenden Tupel genauso bestimmt sind wie in obigen Abschnitt, ist das Ersetzen in den Master- und ChildRelationen ein unproblematischer Spezialfall. Algorithmus 2.6 1. für alle Ri ∈ URels(V) setze Ti := {ti ∈ Ri | ti ist Quelltupel eines v ∈ V u } und für alle ti ∈ Ti definiere tri durch r v .A A ist V-Spur von Ri .A, r ti .A = ti .A sonst 2. für alle Ri ∈ URels(V) und für alle tri aus Schritt 1 und für alle A ∈ Xi falls ∃L →Ri A ∃t0i ∈ Ri (t0i 6∈ Ti ∧ t0i .L = tri .L) dann setze t0i .A = tri .A 3. für alle Ri ∈ URels(V) setze Ri =reduce({Ri \ Ti } ∪ Tir ), wobei Tir = {tri | ti ∈ Ti } Lemma 2.7 Seien S und V[Y ] wie oben. Algorithmus 2.6 ist eine exakte Übersetzung der Ersetzungsoperation u(V ) falls 1. V.A1 , V.A2 zwei V -Spuren des gleichen Attributs Ri .A, dann ist für v ∈ V u v r .A1 = v r .A2 , 2. ein Generator g = (ti1 , . . . , tip ) von v ∈ V u existiert, dann ist g r = (tri1 , . . . , trip ) Generator von v r , trij , wobei tr = t für alle Tupel t, die nicht in Algorithmus 2.3 berechnet werden. 3. falls für alle Ri [Xi ] ∈ URels(V) ein Pfad Xi D(V ) Y ∗ existiert, und 4. falls für alle A ∈ V gilt: falls A ∈ W V -Spur einiger Ri .A ist, die in einer joinKlausel in <Qualifikation> vorkommen, dann existiert ein Pfad Xi D(V ) Y. 2.4 Bewertung und eigener Ansatz Lemma 2.7 ist identisch mit Theorem 2.7, angewendet auf ein Datenbankschema mit Master-Child-Relationen. Das liegt daran, daß die Bedingungen der Beziehung von Master- und Child-Relationen unabhängig von den Bedingungen des Theorems 2.7 sind und die Übersetzbarkeit primär von der Menge der geänderten Attribute und der Menge der Attribute in der Änderungsbedingung abhängt. Die Möglichkeiten der Übersetzung von Sichtänderungen sind bis hier ausreichend untersucht worden, viel weitergehende Möglichkeiten gibt es zur Zeit in der Theorie nicht. Eine denkbare Erweiterung wäre die Übertragung des Begriffs der MasterRelation auf die Child-Relationen, die ihrerseits in Beziehung zu Child-Relationen stehen usw. Dadurch entsteht eine Hierarchie der Relationen, an deren Spitze die Master-Relation steht, unmittelbar darunter ihre Child-Relationen, darunter deren Child-Relationen usw. Dieser Ansatz soll hier aber nicht weiter verfolgt werden. Doch theoretisch sollte diese Verallgemeinerung möglich sein, da die wesentlichen Bedingungen mit den Pfaden in den Sicht-Abhängigkeits-Graphen weiterhin anwendbar sind und die gleichen Ergebnisse liefert. Ein anderer Ansatz wäre die Umsetzung der Master-Child-Beziehung durch die Einführung des nest-Operators auszudrücken, so daß die Hierarchie deutlicher erscheint. Um eine leichte Umsetzung des hier verfolgten Ziels zu haben, wurde der Ansatz nur auf flachen“ Relationen betrachtet, die von einer großen Anzahl gängi” ger DBMS unterstützt werden. 2.4.4 Eingeschränkte Übersetzungen In Hinblick auf die zu generierenden Masken ist die Anzeige weiterer, nicht änderbarer Informationen interessant und soll daher in das Sichtkonzept aufgenommen werden. Das der Sicht zugrundeliegende Datenbankschema soll dafür neben den Master- und Child-Relationen noch Partner-Relationen enthalten, die weitere Quellen der Sicht darstellen, aber deren V -Spuren nicht änderbar sind und daher die Änderbarkeit auf der Sicht nicht beeinflussen. Diese Idee sei an dem Beispiel zu Anfang dieses Abschnitts erläutert. Das Datenbankschema umfasse die Relationenschemata 1. R[NR,DATUM,NAME], 2. P[RECHNUNG,POS,ARTIKEL] und 3. A[NAME,STRASSE,ORT], die Primärschlüssel 1. NAME →A {STRASSE,ORT}, 2. NR →R {DATUM,NAME} und 3. {RECHNUNG,POS} →P ARTIKEL, und die Fremdschlüssel 1. R[NAME] ⊆ A[NAME] und 2. P [RECHNUNG] ⊆ R[NR]. 33 34 Das View-Update-Problem Die Sicht V sei durch V = πY ((R o n A) o nNR=RECHNUNG P ) definiert, wobei Y = {A.STRASSE, A.ORT, A.NAME, R.DATUM, R.NR, P.POS, P.ARTIKEL} Abbildung 2.10 zeigt den zugehörigen Abhängigkeits-Graph. Es wird angenommen, daß R Master-Relation, P Child-Relation und A Partner-Relation ist. Dies ist nicht zwingend vorgeschrieben, durch die Fremdschlüsselbeziehungen ist es auch möglich, A als Master-Relation zu wählen. Dann ist R zugehörige Child-Relation und P Partner-Relation. Erst durch Festlegen einer Master-Relation werden die anderen in der Sicht beteiligten Relationen klassifiziert und anhand der Fremdschlüsselbeziehungen in Child- und Partner-Relationen eingeteilt. Neben den Rechnungsposten wird jetzt auch die Anschrift einer Rechnung in der Sicht angezeigt. Zwar können in einem bestimmten Umfang auch Änderungen an den Attributen, die V -Spur von Attributen des Schemas A sind, vorgenommen werden, jedoch soll der Schwerpunkt auf den Rechnungstupeln liegen und daher Übersetzungen auf die Relationen R und P eingeschränkt werden. Andernfalls würde z. B. das Löschen eines Sichttupels durch Angabe allein der Attribute von A die Löschung aller Rechnungen und zugehöriger Rechnungstupel zu einer Adresse nach sich ziehen. Der Umfang solch einer Änderung hat also einen relativ großen Seiteneffekt, der zwar der Semantik der formulierten Änderung entspricht, dessen Konsequenzen aber eventuell nicht überblickt werden. Daher soll der Fokus auf eine Master-Relation gelenkt werden, die neben eventuell A.STRASSE A.ORT A.NAME V.STRASSE V.ORT V.NAME R.NAME R.DATUM R.NR V.DATUM V.NR P.RECHNUNG P.POS P.ARTIKEL V.POS V.ARTIKEL Abbildung 2.10: Abhängigkeits-Graph zur Sicht V = πY ((R o n A) o nNR=RECHNUNG P) vorhandener Child-Relationen änderbar ist. Alle beteiligten Partner-Relationen stellen nur Kontextinformationen zu einer Master-Relation zur Verfügung, sollen aber in dieser Sicht statisch bleiben. Definition 2.46 Sei V[Y ] eine Sicht über dem Datenbankschema S = {R1 [X1 ], . . . , Rn [Xn ]}. Sei Rk ⊆ S beliebige Teilmenge von Relationenschemata. Dann ist eine Änderung u(V ) eingeschränkt auf Rk übersetzbar, wenn die Änderung u(πY ∗ (V )) auf der Sicht πY ∗ (V ) exakt übersetzbar ist. Dabei ist Y ∗ = {A ∈ V | ∀R ∈ Rk ∃B ∈ R A ist V -Spur von B} die Menge der V -Spuren der Attribute der Schemata aus Rk . 2.4 Bewertung und eigener Ansatz Eingeschränkte Übersetzungen führen Änderungen nur auf den spezifizierten Relationen aus. Dies entspricht zwar nicht dem eigentlichen Begriff der Übersetzung einer Sichtänderung, es sollen aber Kontextinformationen in die Sicht aufgenommen werden, deren Änderbarkeit nicht erlaubt und daher nicht zu untersuchen ist. Unter Berücksichtigung der Bedingungen für die Übersetzbarkeit von Änderungen auf Master-Child-Sichten sind beliebige Sichten denkbar, deren Änderbarkeit von den zugrundeliegenden Master- und Child-Relationen abhängt. Die Übersetzungsalgorithmen in diesem Abschnitt brauchen nur in soweit modifiziert werden, daß sie nur Relationen berücksichtigen, auf denen die Übersetzung eingeschränkt ist. 35 36 Das View-Update-Problem Kapitel 3 Konzeption eines Maskengenerators Nach der Untersuchung der Problematik der Übersetzung von Sichtänderungen wird jetzt ein Konzept für die Realisierung eines Maskengenerators vorgestellt. Der erzeugten Maske soll eine Sicht zugrundeliegen, so daß Änderungen in der Maske, d. h. auf den dargestellten Tupeln, als Änderungen auf der Sicht interpretiert werden können. Mit Hilfe des beschriebenen eigenen Lösungsansatzes soll eine solche Änderung übersetzt werden. Anhand von Anwendungsfällen wird der Systemumfang abgesteckt. Eine Klassifizierung der Objekte innerhalb des Systems wird anschliessend vorgenommen, die Funktionen der Klassen und ihre Beziehungen untereinander erläutert und auf Probleme hingewiesen, die bei einer Implementierung zu berücksichtigen sind. Im folgenden werden Elemente der Unified Modeling Language (UML) für die Beschreibung verwendet. Weitere Informationen zur UML finden sich in [RJB99], [BRJ99], [JBR99] und [Oes97]. Es wird der Umfang des Systems vorgestellt und in den darauf folgenden Abschnitten die wesentlichen Bestandteile beschrieben. 3.1 Ausgangsidee und Systemumfang Die grundlegende Idee ist, daß eine Maske einen Ausschnitt der Informationen einer Datenbankinstanz darstellt, der von dem Kontext, in dem die Maske verwendet wird, abhängt. Eine Sicht über den Relationen der Datenbankinstanz soll genau diesen Ausschnitt berechnen. Der Vorteil einer Sicht ist die Abstraktion der Informationen von den zugrundeliegenden Relationen, der vereinfachte Zugriff auf relevante Informationen und die Beschränkung des Zugriffs für verschiedene Benutzer(gruppen). Eine auf der Sicht aufsetzende Maske soll die von dieser Sicht gelieferten Informationen benutzerfreundlich aufbereiten. Die Sicht stellt eine Art Datenstruktur für die Maske dar, die Maske selbst ist die zugehörige Benutzerschnittstelle. Die dadurch gewonnene Trennung erlaubt z. B. eine leichtere Änderbarkeit der Benutzerschnittstelle unabhängig von der zugrundeliegenden Datenstruktur und umgekehrt. Das zu verwendende Datenbanksystem soll relational sein und SQL als Anfrage- und Modifikationssprache beherrschen. 38 Konzeption eines Maskengenerators Für die Konzeption ist grundsätzlich zu unterscheiden zwischen dem 1. Maskenentwerfer, der ausgehend von einem vorhandenen Datenbankschema eine Sicht generiert, die einer Maske zugrundeliegt, deren Aussehen und Verhalten er zusätzlich festlegt, und dem 2. Maskenbenutzer, der als Anwender über die Maske Zugriff auf die Datenbank erhält und entsprechend den Spezifikationen des Maskenentwerfers Änderungen und Anfragen ausführen darf. Das zu implementierende System umfaßt dementsprechend zwei Programme, ein Entwurfswerkzeug für die Sicht- und Maskenspezifikation und eine Ausführungsumgebung, welche die spezifizierte Maske und Bedienelemente für grundlegende Funktionen anbietet. Die Maske wird auf einem möglichen Zustand des Datenbankschemas operieren. In Abbildung 3.1 wird ein Überblick über die möglichen Anwendungsfälle und die Schnittstellen des Systems nach außen skizziert. Im Entwurfs- Abbildung 3.1: Anwendungsfälle des Maskengenerators und der Ausführungsumgebung der Maske werkzeug wird die Sicht spezifiziert, die daraufhin im DBS erzeugt werden kann. Anschließend können Einstellungen zu den Attributen der Sichtrelation vorgenommen werden und das Layout der Maske angegeben werden, indem die Attribute in der Maske plaziert werden. Es soll die Möglichkeit bestehen, ein Standardlayout der Maskenelemente automatisch zu generieren. Sind alle Angaben zur Maske gemacht, 3.1 Ausgangsidee und Systemumfang so kann diese generiert und in der Ausführungsumgebung verwendet oder auch in eigene Anwendungen integriert werden. Die Ausführungsumgebung ermöglicht dem Benutzer, Daten auszuwählen, diese zu manipulieren und Daten zu exportieren, z. B. ein oder mehrere Tupel in einem Report auszudrucken oder über einen geeigneten Filter in andere Programme wie z. B. Textverarbeitung zu übernehmen. In eine eigene Anwendung integriert ist die Maske voll funktionsfähig, die Anwendung muß dafür die benötigte Infrastruktur, also den Datenbankzugriff, bereitstellen. Dies wird durch die Ausführungsumgebung der Maske zwar gewährleistet, es soll jedoch auch möglich sein, andere Programmumgebungen zu verwenden. Zusätzliche Operationen der Maske können durch Erweiterungen im Quelltext eingefügt werden. Das legt eine objektorientierte Entwicklung nahe, da dann in Unterklassen die Funktionalität spezialisiert werden kann. Das vorgestellte Konzept ist objektorientiert, soll aber weitestgehend unabhängig von einer Programmiersprache sein, die nur eine Vererbungsmöglichkeit bieten muß. Allerdings wird vorausgesetzt, daß eine datenbankunabhängige Schnittstelle vorhanden ist. Im folgenden werden die Anwendungsfälle konkretisiert, wobei das Konzept für die Sichtspezifikation, für die Maskenspezifikation und für die Ausführungsumgebung genauer dargestellt und in Klassendiagrammen der Umfang und die Beziehungen verdeutlicht werden. Anhand dieser Abgrenzung des Systemumfangs wird das Konzept des Entwurfwerkzeugs erstellt. Anhand der Anwendungsfälle kann eine Gruppierung der Klassen in Pakete vorgenommen werden. Die Teile des Systems, die allein während des Maskenentwurfs benötigt werden und nicht während der Laufzeit einer Maske, können in dem Paket jforms zusammengefaßt werden. Dies sind im wesentlichen Klassen, die direkt mit dem Maskengenerator JForms zusammenhängen. Für den Entwurf und für die Laufzeit einer Maske werden Klassen benötigt, die zum einen gewisse allgemeine Funktionen übernehmen und zum anderen Klassen, die im weiteren Sinne mit der Datenbank zusammenhängen. Innerhalb dieses Konzepts werden Klassen mit allgemeinen Funktionen nur für die Realisierung der Sicht-Graphen benötigt. Diese sollen in dem Paket graph zusammengefaßt werden. Klassen für die Datenbankinteraktion werden dem Paket db zugeordnet, welches wegen der komplexen Aufgaben noch weiter unterteilt werden muß. Vorausgesetzt wird eine Datenbankinstanz, deren Schema abfragbar ist. Eine Unterteilung in einen statischen Teil, dem Datenbankschema, und einen variablen Teil, der Datenbankinstanz, wird durch die Pakete db.scheme und db.instance realisiert. Die Benutzeroberfläche der Maske sowie Klassen für die Interaktion mit der Datenbank werden auch innerhalb des Pakets db angesiedelt und gehören konkret zum Paket db.form. Da die Darstellung von Datenbankwerten in einer Maske durch die Vielzahl verschiedener Datentypen relativ komplex ist, ist das Zusammenfassen solcher Klassen sinnvoll. Dies geschieht in dem Paket db.form.field. Abbildung 3.2 zeigt die Abhängigkeiten der Pakete untereinander. Die Klassen des Pakets jforms sind abhängig von Klassen des Pakets graph, welches die Klassen zum Aufbau des Spur- und Abhängigkeitsgraphen umfasst und von den Klassen des Pakets db. Innerhalb des Pakets db sind die Pakete db.instance und db.form von db.scheme abhängig, da hier alle Strukturinformationen zusammengefaßt sind. Bestandteile der Maske aus dem Paket db.form interagieren mit Klassen aus db.instance und sind daher von diesen abhängig. 39 40 Konzeption eines Maskengenerators Abbildung 3.2: Pakete des Maskengenerators und der Ausführungsumgebung 3.2 3.2.1 Spezifikation der Sicht Schemastruktur und Aufbau der Sicht Da die Maske auf einer Relation operiert, nämlich der Sichtrelation, kann der Ansatz aus Abschnitt 2.4 als Grundlage genommen werden. Dazu wird eine Relation des Datenbankschemas als Master-Relation ausgezeichnet, deren Attribute änderbar sind. Weiter müssen die verwendeten Partner-Relationen ausgewählt werden, welche die Quellen der in der Sicht gewünschten Attribute liefern. Ein Teil dieser PartnerRelationen werden als Child-Relationen klassifiziert, deren Attribute in der Sicht ebenfalls änderbar sind. Es sollen keine Einschränkungen des zugrundeliegende Datenbankschemas gemacht werden, jedoch kann die Bestimmung der Child-Relationen nur funktionieren, wenn diese den beschriebenen Bedingungen der FremdschlüsselBeziehung zur Master-Relation genügen. Die Einteilung in Child- und PartnerRelationen kann automatisch erfolgen, wenn die Fremdschlüssel-Beziehungen bekannt sind. Eventuell ist ein Re-Design des Datenbankschemas vorteilhaft, um die Funktionalität der zu entwerfenden Maske zu vergrößern. Da die Generierung der Sicht in SQL erfolgt, entspricht die Auswahl der in der Sicht verwendeten Relationen der From-Klausel in SQL. Es sollte daher auch möglich sein, relationenwertige Anfragen anzugeben, die in der From-Klausel formulierbar sind und keine Relation des Datenbankschemas darstellen, sondern zur Ausführungszeit berechnet werden (berechnete Relation). Allerdings wurde in dieser Arbeit nicht weiter untersucht, ob dies zu weiteren Problemen führen kann. Es ist jedoch anzunehmen, daß dies unbedenklich ist, wenn solche Relationen als Partner-Relationen deklariert werden und damit nicht änderbar sind. Die Auswahl der in der Sicht vorkommenden Attribute aus den angegebenen Relation entspricht der Select-Klausel in SQL. Auch hier ist es möglich, berechnete Attribute anzugeben. Diese sind jedoch grundsätzlich nicht änderbar, ebenso wie die Attribute der berechneten Relationen. Die anzugebende Sichtbedingung entspricht der Where-Klausel in SQL. Fremd- 3.2 Spezifikation der Sicht schlüsselbeziehungen der angegebenen Relationen werden in der Sichtbedingung automatisch berücksichtigt, indem entsprechende Equi-Joins formuliert werden. Sind alle Angaben gemacht, so kann die Sicht generiert werden, wobei die Sichtanfrage in SQL aus diesen drei Elementen aufgebaut wird. Welche Änderungen auf der Sicht durchführbar und in Änderungen auf dem Datenbankschema übersetzbar sind, hängt von den Beziehungen der beteiligten Relationen und der Änderung selbst ab. Dafür werden die Graphen aus Kapitel 2 verwendet. Die Beziehungen werden im Sicht-Abhängigkeits-Graphen deutlich und entsprechend dem Maskenentwerfer mitgeteilt. Durch Angabe der Master-Relation werden mögliche Child-Relationen angezeigt, die in die Sicht aufgenommen werden können und deren Attribute ebenfalls änderbar sind. Die Attribute der Relationen der Sicht, die weder Master- noch Child-Relation sind, also Attribute von den sogenannten Partner-Relationen, sind nicht änderbar. Sichtänderungen werden nur eingeschränkt auf Master- und ChildRelationen übersetzt. Das Datenbankschema wird intern durch die Klassen in Abbildung 3.3 dargestellt. Die Klassen Scheme, Table und Column stellen das vorliegende Datenbankschema dar, wobei Table und Column einem Scheme angehören und daher als gemeinsame Oberklasse SchemeElement haben. Eine Tabelle (Table) umfaßt keine oder mehrere Spalten (Column) und gehört zu einem Schema (Scheme). Informationen wie Primärschlüssel, Not-Null-Attribute, Datentypen werden in der Klasse Column dargestellt und sind nicht änderbar. Diese Klassen stellen die Grundlage für den Aufbau der Sicht dar, da sie die benötigten Informationen zur Verfügung stellen und anhand derer die Sichtrelationen und Sichtattribute ausgewählt werden. Die Sicht (View) besteht daher aus den Klassen ViewTable und ViewColumn. Ebenso wie beim Schema haben die Elemente einer Sicht eine gemeinsame Oberklasse ViewElement. Diese basieren auf Objekten vom Typ Table oder Column aus der Datenbank. Eine ViewTable basiert auf einer Table und ist entweder Master-, Child- oder Partner-Relation in der Sicht. Durch Auswahl der Sicht-Relationen ist auch die Menge der möglichen Sicht-Attribute bestimmt, die durch die Klasse ViewColumn dargestellt werden. Diese Klasse, die auf einer Column basiert, ist besonders für den Entwurf der Maske später entscheidend. Je nach Datentyp von Column ist auch die Darstellung des Sicht-Attributs ViewColumn unterschiedlich. Die Klasse View ist zentrale Klasse bei der Sichtdefinition. Parallel zur Auswahl der Sichtelemente werden im Hintergrund die Sicht-Graphen zu der Sicht aufgebaut, was in Abschnitt 3.2.2 beschrieben wird. Entsprechend der Model-View-Controller Architektur (siehe auch [ELW98]) stellt die Klasse View das Modell einer Sicht dar, welches an verschiedenen Stellen in JForms auf unterschiedliche Art und Weise dargestellt wird. Die Modellklassen ViewTableListModel, ViewColumnListModel und ViewTreeModel sind daher die Schnittstelle von View zur Benutzerschnittstelle des Maskeneditors JForms. Über die Klasse MetaScheme soll der Zugriff auf die Klassen des Datenbankschemas gekapselt werden und ein leichter Zugang zu den enthaltenen Elementen geschaffen werden. Wichtig ist, das schon im Datenbankschema vorhandene Sichten als Relationen erscheinen, d. h. durch die Klasse Table repräsentiert werden. Die Klasse View ist die aktuell entworfene Sicht. 41 42 Konzeption eines Maskengenerators Abbildung 3.3: Übersicht der Klassen zu einem Datenbankschema 3.2.2 Modellierung des Spur- und des Abhängigkeits-Graphen Da die Algorithmen aus Abschnitt 2.4 verwendet werden, werden Klassen benötigt, die die notwendigen Graphen implementieren. Parallel zur Spezifizierung der Sicht wird der zugehörige Spur- und Abhängigkeits-Graph aufgebaut, der auch bei der Anzeige der Maske für die Kontrolle der möglichen Änderungen verwendet wird. Abbildung 3.4 zeigt die dafür notwendigen Klassen. Da es sich um gerichtete Gra- Abbildung 3.4: Übersicht der Klassen zum Aufbau der Sicht-Graphen phen handelt, gibt es die Oberklasse DirectedGraph, allerdings wird der Spur-Graph nicht als gerichteter Graph realisiert, da seine Kanten zwar gerichtet sind, dies aber grundsätzlich in beide Richtungen. Die Oberklasse Graph ist so realisiert, daß beim Einfügen einer Kante zwischen zwei Knoten die beiden Knoten gegenseitig Vorgänger und Nachfolger sind. In der Klasse DirectedGraph wird nur eine Kante von einem Knoten zu seinem Nachfolger eingefügt. Da der Abhängigkeits-Graph die Kanten des Spur-Graphen umfaßt, wird beim Aufbau eines Abhängigkeits-Graphen parallel 3.3 Entwurf der Maske der Spur-Graph aufgebaut. Die Klasse View muß also nur den Abhängigkeits-Graph aufbauen und erhält über diesen Zugriff auf den Spur-Graphen. Für die Übersetzung einer Einfügeänderung wird explizit ein Pfad im Spur-Graphen gefordert, so daß die Sicht nicht nur einen Abhängigkeits-Graphen benötigt. Für die drei Knotentypen gibt es die Klassen ColumnNode für die Relationenattribute, ViewColumnNode für die Sichtattribute und FDNode für die Knoten, welche funktionale Abhängigkeiten darstellen. Alle sind Spezialisierungen der Oberklasse MetaSchemeNode, einer Unterklasse von Vertex. Da alle Informationen in den Knoten stehen, d. h. Objekte vom Typ Column werden in ColumnNodes gespeichert und Objekte vom Typ ViewColum in ViewColumnNodes, ist eine Modellierung von Kanten nicht notwendig. Die Kanten werden über die Nachbar-Beziehungen in den Knoten realisiert. Das Einfügen von Kanten wird durch Angabe zweier zu verbindender Knoten realisiert. In der Klasse DirectedGraph muß allerdings die Sonderrolle von Pfaden über FD-Knoten bei der Pfadsuche berücksichtigt werden. Dafür wird eine Modifikation der Breiten-Suche in Graphen verwendet. 3.3 3.3.1 Entwurf der Maske Aufbau einer Maske zu einer Sicht Eine Maske besteht aus einem Informationsteil, der die Werte eines Tupels der Sicht anzeigt, und aus einem Bedienteil für die Ausführung bestimmter Operationen, um z. B. die Tupel einer Anfragemenge nacheinander anzuzeigen oder Änderungen eines Tupels in die Datenbank zu schreiben. Der Bedienteil kann entweder in dem gleichen Fenster wie der Informationsteil der Maske oder aber auch in einem separaten Fenster untergebracht sein. Der Informationsteil enthält zunächst die Felder eines Tupels der Sicht. Jedoch reicht dies nicht aus, um die Beziehung zwischen Master- und Child-Relation oder auch komplexe Datentypen zufriedenstellend wiederzugeben. In dem Beispiel mit den Rechnungen und den Rechnungsposten aus Abschnitt 2.4 gibt es zu jeder Rechnung mehrere Rechnungsposten und in der Sicht ergibt sich eine große Redundanz der Werte der Rechnungsattribute. Idealer ist eine Darstellung, in der zu einem Rechnungstupel die zugehörigen Posten angezeigt werden, die separat zu den Werten der Rechnung sind. Dies führt allerdings unweigerlich zu einer Aufteilung“ ” der Sicht, in der die Sichtattribute zur Rechnungsrelation getrennt von den Sichtattributen zur Postenrelation behandelt werden. Wird z. B. eine bestimmte Rechnung anhand der Rechnungsnummer gesucht, so werden die Anfragen Select R[X] From V Where Nr=c und Select P[Y] From V Where Nr=c ausgeführt. Die Rechnungstupel könnten z. B. in Form einer Tabelle innerhalb der Maske zu einer Rechnung angezeigt werden. Aus diesem Grund muß eine Möglichkeit geschaffen werden, um neben den Werten einfacher Datentypen, welche in Feldern angezeigt werden, auch komplexe objekt- 43 44 Konzeption eines Maskengenerators wertige Strukturen anzuzeigen. Diese können z. B. in Form von Submasken oder eigenen Tabellen in die Maske integriert werden. Eine Maske Form umfaßt ein Objekt vom Typ FormContainer, welches alle Elemente enthält, die Werte der Datenbank oder sonstige Informationen darstellen. Die Klasse FormControl ist das Bedienelement der Maske, über welches der Maskenbenutzer Operationen auf dem angezeigten Tupel in der Maske veranlassen kann. Um das angezeigte Tupel in der Maske oder auch die Tupelmenge, auf denen die Maske zu einem bestimmten Zeitpunkt operiert, zu exportieren, also z. B. als Report auszugeben, gibt es die abstrakte Klasse FormOutput, die eine Schnittstelle der Maskendaten nach außen darstellt. Aufgrund der oben dargestellten Möglichkeit spezieller Darstel- Abbildung 3.5: Klassenübersicht zum Paket db.form lungsformen der Beziehung zwischen Master-Child-Informationen enthält eine Maske oder genauer ein FormContainer neben Objekten des Typs FormField auch Objekte vom Typ ComplexElement. Um z. B. ein unabhängiges Scrollen oder eine besondere Form der Änderung zu ermöglichen, besteht eine Beziehung zwischen ComplexElement und einem eigenen Bedienteil des Typs FormControl. Die Klassen Record, Table und List sind nur Beispiele für mögliche Realisierungen eines ComplexElements. Ein Record stellt eine Art Submaske dar, z. B. innerhalb einer Rechnung die Darstellung der Attribute eines Rechnungspostens. Eine Table kann z. B. für die Darstellung aller Rechnungstupel einer Rechnung in tabellarischer Form verwendet werden. Zur Realisierung von Auswahllisten, deren Inhalt von bestimmten Attributen anderer 3.3 Entwurf der Maske Relationen abhängen, wie z. B. Fremdschlüsselwerte, kann ein Objekt vom Typ List verwendet werden. Die vorgestellten Klassen vom Typ ComplexElement benötigen alle einen Zugriff auf die Datenbank, der unter Umständen unabhängig vom Zugriff der Sicht ist. Auch die einfachen Felder vom Typ FormField bieten vielfältige Darstellungsmöglichkeiten, dies zeigt Abbildung 3.6 noch genauer und wird im nächsten Abschnitt beschrieben. Neben diesen Elementen der Maske, die einen direkten Bezug zu Datenbankwerten haben, sind auch Bestandteile der Maske möglich, die eine bestimmte Aktion auslösen, sogenannte aktive Elemente (ActiveElement), wie z. B. Buttons. Dies wird hier nicht weiter verfolgt, grundsätzlich ist aber die Spezialisierung der Klasse Form möglich, die geeignete zusätzliche Methoden implementiert, um Aufrufe aktiver Elemente zu bearbeiten. Ein Objekt vom Typ ActiveElement kann einfach in das Layout des FormContainers eingefügt werden. Durch die abstrakte Oberklasse FormContainerElement ist vorgegeben, daß implementierende Unterklassen Angaben zu ihrem Layout an den FormContainer übergeben. 3.3.2 Spezifizierung der Maskenelemente und des Maskenlayouts Von den in der Sichtrelation enthaltenen Attributen wird durch die Angabe der Master-, Child- und Partner-Relationen festgelegt, ob sie änderbar sind oder nicht. Weitere Angaben, welche das Aussehen und die möglichen Benutzerinteraktionen auf den Maskenelementen, denen die Sichtattribute zugrundeliegen, festlegen, können im nächsten Schritt gemacht werden. Dabei sind folgende Angaben für jedes Attribut möglich: • Attributwert sichtbar? • Bezeichnung des Attributs. • Auswahl des Anzeigeelements, welches den Wert des Attributs darstellen soll (z. B. einfaches Textfeld, (Auswahl-)Liste, spezielles Datumsfeld, etc.) und die Eingabe kontrolliert. • Formatierung (z. B. für Datums- oder Zeitfelder). • Default-Wert für Einfüge- und Suchoperation, falls der Wert des Attributs vom Maskenbenutzer nicht spezifiziert wird. • Nullwerte erlauben (soweit vom DBS erlaubt)? • Änderungen erlauben (soweit vom DBS und anhand des Sicht-AbhängigkeitsGraphen erlaubt)? • Suchen erlauben? Soweit möglich, werden Informationen aus dem DBS hinzugezogen, um bestimmte Voreinstellungen zu treffen, wie das Verbieten von Änderungen von Primärschlüsseln, Verbieten von Nullwerten bei Not-Null-Attributen etc. Dies ergibt sich aus der 45 46 Konzeption eines Maskengenerators Sichtdefinition und ist im Maskenentwurf nicht änderbar. In den Klassen des Datenbankschemas Table und Column werden diese Informationen bereitgestellt. Änderungen hierzu müssen konkret am Datenbankschema vorgenommen werden. Da das Entwurfswerkzeug auch als Bestandteil von Dato1 aufgerufen werden kann, können solche Änderungen in Dato durchgeführt werden. Um in der Maske die Tupelwerte anzuzeigen, wird jedem sichtbaren Attribut ein Anzeigeelement zugeordnet, welches die Darstellung und unter Umständen die Eingabeprüfung des Werts übernimmt. Abbildung 3.6 zeigt die Oberklasse FormField mit ihren Beziehungen zu Klassen des Datenbankschemas und der Datenbankinstanz, sowie möglichen Unterklassen, welche die Funktionalität implementieren, die abhängig von dem anzuzeigenden Datentyp ist. Die Menge der Anzeigeelemente ist Abbildung 3.6: Klassenübersicht zum Paket db.form.field während des Maskenentwurfs fest vorgegeben. Eine Programmierschnittstelle bietet allerdings die Möglichkeit, weitere Anzeigeelemente als Unterklassen hinzuzufügen, so daß auch spezielle Darstellungsarten, z. B. für Bilder oder Audiodaten, ausgewählt werden können. Das Anzeigeelement legt dabei fest, wie die Darstellung und Validierung der Werte erfolgen soll und welche Bearbeitungsfunktionen erlaubt sind. Die Klasse FormField hat eine Verbindung zu einem Wert aus der Datenbank in der Klasse Value und zur Beschreibung der Darstellung eine Verbindung zur Klasse ViewColumn. Der sichtbare Teil wird in einer Unterklasse von Component, einer Klasse aus dem Java Developer Kit (JDK), dargestellt und der Inhalt von einem Validator überprüft. Um die Parameter in JForms einstellen zu können, gibt es zu jedem implementierten FormField eine Unterklasse von FieldAdjust, welches die Benutzerschnittstelle für JForms liefert und die Parameter zu einem FormField speichert. Zu jedem FormField gehören die Attribute visible, searchable,deleteable, insertable und replaceable, die angeben, ob ein Feld sichtbar ist und ob es für die entsprechenden 1 Dato ist ein Datenbank-Administrations-Tool für beliebige DBMS, entstanden in der Studienarbeit [vH98] und in Java realisiert. 3.3 Entwurf der Maske Änderungsoperationen spezifiziert werden kann. Die Implementierung eines FormFields muß dies geeignet berücksichtigen. Für die Darstellung boolescher Werte ist die Klasse StateField gedacht, binäre Daten haben die gemeinsame Oberklasse BinaryField, von denen als Beispiel die Klassen ImageField zur Anzeige von Bildern und AudioField zur Darstellung“ von Sound” Daten. Die Klasse TextField ist Oberklasse zur Darstellung aller Grunddatentypen. Als Beispiel für mögliche Unterklassen gibt es CharField zur Darstellung von kürzeren Zeichenketten, LongCharField zur Darstellung von längeren Texten (z. B. als Grundlage für Felder zur Darstellung von HTML-Seiten in der Klasse HTMLField) und FormatField mit den Unterklassen TimeField, DateField und NumberField zur Darstellung von Uhrzeit, Datum und (formatierten) Zahlen. Die Klasse TimeStampField besteht aus Datum und Uhrzeit und ist daher Unterklasse von DateField und TimeField. Bei der Realisierung muß die Mehrfachvererbung, die es z. B. in Java nicht gibt, durch eine geeignete Konstruktion nachgebildet werden, z. B. durch entsprechende Assoziationen. Objekte vom Typ ChoiceElement sind Auswahllisten, die eine Auswahl vorgegebener Werte anzeigen, von denen einer in die Datenbank eingefügt wird, z. B. für die Anrede oder den Familienstand einer Personen-Relation. Neben den Anzeigeelementen, welche sich auf Werte der Sicht beziehen, sind weitere Maskenelemente wie Hintergrundbilder, Trennlinien etc. vorstellbar. Die Anordnung der Maskenelemente soll in einem graphischen Editor erfolgen, der das spätere Aussehen der Maske sichtbar macht. Die zu einem Anzeigeelement einstellbaren Werte müssen in geeigneter Form gespeichert, z. B. muß sich zu einem TextField die Breite oder die Änderbarkeit gemerkt werden. Da die Menge der Anzeigeelemente beliebig erweitern läßt, sind diese Informationen für jedes Element extra zu speichern, eventuell zusammengefaßt in einer Datei zu einer Sicht. 3.3.3 Abbildung der Datentypen Die Zuweisung von Werten aus der Datenbank an Objekte geeigneter Java-Klassen stellt ein eigenes Problem dar, welches hier kurz dargestellt werden soll. Dazu gehört die Transformation der Datenbankwerte in Werte von Java-Typen und die Transformation des Java-Datentyps in eine bestimmte Form, die dem Benutzer in der Maske angezeigt wird. So muß ein Datumswert aus der Datenbank im Java Datumsformat gespeichert werden und in der Maske in einem bestimmten Format angezeigt werden. Beim Einfügen oder Ändern eines Werts muß die entsprechende Rücktransformation vorgenommen werden. Neben diesen einfachen Datentypen muß insbesondere die Transformation von komplexen oder objektwertigen Datentypen, wie sie von vielen aktuellen DBMS unterstützt werden, betrachtet werden. Die JDBC-Schnittstelle2 bietet zwar geeignete Methoden, um Werte auf verschiedene Weise auszulesen. Diese müssen jedoch noch geeignet durch ein FormField oder ComplexElement dargestellt 2 JDBC ist die Java API zur Anbindung von Java Programmen an Datenbanken und besteht aus einer Menge von Interfaces, die von den entsprechenden Datenbanktreibern realisiert werden. JDBC ist nach [HCF97] eigentlich ein Warenzeichen, wird aber oft als Abkürzung für Java Database Connectivity verstanden. 47 48 Konzeption eines Maskengenerators werden. Die Tabelle 3.1 zeigt eine mögliche Transformation von SQL-Datentypen, JDBC-Datentypen und Java-Datentypen, sowie den Klassen zur Darstellung dieser Werte. [HCF97] enthält weiterführende Informationen zu dieser Problematik. InsbeSQL Typ JDBC Typ Größe [byte] CHAR CHAR 255 String CharField VARCHAR2 VARCHAR 255 String LongCharField LONG LONGVARCHAR String LongCharField NUMBER NUMERIC math.BigDecimal NumberField NUMBER DECIMAL math.BigDecimal NumberField NUMBER BIT NUMBER TINYINT 1 byte 1 short 2 NumberField NUMBER SMALLINT 2 short 2 NumberField NUMBER INTEGER 4 int 4 NumberField NUMBER BIGINT 8 long 8 NumberField NUMBER REAL float 4 NumberField NUMBER FLOAT double 8 NumberField NUMBER DOUBLE double 8 NumberField NUMBER BINARY 255 byte[] BinaryField RAW VARBINARY 255 byte[] BinaryField LONGRAW LONGVARBINARY byte[] BinaryField DATE DATE sql.Date DateField DATE TIME sql.Time TimeField DATE TIMESTAMP sql.Timestamp TimeStampField 1bit Java Typ boolean Größe [byte] 1bit FormField StateField NumberField Tabelle 3.1: Zuordnung von Datentypen (JDBC Version 1.0) sondere ist auch die neuere JDBC Version 2.0 zu beachten, die in Bezug auf komplexe Datentypen eine Erweiterung erfahren hat. In einer eigenen Property-Datei soll die Zuordnung abgelegt werden, um mögliche Erweiterungen und neue Masken-Felder leicht in den JForms integrieren zu können. Das Einlesen und ein Teil der Konvertierung von einem Datenbankformat in ein internes Java-Format wird von den Unterklassen von Value vorgenommen, die zuständig für das korrekte Auslesen der Daten ist. Die Schnittstelle zur Datenbank und die Interaktion wird in den Abschnitten 3.4.1 und 3.4.2 beschrieben. Bei der Formatierung von Werten, wie z. B. beim Datum, kann durch Angabe eines Formatstrings auch die Eingabe von Werten vom Benutzer auf Richtigkeit überprüft werden. Dafür ist die Verbindung der Klasse FormField zu einem Validator vorgesehen. Dieser Validator kann in Abhängigkeit des zugehörigen FormField die Überprüfung vornehmen und nicht zum Format passende Werte zurückweisen. Dadurch ist eine Reaktion auf eine Benutzereingabe unmittelbar nach Eingabe in einem Feld möglich und nicht erst beim Fehlschlagen des Schreibens des Tupels in die Datenbank. Auch kann hier durch den Formatstring eine Konvertierung vorgenommen werden, z. B. durch Anfügen von Kürzeln bei einer Nummer zur Identifikation des Benutzers oder ähnliches. 3.4 Die Ausführung der Maske und die Anbindung an eine Datenbankinstanz Eine mögliche Erweiterung der Funktionalität von Suchanfragen ist, einem FormField einen Parser für komplexere Suchausdrücke zuzuweisen. Dieser kann z. B. AND und OR Verknüpfung von Werten in Suchfeldern ermöglichen. 3.3.4 Generieren der Maske Sind die Angaben zu Inhalt und Aussehen der Maske vorgenommen, sind also die Sicht-Attribute durch die Angaben des Maskenentwerfers näher bestimmt, so werden diese in einer Einstellungsdatei gespeichert. Die Klasse Form benutzt diese Datei mit den Einstellungen, um das Layout und die Operationen entsprechend des Entwurfs umzusetzen. Aufgerufen wird die Maske innerhalb der Klasse FormApplication, die Unterklasse von DBApplication ist und von dieser den Zugriff auf die Datenbank erbt. Die Klasse FormContainer übernimmt das Layout der Maskenelemente und die Klasse Form realisiert die Operationen der Maske. Dadurch ist es möglich, Layout der Maske und Funktionalität auf Programmierebene weitestgehend zu separieren und eine leichtere Änderbarkeit zu gewährleisten. Zum einen können die Klassen, die mit der Klasse Form direkt verbunden sind, noch erweitert und ergänzt werden, zum anderen kann die Menge der Darstellungselemente, die Unterklassen von FormField, noch erweitert werden. Die Angaben der einzelnen Anzeigeelemente werden in einer Datei zu einer Maske gespeichert und für die Darstellung der Maske von der Klasse Form eingelesen. Diese richtet die Darstellung, also Form, Größe und Position gemäß den Angaben in der Datei aus. 3.4 3.4.1 Die Ausführung der Maske und die Anbindung an eine Datenbankinstanz Die Datenbankschnittstelle Die Klassen aus Abbildung 3.7 sollen eine Trennung der Maskenumgebung von der Datenbank-API ermöglichen. Eine Operation liefert entweder eine Tupelmenge zurück oder verwendet eine vorhandene Tupelmenge. Die einzelnen Tupel einer Tupelmenge bestehen ihrerseits aus mehreren Werten, die aus der Datenbank stammen. Eine Such-, Lösch- oder Ersetzungsänderung wird auf einer Menge von Tupeln ausgeführt, die einer bestimmten Bedingung genügen, realisiert durch die Klasse Condition. Da die Maske auf der Sichtrelation operiert, müssen die Operationen auf der Maske/Sicht in Operationen auf den Relationen der Datenbankinstanz übersetzt werden. Die Klasse ViewOperation übernimmt diese Übersetzung und implementiert die in Abschnitt 2.4 vorgestellten Algorithmen. Die Klasse Operation ist die Oberklasse der konkreten Datenbankoperationen Search, Insert, Replace und Delete. Über die Klasse Statement der JDBC-Schnittstelle erfolgt die Anbindung an die Datenbank. Ergebnismengen, von JDBC als ResultSet geliefert, werden in der Klasse TupelSet gekapselt. Diese Menge besteht aus mehreren Objekten des Typs Tupel. Dieser wiederum umfaßt die eine Menge von Werten, durch die Klasse Value dargestellt. Die Klasse Value ist abstrakte Oberklasse für 49 50 Konzeption eines Maskengenerators Abbildung 3.7: Klassenübersicht zum Paket db.instance alle Klassen, die das Einlesen der Werte entsprechend des Datentyps vornehmen. Diese Differenzierung wird besonders wichtig beim Einlesen von binären Daten oder objektwertigen Attributen und erlaubt eine gekapselte Behandlung einer möglichen Konvertierung. Die enge Beziehung der Klasse Value zur Klasse FormField erlaubt somit, daß sowohl auf der Ebene der Klasse Form als auch auf der Ebene der Klasse TupelSet keine besonderen Vorkehrungen zum Einlesen verschiedener Datentypen vorgenommen werden müssen. Die Ergebnismenge der Klasse ResultSet der JDBC-Schnittstelle ist, abhängig vom Treiber des implementierenden Datenbanksystems, nicht immer in beiden Richtungen scrollbar, d. h. die Tupel können unter Umständen nur von vorne nach hinten einmal eingelesen werden. Ein Zurückgehen zum vorigen Tupel ist dann nicht möglich. Da die Maske jedoch auch das Rückwärtsbewegen in der Ergebnismenge erlaubt, muß die Klasse TupelSet abhängig vom ResultSet das Auslesen und Speichern der Tupel selbst übernehmen. Die damit verbundenen Probleme wie das Speichern von großen Ergebnismengen, Performance des Einlesevorgangs etc., sind in einer gesonderten Betrachtung zu untersuchen. Es wird davon ausgegangen, daß die Scrollfunktion in der Klasse TupelSet geeignet implementiert wird bzw. ein JDBC-Treiber verwendet wird, der das Scrollen in ResultSets erlaubt. 3.4.2 Interaktion der Maske mit einer Datenbankinstanz Wird die Maske geöffnet, so zeigt sie noch keine Daten an. Der Benutzer bekommt nach Angabe der Auswahlkriterien die Tupel der Ergebnismenge angezeigt und kann diese nacheinander sehen und Änderungen vornehmen. Die Anbindung erfolgt wie in Abbildung 3.8 dargestellt. Über die Maske Form wird eine Operation ViewOperation auf der Sicht ausgeführt, diese wird in Operationen auf der Datenbankinstanz übersetzt und auf dieser anschließend ausgeführt (mittels Unterklassen von Operation). Unter Umständen wird eine Menge von Tupeln durch die Klasse TupelSet zurückgeliefert. Ein Tupel liefert die Werte (Value), die in den Feldern (FormField) der Maske 3.4 Die Ausführung der Maske und die Anbindung an eine Datenbankinstanz Abbildung 3.8: Anbindung der Maske an eine Datenbankinstanz angezeigt werden. Die Art und Weise der Darstellung hängt von den Vorgaben ab, die im Maskenentwurf gemacht wurden. 3.4.3 Zustände und Operationen einer Maske Neben der Darstellung der Werte aus der Datenbank soll die Maske auch Operationen auf den dargestellten Werten ausführen. Die Operationen aus Tabelle 3.2 und 3.3 werden von der Klasse Form implementiert und zum Teil von dem Bedienteil FormControl dem Maskenbenutzer sichtbar gemacht. Die Operationen aus Tabelle 3.2 Operation Beschreibung search Suchen von Tupeln insert Einfügen eines neuen Tupels replace Ändern des aktuellen Tupels delete Löschen des aktuellen Tupels Tabelle 3.2: Operationen einer Maske auf einer Datenbankinstanz, die in eigenen Klassen realisiert werden. werden in dem Package db.instance modelliert, dessen Klassen von der Klasse Form verwendet werden. Die in Tabelle 3.3 dargestellten Operationen werden von der Klasse Form entweder selbst implementiert oder über geeignete Schnittstellen von anderen Klassen übernommen, wie z. B. die Klasse Report, welche eine Möglichkeit des Datenexports realisiert. Reicht der Funktionsumfang nicht aus, so ist es möglich, weitere Unterklassen einzufügen und z. B. über FormControl oder geeignete Menüpunkte zugänglich zu machen. 51 52 Konzeption eines Maskengenerators Operation Beschreibung commit Änderungen in die DB schreiben cancel Änderung rückgängig machen previous Anzeige des vorigen Tupels next Anzeige des nächsten Tupels export Exportiere Werte des aktuellen Tupels oder der aktuellen Auswahl close Schließen der Maske Tabelle 3.3: Weitere Operationen einer Maske, die von der Maske oder von den anderen Operationen realisiert werden. Die verschiedenen Operationen der Maske machen unterschiedliche Zustände der Maske notwendig, z. B. dürfen bei einer Ersetzungsoperation bestimmte Attribute nicht änderbar sein, bei einer Suchoperation sollen alle Attributwerte bis auf die Default-Suchwerte leer sein usw. Abbildung 3.9 zeigt die erforderlichen Zustände, die in Tabelle 3.4 beschrieben sind. Operation Beschreibung VIEW zeigt die Attribute mit den Werten eines Tupels der Sicht an. SEARCH zeigt die Attribute, nach denen gesucht werden kann, mit leeren Werten an. DELETE zeigt die Werte des Tupels, das gelöscht werden soll. INSERT zeigt die Attribute, die für ein neues Tupel eingegeben werden können, mit leeren oder Defaultwerten an. REPLACE zeigt die Attribute, die geändert werden können, mit den Werten eines Tupels an. Tabelle 3.4: Zustände einer Maske Die Maske befindet sich zu Beginn im Suchzustand, um die zu bearbeitende Tupelmenge durch den Benutzer spezifizieren zu lassen. Anschließend wird in den Anzeigezustand gewechselt, der zentrale Zustand der Maske, von dem aus die verschiedenen Operationen ausgeführt werden können. Durch die Verwendung aktiver Elemente, wie in Abschnitt 3.3.1 beschrieben, sind weitere Zustände möglich. 3.5 Der Maskengenerator JForms Für den Entwurf einer Maske wird mit JForms ein Tool zur Verfügung gestellt, welches die Spezifikation einer Sicht unterstützt, Einstellungen der Art und Weise der Darstellung von Datenbankwerten erlaubt und bei der Gestaltung der Maske behilflich ist. In dieser Arbeit wird allerdings das Augenmerk nur auf die Spezifizierung der Sicht gelenkt. Abbildung 3.10 zeigt einige Klassen, die hierfür notwendig sind. 3.5 Der Maskengenerator JForms Abbildung 3.9: Zustandsdiagramm einer Maske vom Typ Form Es ist sowohl als eigenständiges Tool lauffähig oder über Dato3 als Plug-In aufrufbar und benutzt dann die Datenbankverbindung von Dato. Die Spezifizierung der Sicht erfolgt in den beiden Fenstern RelationWindow für die Tabellen der Sicht und AttributeWindow für die Sichtattribute. Im RelationWindow wird das Datenbankschema der Datenbank gezeigt, an der sich der Benutzer angemeldet hat, und die Tabellen der Sicht, die aus dem Schema ausgewählt werden können. Intern wird dabei die Klasse MetaScheme verwendet, welche die notwendigen Informationen über die Datenbankobjekte zur Verfügung stellt. Nach Auswahl einer Relation kann für diese festgelegt werden, ob sie Master-Relation ist. Falls eine Relation als Master-Relation gekennzeichnet wird, so werden die restlichen Relationen der Sicht als Child- oder Partner-Relation klassifiziert, je nachdem, welcher Art eine Fremdschlüsselbeziehung zur Master-Relation ist. Beim Hinzufügen einer Relation in die Sicht werden automatisch für die Schlüsselbeziehungen zwischen allen Relationen Equi-Joins in die Sichtbedingung eingefügt. Welche Attribute in der Sicht verwendet werden, wird im AttributeWindow festgelegt, welches die Sichttabellen und die Attribute anzeigt. Auch die Spezifizierung der Darstellungsart erfolgt an dieser Stelle, also die Auswahl des geeigneten Anzeigeelements, die Änderbarkeit, Wertebereiche etc., wobei die Anzeigeelemente geeignete Default-Werte für ihre Einstellungsmöglichkeiten bereithalten. Parallel zur Auswahl der Sichtelemente wird der Sicht-Abhängigkeits-Graph aufgebaut, aus dem bestimmte Angaben zur Änderbarkeit ablesbar sind. Die Informationen sind in drei Bereiche eingeteilt. Der erste Bereich enthält Informationen zu dem Attribut der Relation, die nicht geändert werden können. Im zweiten Bereich wird das Anzeigeelement vom Typ FormField festgelegt. Je nach Anzeigeelement können unterschiedliche Einstellungen vorgenommen werden, wie z. B. Beschriftung und Größe eines Felds. Zu jedem FormField ist mindestens einstellbar, ob es sichtbar ist und ob das Attribut für die Spezifikation der Operationen search, delete, insert und replace verwendet werden kann. Im dritten Einstellungsbereich wird die Plazierung innerhalb des GridBagLayouts der Maske bestimmt, wobei die unterschiedlichen GridBagConstraints modifiziert 3 siehe [vH98] 53 54 Konzeption eines Maskengenerators Abbildung 3.10: Die Klassen des Maskengenerators JForms werden können. Eine wichtige Erweiterung, die nur erwähnt bleiben soll, ist ein graphischer Editor für die Maske, in welchem die Maskenelemente vom Typ FormContainerElement plaziert werden können. In Java wird das Layout von graphischen Komponenten von sogenannten Layout-Managern übernommen, deren flexibelster von der Klasse GridBagLayout dargestellt wird. Da dieser auch von der Klasse FormContainer zur Plazierung seiner Elemente verwendet wird, sollte es möglich sein, den graphischen Editor auf der Basis des GridBagLayout zu entwerfen und für den Spezialfall des Maskenlayouts anzupassen. Im JavaWorkshop von Sun, einer Java-Entwicklungsumgebung, ist ein solcher Editor zur Plazierung von Objekten des Typs Component in einem Container beispielsweise realisiert. Die GridBagConstraints eines Objekts vom Typ Component bestimmen das Aussehen und die Plazierung innerhalb des Layouts. Sind die oben beschriebenen Angaben zur Sicht und zur Maske eingegeben worden, so kann die Sicht erzeugt werden und die Maske angezeigt werden. Die Einstellungen sind jederzeit änderbar, so werden z. B. Änderungen an den Layout-Parametern eines Feldes durch Aktualisieren der Maske sichtbar. Ein Maskenprojekt wird innerhalb eines eigenen Verzeichnisses in Form verschiedener Property-Dateien gespeichert. Dafür muß der Maske ein Name gegeben werden, der für die Sicht und als Verzeichnisname verwendet wird. Durch Angabe eines Verzeichnisses werden die Property-Dateien des Projekts in einem darunterliegenden Verzeichnis mit dem Projektnamen gespeichert. Für die Ausführung der Maske muß eine Objekt vom Typ View erzeugt werden, indem das Projektverzeichnis angegeben wird. Anschließend wird die Sicht View einem Objekt Form übergeben, welches das Container Objekt liefert, welches in einem beliebigen Frame angezeigt werden kann. Dieser ganze Ablauf wird in der Klasse FormApplication vorgenommen, die mit der Angabe des Projektverzeichnisses gestartet wird. Diese Klasse ist Ausgangspunkt, 3.5 Der Maskengenerator JForms oder besser Oberklasse für alle Anwendungen, welche Masken verwenden und über Menüs zusätzliche Funktionen für den Benutzer bereithalten. Für die in der Maske verwendeten aktiven Elemente wie Buttons kann die zugehörige Realisierung der auszulösenden Operationen z. B. in einer Unterklasse von FormApplication erfolgen bzw. von dort weiter delegiert werden. Werden innerhalb einer Anwendung viele Masken mit aktiven Elementen verwendet, so ist auch eine Aufteilung des Event-Handlings denkbar, indem zu jeder Maske eine Unterklasse von Form erzeugt wird, welche die Events der Buttons dieser Maske abfängt und auf dieser Ebene die Operationen ausführt. 55 56 Konzeption eines Maskengenerators Kapitel 4 Die Implementierung eines Gerüsts“ für den ” Maskengenerator JForms Das in Kapitel 3 vorgestellte Konzept zeigt den Umfang eines Systems Masken” generator“ und eine mögliche Umsetzung unter Berücksichtigung der theoretischen Erkenntnisse aus Kapitel 2. Das Konzept wurde im Hinblick auf Erweiterbarkeit und mit einigen Ausblicken möglicher Erweiterungen entwickelt. Um während des Designs nicht Anwendungsfälle zu übersehen, die ein anschließendes Re-Design bei einer Erweiterung notwendig machen, sind in der vorgestellten Klassenstruktur viele Klassen, die als Beispiele für Implementationen dienen. In dieser Arbeit wird exemplarisch nur ein Teil von dem realisiert, was auf konzeptioneller Ebene schon ausgearbeitet ist. Dieses Kapitel beschreibt die Implementierung eines Gerüsts und der Grundfunktionalität der Maske, soweit die Beschreibung des Konzepts nicht detailliert genug ist. 4.1 Die Darstellung des Datenbankschemas und des Sichtschemas Das Meta-Schema, durch die Klasse MetaScheme dargestellt, wird mit der Übergabe eines Objekts vom Typ DBApplication initialisiert, um über die notwendige Datenbankverbindung zu verfügen. Die Informationen zu den statischen“ Elementen Table ” und Column werden über die JDBC-Klassen DatabaseMetaData und ResultSetMetaData eingelesen. Da dieser Vorgang relativ zeitaufwendig ist, geschieht dies nur bei Bedarf. Das Meta-Schema liegt zu Beginn also nicht komplett vor, so daß der Zugriff auf die Elemente gesteuert werden muß. Daher können Objekte vom Typ Table und Column nicht direkt erzeugt werden, sondern sind über die Klassenmethoden von MetaScheme zugänglich. Da während der Sichtspezifikation von einem statischen Datenbankschema ausgegangen wird, sind die Attribute dieser Objekte nicht änderbar. Abbildung 4.1 zeigt die Methoden von MetaScheme und den statischen“ ” Elementen. Die Sicht vom Typ View wird ebenfalls von MetaScheme geliefert. Diese erzeugt 58 Die Implementierung eines Gerüsts“ für den Maskengenerator JForms ” Abbildung 4.1: Methodenübersicht zum Meta-Schema 4.2 Pfadsuche im Abhängigkeits-Graphen sich bei Angabe eines Verzeichnisses aus den Einstellungen der darin enthaltenen Property-Dateien. Die Klasse View übernimmt die Verwaltung ihrer Elemente selbst, Sicht-Relationen und Sicht-Attribute sind über die Methoden der View zugänglich. Eine Änderung der Sicht ist über die entsprechenden Modellklassen möglich, so daß die Konsistenz der Benutzerschnittstelle leichter sichergestellt werden kann. Beim Einfügen und Löschen von Sichtrelationen und Sichtattributen werden die Änderungen an den Abhängigkeitsgraphen weitergegeben. In Abbildung 4.2 sind die Methoden zur Sicht und in Abbildung 4.3 die der Sicht-Elemente dargestellt. Abbildung 4.2: Methodenübersicht der Klasse View 4.2 Pfadsuche im Abhängigkeits-Graphen In Definition 2.34 haben wir den Begriff des Pfads zwischen Knotenmengen im Abhängigkeits-Graphen definiert, mit der besonderen Eigenschaft der FD-Knoten. Der herkömmliche Breiten-Suche-Algorithmus, mit dessen Hilfe man in gewöhnlichen Graphen Pfade suchen kann, ist nur auf Pfade zwischen zwei Knoten definiert. Daher wurde ein eigener Algorithmus implementiert, der überprüft, ob zwei Knotenmengen laut Definition 2.34 durch einen Pfad verbunden sind. Ein Knoten n kann drei verschiedene Zustände haben: 59 60 Die Implementierung eines Gerüsts“ für den Maskengenerator JForms ” Abbildung 4.3: Methodenübersicht der Sicht-Elemente 1. n wurde nicht besichtigt und ist nicht passierbar (Initialzustand), 2. n wurde besichtigt und ist nicht passierbar oder 3. n wurde besichtigt und ist passierbar. Ein Knoten wurde besichtigt, wenn er das erste Mal im Such-Algorithmus angefaßt“ ” wurde. Diese Markierung ist genau wie beim Breiten-Suche-Algorithmus notwendig, um nicht durch Zyklen in eine Endlosschleife zu gelangen. Ein Knoten, der nicht FD-Knoten ist, ist passierbar, wenn er besichtigt wurde und mindestens ein Vorgänger passierbar ist oder wenn er in der Startmenge der Knoten ist, von welcher der gesuchte Pfad ausgeht. Ein FD-Knoten ist passierbar, wenn er besichtigt wurde und alle seine Vorgänger passierbar sind oder wenn er in der Startmenge der Knoten ist, von welcher der gesuchte Pfad ausgeht. Sei FROM die Menge der Knoten, von welcher der gesuchte Pfad ausgehen, TO die Menge der Knoten, zu welcher der gesuchte Pfad führen soll. Sei NV (not-visited) die Menge der Knoten, die nicht besichtigt wurden, VNP (visited-not-passable) die Menge der Knoten, die besichtigt wurden aber nicht passierbar sind und VP (visited- 4.3 Der Maskeneditor JForms passable) die Menge der Knoten, die besichtigt wurden und passierbar sind. Ein Pfad existiert genau dann, wenn am Ende des Algorithmus gilt: TO ⊆ VP. Zu Beginn seien VNP und VP leer, NV enthalte alle Knoten des Graphen. Alle Knoten von FROM werden in die Menge VP eingefügt und aus der Menge NV entfernt. Für die Nachfolger der Knoten von FROM untersuche, ob sie passierbar sind. Falls ja, füge sie in VP ein, ansonsten in VNP. Entferne sie jeweils aus NV bis NV leer ist. Anschließend führe dies solange mit den Knoten in VNP durch, bis entweder TO ⊆ VP (Pfad gefunden) oder sich die Mengen VNP oder NV nicht mehr verkleinern (kein Pfad gefunden). Im Anhang B.2 ist der Algorithmus in Java umgesetzt, eine Übersicht der Klassenmethoden ist in den Abbildungen B.7 und B.8 im Anhang zu finden. 4.3 Der Maskeneditor JForms Die Klasse JForms ist die Hauptklasse des Maskeneditors.1 Die Sichtdefinition und die Einstellungen der Maske erfolgen über diese Klasse. Neben dem Laden und Speichern der Einstellungen kann die Auswahl der Sicht- und Maskenelemente in verschiedenen Fenstern vorgenommen werden. Das Layout der Maske kann durch Einstellung der verschiedenen Parameter des GridBagConstraints verändert werden. Ein graphischer Editor, der hier nicht realisiert wurde, könnte auf diese Schnittstelle aufsetzen und das GridBagLayout komfortabel per Maus änderbar machen. Die Sicht-Graphen können ausgegeben werden und nach Angabe zweier Knotenmengen kann überprüft werden, ob ein Pfad zwischen diesen existiert. 4.3.1 Auswahl und Einstellungen der Sichtelemente Die Sichtelemente werden in den Fenstern RelationWindow und AttributeWindow2 ausgewählt und spezifiziert. Sie haben eine gemeinsame Oberklasse, welche die ähnliche Darstellung der beiden Fenster bestimmt. Abbildung 4.4 zeigt das Fenster zur Auswahl der Sicht-Relationen. Im oberen Teil können links beliebige Relationen beliebiger Schemata in die Sicht aufgenommen werden, die auf der rechten Seite erscheinen. Im unteren Teil ist die Auswahl einer Master-Relation festzulegen, wobei anschließend die restlichen Relationen in Child- und Partner-Relationen eingeteilt werden. Diese Einteilung kann nicht manuell geändert werden. Aus den Sicht-Relationen sind im AttributeWindow die darzustellenden Attribute der Sicht auswählbar. Zu einem Attribut lassen sich Informationen aus der Datenbank anzeigen, die jedoch nicht geändert werden können, siehe Abbildung 4.5. Die Einstellungsmöglichkeiten eines FormFields sind in Abbildung 4.6 dargestellt. Im oberen Teil des Einstellbereichs sind die Einstellungen sichtbar, die zu jedem FormField gemacht werden können, also ob das Feld sichtbar ist und bei welchen Operationen es spezifiziert werden kann. Das Layout oder die GridBagConstraints, die zu jedem FormField gehören, werden im dritten Teil des Attribut-Fensters eingestellt, siehe Abbildung 4.7. Die Default-Werte in diesem Teil können für jedes implementierte 1 2 Das zugehörige Klassendiagramm mit den Methoden ist in Abbildung B.1 im Anhang zu sehen. Siehe auch die Abbildung B.2 im Anhang. 61 62 Die Implementierung eines Gerüsts“ für den Maskengenerator JForms ” Abbildung 4.4: Auswahl der Sicht-Relationen Abbildung 4.5: Auswahl der Sicht-Attribute und Anzeige der DB-Informationen der entsprechenden Spalte 4.3 Der Maskeneditor JForms Abbildung 4.6: Einstellungen zu einem FormField FormField in einer zu dieser Klasse gehörenden Property-Datei gesondert angegeben werden, so daß z. B. einzeilige Textfelder immer horizontal ausgedehnt oder gestaucht werden3 bei Ändern der Größe der Maske und mehrzeilige Textfelder ihre Größe sowohl horizontal als auch vertikal anpassen.4 Die vielfältigen Parameter des GridBagLayouts lassen eine differenzierte Gestaltung der Maske zu. Sind alle Angaben gemacht, so kann die Sicht erzeugt und das Layout der Maske angesehen werden. Abbildung 4.8 zeigt eine solche generierte Maske. Eine angezeigte, generierte Maske kann mit den geänderten Parametern aktualisiert werden, indem der Button Show Form“ nochmals gedrückt wird. Die Operationen der Maske sind ” direkt ausführbar, so daß die Funktionalität der Maske gleich überprüft werden kann und die verschiedenen Stati der Maske sichtbar werden. 4.3.2 Speichern der Einstellungen in Property-Dateien Da die Einstellungen auf verschiedene Property-Dateien verteilt werden, ist es notwendig, diese in einem Verzeichnis zusammenzufassen. Dieses Verzeichnis trägt den Namen der Maske und kann innerhalb eines beliebigen Verzeichnisbaums gespeichert werden. Neben der Angabe eines Maskennamens muß also noch ein Verzeichnis gewählt werden, in welchem die Maskendaten in dem entsprechenden Unterverzeich3 4 Dies erfolgt durch Setzen des Fill-Parameters auf HORIZONTAL. Dafür wird der Fill-Parameter auf BOTH gesetzt. 63 64 Die Implementierung eines Gerüsts“ für den Maskengenerator JForms ” Abbildung 4.7: Einstellungen zum Layout Abbildung 4.8: Eine generierte Maske 4.4 Der Ablauf der generierten Maske nis abgelegt werden. Aufgeteilt werden die Maskendaten auf folgende Property-Dateien, deren Namen mit .properties enden: Connect: speichert den Namen des JDBC-Treibers und die zugehörige URL. View: speichert den Sichtnamen, der gleich dem Maskennamen ist, den Schemanamen, die Sichtbedingung und die Alias-Namen der Relationen und Attribute. ViewTables: speichert für alle Sicht-Relationen den Sichtnamen, den vollständigen Namen der zugehörigen Relation und den Typ (Master/Child/Partner). ViewColumns: speichert für alle Sicht-Attribute den Sichtnamen, den Namen des zugehörigen Attributs, den Alias-Namen der Sicht-Relation, den Klassennamen des darstellenden FormFields und ob das Attribut für die verschiedenen Operationen spezifiziert werden kann. FormFields: speichert für alle Sicht-Attribute die Angaben des darstellenden FormFields, also die GridBagConstraints sowie von den verschiedenen FormFieldImplementationen abhängige Einstellungen. Da die implementierten FormFields ihre Attribute in Objekten vom Typ Property speichern, erfolgt das Schreiben der Property-Dateien in der View über die Möglichkeit, daß ein Property Objekt seine Angaben direkt in einen OutputStream schreiben kann. Das Einlesen der Werte erfolgt auf umgekehrte Weise. Dazu werden in der Klasse View in einer Schleife alle Sicht-Elemente durchlaufen und die zugehörigen Properties gelesen oder geschrieben. 4.4 Der Ablauf der generierten Maske Das Einlesen der Masken-Einstellungen erfolgt durch Angabe des Maskenverzeichnisses mit den Property-Dateien in der entsprechenden Methode der Klasse MetaScheme (siehe Abbildung 4.1). Dies kann z. B. in einer Unterklasse von FormApplication erfolgen. Nach dem Einlesen kann die Maske in einem Fenster angezeigt und bedient werden. Die Klasse FormApplication wurde so implementiert, daß beim Aufruf der Klasse mit dem Maskenverzeichnis als Parameter ein Fenster mit der entsprechenden Maske geöffnet wird. Eine Operation wird vom Benutzer über die Klasse FormControl ausgelöst, welche eine entsprechende Methode von Form aufruft. Dafür wird zunächst der Zustand der Maske gewechselt, indem der Zustand sowohl an die Klasse FormControl, als auch die Klassen FormContainer und FormContainerElement delegiert wird. Anschließend wird die gewünschte Operation durch Aufruf der entsprechenden Methode der Klasse ViewOperation ausgeführt. In Abbildung 4.9 ist der Ablauf einer Such-Operation dargestellt. Hierbei liefert die Klasse ViewOperation das Anfrageergebnis in Form eines TupelSets zurück, in welchem navigiert werden kann. Das Einlesen der Werte erfolgt in einer implementierenden Unterklasse von Value. An dieser Stelle wird das zugehörige Maskenelement vom Typ FormField informiert, den neu eingelesenen Wert darzustellen. 65 66 Die Implementierung eines Gerüsts“ für den Maskengenerator JForms ” Abbildung 4.9: Ablauf einer Such-Operation Umgesetzt wurden exemplarisch die Such-Operation und die Replace-Operation. Bei der Delete-Operation ist zu beachten, daß vom Benutzer erfragt werden muß, ob sich das Löschen auf die Master-Relation oder auf eine Child-Relation bezieht. Dies kann entweder durch mehrere Delete-Buttons oder durch einen gesonderten Dialog realisiert werden. Bei der Insert-Operation ist zu beachten, daß unspezifizierte Felder entweder durch Null-Werte aufgefüllt werden oder das Einfügen zurückgewiesen wird, falls ein NotNullable-Feld nicht spezifiziert wurde. Das Scrollen im Anfrageergebnis ist in der Maske nur einmal in Vorwärtsrichtung möglich. Dies kann geeignet in der Klasse TupelSet erweitert werden und ist vom verwendeten JDBCTreiber abhängig, der erst ab der Version 2.0 scrollbare ResultSets unterstützt. In der JDBC-Version 2.0 wird auch das Ändern von ResultSets unterstützt, was in dieser Implementierung nicht weiter berücksichtigt wurde, aber bei einer Erweiterung der Funktionalität zu Hilfe genommen werden kann. So gibt es dort unter anderem die Methoden refreshRow, updateRow, insertRow, deleteRow und cancelRowUpdates. Diese Methoden vereinfachen die Implementation von Änderungen auf dem ResultSet sehr und können von der Klasse TupelSet genutzt werden. Da zum Zeitpunkt dieser Arbeit kein entsprechender Treiber zur Verfügung stand, wurden einige Operationen von TupelSet nicht realisiert. Die Abbildungen B.3, B.4 und B.5 zeigen die Methoden zu einer Maske und ihren Feldern. In Abbildung B.6 sind die Methoden der Klassen für den Datenbankzugriff dargestellt. Anhang A Abkürzungen Abkürzung Beschreibung ADT Abstrakter Datentyp API Application Programmers Interface BCNF Boyce-Codd-Normalform DB Datenbank DBS Datenbanksystem DBMS Datenbankmanagementsystem GUI Graphical User Interface JDBC Java Database Connectivity JDK Java Developer Kit JFC Java Foundation Classes RDBMS Relationales DBMS SQL Structured Query Language UML Unified Modeling Language 68 Abkürzungen Anhang B Programmierung B.1 Ausgewählte Klassendiagramme Abbildung B.1: Methoden von JForms 70 Programmierung Abbildung B.2: Methoden der Einstellfenster des Maskeneditors B.1 Ausgewählte Klassendiagramme Abbildung B.3: Methoden der Masken-Klassen Abbildung B.4: Methoden von FormField 71 72 Programmierung Abbildung B.5: Methoden von FieldAdjust Abbildung B.6: Methoden der Klassen für den Zugriff eine Datenbankinstanz B.1 Ausgewählte Klassendiagramme Abbildung B.7: Allgemeine Methoden des Graphen Abbildung B.8: Methoden des Abhängigkeits-Graphen und der spezialisierten Knoten 73 74 Programmierung B.2 Sourcecode zur Pfadsuche in Abhängigkeits-Graphen B.2 Sourcecode zur Pfadsuche in Abhängigkeits-Graphen /**---------------------------------------------------------------------*/ /** **/ public boolean existPath(MetaSchemeNode[] fromarray, MetaSchemeNode[] toarray) { Enumeration iter; Vector from, to, not_visited, visited_passable, visited_not_passable; MetaSchemeNode n; boolean found; int size, fromsize; from = new Vector(fromarray.length); to = new Vector(toarray.length); not_visited = new Vector(vertices.size()); visited_passable = new Vector(vertices.size()); visited_not_passable = new Vector(fdnodes.size()); // kopiere alle Knoten des Graphen in die Menge not_visited und // setze sie als "nicht besucht" iter = vertices.elements(); while (iter.hasMoreElements()) { n = (MetaSchemeNode)iter.nextElement(); n.setVisited(false); n.setPassable(false); not_visited.addElement(n); } // kopiere die Knoten des from-Arrays in einen Vector und markiere sie // als passierbar da sie Startknoten sind for (int i = 0; i < fromarray.length; i++) { from.addElement(fromarray[i]); fromarray[i].setPassable(true); } // kopiere die Knoten des to-Arrays in einen Vector for (int i = 0; i < toarray.length; i++) to.addElement(toarray[i]); size = not_visited.size() + 1; fromsize = from.size() + 1; found = false; while (!found && (size > not_visited.size() || fromsize > from.size()) && !from.isEmpty()) { size = not_visited.size(); fromsize = from.size(); // untersuche alle Nachfolger der Knoten aus from iter = from.elements(); while (iter.hasMoreElements()) visitSuccessors((MetaSchemeNode)iter.nextElement(), not_visited, visited_passable, visited_not_passable); from.removeAllElements(); // Pfad wurde gefunden, da to Teilmenge der Menge der passierbaren 75 76 Programmierung // Knoten ist if (isSubset(to, visited_passable)) found = true; else { iter = visited_not_passable.elements(); while (iter.hasMoreElements()) from.addElement(iter.nextElement()); } } return found; } /**---------------------------------------------------------------------*/ /** **/ private void visitSuccessors(MetaSchemeNode node, Vector not_visited, Vector visited_passable, Vector visited_not_passable) { Enumeration iter; Vector queue; queue = new Vector(); queue.addElement(node); // Anfangsknoten wurde besucht node.setVisited(true); while (!queue.isEmpty()) { node = (MetaSchemeNode)queue.firstElement(); queue.removeElement(node); // entferne Knoten aus der entsprechenden Menge if (node.isVisited()) visited_not_passable.removeElement(node); else not_visited.removeElement(node); node.setVisited(true); // pruefe ob der Knoten passierbare Vorgaenger hat if (!(node instanceof FDNode)) node.testPassable(); // teile Knoten der entsprechenden Menge zu if (node.isPassable()) { visited_passable.addElement(node); // uebernimm die Nachfolger in die Queue und untersuche sie // anschliessend iter = node.sucs.elements(); while (iter.hasMoreElements()) { node = (MetaSchemeNode)iter.nextElement(); if (!node.isVisited()) queue.addElement(node); } B.2 Sourcecode zur Pfadsuche in Abhängigkeits-Graphen } else visited_not_passable.addElement(node); } } /**---------------------------------------------------------------------*/ /** **/ private boolean isSubset(Vector subset, Vector superset) { Enumeration iter; boolean is; is = true; iter = subset.elements(); while (is && iter.hasMoreElements()) if (!superset.contains(iter.nextElement())) is = false; return is; } } 77 78 Programmierung Abbildungsverzeichnis 2.1 Der Spur-Graph für die Sicht V5 aus Abschnitt 2.1.4 . . . . . . . . . 17 2.2 Ein FD-Knoten zur funktionalen Abhängigkeit {B1 , . . . , Bk } →R A . 18 2.3 Der Abhängigkeits-Graph für die Sicht V5 aus Abschnitt 2.1.4 . . . . 18 2.4 Der gleiche Graph wie in Abbildung 2.3, jedoch hat die Sicht die zusätzliche Selektionsbedingung DEP=’Sales’ . . . . . . . . . . . . . 19 Der Abhängigkeits-Graph für die Sicht V = πY (R o nR.E=S.E S) mit Y = {R.A, R.B, R.C, R.D, R.E, S.F } über den Relationenschemata R[A, B, C, D, E] und S[E, F ] mit den funktionalen Abhängigkeiten {A, B, C} →R E und E →S F . . . . . . . . . . . . . . . . . . . . . . 20 2.6 Der Abhängigkeits-Graph für die Sicht V9 aus Abschnitt 2.1.4 . . . . 22 2.7 Der Abhängigkeits-Graph für die Sicht V8 aus Abschnitt 2.1.4 . . . . 23 2.8 Abhängigkeits-Graph zur Sicht V = πY (R o nNR=RECHNUNG P ) . . . . 29 2.9 Abhängigkeits-Graph zu einer Sicht V über der Master-Relation M mit dem Schlüsselkandidaten X 0 = {P1 , . . . , Pk } und den ChildRelationen Ci . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30 2.10 Abhängigkeits-Graph zur Sicht V = πY ((R o n A) o nNR=RECHNUNG P ) 34 2.5 3.1 Anwendungsfälle des Maskengenerators und der Ausführungsumgebung der Maske . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38 3.2 Pakete des Maskengenerators und der Ausführungsumgebung . . . . 40 3.3 Übersicht der Klassen zu einem Datenbankschema . . . . . . . . . . 42 3.4 Übersicht der Klassen zum Aufbau der Sicht-Graphen . . . . . . . . 42 3.5 Klassenübersicht zum Paket db.form . . . . . . . . . . . . . . . . . . 44 3.6 Klassenübersicht zum Paket db.form.field . . . . . . . . . . . . . . 46 3.7 Klassenübersicht zum Paket db.instance . . . . . . . . . . . . . . . 50 3.8 Anbindung der Maske an eine Datenbankinstanz . . . . . . . . . . . 51 3.9 Zustandsdiagramm einer Maske vom Typ Form . . . . . . . . . . . . 53 3.10 Die Klassen des Maskengenerators JForms . . . . . . . . . . . . . . . 54 80 ABBILDUNGSVERZEICHNIS 4.1 Methodenübersicht zum Meta-Schema . . . . . . . . . . . . . . . . . 58 4.2 Methodenübersicht der Klasse View . . . . . . . . . . . . . . . . . . . 59 4.3 Methodenübersicht der Sicht-Elemente . . . . . . . . . . . . . . . . . 60 4.4 Auswahl der Sicht-Relationen . . . . . . . . . . . . . . . . . . . . . . 62 4.5 Auswahl der Sicht-Attribute und Anzeige der DB-Informationen der entsprechenden Spalte . . . . . . . . . . . . . . . . . . . . . . . . . . 62 4.6 Einstellungen zu einem FormField . . . . . . . . . . . . . . . . . . . . 63 4.7 Einstellungen zum Layout . . . . . . . . . . . . . . . . . . . . . . . . 64 4.8 Eine generierte Maske . . . . . . . . . . . . . . . . . . . . . . . . . . 64 4.9 Ablauf einer Such-Operation . . . . . . . . . . . . . . . . . . . . . . 66 B.1 Methoden von JForms . . . . . . . . . . . . . . . . . . . . . . . . . . 69 B.2 Methoden der Einstellfenster des Maskeneditors . . . . . . . . . . . . 70 B.3 Methoden der Masken-Klassen . . . . . . . . . . . . . . . . . . . . . 71 B.4 Methoden von FormField . . . . . . . . . . . . . . . . . . . . . . . . . 71 B.5 Methoden von FieldAdjust . . . . . . . . . . . . . . . . . . . . . . . . 72 B.6 Methoden der Klassen für den Zugriff eine Datenbankinstanz . . . . 72 B.7 Allgemeine Methoden des Graphen . . . . . . . . . . . . . . . . . . . 73 B.8 Methoden des Abhängigkeits-Graphen und der spezialisierten Knoten 73 Literaturverzeichnis [AHV95] S. Abiteboul, R. Hull, V. Vianu: Foundations of Databases. AddisonWesley, Reading, MA, 1995. [BRJ99] G. Booch, J. Rumbaugh, I. Jacobson: The Unified Modeling Language User Guide. Object Technology Series, Addison-Wesley, Reading, MA, 1999. [BS81] F. Bancilhon, N. Spyratos: Update Semantics of Relational Views. ACM Transactions on Database Systems 6:4 (1981), 557–575. [CP84] S. S. Cosmadakis, C. H. Papadimitriou: Updates of Relational Views. Journal of the ACM 31:4 (1984), 142–160. [DB78] U. Dayal, P. A. Bernstein: On the updatability of relational views. In J. Bubenko, S. Yao (eds.), Proceedings of the 4th International Conference on Very Large Data Bases - 1978, IEEE Computer Society Press, 1978, 368–378. [DB82] U. Dayal, P. A. Bernstein: On the Correct Translation of Update Operations on Relational Views. ACM Transactions on Database Systems 7:3 (1982), 381–416. [DD97] C. Date, H. Darwen: A Guide to the SQL Standard (Fourth Edition), 4 edition. Addison-Wesley, Reading, MA, 1997. [ELW98] R. Eckstein, M. Loy, D. Wood: Java Swing. The Java Series, O’Reilly & Associates, Cambridge, 1998. [FC85] A. L. Furtado, M. A. Casanova: Updating Relational Views. In W. Kim, D. S. Reiner, D. S. Batory (eds.), Query Processing in Database Systems, Springer-Verlag, Berlin, 1985, 127–144. [Fla97] D. Flanagan: Java in a Nutshell: A Desktop Quick Reference for Java Programmers, 2nd edition. O’Reilly, 1997. [HCF97] G. Hamilton, R. Cattell, M. Fisher: JDBC TM Database Access with Java TM – A Tutorial and Annotated Reference. The Java TM Series, Addison-Wesley, Reading, MA, 1997. [JBR99] I. Jacobson, G. Booch, J. Rumbaugh: The Unified Software Development Process. Addison-Wesley, Reading, MA, 1999. [KE96] A. Kemper, A. Eickler: Datenbanksysteme – Eine Einführung. Oldenbourg Verlag, München, 1996. 82 LITERATURVERZEICHNIS [Kel82] A. Keller: Updates to Relational Databases through Views Involving Joins. In P. Scheuermann (ed.), Improving Database Usability and Responsiveness, Proceedings of the 2rd Intl. Conf. on Databases, Academic Press, 1982, 363–384. [Kel85a] A. M. Keller: Algorithms for Translating View Updates to Database Updates for Views Involving Selections, Projections, and Joins. In ACM (ed.), 4th ACM Symposium on Principles of Database Systems, ACM Press, New York, 1985, 154–163. [Kel85b] A. M. Keller: Updating relational databases through views. PhD thesis, Stanford University, Stanford, 1985. [KU84] A. M. Keller, J. D. Ullman: On Complementary and Independent Mappings on Databases. In B. Yormark (ed.), Proceedings of the 1984 ACM SIGMOD International Conference on Management of Data, SIGMOD Record 2, ACM Press, New York, 1984. [Lan90] R. Langerak: View updates in relational databases with an independent scheme. ACM Transactions on Database Systems 15:1 (1990), 40–66. [Oes97] B. Oestereich: Objektorientierte Softwareentwicklung mit der Unified Modeling Language (3. Aufl.). Oldenbourg Verlag, München, 1997. [PDBGVG89] J. Paredaens, P. De Bra, M. Gyssens, D. Van Gucht: The Structure of the Relational Database Model. Springer-Verlag, Berlin, 1989. [RJB99] J. Rumbaugh, I. Jacobson, G. Booch: The Unified Modeling Language – Reference Manual. Object Technology Series, Addison-Wesley, Reading, MA, 1999. [TFC83] L. Tucherman, A. L. Furtado, M. A. Casanova: A Pragmatic Approach to Structured Database Design. In M. Schkolnick, C. Thanos (eds.), Proceedings of the 9th International Conference on Very Large Data Bases - 1983, Morgan Kaufmann Publishers, 1983, 219– 231. [vH98] A. von Helmolt. Implementierung eines Datenbank-AdministrationsTools in Java. Studienarbeit, Institut für Informatik, Universität Hannover, Hannover, 1998. Erklärung Hiermit erkläre ich, daß ich die vorliegende Arbeit und die zugehörige Implementierung selbständig verfaßt und dabei nur die angegebenen Quellen und Hilfsmittel benutzt habe. Hannover, den 2. November 1999