Institut für Informatik und Praktische Mathematik der Christ ia n- Alb rec hts- Uni ve rsität zu Kiel Gra phi sc he Sc hni tts te ll e zur G e ner ier ung v on SQ L-A nf ra ge n a n die Studiere nde nda te nba nk – A nf ra ge ne di tor – Bachelorarbeit von Hilmar Falkenberg Kiel, im Oktober 2004 Institut für Informatik und Praktische Mathematik der Christ ia n- Alb rec hts- Uni ve rsität zu Kiel Gra phi sc he Sc hni tts te ll e zur G e ner ier ung v on SQ L-A nf ra ge n a n die Studiere nde nda te nba nk – A nf ra ge ne di tor – Bachelorarbeit von Hilmar Falkenberg Betreuer: Prof. Dr. Hans-Joachim Klein Kiel, im Oktober 2004 1 Vorwort 5 1.1 Projektaufteilung 6 1.2 Anmerkung 6 2 Einleitung 7 2.1 Themenstellung 7 2.2 Inhalt der Arbeit 8 Problemanalyse 9 3 3.1 Allgemeine Anforderungen 9 3.2 Anforderungen vom Prüfungsamt 9 3.3 Anforderungen an die Statistikerstellung 11 3.3.1 Umsetzung 11 3.3.2 Flexibilität 12 4 Graphische Anfragesprachen für Datenbanken 13 4.1 QBE – Query-By-Example 13 4.2 NQS – Network-Query-System 15 4.3 Ansatz dieser Arbeit 15 4.3.1 Konzept 16 4.3.2 Join 17 4.3.3 Bedingungen 17 4.3.4 Aggregatfunktionen 18 4.3.5 Bedingungen für Aggregatfunktionen 18 4.3.6 SQL-Kontrollanzeige für den Administrator 18 5 Umsetzung der Statistikerstellung 19 5.1 HTML-Seite 19 5.2 Javascriptdateien 22 5.3 Erzeugung der SQL-Anweisung 23 5.4 Gespeicherte Datenbankanfragen 23 5.4.1 Anmerkung zu Cookies 24 -1- 6 Umsetzung der Grundlagen 25 Basisklassen (package base) 25 6.1 6.1.1 class SDBDocument 25 6.1.2 class SDBElementList 25 6.1.3 class SDBGroup 25 6.1.4 class SDBGroupElement 26 6.1.5 interface SDBResults 26 6.1.6 class SDBResultset 26 6.1.7 class SDBResultsImpl 27 6.1.8 class SDBRow 27 6.1.9 abstract class SDBServlet 27 6.2 Servlets (package servlet) 28 6.2.1 Parameterliste zur Steuerung der Servlets 28 6.2.2 class SDBSelect 30 6.2.3 class SDBExecute 30 6.2.4 class SDBStatistik 31 7 Analyse der Umsetzung 33 7.1 Tests 33 7.2 Gelöste Probleme 33 7.3 Beschränkungen 34 8 Zusammenfassung 8.1 35 Ausblick 35 8.1.1 Datenbankschema 35 8.1.2 Subqueries 36 8.1.3 Maximale Anzahl von zehn Spalten 36 8.1.4 „Durchblättern“ von Daten 36 9 9.1 Literaturverzeichnis 37 Verwendete Entwicklungsumgebung & Tools 10 Erklärung 39 40 -2- 11 Anhang Datenbankschema 1 Anfrageneditor HTML-Quellcode (statistik.html) 1 Javascripte check.js 11 cookie.js 13 stat_cookies.js 13 stat_erstellen.js 14 stat_events.js 19 stat_globals.js 25 stat_schema.js 26 Cascaded Style Sheet (statistik.css) 29 Hilfedateien für den Anfrageneditor alias.html 29 anzeigen.html 30 Bedingung.html 30 Felder.html 31 Frage.html 32 Funktionen.html 32 GBedingung.html 33 index.html 34 join.html 35 sortieren.html 35 SQL.html 36 Tabelle.html 36 tauschen.html 37 Anfragenverwaltung Javascript (stat_verwalten.js) 37 XSL-Stylesheet (stat_gespeicherte.xsl) 38 XSL-Stylesheets logo.xsl für die Navigationsleiste, Fehlermeldungen und das Logo 39 stat_antwort.xsl für die Ergebnislisten einer Anfrage 40 Administratorenschnittstelle (administrator.html) 41 Sonstiges für den Anfrageneditor general_layout.css 42 -3- javascript.sql 43 stat_statistiken.sql 43 sdbdocument.dtd 44 Javaklassen (package base) class SDBDocument 44 class SDBElementList 49 class SDBGroup 50 class SDBGroupElement 52 interface SDBResults 53 class SDBResultset 54 class SDBResultsImpl 57 class SDBRow 59 abstract class SDBServlet 60 Javaklassen (package servlet) class SDBSelect 62 class SDBExecute 66 class SDBStatistik 67 -4- 1 Vorwort Am Institut für Informatik und Praktische Mathematik der Christian-Albrechts-Universität zu Kiel werden seit einigen Jahren die Daten der Studierenden in einer institutseigenen Datenbank verwaltet. Da die Lizenz für das verwendete Datenbanksystem Ingres in Kürze ausläuft und inzwischen erweiterte Anforderungen an die Datenbankanwendung gestellt werden, ist es notwendig, eine neue Lösung zu erarbeiten. Hierfür wurde am Lehrstuhl „Technologie der Informationssysteme“ das Projekt „Studierendendatenbank“ (SDB) mit der Zielsetzung gegründet, von einer proprietären zu einer datenbanksystemunabhängigen Lösung zu kommen, die auch wesentlich mehr Funktionalität bieten soll. So sollen z.B. auch der Übungsbetrieb mit erfasst werden und Schnittstellen zum UnivIS1 [26] und zum zentralen Studierendensekretariat integriert werden. Für Studenten soll ein Webinterface mit ihren persönlichen Daten zur Verfügung gestellt werden. Während der Diskussion um die Inhalte des Projektes hatte sich Computer Associates dazu entschieden, Ingres freizugeben [35], so dass auf diesem Datenbanksystem die neue Anwendung weiter entwickelt werden kann, ohne dass Lizenzgebühren fällig werden. Um aber trotzdem möglichst datenbanksystemunabhängig zu werden und weil das bisherige System (noch mit 4GL als graphischer Schnittstelle) ersetzt werden soll, wurde festgelegt, dass die neue Studierendendatenbank als three-tier-architecture mit einem Internet-Browser (überwiegend Mozilla 1.6 [36]) auf der Clientseite und Java-Servlet-Technologie [10] (Tomcat [37] als Webserver) und Ingres als Datenbanksystem aufgebaut wird. 1 Das System erlaubt die Erfassung von Informationen aus Forschung und Lehre (Vorlesungen, Personen, Veranstaltungen, Forschungsprojekte, Publikationen, ...). Die einmal erfassten Informationen können in einer Vielzahl von Verzeichnisarten (z.B. individuelle Stundenpläne, Raumbelegungspläne, Veranstaltungskalender, Forschungsberichte, Publikationsverzeichnisse) mit flexiblen Abfragemöglichkeiten (z.B. Telefon- und E-Mail-Verzeichnis, kommentiertes Vorlesungsverzeichnis) abgerufen werden. Erfassung und Abruf der Informationen erfolgt vollständig über das WWW. -5- Folgende Abbildung verdeutlicht die geplante neue Struktur: Web Server Java Servlet Teil dieser Arbeit SDBServlet XML Prozes sor HTML (DOM/SA X) Clients SDBDocument SDBResultSet XSL XSL stylesheet (Tomcat) java.sql.ResultSet (Studenten, Sekreteriat, Prüfungsamt, Lehrpersonal) JDBC DB (Ingres) Geplante three-tier-architecture 1.1 Projektaufteilung Das Projekt Studierendendatenbank ist gegliedert in: Benutzergruppen Bereiche 1. Sicherheit - I. Sekretariate Verschlüsselung Passwörter Rollen (Benutzergruppen) Zertifizierung / Behördenaudit - II. Prüfungsamt 2. Skalierbarkeit / Performance / Verfügbarkeit - Session-Verwaltung Leistung (Antwortzeiten) einfache, flexible Erstellung automatische Generierung von SQL-Anfragen 4. XML - - Statistik Zeugnisse III. Studierende 3. Statistik - Scheine Pflege Dokumentenerstellung / -verwaltung Textbausteine - Web-Interface Abfragen IV. Übungsleiter - Teilnehmerliste Mailliste Rechnerbetriebsgruppe - Accountkontrolle Diese Arbeit beschränkt sich auf die Teile 3. Statistik und II. Prüfungsamt (mit der Statistik und grundlegenden Funktionen). 1.2 Anmerkung In dieser Arbeit wird davon ausgegangen, dass der Leser mit den verschiedenen Prinzipien und Funktionsweisen von XML [28], XSL [29], Java [07][16], Java Servlet [10][11][17], Javascript [06][18], HTML [13], SQL [21][23] in Verbindung mit Java [22] (SQLJ, JDBC) und relationalen Datenbanken [02][05][12] vertraut ist. Daher erfolgt hier keine nähere Beschreibung dazu. -6- 2 Einleitung 2.1 Themenstellung Um die Anfragen von Professoren oder von der Universitätsleitung an das Prüfungsamt nach statistischen Größen, wie z.B. Prüfungsergebnisse bestimmter Jahrgänge, zu bearbeiten, war es bisher notwendig, dass vom Prüfungsamt diese Anfragen an einen Administrator der Studierendendatenbank (meistens ein Mitarbeiter des Lehrstuhls „Technologie der Informationssysteme“) weitergeleitet wurden. Der Administrator musste dann die entsprechenden SQL-Anweisungen formulieren und die Ergebnisse an das Prüfungsamt weiterleiten. Das Ziel des Teilprojektes „Statistiken“ und damit Thema dieser Arbeit ist es, diesen Ablauf wesentlich zu verkürzen und damit so zu vereinfachen, dass die MitarbeiterInnen des Prüfungsamtes diese Daten schnell und problemlos selbst ermitteln können. Da sich die bisherigen Fragen häufig ähnelten und nur in bestimmten SelektionsKriterien unterschieden, erscheint es sinnvoll, eine Anzahl vorgefertigter Datenbankanfragen zu haben, in denen die MitarbeiterInnen des Prüfungsamtes selbst die Bedingungen ändern können (wie z.B. das Datum für einen Jahrgang), um dann die entsprechende Statistik zu erstellen. Eine typische Frage ist z.B.: „Welche Studenten (MatrikelNr, Name, Hauptfach, Nebenfächer, Studienbeginn, Studienfachbezeichnung) haben als erstes oder zweites Nebenfach Nummer 11 oder 25 und haben ihr Studium zwischen dem 01.10.2000 und 01.10.2001 begonnen?“ Diese Frage kann als SQL-Anweisung wie folgt formuliert werden: select s.matrikel_nr, name, s.hauptfach_nr_i, s.nebenfach_nr_1_i, s.nebenfach_nr_2_i, s.studienbeginn, f.bezeichnung from studierende s, studienfaecher f where f.studienfach_nr_i = s.nebenfach_nr_1_i AND (s.nebenfach_nr_1_i = 25 OR s.nebenfach_nr_1_i = 11 OR s.nebenfach_nr_2_i = 25 OR s.nebenfach_nr_2_i = 11) AND s.studienbeginn >= '1.10.2000' AND s.studienbeginn < '1.10.2001' Eine derartige Frage kehrt in etwas anderer Form immer wieder, dann evtl. mit anderen Nebenfachnummern oder für einen anderen Studienbeginn. Daher ist es wünschenswert, eine solche Beispielfrage speichern zu können, um sie zu einem späteren Zeitpunkt an die aktuellen Bedürfnisse anpassen und ausführen zu können. -7- 2.2 Inhalt der Arbeit Im Wesentlichen geht es in dieser Arbeit um den Entwurf und die Realisierung einer neuen einfachen Benutzerschnittstelle für die Erstellung, Veränderung, Ausführung und Verwaltung von Datenbankanfragen. Hinzu kommen noch einige Servlets, die grundlegende Funktionen für die Dateneingabemasken des Prüfungsamtes und die Dokumentenerstellung (s. 4. bei der Projektaufteilung) zur Verfügung stellen. -8- 3 Problemanalyse 3.1 Allgemeine Anforderungen Die zu realisierenden Benutzerschnittstellen sollten weitgehend datenbanksystemund browserunabhängig sein. Alle Schnittstellen (im Wesentlichen die Dateneingabemasken) sollten intuitiv und ohne lange Einarbeitungszeiten bedienbar sein. Es ist dabei zu berücksichtigen, dass nicht alle Datenbankhersteller immer die gesamten java.sql-Spezifikationen in ihren JDBC-Treibern umsetzen. Auch kann die Darstellung in unterschiedlichen Browsern etwas variieren, so dass ein einheitliches Bild einer Bildschirmmaske an allen Arbeitsplätzen unmöglich ist. Zum Entwickeln und Optimieren haben wir uns deshalb auf Ingres mit dem JDBC-Treiber vom 09.10.2002 und auf den Mozilla Browser 1.6 geeinigt. 3.2 Anforderungen vom Prüfungsamt Von der bisherigen Studierendendatenbank sollten alle Funktionen neu implementiert bzw. übernommen werden. Zudem soll z.B. die gesamte Menüstruktur sehr stark an das benutzergewohnte alte System angelehnt werden. Speziell für das Prüfungsamt sind daher folgende Menüpunkte auf jeden Fall umzusetzen: - Studienarbeiten Industriepraktika Liste ausgewählter Klausuren Immatrikulierte Studierende Abgeschlossene Vordiplomprüfungen Abgeschlossene Diplomprüfungen Zertifikatszeugnisse Bewertungsbogen Vordiplom Bewertungsbogen Diplom Erhebung der Prüfungsdaten Anmeldung Diplomarbeiten Außerdem sind noch die Funktionen aus einem Pascal-Programm zu integrieren, das zur Unterstützung bei der Durchführung von Prüfungen erstellt worden war und dessen Wartung zu Problemen führt. Die Arbeit gliedert sich in zwei Teile. So ist zum einen die Implementierung der Javaklassen notwendig (Bestandteil dieser Arbeit: 6. Umsetzung der Grundlagen), -9- zum anderen muss für jeden einzelnen Menüpunkt ein Stylesheet erstellt werden. Die Erstellung der Stylesheets ist Gegenstand einer anderen Bachelorarbeit (Thema: Dokumentenerstellung, siehe Projektaufteilung: 4. XML). Die Java-Klassen bzw. Servlets sollen die entsprechenden Daten aus der Datenbank in ein einheitliches XML-Format bringen, welches, mit dem richtigen Stylesheet kombiniert, eine Eingabemaske aus dem alten System repräsentieren soll. In manchen dieser Eingabemasken (z.B. bei Studienarbeiten) wird unter anderem eine sogenannte Navigationsleiste benötigt, die es dem Benutzer ermöglichen soll, von einem Datensatz zum nächsten zu blättern, um sich so durch alle Daten zu bewegen. Da Ingres in der JDBC-Treiberumsetzung die Methode previous() bei java.sql.ResultSet nicht unterstützt, kann das ‚Durchblättern’ nicht mit den ResultSet-eigenen Methoden next() und previous() erledigt werden. Es muss daher eine Lösung geschaffen werden, die es ermöglicht, sowohl alle Datensätze einer bestimmten Abfrage zu repräsentieren als auch immer nur einen (den gerade aktuellen) aus einer Liste anzuzeigen. Das bedeutet, der ResultSet muss auf irgendeine Art zwischengespeichert werden, anderenfalls müsste für jeden ‚Blättervorgang’ eine erneute Datenbankanfrage ausgeführt werden. Da aber die Datensätze nicht immer in der gleichen Reihenfolge geliefert werden, es sei denn, es wird grundsätzlich eine ORDER BY-Klausel verwendet, ist es schwierig, im allgemeinen Fall (ohne jeweils den entsprechenden UNIQUE KEY zu haben) den nächsten oder vorhergehenden Datensatz zu bestimmen. Beispiel der Navigationsleiste Die Bedienung der Browseroberfläche sollte benutzer- und sessionorientiert sein, d.h. ein Benutzer muss sich zuerst am System anmelden und authentifizieren, bevor er Daten ansehen oder verändern darf. Dazu wird in den Servlets immer eine sogenannte SessionID benötigt; dementsprechend ist es notwendig, ein XMLElement <sessionid> vorzusehen. Auch für die Navigationsleiste ist eine SessionID unablässig: Es muss feststellbar sein, welcher Datensatz für den Benutzer der aktuelle ist. Der aktuelle Datensatz soll in einem javax.servlet.http.httpSession-Objekt gespeichert werden, so dass sich daraus ermitteln lässt, welchen Datensatz der Benutzer als nächstes sehen möchte. - 10 - Für manche Bereiche ist es notwendig, dass zwei ResultSets angezeigt werden. Wenn z.B. zu einem Studenten alle erworben Scheine angezeigt werden sollen, dann stellt dieser Student (mit Matrikelnummer, Name, Vorname, etc.) sozusagen den Masterdatensatz dar und die Liste seiner Scheine wäre der Slave-ResultSet. Im relationalen Datenbankmodell entspricht das einer „1 zu n-Beziehung“, diese muss sich in dem XML-Format widerspiegeln. Weiterhin ist es unbedingt notwendig, gespeicherte Daten verändern zu können. Dementsprechend sind die Operationen INSERT, UPDATE und DELETE einzuplanen. Um dem Benutzer wiedergeben zu können, dass bei diesen Operationen keine Fehler aufgetreten sind, und um ggf. anzuzeigen, wie viele Datensätze z.B. bei einer Änderung betroffen sind, müssen entsprechende XML-Tags vorgesehen werden. Für die Dokumentenerstellung ist es auch nötig, temporäre Tabellen oder Views anzulegen und sie später wieder zu löschen. Für den Fall, dass eine Datenbankoperation nicht erfolgreich durchgeführt werden konnte, müssen lesbare verständliche Fehlermeldungen erzeugt werden, die es ermöglichen, die Ursache zu erkennen, um diese ggf. beheben zu können. 3.3 Anforderungen an die Statistikerstellung 3.3.1 Umsetzung Es muss eine leicht zu bedienende übersichtliche HTML-Seite erzeugt werden, die es ermöglicht, neue Anfragen zu erstellen, bereits vorhandene zu bearbeiten und die aktuelle auszuführen und somit eine Statistik zu erzeugen. Damit nicht unnötig viele Daten über das Netz geschickt werden und dadurch der Server unnötig belastet wird, wird hierbei zugunsten von Javascript (also dynamisches-HMTL) auf einen verstärkten Einsatz von Java-Servlets verzichtet. Die Servlets gestatten zwar, die Seiten dynamisch aufzubauen und so z.B. das Datenbankschema immer aus der Datenbank selbst herauszulesen, jedoch müsste bei jeder Auswahl (z.B. Wahl einer anderen Tabelle), die der Benutzer vornimmt, wieder eine Kommunikation zwischen Client und Server stattfinden. Dies ist speziell in der Erstellungsphase einer neuen Datenbankanfrage unpraktisch. Außerdem ist die Interaktion mit dem Benutzer über den Javascript-Eventhandler wesentlich einfacher. So können z.B. nicht benötigte Teile der Schnittstelle einfach - 11 - ausgeblendet werden, wenn der Benutzer Einstellungen vornimmt, die die Anwendung bestimmter Funktionen gar nicht zulassen. 3.3.2 Flexibilität Der Benutzer sollte möglichst nicht in der Mächtigkeit von SQL-Select-Anweisungen eingeschränkt werden, aber dennoch sollte die Schnittstelle datenbanksystemunabhängig und einfach zu bedienen sein. Daher wird auf den Einsatz von nichtstandardisierten SQL-Funktionen und Outer-Joins verzichtet. Da die Anwendung von Unteranfragen (Subqueries) eine schnelle und einfache Möglichkeit darstellt (die vielen Benutzern logischer erscheint), Ergebnislisten einzuschränken, sollten diese zugelassen werden, auch wenn sie z.Z. nicht von allen Datenbanksystemen unterstützt werden. Dadurch erhalten Anfragen eine höhere Komplexität, so dass auf eine Überprüfung der Unteranfragen auf deren Korrektheit zunächst verzichtet wird (vgl. 8.1). - 12 - 4 Graphische Anfragesprachen für Datenbanken In den letzten Jahren wurden einige graphische Sprachen bzw. Hilfsmittel zur Formulierung von Anfragen an Datenbanken vorgestellt. Diese sollen dem Benutzer ermöglichen, auf einfache Art und Weise Anfragen an eine Datenbank zu stellen. Einen einheitlichen Standard wie SQL für die textbasierte Formulierung von Anfragen gibt es für graphische Anfrageverfahren nicht. SQL selbst kommt aber in diesem speziellen Anwendungsfall als Anfragesprache nicht in Frage, da es nicht zumutbar wäre, dass alle MitarbeiterInnen des Prüfungsamtes SQL lernen, um damit gelegentlich Anfragen nach statistischen Größen formulieren und bearbeiten zu können. 4.1 QBE – Query-By-Example Query-By-Example war die erste graphische Anfragesprache für relationale Datenbanken und wurde 1975 von M.M. Zloof [30][31] vorgestellt. Schon kurze Zeit später wurde in einer Studie [08] die Benutzerfreundlichkeit von QBE belegt. Eine graphische Anfrage an die Studierendendatenbank in Form von QBE würde auf einem alphanumerischen Terminal etwa so aussehen: Beispiel: Drucke (P.) matrikel_nr, name, abschlussnote aus Tabelle s.studierende, mit einer abschlussnote <=2 Seit etwa zehn Jahren stagniert jedoch die Weiterentwicklung von QBE. Bis auf wenige Ausnahmen ist QBE in seiner ursprünglichen Form [14] vom Markt verschwunden, aber die Idee, Anfragen durch das Eintragen von Beispielelementen in Tabellenstrukturen zu erstellen, ist auch heute noch Teil von vielen relationalen Datenbankoberflächen. So stellt z.B. IBM zu der Datenbank DB2 eine auf vereinfachtem QBE basierende Anfrageschnittstelle zur Verfügung [15]. In der Microsoft-Datenbank Access ist ein QBE-ähnlicher Teil integriert, der auch die Bildung von Joins unterstützt. Die obige Anfrage würde in MS Access 2000 folgendermaßen aussehen: - 13 - Darstellung einer vergleichbaren Auswahlabfrage in MS Access 2000 Die gute Verständlichkeit und damit die leichte Erlernbarkeit von QBE, wie sie sich auch in Vorlesungen und vielen Lehrbüchern (z.B. [05][24]) zeigt, ist der Grund, weshalb in dieser Arbeit eine Benutzerschnittstelle entworfen wird, die QBE-ähnlich gestaltet ist. Dabei sollen wesentliche Punkte, insbesondere die Ausdrucksfähigkeit und die flexible Formulierung und Umgestaltung von Anfragen berücksichtigt werden. Parametrisierbare Unteranfragen sind ein wichtiges Konstruktionsprinzip zur Erstellung von Abfragen. Sie wurden bisher jedoch in relationalen Datenbanken kaum berücksichtigt, obwohl sie für viele Arten von Anfragen ein wünschenswertes Strukturierungsmittel sind. Nach der Studie, die die Benutzerfreundlichkeit von QBE untersucht hat [08], waren die Probanden der Studie bereits nach einer kurzen Einarbeitungszeit in der Lage, selbstständig QBE-Anfragen zu formulieren. Dabei erleichterte die QBE-Darstellung der Relationen als Tabellen den Benutzern das Verständnis und die Eingabe der Anfragen. Hauptfehlerquellen der Probanden bei der Formulierung von Anfragen waren die Aggregatfunktionen mit Gruppierungen und die Verwendung der Negation. Ein Grund dafür lag sicher darin, dass die Semantik im Wesentlichen selbst durch Beispiele eingeführt war, die für sich einleuchtend waren, die aber vor allem bei den Konstrukten mehrdeutige Fortsetzungen auf kompliziertere Anfragen zuließen. Für den auf dem Bereichskalkül basierenden „Kern" von QBE ohne Aggregationen kann in der Arbeit von A. Heuer und G. Saake [12] eine formale Semantik nachgelesen werden. - 14 - 4.2 NQS – Network-Query-System NQS [20] verfolgt einen etwas anderen Ansatz als QBE. Bei NQS sieht der Benutzer die Datenbank als ein Schema-Diagramm. Die Tabellen sind dabei wie bei dem Entity-Relationship-Datenmodell [01] über Relationen und Rollen zu einem Graphen verbunden. Für eine Anfrage an die Datenbank wählt der Benutzer einfach mit der Maus die Tabellen aus, die die Attribute beinhalten, die er benötigt. Das System bildet dann den Pfad zwischen den ausgewählten Tabellen als Teilgraphen ab. Der Graph muss rekursionsfrei sein, d.h. der Benutzer muss ggf. vorhandene Rekursionen auflösen, indem er die unerwünschten Zweige entfernt. Falls bestimmte Bedingungen für Attribute zutreffen sollen, kann der Benutzer diese einfach durch Anklicken des entsprechenden Attributs in eine sich öffnenden Textbox eingeben. Zum Ausführen einer solchen graphischen Anfrage wird der dargestellte Teilgraph erst in NQL (Network-Query-Language [19]) umgewandelt und dann die NQLAnweisung gestartet, ähnlich wie bei MS Access auch die Visualisierung einer Abfrage intern immer in eine SQL-Anweisung übersetzt wird. 4.3 Ansatz dieser Arbeit In dieser Arbeit wird der Ansatz von NQS nicht verfolgt, weil eine dynamische Darstellung von Graphen in einem Browser den zeitlichen Rahmen sprengen würde und z.Z. auch nur mit Hilfe von Java Applets oder Ähnlichem realisiert werden könnte. Die Anwendung von QBE in seiner ursprünglichen Form scheint für die Statistikerstellung im Prüfungsamt nicht angebracht. Zum einen ist es für die MitarbeiterInnen des Prüfungsamtes nicht unbedingt erforderlich neue Anfragen zu formulieren, da in erster Linie lediglich die von dem Administrator vorgefertigten und gespeicherten Anfragen von ihnen verändert werden müssen. Zum anderen ist ein strenges QBE-Konzept in einem Browser nicht so ohne weiteres umsetzbar. Zwar könnte mit einem Textfeld auf einer HTML-Seite ein alphanumerisches Terminal simuliert werden, aber das wäre nicht besonders benutzerfreundlich. Die verschiedenen Steuerelemente von HTML-Formularen bieten weitaus bequemere Möglichkeiten. Es werden daher lediglich die Namen der Tabellen zur Auswahl vorhanden sein, anstatt die Tabellen und ihre Attribute komplett - 15 - darzustellen. Dafür jedoch werden die einzelnen Attribute in der Schnittstelle, die der Benutzer auswählen kann, in tabellarischer Form angeordnet sein. Grundsätzlich soll keine neue graphische Anfragesprache erfunden werden. Es soll vielmehr eine HTML-Seite entwickelt werden, die den Benutzer dabei unterstützt SQL-Anweisungen zu erzeugen, die dann an die Datenbank gesendet und dort ausgeführt werden. 4.3.1 Konzept Zur Umsetzung dieser Ziele wurde folgendes Konzept gewählt. Als erstes muss der Benutzer eine oder mehrere Tabellen aus einer Liste aller Tabellen auswählen, die in der Datenbank für die Statistiken in Frage kommen. Dann können einzelne Attribute aus den Tabellen in sogenannten Dropdown-Listen ausgewählt werden. Die Dropdown-Listen sind in tabellarischer Form nebeneinander angeordnet, so dass der Eindruck entsteht, dass es sich um eine neue Tabelle handelt. Dies ist besonders intuitiv, da die bisher angeforderten Statistiken immer eine tabellarische Form hatten. Diese Form ergibt sich durch die Ergebnisse einer SQL-Select-Anweisung, die immer eine Tabelle bzw. eine Sicht (View) darstellen. In den Zeilen unter den ausgewählten Attributen hat der Benutzer verschiedene Möglichkeiten, die Ergebnisliste zu manipulieren. So kann z.B. mit einer Checkbox für jede Spalte bestimmt werden, ob die Spalte im Ergebnis angezeigt werden soll. Außerdem kann ausgewählt werden, ob nach einem Attribut auf- oder absteigend oder gar nicht sortiert werden soll. In der ersten Spalte befinden sich die Zeilenerklärungen, die mit einem Hyperlink zu entsprechenden Hilfetexten führen. Die ersten drei Zeilen werden immer angezeigt, bei den weiteren kann der Benutzer die Zeile und die damit verbundene Funktionalität (s.u.) an- oder ausschalten. Dies dient der Übersichtlichkeit, damit der Benutzer nicht durch die Auflistung aller Eingabemöglichkeiten überfordert wird. Um die Schnittstelle möglichst einfach und noch übersichtlicher zu gestalten, wird immer nur eine zusätzliche Spalte zu den vom Benutzer ausgewählten Spalten angezeigt (bis zu maximal zehn Spalten). Zusätzlich wird der Benutzer durch farbliche Markierungen in der Tabelle auf die für die Ausgabe relevanten Zellen hingewiesen. - 16 - 4.3.2 Join Da es sich um eine relationale Datenbank handelt, müssen, falls der Benutzer mehrere Tabellen ausgewählt hat, diese noch miteinander in Beziehung gesetzt werden, anderenfalls würde das Kreuzprodukt der Tabellen gebildet. Dafür ist eine Extrazeile „verknüpfen mit“ vorgesehen, in der der Benutzer ein Attribut einer anderen Tabelle auswählt, mit dem er diese Spalte, d.h. das zuvor ausgewählte Attribut, verknüpfen möchte. Für z.B. die „Liste der Studenten und deren erworbene Scheine zu einer Veranstaltung“ müssen die Tabellen Studierende und Scheine ausgewählt werden und die Tabellen über das gemeinsame Attribut MatrikelNr verknüpft werden. 4.3.3 Bedingungen Um Bedingungen wie z.B. Veranstaltungsnummer = 42 (s. Beispiel unten) zu realisieren, gibt es insgesamt drei zusätzliche Zeilen. Schreibt der Benutzer seine exemplarischen Daten z.B. „42“, „23“ (vgl. QBE) untereinander in eine Spalte, so werden diese maximal drei Werte mit dem logischen ODER verknüpft, so dass folgende WHERE-Klausel erzeugt würde: „where veranstaltung = 42 or veranstaltung = 23“. Werden die Bedingungsdaten nebeneinander, d.h. in einer Zeile aber in verschiedenen Spalten eingetragen, so werden die Bedingungen auf dieser Ebene mit dem logischen UND verknüpft. Eine Beispielanfrage im Vergleich: QBE vs. SDB-Anfrageneditor QBE: Verknüpfungen werden mit Beispieldaten in Klammern, Bedingungen werden mit vorangestellten Vergleichsoperatoren realisiert. - 17 - Erstellter Studierendendatenbank-Anfrageneditor 4.3.4 Aggregatfunktionen Die Aggregatfunktionen müssen ebenso wie die Bedingungen und die Verknüpfungen (Join) zuerst mit der Checkbox in der ersten Spalte eingeschaltet werden. Der Benutzer kann aus den für Statistiken am häufigsten benötigten folgenden Aggregatfunktionen wählen: Durchschnitt, Minimum, Maximum, Summe, Anzahl und Gruppierung. Als Standard ist die Gruppierung nach einem Attribut eingestellt. 4.3.5 Bedingungen für Aggregatfunktionen In SQL werden Bedingungen für Aggregatfunktionen als HAVING-Klausel formuliert. Hierbei wird der Benutzer wiederum mit maximal drei Zeilen (vgl. 4.3.3) unter den Aggregatfunktionen bei der Erstellung einer solchen Klausel unterstützt. Um es dem Benutzer so übersichtlich wie möglich zu gestalten, werden diese Zeilen aber nur angezeigt, wenn auch zuvor die Aggregatfunktionen eingeschaltet wurden. 4.3.6 SQL-Kontrollanzeige für den Administrator Der Datenbankadministrator hat zur Kontrolle in der letzten Zeile ein Textfeld, in das die automatisch erzeugte SQL-Anweisung geschrieben wird. So kann auf einfache Weise verglichen werden, ob die mit dem Anfrageneditor erstellte Anweisung der ursprünglichen Fragestellung entspricht. Das allgemein auftretende Problem, dass umgangssprachliche Fragen nicht immer eindeutig sind und daher unterschiedlich in SQL formuliert werden können, bleibt aber bestehen. Dies ist jedoch im Wesentlichen ein Kommunikationsproblem zwischen dem Fragenden demjenigen, der die Frage mit Hilfe der Datenbank beantworten soll. - 18 - und 5 Umsetzung der Statistikerstellung Vergleichbare Arbeiten (siehe www.google.de „qbe, browser, web“) bestehen oft aus einem Programm, welches nicht in einen Internet-Browser integriert ist, sondern nur die Funktion bietet, Daten aus der Datenbank mit einem Daten-Browser im Internet zu publizieren. Ein Projekt der Université Mons-Hainaut (Belgien) hat zwar das Ziel ein Webinterface auf QBE-Basis für bestehende relationale Datenbanken zu entwickeln, aber es wird dabei auf die Technologie von PHP, Perl und CGI-Scripte zurückgegriffen und nicht die flexible Datenverarbeitung von XML-Dokumenten angestrebt. Da uns bis zum jetzigen Zeitpunkt eine „QBE-Internet-Browser-Lösung“, die für unsere Bedürfnisse ausreichend wäre, nicht bekannt ist, wurde folgende neue Lösung entwickelt. 5.1 HTML-Seite Die komplette Seite besteht aus einer Tabelle mit 15 Zeilen und 11 Spalten. Wie schon im Konzept erwähnt, steht in der ersten Spalte immer die Bedeutung für eine Zeile. Es gibt zusätzlich maximal zehn weitere Spalten, die sich dynamisch ein- und ausblenden. Die Zeilen 1, 2, 14 und 15 erstrecken sich über die gesamte Tabellenbreite, die anderen sind abhängig von der Anzahl der ausgewählten Attribute. Nachfolgend werden die Funktionen der einzelnen Zeilen erläutert. 1. Zeile „Frage“: Hier ist ein maximal 100 Zeichen langes Textfeld vorhanden. In dieses soll eine Frage, eine Beschreibung oder ein Name für die Anfrage eingegeben werden. Die gespeicherte Anfrage ist dann später unter dem eingegebenen Text wiederzufinden. 2. Zeile „Tabellenauswahl“: Hier befindet sich eine Auswahlliste mit den Tabellennamen, die für die Statistiken relevant sind. Diese Liste wurde halbautomatisch mit einem Datenbankscript erzeugt (siehe Anhang javascript.sql). Falls das Datenbankschema geändert wird und Tabellen hinzukommen oder wegfallen, muss diese Liste manuell dem neuen Schema angepasst werden. Ein Eintrag in der Liste hat folgende Form: <option value="studierende s" label="Studierende" > Studierende </option> - 19 - Wichtig dabei ist der Alias für die Tabelle in dem Attribut value (in diesem Beispiel „s“ für studierende), damit die erzeugte SQL-Anweisung nicht zu lang und dadurch unübersichtlich wird. Derselbe Alias muss auch in der Javascriptdatei stat_schema.js (siehe Anhang) verwendet werden. 3. Zeile „Spalten tauschen“: In dieser Zeile werden Buttons mit Pfeilen angezeigt, wenn der Benutzer mehr als ein Attribut ausgewählt hat. Mit einem Mausklick auf einen derartigen Button werden zwei nebeneinanderliegende Spalten miteinander vertauscht. Damit hat der Benutzer die Möglichkeit, schnell und bequem die Reihenfolge der Attribute in den Spalten zu verändern. 4. Zeile „Feld / aus Tabelle“: Hier kann der Benutzer die Felder / Attribute der von ihm zuvor ausgewählten Tabellen in Dropdown-Listen anwählen. Die Attribute sind dabei nach den Tabellen gruppiert und dann alphabetisch sortiert. Damit der Benutzer immer leicht erkennen kann, aus welcher Tabelle er ein bestimmtes Attribut ausgewählt hat, ist unter jeder Dropdown-Liste ein Textfeld angeordnet, in dem der jeweilige Tabellenname angezeigt wird. Damit die Listen übersichtlich bleiben und nur die Attribute der ausgewählten Tabellen angezeigt werden, werden diese Dropdown-Listen dynamisch mit einem Javascript gefüllt. 5. Zeile „anzeigen / sortieren / Spaltenüberschrift“: Mit einer Checkbox kann der Benutzer entscheiden, ob das Attribut dieser Spalte auch in der Ergebnisliste ausgegeben werden soll (SELECT), oder ob es nur ausgewählt wurde, um eine Bedingung (WHERE) zu formulieren. Mit einer Dropdown-Liste kann die Sortierung (ORDER BY) für dieses Attribut eingestellt werden. Ein zusätzliches Textfeld erlaubt die Eingabe einer anderen Spaltenüberschrift (AS). Dies ist besonders bei der Verwendung von Aggregatfunktionen von Vorteil, da sonst von der Datenbank nichts-aussagende Spaltenüberschriften (bei Ingres z.B. „col1“) automatisch erzeugt werden. 6. Zeile „verknüpfen mit / aus Tabelle“: Dies ist die erste Zeile, die mit der Checkbox in der ersten Spalte komplett einoder ausgeblendet werden kann, wenn eine Verknüpfung von zwei oder mehr Tabellen nicht erforderlich ist. Ansonsten ist diese Zeile genauso aufgebaut wie Zeile 4. Zusätzlich gibt es noch eine Dropdown-Liste mit Vergleichsoperatoren, - 20 - so dass auch Verknüpfungen zwischen Tabellen möglich sind, in denen ein Attributwert kleiner oder größer als der zu vergleichende ist. Diese Art der Verknüpfung bietet mehr Möglichkeiten als die übliche JOIN-Operation. 7. – 9. Zeile „Bedingung“, „oder“, „oder“: Diese Zeilen haben den stärksten QBE-Charakter. Wie schon im Abschnitt Bedingungen 4.3.3 beschrieben, kann hier der Benutzer einfach die Kriterien bzw. Werte eintragen, die ein Attribut enthalten soll. Dazu stehen ihm wieder in einer Dropdown-Liste eine Anzahl von Vergleichsoperatoren zur Verfügung. Neben den aus der Mathematik bekannten Vergleichsoperatoren (<, ≤, =, ≥, >, ≠) sind die datenbanktypischen: IS NULL, IS NOT NULL, LIKE, IN, NOT IN ebenfalls implementiert. Eine Besonderheit stellt der zusätzliche letzte Punkt („SUBQUERY“) in der Vergleichsoperatorenliste dar. Wenn „SUBQUERY“ als Operator ausgewählt wird, kann in dem Textfeld, in das sonst die Vergleichswerte eingetragen werden, eine SQL-Unterabfrage geschrieben werden. Da diese Unterabfrage auf keinerlei Korrektheit geprüft wird, muss es sich nicht unbedingt um eine Unterabfrage handeln. So kann der Benutzer jede Bedingung formulieren, die vom jeweiligen Datenbanksystem unterstützt wird. 10. Zeile „Funktion“: In dieser Zeile können die Aggregatfunktionen (vgl. 4.3.4) ein- bzw. ausgeschaltet werden. Eine Javascriptfunktion sorgt dafür, dass nur eine korrekte Auswahl getroffen werden kann. Beispielsweise ist in SQL eine COUNT(*)Anweisung erlaubt, nicht aber eine SUM(*)-Anweisung. 11. – 13. Zeile „Bedingung für Gruppe“, „oder“, „oder“: Die HAVING-Klausel kann mit diesen drei Zeilen erstellt werden (vgl. 4.3.5). Die Funktionsweise entspricht den Zeilen 7 – 9 und wird daher hier nicht weiter beschrieben. 14. Zeile „Aktionsmöglichkeiten“: Der Benutzer hat verschiedene Aktionsmöglichkeiten, zwischen denen er auswählen kann, wie z.B. Speichern, Ausführen oder Rücksetzen einer formulierten Anfrage. Diese Aktionen können jeweils mit einem Mausklick auf den entsprechenden Button ausgeführt werden. Zusätzlich gibt es in dieser Zeile noch einen Link zu der Liste mit den gespeicherten Anfragen. - 21 - 15. Zeile „erzeugter SQL“: Hier ist ein nicht veränderbares Textfeld vorhanden, in das zur Kontrolle der erzeugte SQL-Ausdruck geschrieben wird. Dieser kann ggf. auch markiert und kopiert werden, so dass die Anfrage auch in ein Datenbankscript o.ä. geschrieben werden kann. 5.2 Javascriptdateien In dem HTML-Tag <head> werden folgende Javascripte geladen: check.js stellt verschiedene Funktionen zum Überprüfen von Textfeldern auf bestimmte Datentypen zur Verfügung. Diese Datei wird unter anderem auch bei der Navigationsleiste benötigt, um zu testen, ob eine Datensatznummer gültig ist. cookie.js stellt die Basisfunktionen zum Setzen und Löschen von Cookies zur Verfügung. Diese Datei wird z.Z. in keiner anderen Maske benötigt, ist aber so allgemein gehalten, dass sie nicht nur für die Datenbankanfragenerstellung geeignet ist. stat_globals.js deklariert alle globalen Variablen. stat_schema.js erstellt das zweidimensionale Array felder[i][j]. Dabei ist unter dem i-ten Eintrag das Array mit den Attributen der i-ten Tabelle (vgl. 2. Zeile „Tabellenauswahl“ in 5.1) zu finden. Der j-te Eintrag enthält dann das j-te Attribut der i-ten Tabelle. Ein solches Attribut ist durch den angezeigten Namen, einem Alias und den Datentyp charakterisiert. Wenn das Datenbankschema verändert wird, müssen in dieser Datei ebenfalls die hinzugefügten Attribute ergänzt oder die gelöschten herausgenommen werden, damit keine fehlerhaften SQL-Anweisungen mit dem Anfrageneditor erzeugt werden. stat_cookies.js fasst die Funktionen zum Speichern und Wiederherstellen der Cookies zusammen, die für den Anfrageneditor wichtig sind. stat_erstellen.js implementiert die wichtigsten Funktionen zum Erzeugen der SQLAnweisung (setSelect()) und zum dynamischen Füllen der AttributDropdown-Listen (fill_feld()). Hinzu kommen noch einige Funktionen, mit - 22 - denen das Erscheinungsbild der HTML-Seite dynamisch verändert werden kann, z.B. durch das Setzen von einer Hintergrundfarbe für besondere Zellen. stat_events.js fasst alle Funktionen zusammen, die durch bestimmte Ereignisse (Benutzeraktionen) hervorgerufene Javascript-Events behandeln. Dabei wurde besonderen Wert auf die Namensgebung der Funktionen gelegt, so dass leicht erkennbar ist, bei welchem Event eine Funktion aufgerufen wird. 5.3 Erzeugung der SQL-Anweisung Die SQL-Anweisung wird on-the-fly, d.h. sobald mindestens ein Attribut ausgewählt und zur Anzeige markiert wurde, in der Funktion setSelect() erzeugt. Je nachdem welche Einstellungen der Benutzer vornimmt, wird die SQL-Anweisung dann erweitert oder auch wieder gelöscht, wenn z.B. kein Attribut zur Anzeige markiert ist (vgl. 5. Zeile in 5.1). Die Erzeugung der SQL-Anweisung orientiert sich stark an der Grammatik für SQL. So wird zunächst für jede Klausel ein String erzeugt, in dem die entsprechenden SQL-Keywords gespeichert sind. Dann werden der Reihe nach die einzelnen Spalten durchgegangen und dabei z.B. der SELECT-String um die ausgewählten Attribute erweitert. Zum Schluss, wenn alle Klauseln vollständig zusammengesetzt wurden, wird durch die Konkatenation d.h. durch das hintereinander Schreiben der Klauseln die SQL-Anweisung erzeugt. Neben der Erzeugung der SQL-Anweisung werden alle vorgenommenen Einstellungen in den Cookies gespeichert. Zur besseren Übersichtlichkeit werden zusätzlich die für die SQL-Anweisung relevanten Zellen farblich markiert. 5.4 Gespeicherte Datenbankanfragen Die Datenbankanfragen werden mit einem Mausklick auf den Button „Abfrage speichern“ in der Tabelle pra03.stat_statistiken gespeichert. Diese hat folgenden Aufbau (vgl. Create-Script stat_statistiken.sql im Anhang): Ein integer-Feld „lfd_nr“ stellt den Primärschlüssel dar. Daher muss eine fortlaufende Nummer immer angegeben werden. Im „datum“-Feld soll das Datum der letzten Änderung dieser Datenbankanfrage festgehalten werden. - 23 - Das varchar-Feld „frage“ bietet Platz für 100 Zeichen und soll es ermöglichen, einer Datenbankanfrage einen aussagekräftigen Namen zuzuordnen oder die ursprüngliche Fragestellung einzutragen. In dem „query“-Feld werden die fertigen und korrekten SQL-Anweisungen mit einer maximalen Länge von 1000 Zeichen gespeichert. Dieses Feld darf nicht leer sein. Wenn eine Datenbankanfrage direkt, d.h. von der Liste der gespeicherten Datenbankanfragen aufgerufen wird, wird dieses Feld ausgelesen und die darin enthaltene SQL-Anweisung ausgeführt. Die Längenbeschränkung auf maximal 1000 Zeichen sollte keine Probleme bereiten, da die bisherigen SQL-Anweisungen eine durchschnittliche Länge von ca. 450 Zeichen hatten. Dennoch ist es theoretisch möglich, dass bei sehr großen UNTERANFRAGEN dieses Limit überschritten wird. Für die Speicherung der Cookies wurde ein long-varchar-Feld „cookie“ angelegt. Damit ist es relativ leicht möglich, eine gespeicherte Datenbankanfrage so wiederherzustellen, dass sie in der dafür vorgesehenen HTML-Seite bearbeitet und verändert werden kann. Dieses Feld kann auch leer (NULL) gelassen werden. Das hat aber zur Folge, dass diese Datenbankanfrage nicht verändert werden kann. In diesem Fall erscheint in der Liste der gespeicherten Datenbankanfragen der Button „bearbeiten“ nicht. Diese Funktionsweise gestattet es einem Administrator eine Datenbankanfrage direkt in der Datenbank abzulegen, ohne diese mit der „EditorSeite“ erstellt zu haben. So können immer wiederkehrende Fragen, die keiner Änderung bedürfen, auch davor geschützt werden. Außerdem können so Datenbankanfragen, die datenbanksystemspezifische Funktionen enthalten, die z.Z. nicht von dem Editor unterstützt werden, trotzdem an dieser Stelle allen Benutzern auf einfache Art und Weise zugänglich gemacht werden. 5.4.1 Anmerkung zu Cookies Maximal können pro Website 20 Cookies erstellt werden. Jeder Cookie kann maximal bis zu 20KB groß sein. Da jedoch die Werte der Cookies mit der JavaScriptfunktion escape() noch entsprechend maskiert werden, können ggf. auch mehr als 400KB an Daten entstehen, daher wird zum Abspeichern der Cookies in der Datenbank ein long-varchar-Feld verwendet. Allerdings ist es zweifelhaft, ob wirklich so komplexe Datenbankanfragen erstellt werden müssen. In der Vergangenheit waren die Datenbankanfragen nicht so umfangreich. - 24 - 6 Umsetzung der Grundlagen In diesem Abschnitt werden die Umsetzung der einzelnen Java-Klassen und deren Aufgaben beschrieben. Die Klassen sind in zwei Pakete aufgeteilt. 6.1 Basisklassen (package base) 6.1.1 class SDBDocument In der Klasse SDBDocument werden alle Daten für eine Ein- bzw. Ausgabemaske im XML-Format zusammengefasst. In dem Konstruktor der Klasse wird zuerst ein org.w3c.dom.Document instanziert. Anschließend werden die verschiedenen XML-Tags je nach Servlet und Anforderung erzeugt. In der toString()-Methode wird dann aus dem org.w3c.dom.Document mit Hilfe von einem org.apache. xml.serialize.XMLSerializer ein String erzeugt. Eine Doc-Type-Definition für diesen XML-String ist in der Datei sdbdocument.dtd (siehe Anhang) zu finden. Diese kann aber nie vollständig sein, da in dem Tag <formdata> alle Parameter aufgelistet werden, die dem Servlet zugesandt worden sind. Für diesen Tag gibt es daher keine vollständige Beschreibung, da nicht abzusehen ist, welche Parameter an ein Servlet übergeben werden. Eine Liste der typischen Parameter zur Steuerung der Servlets wird unter 6.2.1 Parameterliste beschrieben. 6.1.2 class SDBElementList SDBElementList stellt die Basisklasse für SDBResultsImpl und SDBGroup dar. Es handelt sich dabei um eine dynamische Liste, die je nach Anforderungen ihre Kapazität verdoppelt oder halbiert. Gespeichert werden die org.w3c.dom. Element-Objekte in einem Array. 6.1.3 class SDBGroup Die Klasse SDBGroup soll alle Arten von Optionsgruppen aus dem HTML-Standard realisieren. Dabei ist ein einheitliches XML-Format für Dropdown-Listen, Radiobuttons und Checkboxen vorgesehen. Mit dem richtigen Stylesheet kombiniert ergibt sich dann der entsprechende HTML-Tag. Gerade an den Stellen, an denen eine gewisse referentielle Integrität gefordert wird, z.B. bei Diplomarbeiten, bei denen als Betreuer eine Lehrpersonalnummer eingetragen werden muss, sollte der Benutzer durch eine dynamisch gefüllte Dropdown-Liste mit dem gesamten - 25 - Lehrpersonal (Name und Nummer) bei seiner Eingabe unterstützt werden. Für dieses häufig wiederkehrende Key-Value-Prinzip wurde diese Klasse erstellt. 6.1.4 class SDBGroupElement Ein SDBGroupElement stellt eine einzelne Option für die SDBGroup zur Verfügung und besteht aus einem Key und einem Value,. 6.1.5 interface SDBResults Das Interface SDBResults soll eine einfache Schnittstelle bieten, falls in Zukunft einmal das benutzte Datenbanksystem die volle JDBC-API unterstützt und so auf die Funktionalität des ResultSets zurückgegriffen werden kann. Anstatt den ResultSet aus der Datenbank komplett auszulesen und in einer Klasse SDBResultset zwischenzuspeichern, um das Vorwärts- und Rückwärtsblättern zu ermöglichen, könnten dann die Methoden des java.sql.ResultSet next() und previous() direkt verwendet werden. 6.1.6 class SDBResultset Die Klasse SDBResultset baut das XML-Element <Resultset> auf. Dazu wird dem Konstruktor ein java.sql.ResultSet, ein org.w3c.dom.Document und ggf. ein String mit der erzeugenden SQL-Select-Anweisung übergeben. Mit der createElement()-Methode der Klasse Document, wird, falls ein String-Objekt mit übergeben wurde, ein <statement>-Element erzeugt, das die SQL-Anweisung beinhaltet, anderenfalls fehlt das <statement>-Element. Aus den Informationen des java.sql.ResultSetMetaData-Objekts wird anschließend das <table>- Element mit den dazugehörigen <column>-Elementen erzeugt. Entsprechend dem Konzept der java.sql-API wird so die Datenbeschreibung strikt von den Daten getrennt gespeichert. Die Daten werden in einem SDBResultsImpl-Objekt zwischengespeichert, d.h. in der Methode initResults() wird der übergebene ResultSet einmal komplett durchlaufen, alle Daten ausgelesen und für jeden Datensatz ein SDBRow-Objekt instanziert. Dieses SDBRow-Objekt wird dann in dem SDBResultsImpl-Objekt gespeichert. Anschließend werden der übergebene ResultSet und sein erzeugendes Statement geschlossen und damit die verknüpften Datenbankres- - 26 - sourcen freigegeben. Um die Funktionalität einer Navigationsleiste zu implementieren, wird das <results>-Element (siehe 6.1.7 class SDBResultsImpl) je nach angefordertem Datensatz ersetzt. 6.1.7 class SDBResultsImpl Diese Klasse stellt eine Erweiterung der SDBElementList dar und implementiert das Interface SDBResults. In einem SDBResultsImpl-Objekt werden die Daten eines ResultSets in Form von SDBRow-Objekten in einem Array zwischengespeichert. Die hier implementierten Methoden des Interfaces geben jeweils ein <results>-Element mit entweder einem Datensatz (ein <row>-Element) oder allen Datensätzen (0 bis n <row>-Elemente) zurück. 6.1.8 class SDBRow Jedes SDBRow-Objekt stellt einen Datensatz dar. Die Klasse erzeugt dazu ein <row>-Element mit so vielen <col>-Elementen, wie in der SQL-Anweisung selektiert wurden bzw. in den ursprünglichen java.sql.ResultSet-Columns vorhanden sind. Bei sehr großen Datenmengen sollten an dieser Stelle evtl. noch kürzere XML-Elementnamen, z.B. <r> und <c> gewählt werden, um die Performance nicht zu gefährden. 6.1.9 abstract class SDBServlet Diese abstrakte Klasse stellt grundlegende Funktionen zur Verfügung, die in jedem Servlet gebraucht werden. In der init()-Methode, die automatisch vom Webserver beim Start eines Servlets aufgerufen wird, wird der JDBC-Datenbanktreiber instanziert. In der destroy()-Methode, die beim Beenden aufgerufen wird, werden noch nicht geschlossene Datenbankverbindungen getrennt. Die Methode process() transformiert eine XML- und eine XSL-javax.xml.transform. Source mit Hilfe eines javax.xml.transform.Transformer in einen Datenausgabestrom. Die wesentlichen Funktionen für den Zugriff auf das sessiongebundene SDBDocument, wie z.B. newDocument() zum Anlegen eines neuen Dokumentes in der aktuellen Session sind ebenfalls in dieser Klasse implementiert. Da in allen Servlets keine Unterscheidung zwischen den verschiedenen Kommunikationsformen - 27 - post bzw. get vorgenommen werden muss, ist auch die Methode doPost() schon implementiert. Diese leitet nur die HttpServletRequest- und HttpServletResponse-Objekte an die abstrakte Methode doGet() weiter. Damit genügt es, in von dieser Klasse abgeleiteten Servlets die Methode doGet() zu implementieren. In den HTML-Formularen ist es dann egal, ob <form method="get"> oder <form method="post"> verwendet wird, da sich das Servlet in beiden Fällen gleich verhält. Es ist dabei nur zu bedenken, dass bei „get“ die Menge der zu versendenden Daten vom Client an den Server durch die maximale Länge der übertragenen URI / URL begrenzt ist [08]. 6.2 Servlets (package servlet) Im Rahmen dieser Arbeit wurden drei Servlets (siehe 6.2.2 class SDBSelect, 6.2.3 class SDBExecute, 6.2.4 class SDBStatistik) entwickelt. Alle drei lassen sich mit folgenden Parametern steuern. 6.2.1 Parameterliste zur Steuerung der Servlets 6.2.1.1 Parameter: requery Wird der Parameter „requery“ an ein Servlet gesendet, wird ein neues SDBDocument angelegt. Diese Funktionalität ist notwendig, weil sonst im Laufe einer Session immer mehr <resultset>- Elemente in dem SDBDocument gespeichert werden würden und daher in den Stylesheets nicht ermittelt werden könnte, welcher Resultset wo angezeigt werden soll. Aus diesem Grund sollte bei einem Wechsel zwischen zwei verschiedenen Eingabemasken immer auch ein requery an das Servlet gesendet werden, es sei denn, es werden zwei <resultset>-Elemente gewünscht (vgl. Anforderungen 3.2). So kann z.B. in einer ersten Eingabemaske ein Student ausgewählt und in einer folgenden seine erworbenen Scheine zusätzlich aufgelistet werden. Der Wert des Parameters ist ohne Bedeutung, da nur überprüft wird, ob er vorhanden ist. Ist das der Fall, wird ein neues SDBDocument angelegt. Ist er nicht an das Servlet gesendet worden, wird das SDBDocument von der aktuellen Session weiterverwendet. 6.2.1.2 Parameter: query An ein Servlet können ein oder mehrere „queries“ geschickt werden. Jeder String, - 28 - der als query an ein Servlet geschickt wird, wird darauf getestet, ob er mit SELECT anfängt (vgl. servlet.SDBSelect.setQuerys()). In diesem Fall wird versucht, eine Datenbankverbindung herzustellen und die Select-Anweisung auszuführen (vgl. base.SDBServlet.setResultSet()). Wenn dies gelingt, wird ein <resultset>-Element in das aktuelle SDBDocument eingefügt, anderenfalls werden entsprechende Fehlermeldungen erzeugt. 6.2.1.3 Parameter: nav_[1-7] Alle Parameter, die mit nav_ beginnen, werden dahingehend überprüft, ob hinter dem Unterstrich eine Ziffer folgt. Die Ziffern haben dabei folgende Bedeutungen: 1: Der erste Datensatz wird angezeigt. 2: Ausgehend von der aktuellen Position wird um zehn Datensätze zurückgerückt. 3: Ausgehend von der aktuellen Position wird um einen Datensatz zurückgerückt. 4: Ist zusätzlich der Parameter row vorhanden und eine Zahl zwischen 1 und der Anzahl der Datensätze eingetragen, wird zu dem Datensatz mit dieser Nummer gesprungen. 5: Ausgehend von der aktuellen Position wird um zehn Datensätze vorgerückt. 6: Ausgehend von der aktuellen Position wird um einen Datensatz vorgerückt. 7: Der letzte Datensatz wird angezeigt Falls keine Ziffer zwischen 1 und 7 hinter dem Unterstrich steht, werden alle Datensätze angezeigt. 6.2.1.4 Parameter: stylesheet Mit dem Parameter stylesheet wird dem Servlet mitgeteilt, welchen Stylesheet es verwenden soll, um aus den XML-Daten des SDBDocuments eine HMTL-Seite zu erzeugen. 6.2.1.5 Parameter: form Dieser Parameter soll die Einstellung verschiedener Ausgabeformate ermöglichen. Zur Zeit werden aber nur zwei Formate unterstützt. Das Standardformat ist HTML und wird immer verwendet, auch wenn dieser Parameter nicht gesetzt wird. Wenn form=xml an das Servlet gesendet wird, wird der XML-String eines SDBDocuments unverändert gelassen. In den doGet()-Methoden der Servlets läßt sich vor der Datenausgabe (siehe process()) leicht jedes andere Format einstellen. Da die javax.servlet.http-Technologie es nicht zulässt, allein durch Angabe eines anderen Stylesheets das - 29 - Ausgabeformat einzustellen, muss dieses zusätzlich immer mit der Methode HttpServletResponse.setContentType() gesetzt werden. 6.2.1.6 Parameter: xmlparam Dieser Parameter gestattet es, an einen Stylesheet selbst wiederum Parameter weiterzugeben. Diese Technik wird zum Beispiel bei den Statistiken verwendet, um ein schnelles einfaches Umsortieren der Ergebnislisten zu ermöglichen. Dazu wird xmlparam=order_by_column:1 an das Servlet gesendet, dieses setzt anschließend in der SDBServlet.process()-Methode mit javax.xml.transform.Transformer.setParameter(order_by_column, 1) den entsprech- enden XSL-Parameter. In dem Stylesheet (siehe Anhang stat_antwort.xsl) kann dann auf den Wert zugegriffen werden und wie in diesem Beispiel nach der 1. Spalte sortiert werden. 6.2.2 class SDBSelect Dieses Servlet unterstützt alle unter 6.2.1 angegebenen Parameter. Damit eignet es sich lediglich zur Anzeige jedoch nicht zum Ändern von Daten. Entsprechend den Anforderungen für Navigationsleisten bietet es die Möglichkeit, immer nur einen Datensatz oder aber alle anzuzeigen. 6.2.3 class SDBExecute Aus Sicherheitsgründen sind die Möglichkeiten zur Datenmanipulation (insert, update, delete, etc.) durch das Servlet SDBExecute von der Selektion getrennt. Es stellt eine Erweiterung von SDBSelect dar und verarbeitet zusätzlich den folgenden Parameter sql. 6.2.3.1 Spezialparameter: sql Mit Hilfe des sql-Parameters können alle Arten von SQL-Anweisungen an das Servlet geschickt werden. Ähnlich wie bei dem Parameter query werden diese der Reihe nach, d.h. in der Reihenfolge ausgeführt, wie sie in der URL vorkommen bzw. an das Servlet gesendet werden. Es wird dabei keinerlei Überprüfung vorgenommen, ob das Statement korrekt ist oder ob es überhaupt ausgeführt werden darf. So ist es auch möglich, create table-Anweisungen wie auch drop table-Anweisungen auszuführen. Damit ist eine weitere Anforderung (vgl. 3.2 Anforderungen vom - 30 - Prüfungsamt) umgesetzt, denn in bestimmten Masken ist es notwendig temporäre Tabellen anzulegen. Alle SQL-Anweisungen werden in einer Transaktion zusammengefasst und nur mit commit beendet, wenn es keine Fehler gibt. Falls noch weitere Parameter, wie z.B. query an das Servlet geschickt werden, werden diese erst danach behandelt. 6.2.4 class SDBStatistik Das Servlet SDBStatistik erbt zwar genau wie SDBExecute auch von SDBSelect, hat aber eine grundlegend andere doGet()-Methode und damit auch eine andere Verarbeitung. Entsprechend der Implementierung wird davon ausgegangen, dass es ausschließlich von der Anfrageneditor-HTML-Seite oder von der Seite mit den gespeicherten Datenbankanfragen aufgerufen wird. Je nachdem welchen Wert der folgende Parameter doWhat hat, wird eine andere Methode ausgeführt. Damit sind alle Aufgaben für die Verwaltung der Datenbankanfragen für die Statistikerstellung in einem Servlet zusammengefasst. Falls der Parameter nicht an das Servlet übergeben wird, wird immer die Liste der gespeicherten Statistiken erzeugt. 6.2.4.1 Spezialparameter: doWhat In Abhängigkeit von dem Wert des Parameters steuert dieser das Servlet. Als Werte sind zulässig: speichern/save, bearbeiten/edit, ausführen/execute, löschen/delete, es kann jeweils der deutsche wie auch der englische Begriff verwendet werden. So kann direkt auf einen Button (vgl. HTML: <input type=“button“ name=“doWhat“ value=“speichern“>) das deutsche Wort geschrieben werden, denn der Wert des Buttons wird durch den angezeigten Text bestimmt. Um evtl. auftretende Probleme mit den deutschen Umlauten zu vermeiden, wurden zusätzlich die englischen Bezeichnungen mit aufgenommen. speichern/save Mit diesem Wert wird das Servlet dazu veranlasst, die Cookies auszulesen (vgl. 6.2.4.2). Je nachdem, ob eine STATID als Parameter mit übergeben wurde, wird ein insert (keine STATID) oder ein update (mit entsprechender STATID) auf der Tabelle pra03. stat_statistiken vorgenommen. Anschließend wird die Liste der - 31 - gespeicherten Anfragen mit einem Hinweis dargestellt, ob das Speichern erfolgreich war. bearbeiten/edit Wird einer dieser beiden Werte an das Servlet ge- sendet, ist ein zusätzlicher Parameter STATID unablässig. Es wird dann der Datensatz mit der entsprechenden lfd_nr aus der Tabelle pra03. stat_statistiken gelesen und die Cookies aus dem long-varchar-Feld werden wieder hergestellt (vgl. 6.2.4.2), so dass nach einem HttpServletResponse.sendRedirect("statistik.html") eine Bearbeitung in dem Anfrageneditor vorgenommen werden kann. ausführen/execute Diese Werte steuern das Servlet so, dass entweder die aktuelle Anfrage gemäß der Eingabe in dem Anfrageneditor ausgeführt wird oder eine aus der Liste der gespeicherten Datenbankanfragen ausgewählte Anfrage. Dazu wird diese aus der Tabelle pra03.stat_statistiken zuerst ausgelesen und dann ausgeführt. löschen/delete Der Aufruf des Servlets mit diesen Werten wird nur von der Seite mit den gespeicherten Datenbankanfragen vorgenommen und führt dazu, dass die Datenbankanfrage mit der lfd_nr (entspricht mitgesendeter STATID) gelöscht wird. Anschließend wird wieder die Liste mit den gespeicherten Anfragen mit einem Hinweis dargestellt, ob das Löschen erfolgreich war. 6.2.4.2 private class StatCookie Diese Klasse übernimmt die Umwandlung der Cookies in einen langen zusammenhängenden String und auch wieder zurück. Wird eine Statistik gespeichert, werden die Cookies von dem Client gelesen und hintereinander in einen String mit den Trennsymbolen (:::: und ####) geschrieben. Dieser String wird in dem longvarchar-Feld der Tabelle pra03.stat_statistiken gespeichert (vgl. 5.4 Gespeicherte Datenbankanfragen). Soll stattdessen eine Anfrage bearbeitet werden, wird der String aus dem long-varchar-Feld ausgelesen und wieder in die einzelnen Cookies zerlegt, die anschließend bei dem Client wieder gesetzt werden. Der Anfrageneditor kann die Werte mit einem Javascript auslesen und die entsprechenden Einstellungen in den Textfeldern, Dropdown-Listen und Checkboxen vornehmen, so dass die Anfrage bearbeitet werden kann. - 32 - 7 Analyse der Umsetzung 7.1 Tests Die Servlets (SDBSelect, SDBExecute) wurden schon in der Erstellungsphase der Stylesheets im Rahmen der Bachelorarbeit für den Bereich 4. XML (Dokumentenerstellung) ausgiebig getestet. Zum Teil stellten sich erst beim Entwickeln der Stylesheets weitere Anforderungen an die Servlets heraus. Da sie noch in der Anfangsphase der Codierung festgestellt wurden, wurden diese auch gleich umgesetzt, so dass z.Z. keine weiteren Veränderungen an den Servlets anstehen. Bei den ersten Versionen des Anfrageneditors fühlten sich die Testpersonen, die evtl. später neue Datenbankanfragen erzeugen sollen, etwas „erschlagen“ von den vielen Eingabefeldern. Die Unübersichtlichkeit der Eingabemaske wurde ebenfalls bemängelt. In den folgenden Versionen wurde daher dynamisches-HTML eingeführt, damit nicht benötigte Eingabefelder ausgeblendet werden können und besonders wichtige Zellen in der Tabellestruktur des Editors farblich hervorgehoben werden. Mit dieser Lösung waren auch die MitarbeiterInnen des Prüfungsamtes sehr zufrieden. Gerade diesen Anwendern kommt es auf eine sehr einfache und übersichtliche Bedienung an, da sie über keine SQL-Kenntnisse verfügen und somit nicht in der Lage sind, die Fragestellung mit der erzeugten SQL-Anweisung abzugleichen. Bisher wurden einige der früheren Fragen als Datenbankanfragen mit dem Anfrageneditor neu erstellt, bearbeitet, ausgeführt, als XML exportiert, gespeichert und wieder gelöscht. Es wurden dabei keinerlei Probleme erkannt. 7.2 Gelöste Probleme Große Probleme bereitete anfangs die Tatsache, dass die ResultSets sich nur einmal „forwardonly“ lesen ließen. Die Frage, an welcher Stelle und in welchem Format die Daten am besten zwischengespeichert werden und ob sie überhaupt in einem Puffer gehalten werden sollten, löste einige Diskussionen unter den Projektbeteiligten aus. Die gefundene Lösung mit dem Speichern der Daten als ElementObjekte in einem Array erscheint nach den bisherigen Tests als praktikabel. Keine leichte Aufgabe bei der Codierung ist es Datenbankanfragen so zu speichern, dass sie später wieder in einen Editor zum Bearbeiten geladen werden können. Wird z.B. nur die erzeugte SQL-Anweisung gespeichert, muss das Erscheinungsbild einer - 33 - gespeicherten und wieder geladenen Anfrage in dem Anfrageneditor nicht unbedingt dem Erscheinungsbild vor dem „speichern/laden-Prozess“ gleichen. Das liegt daran, dass beim Wiederherstellen aus dem SQL-Text nicht festgestellt werden kann, in welcher Reihenfolge der Benutzer die Attribute in dem Anfrageneditor dargestellt hatte. Er könnte zuerst alle Attribute ausgewählt haben, die selektiert werden sollten und dann die für die Bedingungen oder in umgekehrter bzw. gemischter Reihenfolge. Daher wurde die Lösung mit den Cookies gewählt. Nur hiermit kann wirklich sichergestellt werden, dass eine Anfrage so wiederhergestellt wird, wie sie auch gespeichert wurde. Mangelnde Kenntnisse in der Webprogrammierung haben viel Zeit gekostet herauszufinden, dass es nicht möglich ist, mehr als 20 Cookies zu verwenden und dass die Datenmengen beim Versenden von HTML-Formulardaten bei der Verwendung von „get“, browser- und webserverabhängig begrenzt sind. 7.3 Beschränkungen Bisher ist es bei der Anfragenerstellung nicht möglich, Outer-Joins zu verwenden. Eine Tabelle kann auch nicht mehrfach ausgewählt werden, so dass ebenfalls keine Self-Referential-Joins genutzt werden können. Für die bisher gestellten Fragen war dies nicht notwendig. Sollte es wiedererwartend doch notwendig sein, wäre es evtl. sinnvoll, ähnlich wie bei den Unteranfragen eine frei veränderbare FROM-Klausel einzuführen. Gegebenenfalls müssten weitere Möglichkeiten überlegt und erprobt werden. Der Anfrageneditor ist z.Z. auf maximal zehn Spalten für Attribute begrenzt. Bei der Programmierung der Javascripte wurde allerdings darauf geachtet, relativ einfach die Anzahl der Spalten erhöhen zu können. Nach den bisherigen Tests und den früheren Anfragen scheint dies jedoch nicht notwendig zu sein. - 34 - 8 Zusammenfassung Für einen Datenbankadministrator oder für versierte Datenbankbenutzer mit SQLErfahrungen ist nur eine sehr kurze Einarbeitungszeit nötig, um neue Datenbankanfragen mit der neuen Schnittstelle (dem Anfrageneditor) zu entwerfen. Inwieweit die MitarbeiterInnen des Prüfungsamtes in der Lage sein werden, selbst neue Anfragen zu erstellen, bleibt abzuwarten. Bei der durchgeführten Vorstellung des Anfrageneditors im Prüfungsamt waren die MitarbeiterInnen diesem System gegenüber sehr aufgeschlossen und daran interessiert, es auf seine Möglichkeiten zu testen. Schon nach ca. einer halbstündigen Einführung waren sie in der Lage, eine vorgefertigte Anfrage in den Editor zu laden und die Bedingungen nach ihren Bedürfnisse anzupassen. Damit ist eine wesentliche Anforderung erfüllt. Eine noch stärker an QBE oder NQS angelehnte Schnittstelle wäre ebenfalls realisierbar gewesen, allerdings nur mit dem Einsatz von z.B. Java-Applets oder in einer Nicht-Browser-Lösung, auf die ausdrücklich verzichtet werden sollte. Das vorgestellte System eignet sich nicht nur für Datenbankanfragen, um daraus Statistiken zu erstellen, mit ihm kann sich auch ein Datenbankadministrator Anfragen für seine tägliche Datenüberwachung und -pflege erzeugen. So wurden schon bei den ersten Tests Anfragen erzeugt, die doppelte Einträge in der Lehrpersonaltabelle aufdeckten. Mit Hilfe des Servlets SDBExecute können solche doppelten Einträge in einer Administratorschnittstelle schnell korrigiert oder gelöscht werden. 8.1 Ausblick In diesem Abschnitt soll aufgezeigt werden, welche Veränderungen (Verbesserungen, Erweiterungen) nach einer angemessenen Erprobungsphase evtl. sinnvoll wären. 8.1.1 Datenbankschema Das Datenbankschema ist z.Z. in die HTML-Seite der Statistik bzw. in die dazugehörigen Javascripte fest eincodiert. Es wäre ebenfalls möglich diese von einem Servlet dynamisch zu erzeugen. - 35 - 8.1.2 Subqueries Bisher werden Subqueries bei den Bedingungen nicht weiter überprüft. Es könnte an dieser Stelle das Öffnen eines weiteren Eingabefensters vorgesehen werden, das den Benutzer unterstützt, eine Unterabfrage zu erzeugen, genauso wie es bereits bei der Erstellung der eigentlichen Anfrage realisiert wurde. 8.1.3 Maximale Anzahl von zehn Spalten Die Anzahl der zur Verfügung stehenden Spalten für die Attribute könnte evtl. erweitert werden. Jedoch sollten für die bisherigen Anforderungen zehn Spalten vorerst genügen. 8.1.4 „Durchblättern“ von Daten Falls zukünftig auf ein anderes Datenbanksystem umgestiegen wird, das die volle JDBC API ohne Einschränkungen unterstützt, sollte überprüft werden, inwiefern es besser wäre, die Daten nicht in den Servlets zwischenzuspeichern, sondern direkt auf den ResultSets zu operieren. Dann könnten ggf. die Klassen SDBElementList, SDBResultsImpl, SDBResultset und SDBRow entfallen. - 36 - 9 Literaturverzeichnis [01] P.P. Chen (1976): "The entity-relationship model toward a unified view of data", ACM Trans. on Database Systems 1 (1), S. 9-36 [02] E.F. Codd (1970): "A Relational Model of Data for Large Shared Data Banks“, Communications of the ACM, 13 (6), S. 377-387 http://www.acm.org/classics/nov95/ (12.09.2004) [03] CSS Cascading Style Sheets http://www.w3c.org/Style/CSS/ (12.09.2004) [04] DOM Document Object Model http://www.w3c.org/DOM/ (12.09.2004) [05] R. Elmasri, S. B. Navathe (1994): "Fundamentals of Database Systems“, 2nd Ed., Addison-Wesley, Amsterdam [06] D. Flanagan (1997): "JavaScript - Das umfassende Referenzwerk“, O'Reilly [07] D. Flanagan (1999): "JAVA in a Nutshell“, O'Reilly [08] Form submission method im HTML 4 Standard http://www.w3.org/TR/html4/interact/forms.html#submitformat (03.10.2004) [09] J.D. Gould, J.C. Thomas (1975): "A psychological study of query by example“, Proc. 10th CompCon, IEEE CS Press, S. 439-445 [10] M. Hall, L. Brown (2003): "Core Servlets and JavaServer Pages“, 2nd Ed., Prentice Hall [11] P. Hanna (2000): "Instant Java Servlets“, McGraw Hill [12] A. Heuer, G. Saake (1995): "Datenbanken - Konzepte und Sprachen“, Thomson Publishing, Bonn [13] HTML HyperText Markup Language http://www.w3.org/MarkUp/ (12.09.2004) [14] IBM (1983): "Query-By-Example - Terminal User's Guide“, 4th Ed. [15] IBM-DB2 QMF / QBE http://publib.boulder.ibm.com/infocenter/dzichelp/inde x.jsp?topic=/com.ibm.qmf.doc.using_8.1.0/dsqk2mst338.h tm (24.09.2004) - 37 - [16] Java http://java.sun.com/ (12.09.2004) http://www.java.net/ (12.09.2004) [17] Java Servlets http://java.sun.com/products/servlet/ (12.09.2004) [18] Javascript http://de.selfhtml.org/javascript/index.htm (12.09.2004) [19] H.-J. Klein (1989): "Pragmatics and Semantics of NQL, a Descriptive Query Language for Network Databases“, Information Systems, 14 (1), S. 29-45 [20] H.-J. Klein, D. Krämer (1995): "NQS a graphical query system for data models with binary relationship types“, Proc. Visual Database Systems 3, Chapman & Hall, S. 394-409 [21] J. Melton (2003): "Advanced SQL:1999. Understanding Object-Relational and Other Advanced Features“, Morgan Kaufmann [22] J. Melton, A. Eisenberg (2000): "Understanding SQL and Java Together. A Guide to SQLJ, JDBC, and Related Technologies“, Morgan Kaufmann [23] J. Melton, A.R. Simon (2002): "SQL:1999. Understanding Relational Language Concepts“, Morgan Kaufmann [24] Query By Example (QBE) Web interface to an existing RDBMS, http://ssi.umh.ac.be/tpfbd2002-03.shtml (06.10.2004), Université Mons-Hainaut (U.M.H.) [25] J.D. Ullman (1988): "Principles of Database and Knowledge Base Systems Vol. I“, 3rd Ed., Computer Science Press, Rockville, MD [26] UnivIS http://www.univis.de/ (06.10.2004) [27] URI/URL http://www.w3c.org/Addressing/ (12.09.2004) [28] XML Extensible Markup Language http://www.w3.org/XML/ (12.09.2004) [29] XSL Extensible Stylesheet Language http://www.w3.org/Style/XSL/ (12.09.2004) [30] M.M. Zloof (1975): "Query-by-example“, AFIPS Conference Proceedings National Computer Conference 44, S. 431-438 [31] M.M. Zloof (1977): "Query by Example: a data base language“, IBM Systems Journal 16 (4) S. 324-343 - 38 - 9.1 Verwendete Entwicklungsumgebung & Tools [32] CSS Validator http://jigsaw.w3.org/css-validator/ (12.09.2004) [33] Eclipse http://www.eclipse.org/ (12.09.2004) [34] HTML Validator http://validator.w3.org/ (12.09.2004) [35] Ingres http://opensource.ca.com/projects/ingres/ (12.09.2004) [36] Mozilla 1.6 http://www.mozilla.org/releases/mozilla1.6/ (27.09.2004) [37] Tomcat http://jakarta.apache.org/tomcat/ (12.09.2004) - 39 - 10 Erklärung Hiermit versichere ich, dass ich diese Arbeit selbstständig verfasst und keine anderen als die angegebenen Hilfsmittel benutzt habe. Diese Arbeit ist bisher noch nicht anderweitig als Bachelorarbeit eingereicht oder veröffentlicht worden. Kiel, 07.10.2004 Hilmar Falkenberg - 40 - DIPLOMARBEITEN INDUSTRIEPRAKTIKA 1 1 (0,1) STUDIERENDE 1 ----------------------------------- 1 1 (0,1) DIPLOM_PRUEFUNGEN ANERKENNUNGEN -------------------------------Matrikel_nr Lehrpersonal_nr_1 Lehrpersonal_nr_2 N Datum N Note N (0,n) Fach_nr Wiederholung_ja_nein Kommentar N (0,n) (0,n) ----------------------Matrikel_nr Leistung (0,n) Leistpunkte N Note N UNTERBRECHUNGEN Datum ------------------------Verantwortlich (0,n) Matrikel_nr Kommentar N Beginn Ende N Grund N DIPLOM --------------------------------------Matrikel_nr Datum_letzte_pruefung N Datum_erstellung_zeugnis N Gesamtnote N Bemerkung N Nbestanden_ja_nein Anmeldedatum Kommentar N VORDIPLOM ------------------------------------Matrikel_nr Datum_letzte_pruefung N Gesamtnote N Bemerkung N Nbestanden_ja_nein Anmeldedatum Kommentar N Fach_nr Bezeichnung Kommentar N 1 -------------------------- 1 PRUEFUNGSFAECHER 1 Matrikel_nr Name Vorname Geschlecht ---------------------------1 Geburtsdatum Matrikel_nr Datum 1 Strasse N Name_des_betriebes (0,n) Plz N (0,n) (0,m) Ort N Dauer N Telefon_1 N ANGESTR_ABSCHLUSS Anerkannt_ja_nein (0,n) (0,1) ------------------------------Telefon_2 N Kommentar N Email_institut N Angestr_abschluss_nr Email_privat N Bezeichnung STUDIENFAECHER Hauptfach_nr N INDUSTRIEPRAKTIKA_ING ------------------------(0,m) Nebenfach_nr_1 N -----------------------------(0,n) Studienfach_nr (1,n) Nebenfach_nr_2 N Matrikel_nr Bezeichnung STUDIENFORM 1 LEHRSTUHL Angestr_abschluss_nr N (0,n) Datum_erstellt (0,1) ---------------------(0,n) ------------------Fachsemester N Dauer_mech_gp N Studienform_nr Lehrstuhl_nr Studienbeginn N Dauer_elek_gp N Bezeichnung Bezeichnung Studienabschluss N Dauer_fachpraxis N 1 (0,n) Exmatrikuliert_ja_nein Geprueft_ja_nein SCHEINE Kommentar N 1 (0,1) ---------------------------------STUDIENARBEITEN (0,n) 1 Zuletzt_bearbeitet N Scheintyp_nr Abschlussnote N ----------------------Veranstaltung_nr Studienform_nr N Matrikel_nr Semester 1 Datum Matrikel_nr (0,1) Lehrpersonal_nr Datum Thema ZERTIFIKAT_PRUEFUNGEN Text_zeile_1 N 1 (0,1) Beurteilung N -------------------------------- (0,1) 1 (0,n) (4,n) Text_zeile_2 N Kommentar N Matrikel_nr LEHRPERSONAL 1 Kommentar N Datum_zeugnis -------------------------Note_ja_nein Pruefungsfach_1 Lehrpersonal_nr Note N Pruefungsfach_2 Titel N Thema N Name Stundenzahl N 1 Vorname Wiederholung 1 1 (0,n) Zurueckgetreten_ja_nein VERANSTALTUNGEN Fakultaet WIRD_GEHALTEN_VON -----------------------------------------------------------------Institut_ja_nein Zuordnung 1 (1,n) Veranstaltung_nr Veranstaltung_nr Lehrstuhl_nr N (0,n) 1 1 (0,n) Semester Semester Bezeichnung Lehrpersonal_nr SCHEINTYPEN Teilnehmerzahl_beginn N -------------------Teilnehmerzahl_ende N Scheintyp_nr Vtyp_nr Bezeichnung Stundenzahl GRUPPEN VERANSTALTUNGEN_FACHGEBIET Ects_univis FACHGEBIET -----------------------1 ------------------------------------------ (0,n) Ects_schein ------------------- 1 Semester Veranstaltung_nr 1 Kommentar N Fachgebiet_nr (0,n) (0,n) (0,n) (0,n) Veranstaltung_nr Semester (0,n) Bezeichnung VERANST_TEILNEHMER 1 Gruppe_nr Lfd_nr 1 Zeit N ----------------------------Fachgebiet_nr Leiter N Semester VERANSTALTUNGSTYPEN Anzahl_max N Veranstaltung_nr ----------------------------------Anzahl_akt N Matrikel_nr Vtyp_nr Bemerkung N Gruppe_nr Veranstaltungstyp ---------------------------------Matrikel_nr Anmeldedatum Note N Thema (0,n) Betreuer N Gutachter_1 Gutachter_2 N Abgabedatum N Lehrstuhl_nr N Zurueckgegeben_ja_nein Kommentar N (0,n) --------------------------------Matrikel_nr Lehrpersonal_nr_1 Lehrpersonal_nr_2 N Datum N Note N Fach_nr Wiederholung_ja_nein (0,n) Klausur_ja_nein Kommentar N VORDIPLOM_PRUEFUNGEN (0,n) Schema Studierendendatenbank : Stand 27. Sep. 2004 Anhang 1 von 71 Gutachter 1 Gutachter 2 Seite: 1 von 20 Seite: 1 von 20 <!-- 2. Zeile: Tabellenauswahl, hier ist die Liste mit den Tabellen, die für die Anfragen zur Verfügung stehen. Wenn sich das Datenbankschema ändert, müssen hier ggf. Tabellen ergänzt werden. Pro Tabelle eine Option. <td id="R0C2" colspan="10"><input maxlength="255" size="150" type="text" name="frage" onchange="onChangeFrage(this.value)" /></td> </tr> <!-- Die ganze Tabelle ist in ein Formular eingebettet --> <form action="Statistiken" method="post" name="StatistikFormular"> <table border="1" align="center" summary="Tabelle dient nur fürs Layout"> <!-- 1. Zeile: Frage, 100 Zeichenlanges Textfeld für einen Namen der Anfrage --> <tr id="ROW0"> <td id="R0C1" class="disabled" align="right"><a href="javascript:popUp(&#39;help/Frage.html&#39;)">Frage</a> </td> <!-- Body-Events: onload="onLoadStatBody()" --> <body onload="onLoadStatBody()"> <h3>Anfrageneditor für die Studierendendatenbank</h3> <title>Anfrageneditor für die Studierendendatenbank</title> <!-- Liste der zu importierdenden Javascripte und Stylesheets --> <script language="javascript" src="scripts/check.js" type="text/javascript"> </script> <script language="javascript" src="scripts/cookie.js" type="text/javascript"> </script> <script language="javascript" src="scripts/stat_globals.js" type="text/javascript"> </script> <script language="javascript" src="scripts/stat_schema.js" type="text/javascript"> </script> <script language="javascript" src="scripts/stat_cookies.js" type="text/javascript"> </script> <script language="javascript" src="scripts/stat_erstellen.js" type="text/javascript"> </script> <script language="javascript" src="scripts/stat_events.js" type="text/javascript"> </script> <link rel="stylesheet" type="text/css" href="styles/statistik.css" /> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: statistik.html Version: $Revision: 1.10 $ == Autor: Hilmar Falkenberg $Date: 2004/10/06 17:33:12 $ == == Beschreibung: Der Anfrageneditor - die BASIS-Seite zum erstellen neuer == Datenbankanfragen und zum bearbeiten von gespeicherten Anfragen. == Aufruf mit 'statistik.html?neu' öffnet den Editor, ohne alte Werte aus == den Cookies wiederherzustellen. Wird die Seite nur mit 'statistik.html' == aufgerufen, wird nach den Cookies gesucht und die zuletzt bearbeitete == Anfrage in den Editor geladen. ========================================================================== --> Datei: statistik.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: statistik.html 2 von 71 Seite: 2 von 20 Seite: 2 von 20 <option value="studienarbeiten sa" label="Studienarbeiten"> Studienarbeiten </option> <option value="scheintypen scht" label="Scheintypen"> Scheintypen </option> <option value="scheine sch" label="Scheine"> Scheine </option> <option value="pruefungsfaecher pf" label="Prüfungsfächer"> Prüfungsfächer </option> <option value="lehrstuhl ls" label="Lehrstuhl"> Lehrstuhl </option> <option value="lehrpersonal lp" label="Lehrpersonal"> Lehrpersonal </option> <option value="industriepraktika_ing ii" label="Industriepraktika (Ing)"> Industriepraktika (Ing) </option> <option value="industriepraktika i" label="Industriepraktika"> Industriepraktika </option> <option value="gruppen g" label="Gruppen"> Gruppen </option> <option value="fachgebiet f" label="Fachgebiet"> Fachgebiet </option> <option value="diplomarbeiten da" label="Diplomarbeiten"> Diplomarbeiten </option> <option value="diplom_pruefungen dp" label="Diplom-Prüfungen"> Diplom-Prüfungen </option> <option value="diplom d" label="Diplom"> Diplom </option> <option value="angestr_abschluss aa" label="Angestr-Abschluss"> Angestr-Abschluss </option> <tr id="ROW1"> <td id="R1C1" colspan="1"><select name="Tabellen" size="5" onchange="onChangeTabellen();" multiple="multiple"> <option value="anerkennungen a" label="Anerkennungen"> Anerkennungen </option> Events: onchange="onChangeTabellen();" Datei: statistik.html 69 70 --> 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: statistik.html Anhang <option value="zertifikat_pruefungen z" label="Zertifikat-Prüfungen"> Zertifikat-Prüfungen </option> </select> </td> <option value="wird_gehalten_von w" label="Wird gehalten von"> Wird gehalten von </option> <option value="vordiplom_pruefungen vdp" label="Vordiplom-Prüfungen"> Vordiplom-Prüfungen </option> <option value="vordiplom vd" label="Vordiplom"> Vordiplom </option> <option value="veranstaltungstypen vtyp" label="Veranstaltungstypen"> Veranstaltungstypen </option> <option value="veranstaltungen_fachgebiet vf" label="Veranstaltungen-Fachgebiet"> Veranstaltungen-Fachgebiet </option> <option value="veranstaltungen v" label="Veranstaltungen"> Veranstaltungen </option> <option value="veranst_teilnehmer vt" label="Veranst-Teilnehmer"> Veranst-Teilnehmer </option> <option value="unterbrechungen u" label="Unterbrechungen"> Unterbrechungen </option> <option value="studierende s" label="Studierende"> Studierende </option> <option value="studienform sfo" label="studienform"> Studienform </option> <option value="studienfaecher sf" label="Studienfächer"> Studienfächer </option> Seite: 3 von 20 Seite: 3 von 20 <td id="R1C2" colspan="10" class="disabled"> <p>Wählen Sie (links) die Tabellen aus, die Sie in die Abfrage mit einbeziehen möchten.<br /> <em>Tipp: Sie können auch mehrere Tabellen markieren, wenn Sie die Steuerungstaste (&#39;Strg&#39; bzw. &#39;Ctrl&#39;) gedrückt halten.</em><br /> Wählen Sie dann die Felder aus, die angezeigt werden sollen.<br /> <a target="new" href="help/studi_schema_neu.pdf">Datenbankschema< </td> </tr> Datei: statistik.html 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: statistik.html Seite: 4 von 20 3 von 71 Datei: statistik.html Seite: 4 von 20 205 <!-- 3. Zeile: Spalten tauschen, hier sind die Buttons zum vertauschen von 206 zwei nebeneinanderliegenden Spalten. 207 Events: onclick="onClickFlip__(SPALTENNUMMER, SPALTENNUMMER)" 208 --> 209 <tr id="ROW2" align="center"> 210 <td id="R2C1" class="disabled" align="right"><a 211 href="javascript:popUp(&#39;help/tauschen.html&#39;)">Spalten 212 tauschen</a> </td> 213 214 <td id="R2C2" class="nonvisible"><input type="button" 215 id="flipr0" value=" &gt;&gt; " 216 onclick="onClickFlip__(0, 1)" /></td> 217 218 <td id="R2C3" class="nonvisible"><input type="button" 219 id="flipl1" value=" &lt;&lt; " 220 onclick="onClickFlip__(0, 1)" /> <input type="button" 221 id="flipr1" value=" &gt;&gt; " 222 onclick="onClickFlip__(1, 2)" /></td> 223 224 <td id="R2C4" class="nonvisible"><input type="button" 225 id="flipl2" value=" &lt;&lt; " 226 onclick="onClickFlip__(1, 2)" /> <input type="button" 227 id="flipr2" value=" &gt;&gt; " 228 onclick="onClickFlip__(2, 3)" /></td> 229 230 <td id="R2C5" class="nonvisible"><input type="button" 231 id="flipl3" value=" &lt;&lt; " 232 onclick="onClickFlip__(2, 3)" /> <input type="button" 233 id="flipr3" value=" &gt;&gt; " 234 onclick="onClickFlip__(3, 4)" /></td> 235 236 <td id="R2C6" class="nonvisible"><input type="button" 237 id="flipl4" value=" &lt;&lt; " 238 onclick="onClickFlip__(3, 4)" /> <input type="button" 239 id="flipr4" value=" &gt;&gt; " 240 onclick="onClickFlip__(4, 5)" /></td> 241 242 <td id="R2C7" class="nonvisible"><input type="button" 243 id="flipl5" value=" &lt;&lt; " 244 onclick="onClickFlip__(4, 5)" /> <input type="button" 245 id="flipr5" value=" &gt;&gt; " 246 onclick="onClickFlip__(5, 6)" /></td> 247 248 <td id="R2C8" class="nonvisible"><input type="button" 249 id="flipl6" value=" &lt;&lt; " 250 onclick="onClickFlip__(5, 6)" /> <input type="button" 251 id="flipr6" value=" &gt;&gt; " 252 onclick="onClickFlip__(6, 7)" /></td> 253 254 <td id="R2C9" class="nonvisible"><input type="button" 255 id="flipl7" value=" &lt;&lt; " 256 onclick="onClickFlip__(6, 7)" /> <input type="button" 257 id="flipr7" value=" &gt;&gt; " 258 onclick="onClickFlip__(7, 8)" /></td> 259 260 <td id="R2C10" class="nonvisible"><input type="button" 261 id="flipl8" value=" &lt;&lt; " 262 onclick="onClickFlip__(7, 8)" /> <input type="button" 263 id="flipr8" value=" &gt;&gt; " 264 onclick="onClickFlip__(8, 9)" /></td> 265 266 <td id="R2C11" class="nonvisible"><input type="button" 267 id="flipl9" value=" &lt;&lt; " 268 onclick="onClickFlip__(8, 9)" /></td> 269 </tr> 270 271 <!-- 4. Zeile: Feld, hier sind die Dropdownfelder mit den Attributen; 272 wird dynamisch durch "onChangeTabellen()" gefüllt und Datei: statistik.html Anhang Seite: 5 von 20 Seite: 5 von 20 <td id="R3C9" class="nonvisible"><select name="Feld7" size="1" <td id="R3C8" class="nonvisible"><select name="Feld6" size="1" onchange="onChangeFeld_(6)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle6" size="20" readonly="readonly" /></td> <td id="R3C7" class="nonvisible"><select name="Feld5" size="1" onchange="onChangeFeld_(5)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle5" size="20" readonly="readonly" /></td> <td id="R3C6" class="nonvisible"><select name="Feld4" size="1" onchange="onChangeFeld_(4)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle4" size="20" readonly="readonly" /></td> <td id="R3C5" class="nonvisible"><select name="Feld3" size="1" onchange="onChangeFeld_(3)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle3" size="20" readonly="readonly" /></td> <td id="R3C4" class="nonvisible"><select name="Feld2" size="1" onchange="onChangeFeld_(2)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle2" size="20" readonly="readonly" /></td> <td id="R3C3" class="nonvisible"><select name="Feld1" size="1" onchange="onChangeFeld_(1)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle1" size="20" readonly="readonly" /></td> <td id="R3C2" class="nonvisible"><select name="Feld0" size="1" onchange="onChangeFeld_(0)"> <option> </option> </select> <br /> <input class="disabled" type="text" name="Tabelle0" size="20" readonly="readonly" /></td> <tr id="ROW3" align="center"> <td id="R3C1" class="disabled" align="right"><a href="javascript:popUp(&#39;help/Felder.html&#39;)">Feld</a> <br /> <a href="javascript:popUp(&#39;help/Tabelle.html&#39;)">aus Tabelle</a> </td> die readonly Felder mit den Tabellennamen des ausgewählten Attributs Events: onchange="onChangeFeld_(SPALTENNUMMER)" Datei: statistik.html 273 274 275 276 --> 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: statistik.html Seite: 6 von 20 4 von 71 Datei: statistik.html Seite: 6 von 20 341 onchange="onChangeFeld_(7)"> 342 <option> 343 </option> 344 </select> <br /> 345 <input class="disabled" type="text" name="Tabelle7" size="20" 346 readonly="readonly" /></td> 347 348 <td id="R3C10" class="nonvisible"><select name="Feld8" 349 size="1" onchange="onChangeFeld_(8)"> 350 <option> 351 </option> 352 </select> <br /> 353 <input class="disabled" type="text" name="Tabelle8" size="20" 354 readonly="readonly" /></td> 355 356 <td id="R3C11" class="nonvisible"><select name="Feld9" 357 size="1" onchange="onChangeFeld_(9)"> 358 <option> 359 </option> 360 </select> <br /> 361 <input class="disabled" type="text" name="Tabelle9" size="20" 362 readonly="readonly" /></td> 363 </tr> 364 365 <!-- 5. Zeile: anzeigen / sortieren / Spaltenüberschrift; 366 eine Checkbox für die Anzeige des Attributs; 367 eine Dropdownliste mit drei Werten (LEER, asc, desc) zum sortieren 368 ein Textfeld zum eingeben eines Alias für diese Spalte 369 Events: onclick="onClickFeld_anz(SPALTENNUMMER)" 370 onchange="onChangeFeld_sort()" 371 onchange="onChangeAlias_(SPALTENNUMMER)" 372 --> 373 <tr id="ROW4" align="center"> 374 <td id="R4C1" class="disabled" align="right"> 375 <p><a 376 href="javascript:popUp(&#39;help/anzeigen.html&#39;)">anzeigen</a> 377 / <a 378 href="javascript:popUp(&#39;help/sortieren.html&#39;)">sortieren</ 379 <a 380 href="javascript:popUp(&#39;help/alias.html&#39;)">Spaltenüberschr 381 </td> 382 383 <td id="R4C2" class="nonvisible"><input type="checkbox" 384 name="Feld0anz" onclick="onClickFeld_anz(0)" /><select 385 name="Feld0sort" size="1" onchange="onChangeFeld_sort()"> 386 <option> 387 </option> 388 389 <option value=" asc"> 390 aufsteigend 391 </option> 392 393 <option value=" desc"> 394 absteigend 395 </option> 396 </select> <br /> 397 <input type="text" name="Alias0" onchange="onChangeAlias_(0)" 398 size="20" /></td> 399 400 <td id="R4C3" class="nonvisible"><input type="checkbox" 401 name="Feld1anz" onclick="onClickFeld_anz(1)" /><select 402 name="Feld1sort" size="1" onchange="onChangeFeld_sort()"> 403 <option> 404 </option> 405 406 <option value=" asc"> 407 aufsteigend 408 </option> Datei: statistik.html Anhang Datei: statistik.html 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 Datei: statistik.html <option value=" asc"> aufsteigend </option> Seite: 7 von 20 <td id="R4C7" class="nonvisible"><input type="checkbox" name="Feld5anz" onclick="onClickFeld_anz(5)" /><select name="Feld5sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias4" onchange="onChangeAlias_(4)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C6" class="nonvisible"><input type="checkbox" name="Feld4anz" onclick="onClickFeld_anz(4)" /><select name="Feld4sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias3" onchange="onChangeAlias_(3)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C5" class="nonvisible"><input type="checkbox" name="Feld3anz" onclick="onClickFeld_anz(3)" /><select name="Feld3sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias2" onchange="onChangeAlias_(2)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C4" class="nonvisible"><input type="checkbox" name="Feld2anz" onclick="onClickFeld_anz(2)" /> <select name="Feld2sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias1" onchange="onChangeAlias_(1)" size="20" /></td> Seite: 7 von 20 5 von 71 Datei: statistik.html 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 Datei: statistik.html Anhang <option value=" asc"> aufsteigend </option> Seite: 8 von 20 <td id="R4C11" class="nonvisible"><input type="checkbox" name="Feld9anz" onclick="onClickFeld_anz(9)" /> <select name="Feld9sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias8" onchange="onChangeAlias_(8)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C10" class="nonvisible"><input type="checkbox" name="Feld8anz" onclick="onClickFeld_anz(8)" /><select name="Feld8sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias7" onchange="onChangeAlias_(7)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C9" class="nonvisible"><input type="checkbox" name="Feld7anz" onclick="onClickFeld_anz(7)" /><select name="Feld7sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias6" onchange="onChangeAlias_(6)" size="20" /></td> <option value=" asc"> aufsteigend </option> <td id="R4C8" class="nonvisible"><input type="checkbox" name="Feld6anz" onclick="onClickFeld_anz(6)" /><select name="Feld6sort" size="1" onchange="onChangeFeld_sort()"> <option> </option> <option value=" desc"> absteigend </option> </select> <br /> <input type="text" name="Alias5" onchange="onChangeAlias_(5)" size="20" /></td> Seite: 8 von 20 Seite: 9 von 20 Datei: statistik.html Seite: 9 von 20 545 546 <option value=" desc"> 547 absteigend 548 </option> 549 </select> <br /> 550 <input type="text" name="Alias9" onchange="onChangeAlias_(9)" 551 size="20" /></td> 552 </tr> 553 554 <!-- 6. Zeile: verknüpfen mit / aus Tabelle, mit einer Vergleichsoperatorenliste 555 (dynamisch gefüllt in onLoadStatBody()) und 556 der Liste der wählbaren Attributen siehe 4. Zeile 557 Events: onclick="onCheckBox1(this.checked)" 558 onchange="onChangeCond_0()" 559 onchange="onChangeFeld_join()" 560 --> 561 <tr id="ROW5" align="center"> 562 <td id="R5C1" align="right"><input type="checkbox" 563 name="CheckBox1" onclick="onCheckBox1(this.checked)" /><a 564 href="javascript:popUp(&#39;help/join.html&#39;)">verknüpfen 565 mit</a> <br /> 566 <a href="javascript:popUp(&#39;help/Tabelle.html&#39;)">aus 567 Tabelle</a> </td> 568 569 <td id="R5C2" class="nonvisible"><select name="Cond00" 570 size="1" onchange="onChangeCond_0()"> 571 <option> 572 </option> 573 </select><select name="Feld0join" size="1" 574 onchange="onChangeFeld_join()"> 575 <option> 576 </option> 577 </select> <br /> 578 <input class="disabled" type="text" name="VTabelle0" 579 size="20" readonly="readonly" /></td> 580 581 <td id="R5C3" class="nonvisible"><select name="Cond10" 582 size="1" onchange="onChangeCond_0()"> 583 <option> 584 </option> 585 </select><select name="Feld1join" size="1" 586 onchange="onChangeFeld_join()"> 587 <option> 588 </option> 589 </select> <br /> 590 <input class="disabled" type="text" name="VTabelle1" 591 size="20" readonly="readonly" /></td> 592 593 <td id="R5C4" class="nonvisible"><select name="Cond20" 594 size="1" onchange="onChangeCond_0()"> 595 <option> 596 </option> 597 </select><select name="Feld2join" size="1" 598 onchange="onChangeFeld_join()"> 599 <option> 600 </option> 601 </select> <br /> 602 <input class="disabled" type="text" name="VTabelle2" 603 size="20" readonly="readonly" /></td> 604 605 <td id="R5C5" class="nonvisible"><select name="Cond30" 606 size="1" onchange="onChangeCond_0()"> 607 <option> 608 </option> 609 </select><select name="Feld3join" size="1" 610 onchange="onChangeFeld_join()"> 611 <option> 612 </option> Datei: statistik.html 6 von 71 Datei: statistik.html 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 Datei: statistik.html Anhang Seite: 10 von 20 <td id="R5C11" class="nonvisible"><select name="Cond90" size="1" onchange="onChangeCond_0()"> <option> </option> <td id="R5C10" class="nonvisible"><select name="Cond80" size="1" onchange="onChangeCond_0()"> <option> </option> </select><select name="Feld8join" size="1" onchange="onChangeFeld_join()"> <option> </option> </select> <br /> <input class="disabled" type="text" name="VTabelle8" size="20" readonly="readonly" /></td> <td id="R5C9" class="nonvisible"><select name="Cond70" size="1" onchange="onChangeCond_0()"> <option> </option> </select><select name="Feld7join" size="1" onchange="onChangeFeld_join()"> <option> </option> </select> <br /> <input class="disabled" type="text" name="VTabelle7" size="20" readonly="readonly" /></td> <td id="R5C8" class="nonvisible"><select name="Cond60" size="1" onchange="onChangeCond_0()"> <option> </option> </select><select name="Feld6join" size="1" onchange="onChangeFeld_join()"> <option> </option> </select> <br /> <input class="disabled" type="text" name="VTabelle6" size="20" readonly="readonly" /></td> <td id="R5C7" class="nonvisible"><select name="Cond50" size="1" onchange="onChangeCond_0()"> <option> </option> </select><select name="Feld5join" size="1" onchange="onChangeFeld_join()"> <option> </option> </select> <br /> <input class="disabled" type="text" name="VTabelle5" size="20" readonly="readonly" /></td> <td id="R5C6" class="nonvisible"><select name="Cond40" size="1" onchange="onChangeCond_0()"> <option> </option> </select><select name="Feld4join" size="1" onchange="onChangeFeld_join()"> <option> </option> </select> <br /> <input class="disabled" type="text" name="VTabelle4" size="20" readonly="readonly" /></td> </select> <br /> <input class="disabled" type="text" name="VTabelle3" size="20" readonly="readonly" /></td> Seite: 10 von 20 Seite: 11 von 20 Datei: statistik.html Seite: 11 von 20 681 </select><select name="Feld9join" size="1" 682 onchange="onChangeFeld_join()"> 683 <option> 684 </option> 685 </select> <br /> 686 <input class="disabled" type="text" name="VTabelle9" 687 size="20" readonly="readonly" /></td> 688 </tr> 689 690 <!-- 7. Zeile: Bedingung, mit Vergleichoperatorenliste und Textfeld 691 Events: onclick="onCheckBox2(this.checked)" 692 onchange="check(TEXTFELD, SPALTENNUMMER, 1)" 693 --> 694 <tr id="ROW6" align="center"> 695 <td id="R6C1" align="right"><input type="checkbox" 696 name="CheckBox2" onclick="onCheckBox2(this.checked)" /><a 697 href="javascript:popUp(&#39;help/Bedingung.html&#39;)">Bedingung</a> 698 </td> 699 700 <td id="R6C2" class="nonvisible"><select name="Cond01" 701 size="1" 702 onchange="check(document.StatistikFormular.Where0, 0, 1)"> 703 <option> 704 </option> 705 </select><input type="text" name="Where0" 706 onchange="check(this, 0, 1)" size="20" /></td> 707 708 <td id="R6C3" class="nonvisible"><select name="Cond11" 709 size="1" 710 onchange="check(document.StatistikFormular.Where1, 1, 1)"> 711 <option> 712 </option> 713 </select><input type="text" name="Where1" 714 onchange="check(this, 1, 1)" size="20" /></td> 715 716 <td id="R6C4" class="nonvisible"><select name="Cond21" 717 size="1" 718 onchange="check(document.StatistikFormular.Where2, 2, 1)"> 719 <option> 720 </option> 721 </select><input type="text" name="Where2" 722 onchange="check(this, 2, 1)" size="20" /></td> 723 724 <td id="R6C5" class="nonvisible"><select name="Cond31" 725 size="1" 726 onchange="check(document.StatistikFormular.Where3, 3, 1)"> 727 <option> 728 </option> 729 </select><input type="text" name="Where3" 730 onchange="check(this, 3, 1)" size="20" /></td> 731 732 <td id="R6C6" class="nonvisible"><select name="Cond41" 733 size="1" 734 onchange="check(document.StatistikFormular.Where4, 4, 1)"> 735 <option> 736 </option> 737 </select><input type="text" name="Where4" 738 onchange="check(this, 4, 1)" size="20" /></td> 739 740 <td id="R6C7" class="nonvisible"><select name="Cond51" 741 size="1" 742 onchange="check(document.StatistikFormular.Where5, 5, 1)"> 743 <option> 744 </option> 745 </select><input type="text" name="Where5" 746 onchange="check(this, 5, 1)" size="20" /></td> 747 748 <td id="R6C8" class="nonvisible"><select name="Cond61" Datei: statistik.html Seite: 12 von 20 7 von 71 Datei: statistik.html Seite: 12 von 20 749 size="1" 750 onchange="check(document.StatistikFormular.Where6, 6, 1)"> 751 <option> 752 </option> 753 </select><input type="text" name="Where6" 754 onchange="check(this, 6, 1)" size="20" /></td> 755 756 <td id="R6C9" class="nonvisible"><select name="Cond71" 757 size="1" 758 onchange="check(document.StatistikFormular.Where7, 7, 1)"> 759 <option> 760 </option> 761 </select><input type="text" name="Where7" 762 onchange="check(this, 7, 1)" size="20" /></td> 763 764 <td id="R6C10" class="nonvisible"><select name="Cond81" 765 size="1" 766 onchange="check(document.StatistikFormular.Where8, 8, 1)"> 767 <option> 768 </option> 769 </select><input type="text" name="Where8" 770 onchange="check(this, 8, 1)" size="20" /></td> 771 772 <td id="R6C11" class="nonvisible"><select name="Cond91" 773 size="1" 774 onchange="check(document.StatistikFormular.Where9, 9, 1)"> 775 <option> 776 </option> 777 </select><input type="text" name="Where9" 778 onchange="check(this, 9, 1)" size="20" /></td> 779 </tr> 780 781 <!-- 8. Zeile: 'oder' 1, mit Vergleichoperatorenliste und Textfeld 782 Events: onclick="onCheckBox3(this.checked)" 783 onchange="check(TEXTFELD, SPALTENNUMMER, 2)" 784 --> 785 <tr id="ROW7" class="nonvisible" align="center"> 786 <td id="R7C1" align="right"><input type="checkbox" 787 name="CheckBox3" onclick="onCheckBox3(this.checked)" /><a 788 href="javascript:popUp(&#39;help/Bedingung.html&#39;)">oder</a> 789 </td> 790 791 <td id="R7C2" class="nonvisible"><select name="Cond02" 792 size="1" 793 onchange="check(document.StatistikFormular.Where0Or1, 0, 2)"> 794 <option> 795 </option> 796 </select><input type="text" name="Where0Or1" 797 onchange="check(this, 0, 2)" size="20" /></td> 798 799 <td id="R7C3" class="nonvisible"><select name="Cond12" 800 size="1" 801 onchange="check(document.StatistikFormular.Where1Or1, 1, 2)"> 802 <option> 803 </option> 804 </select><input type="text" name="Where1Or1" 805 onchange="check(this, 1, 2)" size="20" /></td> 806 807 <td id="R7C4" class="nonvisible"><select name="Cond22" 808 size="1" 809 onchange="check(document.StatistikFormular.Where2Or1, 2, 2)"> 810 <option> 811 </option> 812 </select><input type="text" name="Where2Or1" 813 onchange="check(this, 2, 2)" size="20" /></td> 814 815 <td id="R7C5" class="nonvisible"><select name="Cond32" 816 size="1" Datei: statistik.html Anhang Seite: 13 von 20 Datei: statistik.html Seite: 13 von 20 817 onchange="check(document.StatistikFormular.Where3Or1, 3, 2)"> 818 <option> 819 </option> 820 </select><input type="text" name="Where3Or1" 821 onchange="check(this, 3, 2)" size="20" /></td> 822 823 <td id="R7C6" class="nonvisible"><select name="Cond42" 824 size="1" 825 onchange="check(document.StatistikFormular.Where4Or1, 4, 2)"> 826 <option> 827 </option> 828 </select><input type="text" name="Where4Or1" 829 onchange="check(this, 4, 2)" size="20" /></td> 830 831 <td id="R7C7" class="nonvisible"><select name="Cond52" 832 size="1" 833 onchange="check(document.StatistikFormular.Where5Or1, 5, 2)"> 834 <option> 835 </option> 836 </select><input type="text" name="Where5Or1" 837 onchange="check(this, 5, 2)" size="20" /></td> 838 839 <td id="R7C8" class="nonvisible"><select name="Cond62" 840 size="1" 841 onchange="check(document.StatistikFormular.Where6Or1, 6, 2)"> 842 <option> 843 </option> 844 </select><input type="text" name="Where6Or1" 845 onchange="check(this, 6, 2)" size="20" /></td> 846 847 <td id="R7C9" class="nonvisible"><select name="Cond72" 848 size="1" 849 onchange="check(document.StatistikFormular.Where7Or1, 7, 2)"> 850 <option> 851 </option> 852 </select><input type="text" name="Where7Or1" 853 onchange="check(this, 7, 2)" size="20" /></td> 854 855 <td id="R7C10" class="nonvisible"><select name="Cond82" 856 size="1" 857 onchange="check(document.StatistikFormular.Where8Or1, 8, 2)"> 858 <option> 859 </option> 860 </select><input type="text" name="Where8Or1" 861 onchange="check(this, 8, 2)" size="20" /></td> 862 863 <td id="R7C11" class="nonvisible"><select name="Cond92" 864 size="1" 865 onchange="check(document.StatistikFormular.Where9Or1, 9, 2)"> 866 <option> 867 </option> 868 </select><input type="text" name="Where9Or1" 869 onchange="check(this, 9, 2)" size="20" /></td> 870 </tr> 871 872 <!-- 9. Zeile: 'oder' 2, mit Vergleichoperatorenliste und Textfeld 873 Events: onclick="onCheckBox4(this.checked)" 874 onchange="check(TEXTFELD, SPALTENNUMMER, 3)" 875 --> 876 <tr id="ROW8" class="nonvisible" align="center"> 877 <td id="R8C1" align="right"><input type="checkbox" 878 name="CheckBox4" onclick="onCheckBox4(this.checked)" /><a 879 href="javascript:popUp(&#39;help/Bedingung.html&#39;)">oder</a> 880 </td> 881 882 <td id="R8C2" class="nonvisible"><select name="Cond03" 883 size="1" 884 onchange="check(document.StatistikFormular.Where0Or2, 0, 3)"> Datei: statistik.html 8 von 71 Datei: statistik.html 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 Datei: statistik.html Anhang Seite: 14 von 20 <td id="R8C10" class="nonvisible"><select name="Cond83" size="1" onchange="check(document.StatistikFormular.Where8Or2, 8, 3)"> <option> </option> </select><input type="text" name="Where8Or2" onchange="check(this, 8, 3)" size="20" /></td> <td id="R8C9" class="nonvisible"><select name="Cond73" size="1" onchange="check(document.StatistikFormular.Where7Or2, 7, 3)"> <option> </option> </select><input type="text" name="Where7Or2" onchange="check(this, 7, 3)" size="20" /></td> <td id="R8C8" class="nonvisible"><select name="Cond63" size="1" onchange="check(document.StatistikFormular.Where6Or2, 6, 3)"> <option> </option> </select><input type="text" name="Where6Or2" onchange="check(this, 6, 3)" size="20" /></td> <td id="R8C7" class="nonvisible"><select name="Cond53" size="1" onchange="check(document.StatistikFormular.Where5Or2, 5, 3)"> <option> </option> </select><input type="text" name="Where5Or2" onchange="check(this, 5, 3)" size="20" /></td> <td id="R8C6" class="nonvisible"><select name="Cond43" size="1" onchange="check(document.StatistikFormular.Where4Or2, 4, 3)"> <option> </option> </select><input type="text" name="Where4Or2" onchange="check(this, 4, 3)" size="20" /></td> <td id="R8C5" class="nonvisible"><select name="Cond33" size="1" onchange="check(document.StatistikFormular.Where3Or2, 3, 3)"> <option> </option> </select><input type="text" name="Where3Or2" onchange="check(this, 3, 3)" size="20" /></td> <td id="R8C4" class="nonvisible"><select name="Cond23" size="1" onchange="check(document.StatistikFormular.Where2Or2, 2, 3)"> <option> </option> </select><input type="text" name="Where2Or2" onchange="check(this, 2, 3)" size="20" /></td> <td id="R8C3" class="nonvisible"><select name="Cond13" size="1" onchange="check(document.StatistikFormular.Where1Or2, 1, 3)"> <option> </option> </select><input type="text" name="Where1Or2" onchange="check(this, 1, 3)" size="20" /></td> <option> </option> </select><input type="text" name="Where0Or2" onchange="check(this, 0, 3)" size="20" /></td> Seite: 14 von 20 Seite: 15 von 20 Datei: statistik.html Seite: 15 von 20 953 954 <td id="R8C11" class="nonvisible"><select name="Cond93" 955 size="1" 956 onchange="check(document.StatistikFormular.Where9Or2, 9, 3)"> 957 <option> 958 </option> 959 </select><input type="text" name="Where9Or2" 960 onchange="check(this, 9, 3)" size="20" /></td> 961 </tr> 962 963 <!-- 10. Zeile: Funktion, Auswahl der Aggregatfunktionen, Dropdownliste wird in 964 onLoadStatBody() befüllt 965 Events: onclick="onCheckBox5(this.checked)" 966 onchange="onChangeFeld_group()" 967 --> 968 <tr id="ROW9" align="center"> 969 <td id="R9C1" align="right"><input type="checkbox" 970 name="CheckBox5" onclick="onCheckBox5(this.checked)" /><a 971 href="javascript:popUp(&#39;help/Funktionen.html&#39;)">Funktion</a> 972 </td> 973 974 <td id="R9C2" class="nonvisible"><select name="Feld0group" 975 size="1" onchange="onChangeFeld_group()"> 976 <option> 977 </option> 978 </select></td> 979 980 <td id="R9C3" class="nonvisible"><select name="Feld1group" 981 size="1" onchange="onChangeFeld_group()"> 982 <option> 983 </option> 984 </select></td> 985 986 <td id="R9C4" class="nonvisible"><select name="Feld2group" 987 size="1" onchange="onChangeFeld_group()"> 988 <option> 989 </option> 990 </select></td> 991 992 <td id="R9C5" class="nonvisible"><select name="Feld3group" 993 size="1" onchange="onChangeFeld_group()"> 994 <option> 995 </option> 996 </select></td> 997 998 <td id="R9C6" class="nonvisible"><select name="Feld4group" 999 size="1" onchange="onChangeFeld_group()"> 1000 <option> 1001 </option> 1002 </select></td> 1003 1004 <td id="R9C7" class="nonvisible"><select name="Feld5group" 1005 size="1" onchange="onChangeFeld_group()"> 1006 <option> 1007 </option> 1008 </select></td> 1009 1010 <td id="R9C8" class="nonvisible"><select name="Feld6group" 1011 size="1" onchange="onChangeFeld_group()"> 1012 <option> 1013 </option> 1014 </select></td> 1015 1016 <td id="R9C9" class="nonvisible"><select name="Feld7group" 1017 size="1" onchange="onChangeFeld_group()"> 1018 <option> 1019 </option> 1020 </select></td> Datei: statistik.html Seite: 16 von 20 9 von 71 Datei: statistik.html Seite: 16 von 20 1021 1022 <td id="R9C10" class="nonvisible"><select name="Feld8group" 1023 size="1" onchange="onChangeFeld_group()"> 1024 <option> 1025 </option> 1026 </select></td> 1027 1028 <td id="R9C11" class="nonvisible"><select name="Feld9group" 1029 size="1" onchange="onChangeFeld_group()"> 1030 <option> 1031 </option> 1032 </select></td> 1033 </tr> 1034 1035 <!-- 11. Zeile: Bedingungen für die Aggregatfunktionen, gleicher Aufbau wie 1036 Zeilen 7 - 9 1037 Events: onclick="onCheckBox6(this.checked)" 1038 onchange="check(TEXTFELD, SPALTENNUMMER, 4)" 1039 --> 1040 <tr id="ROW10" class="nonvisible" align="center"> 1041 <td id="R10C1" align="right"><input type="checkbox" 1042 name="CheckBox6" onclick="onCheckBox6(this.checked)" /><a 1043 href="javascript:popUp(&#39;help/GBedingung.html&#39;)">Bedingung 1044 für Gruppe</a> </td> 1045 1046 <td id="R10C2" class="nonvisible"><select name="Cond04" 1047 size="1" 1048 onchange="check(document.StatistikFormular.Having0, 0, 4)"> 1049 <option> 1050 </option> 1051 </select><input type="text" name="Having0" 1052 onchange="check(this, 0, 4)" size="20" /></td> 1053 1054 <td id="R10C3" class="nonvisible"><select name="Cond14" 1055 size="1" 1056 onchange="check(document.StatistikFormular.Having1, 1, 4)"> 1057 <option> 1058 </option> 1059 </select><input type="text" name="Having1" 1060 onchange="check(this, 1, 4)" size="20" /></td> 1061 1062 <td id="R10C4" class="nonvisible"><select name="Cond24" 1063 size="1" 1064 onchange="check(document.StatistikFormular.Having2, 2, 4)"> 1065 <option> 1066 </option> 1067 </select><input type="text" name="Having2" 1068 onchange="check(this, 2, 4)" size="20" /></td> 1069 1070 <td id="R10C5" class="nonvisible"><select name="Cond34" 1071 size="1" 1072 onchange="check(document.StatistikFormular.Having3, 3, 4)"> 1073 <option> 1074 </option> 1075 </select><input type="text" name="Having3" 1076 onchange="check(this, 3, 4)" size="20" /></td> 1077 1078 <td id="R10C6" class="nonvisible"><select name="Cond44" 1079 size="1" 1080 onchange="check(document.StatistikFormular.Having4, 4, 4)"> 1081 <option> 1082 </option> 1083 </select><input type="text" name="Having4" 1084 onchange="check(this, 4, 4)" size="20" /></td> 1085 1086 <td id="R10C7" class="nonvisible"><select name="Cond54" 1087 size="1" 1088 onchange="check(document.StatistikFormular.Having5, 5, 4)"> Datei: statistik.html Anhang Seite: 17 von 20 Datei: statistik.html Seite: 17 von 20 1089 <option> 1090 </option> 1091 </select><input type="text" name="Having5" 1092 onchange="check(this, 5, 4)" size="20" /></td> 1093 1094 <td id="R10C8" class="nonvisible"><select name="Cond64" 1095 size="1" 1096 onchange="check(document.StatistikFormular.Having6, 6, 4)"> 1097 <option> 1098 </option> 1099 </select><input type="text" name="Having6" 1100 onchange="check(this, 6, 4)" size="20" /></td> 1101 1102 <td id="R10C9" class="nonvisible"><select name="Cond74" 1103 size="1" 1104 onchange="check(document.StatistikFormular.Having7, 7, 4)"> 1105 <option> 1106 </option> 1107 </select><input type="text" name="Having7" 1108 onchange="check(this, 7, 4)" size="20" /></td> 1109 1110 <td id="R10C10" class="nonvisible"><select name="Cond84" 1111 size="1" 1112 onchange="check(document.StatistikFormular.Having8, 8, 4)"> 1113 <option> 1114 </option> 1115 </select><input type="text" name="Having8" 1116 onchange="check(this, 8, 4)" size="20" /></td> 1117 1118 <td id="R10C11" class="nonvisible"><select name="Cond94" 1119 size="1" 1120 onchange="check(document.StatistikFormular.Having9, 9, 4)"> 1121 <option> 1122 </option> 1123 </select><input type="text" name="Having9" 1124 onchange="check(this, 9, 4)" size="20" /></td> 1125 </tr> 1126 1127 <!-- 12. Zeile: Bedingungen für die Aggregatfunktionen, gleicher Aufbau wie 1128 Zeilen 7 - 9 1129 Events: onclick="onCheckBox7(this.checked)" 1130 onchange="check(TEXTFELD, SPALTENNUMMER, 5)" 1131 --> 1132 <tr id="ROW11" class="nonvisible" align="center"> 1133 <td id="R11C1" align="right"><input type="checkbox" 1134 name="CheckBox7" onclick="onCheckBox7(this.checked)" /><a 1135 href="javascript:popUp(&#39;help/GBedingung.html&#39;)">oder</a> 1136 </td> 1137 1138 <td id="R11C2" class="nonvisible"><select name="Cond05" 1139 size="1" 1140 onchange="check(document.StatistikFormular.Having0Or1, 0, 5)"> 1141 <option> 1142 </option> 1143 </select><input type="text" name="Having0Or1" 1144 onchange="check(this, 0, 5)" size="20" /></td> 1145 1146 <td id="R11C3" class="nonvisible"><select name="Cond15" 1147 size="1" 1148 onchange="check(document.StatistikFormular.Having1Or1, 1, 5)"> 1149 <option> 1150 </option> 1151 </select><input type="text" name="Having1Or1" 1152 onchange="check(this, 1, 5)" size="20" /></td> 1153 1154 <td id="R11C4" class="nonvisible"><select name="Cond25" 1155 size="1" 1156 onchange="check(document.StatistikFormular.Having2Or1, 2, 5)"> Datei: statistik.html Seite: 18 von 20 10 von 71 Datei: statistik.html Seite: 18 von 20 1157 <option> 1158 </option> 1159 </select><input type="text" name="Having2Or1" 1160 onchange="check(this, 2, 5)" size="20" /></td> 1161 1162 <td id="R11C5" class="nonvisible"><select name="Cond35" 1163 size="1" 1164 onchange="check(document.StatistikFormular.Having3Or1, 3, 5)"> 1165 <option> 1166 </option> 1167 </select><input type="text" name="Having3Or1" 1168 onchange="check(this, 3, 5)" size="20" /></td> 1169 1170 <td id="R11C6" class="nonvisible"><select name="Cond45" 1171 size="1" 1172 onchange="check(document.StatistikFormular.Having4Or1, 4, 5)"> 1173 <option> 1174 </option> 1175 </select><input type="text" name="Having4Or1" 1176 onchange="check(this, 4, 5)" size="20" /></td> 1177 1178 <td id="R11C7" class="nonvisible"><select name="Cond55" 1179 size="1" 1180 onchange="check(document.StatistikFormular.Having5Or1, 5, 5)"> 1181 <option> 1182 </option> 1183 </select><input type="text" name="Having5Or1" 1184 onchange="check(this, 5, 5)" size="20" /></td> 1185 1186 <td id="R11C8" class="nonvisible"><select name="Cond65" 1187 size="1" 1188 onchange="check(document.StatistikFormular.Having6Or1, 6, 5)"> 1189 <option> 1190 </option> 1191 </select><input type="text" name="Having6Or1" 1192 onchange="check(this, 6, 5)" size="20" /></td> 1193 1194 <td id="R11C9" class="nonvisible"><select name="Cond75" 1195 size="1" 1196 onchange="check(document.StatistikFormular.Having7Or1, 7, 5)"> 1197 <option> 1198 </option> 1199 </select><input type="text" name="Having7Or1" 1200 onchange="check(this, 7, 5)" size="20" /></td> 1201 1202 <td id="R11C10" class="nonvisible"><select name="Cond85" 1203 size="1" 1204 onchange="check(document.StatistikFormular.Having8Or1, 8, 5)"> 1205 <option> 1206 </option> 1207 </select><input type="text" name="Having8Or1" 1208 onchange="check(this, 8, 5)" size="20" /></td> 1209 1210 <td id="R11C11" class="nonvisible"><select name="Cond95" 1211 size="1" 1212 onchange="check(document.StatistikFormular.Having9Or1, 9, 5)"> 1213 <option> 1214 </option> 1215 </select><input type="text" name="Having9Or1" 1216 onchange="check(this, 9, 5)" size="20" /></td> 1217 </tr> 1218 1219 <!-- 13. Zeile: Bedingungen für die Aggregatfunktionen, gleicher Aufbau wie 1220 Zeilen 7 - 9 1221 Events: onclick="onCheckBox8(this.checked)" 1222 onchange="check(TEXTFELD, SPALTENNUMMER, 6)" 1223 --> 1224 <tr id="ROW12" class="nonvisible" align="center"> Datei: statistik.html Anhang Datei: statistik.html 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 Datei: statistik.html Seite: 19 von 20 <td id="R12C9" class="nonvisible"><select name="Cond76" size="1" onchange="check(document.StatistikFormular.Having7Or2, 7, 6)"> <option> </option> </select><input type="text" name="Having7Or2" onchange="check(this, 7, 6)" size="20" /></td> <td id="R12C8" class="nonvisible"><select name="Cond66" size="1" onchange="check(document.StatistikFormular.Having6Or2, 6, 6)"> <option> </option> </select><input type="text" name="Having6Or2" onchange="check(this, 6, 6)" size="20" /></td> <td id="R12C7" class="nonvisible"><select name="Cond56" size="1" onchange="check(document.StatistikFormular.Having5Or2, 5, 6)"> <option> </option> </select><input type="text" name="Having5Or2" onchange="check(this, 5, 6)" size="20" /></td> <td id="R12C6" class="nonvisible"><select name="Cond46" size="1" onchange="check(document.StatistikFormular.Having4Or2, 4, 6)"> <option> </option> </select><input type="text" name="Having4Or2" onchange="check(this, 4, 6)" size="20" /></td> <td id="R12C5" class="nonvisible"><select name="Cond36" size="1" onchange="check(document.StatistikFormular.Having3Or2, 3, 6)"> <option> </option> </select><input type="text" name="Having3Or2" onchange="check(this, 3, 6)" size="20" /></td> <td id="R12C4" class="nonvisible"><select name="Cond26" size="1" onchange="check(document.StatistikFormular.Having2Or2, 2, 6)"> <option> </option> </select><input type="text" name="Having2Or2" onchange="check(this, 2, 6)" size="20" /></td> <td id="R12C3" class="nonvisible"><select name="Cond16" size="1" onchange="check(document.StatistikFormular.Having1Or2, 1, 6)"> <option> </option> </select><input type="text" name="Having1Or2" onchange="check(this, 1, 6)" size="20" /></td> <td id="R12C2" class="nonvisible"><select name="Cond06" size="1" onchange="check(document.StatistikFormular.Having0Or2, 0, 6)"> <option> </option> </select><input type="text" name="Having0Or2" onchange="check(this, 0, 6)" size="20" /></td> <td id="R12C1" align="right"><input type="checkbox" name="CheckBox8" onclick="onCheckBox8(this.checked)" /><a href="javascript:popUp(&#39;help/GBedingung.html&#39;)">oder</a> </td> Seite: 19 von 20 11 von 71 <td id="R12C10" class="nonvisible"><select name="Cond86" size="1" onchange="check(document.StatistikFormular.Having8Or2, 8, 6)"> <option> </option> </select><input type="text" name="Having8Or2" onchange="check(this, 8, 6)" size="20" /></td> Seite: 20 von 20 Seite: 20 von 20 <!-- Datum, Autor, valid XHTML, valid CSS --> <p style="text-align: right">2004-10-01 <a href="mailto:[email protected]">Hilmar Falkenberg</a> <a href="http://validator.w3.org/check?uri=referer"><img style="border:0;width:88px;height:31px" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a> <a href="http://jigsaw.w3.org/css-validator/"><img style="border:0;width:88px;height:31px" src="http://jigsaw.w3.org/css-validator/images/vcss" alt="Valid CSS!" /></a></p> </body> </html> <td id="R14C2" colspan="10"><textarea class="disabled" name="query" cols="115" rows="7" readonly="readonly"></textarea></td> </tr> </table> </form> <!-- 15. Zeile: das große Textfeld, wo der erzeugte SQL rein geschrieben wird Events: onclick="onClickStart()" onclick="onClickSave()" onclick="onClickNew()" --> <tr id="ROW14" class="disabled"> <td id="R14C1" align="right"><a href="javascript:popUp(&#39;help/SQL.html&#39;)">erzeugter SQL</a> </td> <!-- 14. Zeile: Drei Buttons (Abfrage starten, Abfrage speichern, alles zurücksetzen und ein Link zu den gespeicherten Abfragen Events: onclick="onClickStart()" onclick="onClickSave()" onclick="onClickNew()" --> <tr id="ROW13"> <td id="R13C1" align="left" colspan="11"><input type="hidden" name="STATID" value="" /> <input type="hidden" name="doWhat" value="execute" /> <input type="button" value="Abfrage starten" onclick="onClickStart()" /> <input type="button" value="Abfrage speichern" onclick="onClickSave()" /> <input type="button" value="alles zurücksetzen?" onclick="onClickNew()" /> <a href="Statistiken?requery=yes">zu den gespeicherten Statistiken</a> </td> </tr> <td id="R12C11" class="nonvisible"><select name="Cond96" size="1" onchange="check(document.StatistikFormular.Having9Or2, 9, 6)"> <option> </option> </select><input type="text" name="Having9Or2" onchange="check(this, 9, 6)" size="20" /></td> </tr> Datei: statistik.html 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 Datei: statistik.html Anhang Seite: 1 von 3 Seite: 1 von 3 if (month < 1 || month > 12) { // Monat testen alert("Der Monat muss zwischen 1 und 12 sein."); dateField.focus(); return false; } if (day < 1 || day > 31) { // Tag testen alert("Der Tag muss zwischen 1 und 31 sein."); dateField.focus(); return false; } if ((month==4 || month==6 || month==9 || month==11) && day==31) { // Tag je nach Monat testen alert("Der Monat "+month+" hat keine 31 Tage!") dateField.focus(); return false } if (month == 2) { // 29. Februar Test var isleap = (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0)); if (day>29 || (day==29 && !isleap)) { alert("Der Februar hat " + year + " keine " + day + " Tage!"); dateField.focus(); return false; if (matchArray_de != null) { // zerlegen des Datums in die einzelnen day = parseInt(matchArray_de[1],10); // Bestandteile, je nachdem, welches vo month = parseInt(matchArray_de[3],10); // den beiden Formaten nun vorliegt. year = parseInt(matchArray_de[4],10); // } if (matchArray_INGRES != null) { year = parseInt(matchArray_INGRES[1],10); month = parseInt(matchArray_INGRES[2],10); day = parseInt(matchArray_INGRES[3],10); } if (matchArray_de == null && matchArray_INGRES == null) { // keines der beiden Pattern passt! alert("Dies: "+dateField.value+"\nist kein gültiges Datum!\n\n"+ "Bitte geben Sie ein Datum in der Form TT.MM.JJJJ oder 'JJJJ-MM-DD' ein. dateField.focus(); return false; } ////////////////////////////////////////////////////////////////////////////// // Überprüft auf folgende Datumformate: // DD/MM/YY DD/MM/YYYY DD-MM-YY DD-MM-YYYY DD.MM.YY DD.MM.YYYY 'YYYY-MM-DD' // Setzt den Feldwert auf: 'YYYY-MM-DD' incl. der Anführungsstriche!!! // Wird die Jahreszahl nur zweistellig eingegeben wird immer 20xx angenommen! //---------------------------------------------------------------------------function isValidDate(dateField){ var day, month, year; //zum speichern der einzelnen Werte // die beiden Regulären-Ausdrücke zum Patternmatching // 2004-08-26 http://developer.netscape.com/viewsource/angus_strings.html var date_de = /(\d{1,2})(-|\.)(\d{1,2})\2(\d{4}|\d{2})/; var date_INGRES = /\'(\d{4})\-(\d{2})\-(\d{2})\'/; var matchArray_de = dateField.value.match(date_de); // ist es deutsch? var matchArray_INGRES = dateField.value.match(date_INGRES); // oder DB-Ingres? ////////////////////////////////////////////////////////////////////////////// // File: check.js Version: $Revision: 1.10 $ // Autor: Hilmar Falkenberg $Date: 2004/10/04 19:44:49 $ // // Beschreibung: // Stellt verschiedene Funktionen zur Überprüfung von Datenfeldern zur // Verfügung. Dabei gibt jede Funktion immer 'true' oder 'false' zurück. // Außerdem wird ggf. der Wert des Feldes konvertiert. So wird z.B. bei // isValidDate() aus dem Datum 29.02.2004 --> '2004-02-29' incl. der // Anführungsstriche!!! //============================================================================ Datei: check.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: check.js 12 von 71 } // // // // // // // // incl. der Anführungsstriche zurückgegeben! 'YYYY-MM-DD' Jetzt noch die Ausgabe richtig formatieren. D.h. es wird Seite: 2 von 3 value = "'" + newValue + "'"; while(quot_index != -1){ newValue += value.substring(0, quot_index) + "''"; value = value.substring(quot_index + 1); quot_index = value.indexOf("'"); } newValue += value; Seite: 2 von 3 return true; } ////////////////////////////////////////////////////////////////////////////// // aus Kompatibilitätsgründen noch beibehalten --> function isIntLowerThan() //---------------------------------------------------------------------------function checkDatensatz(zahlenField, max){ return isIntLowerThan(zahlenField, max); } ////////////////////////////////////////////////////////////////////////////// // Überprüft, ob der eingegebene Wert ein INTEGER ist, und zwischen 1 und // dem übergebenen Maximum ist. Dabei wird die JAVASCRIPT Funktion // "parseInt()" verwendet! //---------------------------------------------------------------------------function isIntLowerThan(intField, max){with (intField){ var zahl = parseInt(value,10); if(zahl != 'NaN' && !(1 <= zahl && zahl <= max)){ alert("Bitte geben Sie eine ganze Zahl zwischen 1 und " + max.toString() + " ein!"); focus(); return false; } value = zahl; return true; }} ////////////////////////////////////////////////////////////////////////////// // Überprüft, ob der eingegebene Wert ein INTEGER ist. Dabei wird die // JAVASCRIPT Funktion "parseInt()" verwendet! //---------------------------------------------------------------------------function isInt(intField){with (intField){ var intPattern = /\d+/; var matchArray = value.match(intPattern); if(matchArray){ value = parseInt(matchArray[0],10); return true; } alert("Bitte geben Sie eine ganze Zahl ein!"); return false; }} ////////////////////////////////////////////////////////////////////////////// // Maskiert den eingegebenen Wert als einen STRING mit ' (Single-Quote) // Falls es schon in einfachen Anführungszeichen steht passiert nichts! //---------------------------------------------------------------------------function isString(stringField){with (stringField){ var isQuoted = (value.charAt(0) == "'") && (value.charAt(value.length - 1) == "'" if(!isQuoted){ var quot_index = value.indexOf("'"); var newValue = ''; dateField.value = "'"; if(year < 100) dateField.value += '20'; if(year < 10) dateField.value += '0'; dateField.value += year.toString() + "-"; if(month < 10) dateField.value += '0'; dateField.value += month.toString() + "-"; if(day < 10) dateField.value += '0'; dateField.value += day.toString() + "'"; } Datei: check.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: check.js Anhang Seite: 3 von 3 Seite: 3 von 3 }} ////////////////////////////////////////////////////////////////////////////// // Überprüft, ob der eingegebene Wert ein FLOAT ist. Dabei wird zuerst // getestet, ob die Zahl mit einem Komma oder mit einem Punkt eingegeben wurde // und dann wird die JAVASCRIPT Funktion "parseFloat()" verwendet! //---------------------------------------------------------------------------function isFloat(intField){with (intField){ var floatPattern = /((\d+)(\,|\.)(\d+))|(\d+)/; var matchArray = value.match(floatPattern); if(matchArray){ if(matchArray[1]) // Die Zahl wurde mit einem Komma eingegeben value = parseFloat(matchArray[2]+"."+matchArray[4]); else value = parseFloat(matchArray[5]); return true; } alert("Bitte geben Sie eine Zahl ein!"); return false; }} ////////////////////////////////////////////////////////////////////////////// // Überprüft, ob der eingegebene Wert ein INTEGER ist. Dabei wird die // JAVASCRIPT Funktion "parseInt()" verwendet! //---------------------------------------------------------------------------function isIntList(intField){with (intField){ var intPattern = /\((\s*\d+\s*\,\s*)+\d+\s*\)/; var matchArray = value.match(intPattern); if(matchArray){ value = matchArray[0]; return true; } alert("Bitte geben Sie eine Liste von Zahlen ein!\n" +"In der Form: (0, 8, 15, 42)"); return false; }} return true; } return true; Datei: check.js 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 Datei: check.js 13 von 71 Seite: 1 von 1 Seite: 1 von 1 } ////////////////////////////////////////////////////////////////////////////// // testet ob Cookies verwendet werden dürfen, bzw. vom Client eingeschaltet // sind - ggf. wird eine Meldung mit der Bitte zum einschalten erzeugt //---------------------------------------------------------------------------function checkCookie(){ setCookie("CookieTest", "OK"); if (!getCookie("CookieTest")){ alert('Bitte aktivieren Sie COOKIES in Ihrem Browser,' + '\num die volle Funktionalität dieser Seite nutzen zu können!'); return false; } else{ eraseCookie("CookieTest"); return true; } } ////////////////////////////////////////////////////////////////////////////// // löscht den Cookie 'name', bzw. setzt das Verfallsdatum auf 1970 //---------------------------------------------------------------------------function eraseCookie(name){ document.cookie = name + "=; expires=Thu, 01-Jan-70 00:00:01 GMT"; } // in Diskussionsforen im Internet werden die einzelnen De-maskierungs// möglichkeiten heftig diskutiert. Mit 'unescape()' gibt es z.Z. die // wenigsten Probleme (vgl. setCookie) //return java.net.URLDecoder.decode(cook); //return decodeURIComponent(cook); //return decodeURI(cook); return unescape(cook); } i++; } return null; ////////////////////////////////////////////////////////////////////////////// // setzt einen Cookie mit 'name', auf den 'wert' //---------------------------------------------------------------------------function setCookie(name, wert){ // in Diskussionsforen im Internet werden die einzelnen Maskierungs// möglichkeiten heftig diskutiert. Mit 'escape()' gibt es z.Z. die // wenigsten Probleme (vgl. getCookie) document.cookie = name + '=' + escape(wert); //document.cookie = name + '=' + encodeURI(wert); //document.cookie = name + '=' + encodeURIComponent(wert); //document.cookie = name + '=' + java.net.URLEncoder.encode(wert); } ////////////////////////////////////////////////////////////////////////////// // gibt den Wert des Cookies 'name' zurück //---------------------------------------------------------------------------function getCookie(name){ var i=0; //Suchposition im Cookie var suche = name + "="; while (i < document.cookie.length){ if (document.cookie.substring(i, i + suche.length) == suche){ var ende = document.cookie.indexOf(";", i + suche.length); ende = (ende > -1) ? ende : document.cookie.length; var cook = document.cookie.substring(i + suche.length, ende); ////////////////////////////////////////////////////////////////////////////// // File: cookie.js Version: $Revision: 1.2 $ // Autor: Hilmar Falkenberg $Date: 2004/10/04 19:51:36 $ // // Beschreibung: // Allgemeine Cookie Funktionen... //============================================================================ Datei: cookie.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 Datei: cookie.js Anhang Seite: 1 von 2 // alle Spalten ausblenden for(var i = showFeldUpTo; i > 0 ; i--){ feldcombo[i].selectedIndex = 0; onChangeFeld_(i); } // Zeilen ausblenden visi("ROW2", false); visi("ROW3", false); visi("ROW4", false); visi("ROW5", false); visi("ROW6", false); visi("ROW9", false); Seite: 1 von 2 } ////////////////////////////////////////////////////////////////////////////// // bereitet den Anfrageneditor für eine neue Anfrage vor, d.h. alle Cookies // löschen und überflüssige Felder / Tabellenzellen ausblenden //---------------------------------------------------------------------------function neu(){ // Cookies löschen eraseCookie("TABLE"); for(var i=0; i<10; i++) eraseCookie("FELD"+i); eraseCookie("CHECK"); eraseCookie("FRAGE"); eraseCookie("STATID"); saveCheck(); setCookie("CHECK", cook_CHECK); setCookie("FRAGE", cook_FRAGE); setCookie("TABLE", cook_TABLE); for(var i=0; i<10; i++) setCookie("FELD"+i, cook_FELD[i]); ////////////////////////////////////////////////////////////////////////////// // speichert die Wahrheitswerte der Zeilen-Checkboxen in dem String cook_CHECK // damit beim wiedereinlesen einer Anfrage festgestellt werden kann, welche // Zeilen angezeigt werden müssen //---------------------------------------------------------------------------function saveCheck(){ cook_CHECK = showFeldUpTo + '|'; cook_CHECK += document.StatistikFormular.CheckBox1.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox2.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox3.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox4.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox5.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox6.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox7.checked +'|'; cook_CHECK += document.StatistikFormular.CheckBox8.checked +'|'; } ////////////////////////////////////////////////////////////////////////////// // löscht die alten Cookies und setzt die aktuellen Werte //---------------------------------------------------------------------------function saveCookies(){ eraseCookie("TABLE"); for(var i=0; i<10; i++) eraseCookie("FELD"+i); eraseCookie("CHECK"); eraseCookie("FRAGE"); ////////////////////////////////////////////////////////////////////////////// // File: stat_cookies.js Version: $Revision: 1.3 $ // Autor: Hilmar Falkenberg $Date: 2004/10/04 20:02:13 $ // // Beschreibung: stellt die Cookie Funktionen speziell für den Anfrageneditor // zur Verfügung //============================================================================ Datei: stat_cookies.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_cookies.js 14 von 71 Seite: 2 von 2 Seite: 2 von 2 } ////////////////////////////////////////////////////////////////////////////// // speichert die Werte der Cookies wieder in den entsprechenden Strings, aus // denen dann die Einstellungen ausgelesen werden können (s. wiederherstellen) //---------------------------------------------------------------------------function restore(){ cook_TABLE = getCookie("TABLE"); for(var i=0; i<10; i++) cook_FELD[i] = getCookie("FELD"+i); cook_CHECK = getCookie("CHECK"); cook_FRAGE = getCookie("FRAGE"); }o // alle Textfelder leeren document.StatistikFormular.reset(); document.StatistikFormular.STATID.value = ''; document.StatistikFormular.frage.value = ''; document.location.search = ''; // Verknüpfung, Bedingungen und Funktionen ausschalten onCheckBox1(false); onCheckBox2(false); onCheckBox5(false); Datei: stat_cookies.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 Datei: stat_cookies.js Anhang Seite: 1 von 10 var tabellenname = null; sql_from = 'FROM '; cook_TABLE = ''; Seite: 1 von 10 } ////////////////////////////////////////////////////////////////////////////// // baut den String mit der FROM-Klausel auf und füllt die Dropdownlisten der // 4. und 6. Zeile, also die Attribute der ausgewählten Tabellen //---------------------------------------------------------------------------function fill_feld(formular, k){ if(k>=10) return; showFeldUpTo = 0; showRow[2] = false; } nextChild = joincombo[k].firstChild; while (nextChild){ joincombo[k].removeChild(nextChild); nextChild = joincombo[k].firstChild; } // Auswahlliste der 6. Zeile joincombo[k].options.length = 0; joincombo[k].options[0] = new Option ("", ""); joincombo[k].options[0].selected = true; for(var k = 0; k < feldcombo.length; k++){ var nextChild = feldcombo[k].firstChild; while (nextChild){ feldcombo[k].removeChild(nextChild); nextChild = feldcombo[k].firstChild; } // Auswahlliste der 4. Zeile feldcombo[k].options.length = 0; feldcombo[k].options[0] = new Option ("", ""); feldcombo[k].options[0].selected = true; feldcombo[k].options[STAR] = new Option ("* (alle)", "*"); ////////////////////////////////////////////////////////////////////////////// // löscht alle Optionen (Attribute der Tabellen) aus den Dropdownlisten der // 4. und 6. Zeile //---------------------------------------------------------------------------function empty_feld(){ cook_TABLE = ''; inBenutzung = new Array(); inBenutzung[0] = new myOption("","",""); inBenutzung[STAR] = new myOption("* (alle)","*",""); inBenutzung[STAR].table = ""; ////////////////////////////////////////////////////////////////////////////// // File: stat_erstellen.js Version: $Revision: 1.3 $ // Autor: Hilmar Falkenberg $Date: 2004/10/04 19:45:01 $ // // Beschreibung: verschiedene Funktionen für den Anfrageneditor // // DIE SQL-Anweisung wird mit setSelect() erzeugt! // // Funktionsliste: // empty_feld() // fill_feld() // popUp() // setColor() // setSelect() // show() // showRowCol() // visi() // wiederherstellen() //============================================================================ Datei: stat_erstellen.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_erstellen.js 15 von 71 Seite: 2 von 10 // alle eingestellten Werte in den Strings für die Cookies speichern if(feldcombo[i].selectedIndex > NICHTS){ var akt_feld = feldcombo[i].value; cook_FELD[i] += feldcombo[i].selectedIndex + "|"; cook_FELD[i] += anzeigecheck[i].checked + "|"; //gehe durch alle 10 Felder.. for (var i = 0; i < feldcombo.length; i++){ setColor("R4C" + (2 + i), COLOR_NICHTS); setColor("R5C" + (2 + i), COLOR_NICHTS); setColor("R6C" + (2 + i), COLOR_NICHTS); setColor("R7C" + (2 + i), COLOR_NICHTS); setColor("R8C" + (2 + i), COLOR_NICHTS); setColor("R9C" + (2 + i), COLOR_NICHTS); setColor("R10C" + (2 + i), COLOR_NICHTS); setColor("R11C" + (2 + i), COLOR_NICHTS); setColor("R12C" + (2 + i), COLOR_NICHTS); //alte Cookiewerte zurücksetzen for(var i=0; i<10; i++) cook_FELD[i] = ''; //lokale Variablen zum zwischenspeichern von TeilStrings... var and0 = ''; var and1 = ''; var and2 = ''; var oder = ''; var join = ''; var hav_and0 = ''; var hav_and1 = ''; var hav_and2 = ''; var hav_oder = ''; var feldfunkt = null; } ////////////////////////////////////////////////////////////////////////////// // SELECT, WHERE, GROUP BY, HAVING, ORDER BY-Klausel als einzelnen Strings // werden nach und nach aufgebaut, //---------------------------------------------------------------------------function setSelect(){ //SQL-Anweisungen initialisieren sql_select = 'SELECT '; sql_where = 'WHERE '; sql_groupby = 'GROUP BY '; sql_having = 'HAVING '; sql_orderby = 'ORDER BY '; } inBenutzung[STAR].table = inBenutzung[STAR].table.substr(0, inBenutzung[STAR].tab } } Seite: 2 von 10 for(var j = 0; j < felder[i].length; j++){ if(k ==0){ inBenutzung[feldcombo[k].length] = felder[i][j]; inBenutzung[feldcombo[k].length].table = tabellenname; } feldcombo[k].options[feldcombo[k].length] = new Option(felder[i][j].n joincombo[k].options[joincombo[k].length] = new Option(felder[i][j].n } with(document.StatistikFormular.Tabellen){ for (var i = 0; i < length; i++){ if (options[i].selected){ tabellenname = options[i].label; inBenutzung[STAR].table += tabellenname + " & "; cook_TABLE += i + '|'; sql_from += options[i].value + ', '; feldcombo[k].appendChild(OptionGroup(tabellenname)); joincombo[k].appendChild(OptionGroup(tabellenname)); Datei: stat_erstellen.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: stat_erstellen.js Anhang } += += += += += += += += += += += += += += += += += sortcombo[i].selectedIndex aliasnamen[i].value comparecombo[i][0].selectedIndex joincombo[i].selectedIndex comparecombo[i][1].selectedIndex wherefelder[i][0].value comparecombo[i][2].selectedIndex wherefelder[i][1].value comparecombo[i][3].selectedIndex wherefelder[i][2].value groupcombo[i].selectedIndex comparecombo[i][4].selectedIndex havingfelder[i][0].value comparecombo[i][5].selectedIndex havingfelder[i][1].value comparecombo[i][6].selectedIndex havingfelder[i][2].value + + + + + + + + + + + + + + + + + "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; "|"; Seite: 3 von 10 Seite: 3 von 10 /**********************************************************************/ // die einzelnen Teile der SELECT-Clause /**********************************************************************/ //Falls dieses Feld angezeigt werden soll... if(anzeigecheck[i].checked && feldcombo[i].selectedIndex > NICHTS){ setColor("R4C" + (2 + i), COLOR_ANZEIGEN); //Falls die Aggregatfunktionen eingeschaltet sind... if(document.StatistikFormular.CheckBox5.checked){ //wenn Bedingung gewählt wurde bzw. überhaupt kein Feld... if(groupcombo[i].selectedIndex == WHERE){ groupcombo[i].selectedIndex = GROUPBY; setColor("R9C" + (2 + i), COLOR_GROUPBY); } else{ //falls '* (alle)' ausgewählt wurde... if(feldcombo[i].selectedIndex == STAR){ //setze automatisch auf COUNT(*) groupcombo[i].options[6].selected = true; if(aliasnamen[i].value == '* (alle)') aliasnamen[i].value = 'Anzahl'; } //wenn gruppiert werden soll... if(groupcombo[i].selectedIndex == GROUPBY){ setColor("R9C" + (2 + i), COLOR_GROUPBY); sql_select += akt_feld; feldfunkt = akt_feld; } else { // bei allen Aggregatfunktionen setColor("R9C" + (2 + i), COLOR_FUNKTION); feldfunkt = groupcombo[i].value + akt_feld + ')'; sql_select += feldfunkt; } } /**********************************************************************/ // selbiges für die Verknüpfungen (JOIN) /**********************************************************************/ if(inBenutzung && inBenutzung[joincombo[i].selectedIndex]) vtabellen[i].value = inBenutzung[joincombo[i].selectedIndex].table; else vtabellen[i].value = ''; /**********************************************************************/ // Benutzerhinweis, welches Feld aus welcher Tabelle stammt /**********************************************************************/ if(inBenutzung && inBenutzung[feldcombo[i].selectedIndex]) tabellen[i].value = inBenutzung[feldcombo[i].selectedIndex].table; else tabellen[i].value = ''; cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] cook_FELD[i] Datei: stat_erstellen.js 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: stat_erstellen.js 16 von 71 Seite: 4 von 10 Seite: 4 von 10 if(comparecombo[i][3].selectedIndex > NOTNULL && comparecombo[i][3].sele and2 += akt_feld + comparecombo[i][3].value + wherefelder[i][2].value else if(comparecombo[i][3].selectedIndex == SUBQUERY){ } //oder if(document.StatistikFormular.CheckBox4.checked && comparecombo[i][3].selec if(wherefelder[i][2].value || comparecombo[i][3].selectedIndex <= NOTNULL){ setColor("R8C" + (2 + i), COLOR_BEDINGUNG); if(comparecombo[i][2].selectedIndex > NOTNULL && comparecombo[i][2].sele and1 += akt_feld + comparecombo[i][2].value + wherefelder[i][1].value else if(comparecombo[i][2].selectedIndex == SUBQUERY){ and1 += wherefelder[i][1].value + ' AND '; setColor("R7C" + (2 + i), COLOR_SUBQUERY); } else if(comparecombo[i][2].selectedIndex <= NOTNULL) and1 += akt_feld + comparecombo[i][2].value + ' AND '; } //oder if(document.StatistikFormular.CheckBox3.checked && comparecombo[i][2].selec if(wherefelder[i][1].value || comparecombo[i][2].selectedIndex <= NOTNULL){ setColor("R7C" + (2 + i), COLOR_BEDINGUNG); if(comparecombo[i][1].selectedIndex > NOTNULL && comparecombo[i][1].sele and0 += akt_feld + comparecombo[i][1].value + wherefelder[i][0].value else if(comparecombo[i][1].selectedIndex == SUBQUERY){ and0 += wherefelder[i][0].value + ' AND '; setColor("R6C" + (2 + i), COLOR_SUBQUERY); } else if(comparecombo[i][1].selectedIndex <= NOTNULL) and0 += akt_feld + comparecombo[i][1].value + ' AND '; //Bedingung if(document.StatistikFormular.CheckBox2.checked && comparecombo[i][1].selec if(wherefelder[i][0].value || comparecombo[i][1].selectedIndex <= NOTNULL){ setColor("R6C" + (2 + i), COLOR_BEDINGUNG); /**********************************************************************/ // die einzelnen Teile der WHERE-Clause /**********************************************************************/ //nur wenn EIN echtes Feld ausgwählt wurde... if(feldcombo[i].selectedIndex > STAR){ //falls eine Verknüpfung [JOIN] erstellt werden soll... if(document.StatistikFormular.CheckBox1.checked) if(joincombo[i].selectedIndex != NICHTS && comparecombo[i][0].selectedIndex join += akt_feld + comparecombo[i][0].value; join += joincombo[i].value; join += ' AND '; setColor("R5C" + (2 + i), COLOR_JOIN); } } else{ // bei SELECT * gibt es kein Alias !!! if(feldcombo[i].selectedIndex == STAR){ aliasnamen[i].value = ''; } sql_select += akt_feld; } // Hinzufügen des Alias if(aliasnamen[i].value) sql_select += ' AS "' + aliasnamen[i].value + '"'; sql_select += ', '; }// SELECT-Klausel ist damit fertig else{ // wenn es nicht angezeigt wird oder kein Feld ausgewählt wurde, // kann auch der alias weg... anzeigecheck[i].checked = false; aliasnamen[i].value = ''; } Datei: stat_erstellen.js 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: stat_erstellen.js Anhang Seite: 5 von 10 Seite: 5 von 10 } //oder if(document.StatistikFormular.CheckBox7.checked && comparecombo[i][5].selec if(havingfelder[i][1].value || comparecombo[i][5].selectedIndex <= NOTNULL) setColor("R11C" + (2 + i), COLOR_BEDINGUNG); if(comparecombo[i][4].selectedIndex > NOTNULL && comparecombo[i][4].sele hav_and0 += feldfunkt + comparecombo[i][4].value + havingfelder[i][0] else if(comparecombo[i][4].selectedIndex == SUBQUERY){ hav_and0 += havingfelder[i][0].value + ' AND '; setColor("R10C" + (2 + i), COLOR_SUBQUERY); } else if(comparecombo[i][4].selectedIndex <= NOTNULL) hav_and0 += feldfunkt + comparecombo[i][4].value + ' AND '; //Bedingung für Gruppe (wenn es eine Having-Condition eingegeben wurde...) if(document.StatistikFormular.CheckBox6.checked && comparecombo[i][4].selec if(havingfelder[i][0].value || comparecombo[i][4].selectedIndex <= NOTNULL) setColor("R10C" + (2 + i), COLOR_BEDINGUNG); if(anzeigecheck[i].checked && document.StatistikFormular.CheckBox5.checked){ //wenn wirklich gruppiert werden soll... if(groupcombo[i].selectedIndex == GROUPBY && feldcombo[i].selectedIndex > S sql_groupby += akt_feld + ', '; } /**********************************************************************/ // die GROUP BY-Klausel & HAVING-Klausel... /**********************************************************************/ if(groupcombo[i].selectedIndex == NICHTS){ havingfelder[i][0].value = ''; havingfelder[i][1].value = ''; havingfelder[i][2].value = ''; comparecombo[i][4].selectedIndex = NICHTS; comparecombo[i][5].selectedIndex = NICHTS; comparecombo[i][6].selectedIndex = NICHTS; } } } // Falls SELECT * FROM ... kann man immernoch ein Subquery als Bedingung ang else if(feldcombo[i].selectedIndex == STAR){ // 1. mögliches Subquery if(document.StatistikFormular.CheckBox2.checked && wherefelder[i][0].value && comparecombo[i][1].selectedIndex == SUBQUERY){ and0 += wherefelder[i][0].value + ' AND '; setColor("R6C" + (2 + i), COLOR_SUBQUERY); } // 2. mögliches Subquery if(document.StatistikFormular.CheckBox3.checked && wherefelder[i][1].value && comparecombo[i][2].selectedIndex == SUBQUERY){ and0 += wherefelder[i][1].value + ' AND '; setColor("R7C" + (2 + i), COLOR_SUBQUERY); } // 3. mögliches Subquery if(document.StatistikFormular.CheckBox4.checked && wherefelder[i][2].value && comparecombo[i][3].selectedIndex == SUBQUERY){ and0 += wherefelder[i][2].value + ' AND '; setColor("R8C" + (2 + i), COLOR_SUBQUERY); } }//WHERE ist damit fast fertig, Rest folgt weiter unten } else if(comparecombo[i][3].selectedIndex <= NOTNULL) and2 += akt_feld + comparecombo[i][3].value + ' AND '; and2 += wherefelder[i][2].value + ' AND '; setColor("R8C" + (2 + i), COLOR_SUBQUERY); Datei: stat_erstellen.js 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: stat_erstellen.js 17 von 71 } } /**********************************************************************/ // die ORDER BY-Klausel... /**********************************************************************/ if(feldcombo[i].selectedIndex > STAR && sortcombo[i].value){ if(aliasnamen[i].value) sql_orderby += '"' + aliasnamen[i].value + '"' + sortcombo[i].value + ', else sql_orderby += akt_feld + sortcombo[i].value + ', '; } else sortcombo[i].options[0].selected = true; if(comparecombo[i][6].selectedIndex > NOTNULL && comparecombo[i][6].sele hav_and2 += feldfunkt + comparecombo[i][6].value + havingfelder[i][2] else if(comparecombo[i][6].selectedIndex == SUBQUERY){ hav_and2 += havingfelder[i][2].value + ' AND '; setColor("R12C" + (2 + i), COLOR_SUBQUERY); } else if(comparecombo[i][6].selectedIndex <= NOTNULL) hav_and2 += feldfunkt + comparecombo[i][6].value + ' AND '; } //oder if(document.StatistikFormular.CheckBox8.checked && comparecombo[i][6].selec if(havingfelder[i][2].value || comparecombo[i][6].selectedIndex <= NOTNULL) setColor("R12C" + (2 + i), COLOR_BEDINGUNG); if(hav_oder.length > 0) sql_having += hav_oder.substring(0, hav_oder.length - 5); else Seite: 6 von 10 /**********************************************************************/ //endgültiges zusammensetzen der Having-Klausel... /**********************************************************************/ if(hav_and0) hav_oder += '(' + hav_and0.substring(0, hav_and0.length - 5) + ')\n\tOR '; if(hav_and1) hav_oder += '(' + hav_and1.substring(0, hav_and1.length - 5) + ')\n\tOR '; if(hav_and2) hav_oder += '(' + hav_and2.substring(0, hav_and2.length - 5) + ')\n\tOR '; /**********************************************************************/ //endgültiges zusammensetzen der Where-Klausel... /**********************************************************************/ if(and0) oder += '(' + and0.substring(0, and0.length - 5) + ')\n\tOR '; if(and1) oder += '(' + and1.substring(0, and1.length - 5) + ')\n\tOR '; if(and2) oder += '(' + and2.substring(0, and2.length - 5) + ')\n\tOR '; if(join.length > 0 && oder.length > 0) sql_where += join + '\n\t(' + oder.substring(0, oder.length - 5) + ')'; else if(join.length > 0) sql_where += join.substring(0, join.length - 5); else if(oder.length > 0) sql_where += oder.substring(0, oder.length - 5); else sql_where = null; } Seite: 6 von 10 if(comparecombo[i][5].selectedIndex > NOTNULL && comparecombo[i][5].sele hav_and1 += feldfunkt + comparecombo[i][5].value + havingfelder[i][1] else if(comparecombo[i][5].selectedIndex == SUBQUERY){ hav_and1 += havingfelder[i][1].value + ' AND '; setColor("R11C" + (2 + i), COLOR_SUBQUERY); } else if(comparecombo[i][5].selectedIndex <= NOTNULL) hav_and1 += feldfunkt + comparecombo[i][5].value + ' AND '; Datei: stat_erstellen.js 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 Datei: stat_erstellen.js Anhang Seite: 7 von 10 if(cook_CHECK){ // wiederherstellen der ganzen Checkboxen für die Zeilen //die evtl. vorhandene LfdNr der Statistik wiederherstellen document.StatistikFormular.STATID.value = getCookie("STATID"); Seite: 7 von 10 } } ////////////////////////////////////////////////////////////////////////////// // macht HTML-Element mit der ID = nr, sichtbar oder unsichtbar //---------------------------------------------------------------------------function visi(nr, onoff){ if (document.getElementById){ var vista = onoff ? 'visible' : 'hidden'; var element = document.getElementById(nr); if(element) element.style.visibility = vista; } } ////////////////////////////////////////////////////////////////////////////// // macht die Zelle(row=Zeile, col=Spalte) der Tabelle sichtbar/unsichtbar //---------------------------------------------------------------------------function showRowCol(row, col, onoff){ visi("R" + row + "C" + col, onoff); } ////////////////////////////////////////////////////////////////////////////// // setzt die Hintergrundfarbe eines HTML-Elements //---------------------------------------------------------------------------function setColor(nr, color){ if (document.layers){ document.layers[nr].bgColor = color; } else if (document.all){ document.all[nr].bgColor = color; } else if (document.getElementById){ document.getElementById(nr).bgColor = color; } } ////////////////////////////////////////////////////////////////////////////// // stellt alle in den Cookies gespeicherten Werte wieder her, sodass die // zuletzt bearbeitete Anfrage wieder im Editor verfügbar ist //---------------------------------------------------------------------------function wiederherstellen(){ empty_feld(); //erst alles alte löschen restore(); //gespeicherte Cookies holen } else{ value = ''; } if(sql_where) value += sql_where + '\n'; if(sql_groupby.length > 11) value += sql_groupby.substring(0, sql_groupby.length - 2) + '\n'; if(sql_having) value += sql_having + '\n'; if(sql_orderby.length > 11) value += sql_orderby.substring(0, sql_orderby.length - 2); /**********************************************************************/ // QUERY Ausgabe... /**********************************************************************/ with(document.StatistikFormular.query){ if(sql_select.length > 11){ value = sql_select.substring(0, sql_select.length - 2) + '\n'; value += sql_from.substring(0, sql_from.length - 2) + '\n'; sql_having = null; Datei: stat_erstellen.js 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 Datei: stat_erstellen.js 18 von 71 wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[12] = document.StatistikFormular.CheckBox8.checked = eval(wert); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[11] = document.StatistikFormular.CheckBox7.checked = eval(wert); visi("ROW12", showRow[11]); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[10] = document.StatistikFormular.CheckBox6.checked = eval(wert); visi("ROW11", showRow[10]); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[9] = document.StatistikFormular.CheckBox5.checked = eval(wert); visi("ROW10", showRow[9]); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[8] = document.StatistikFormular.CheckBox4.checked = eval(wert); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[7] = document.StatistikFormular.CheckBox3.checked = eval(wert); visi("ROW8", showRow[7]); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[6] = document.StatistikFormular.CheckBox2.checked = eval(wert); visi("ROW7", showRow[6]); wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showRow[5] = document.StatistikFormular.CheckBox1.checked = eval(wert); Seite: 8 von 10 //wird das Feld auch angezeigt... wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); anzeigecheck[i].checked = eval(wert); var i = 0; // die einzelnen Spalten wiederherstellen for( ; i < cook_FELD.length && i < showFeldUpTo; i++) if(cook_FELD[i]){ //richtiges Feld auswählen... var wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); feldcombo[i].selectedIndex = wert; // die benötigeten Dropdownlisten mit den Attributen füllen for(var i = 0; i <= showFeldUpTo; i++) fill_feld(document.StatistikFormular, i); if(cook_TABLE){ // die Tabellenauswahl wiederherstellen while(cook_TABLE.indexOf("|") != -1){ var tab_index = cook_TABLE.substring(0, cook_TABLE.indexOf("|")); cook_TABLE = cook_TABLE.substring(cook_TABLE.indexOf("|") + 1); document.StatistikFormular.Tabellen.options[tab_index].selected = true; } } Seite: 8 von 10 // also, welche Zeilen sind eingeschaltet gewesen? var wert = cook_CHECK.substring(0, cook_CHECK.indexOf("|")); cook_CHECK = cook_CHECK.substring(cook_CHECK.indexOf("|") + 1); showFeldUpTo = wert; Datei: stat_erstellen.js 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 Datei: stat_erstellen.js Anhang Seite: 9 von 10 Seite: 9 von 10 //HAVING-Vergleichsoperator 2 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][5].selectedIndex = wert; //HAVING-Bedigung 2 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); //HAVING-Vergleichsoperator 1 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][4].selectedIndex = wert; //HAVING-Bedigung 1 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); havingfelder[i][0].value = wert; //welche Funktion wurde gewählt wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); groupcombo[i].selectedIndex = wert; //WHERE-Vergleichsoperator 3 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][3].selectedIndex = wert; //WHERE-Bedingung 3 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); wherefelder[i][2].value = wert; //WHERE-Vergleichsoperator 2 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][2].selectedIndex = wert; //WHERE-Bedingung 2 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); wherefelder[i][1].value = wert; //WHERE-Vergleichsoperator 1 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][1].selectedIndex = wert; //WHERE-Bedingung 1 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); wherefelder[i][0].value = wert; //wie soll der JOIN bzw. Verknüpfung aussehen... wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][0].selectedIndex = wert; //mit welchem Feld soll verknüpft werden... wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); joincombo[i].selectedIndex = wert; //hat es evtl. einen Alias... wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); aliasnamen[i].value = wert; //wie soll es sortiert werden... wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); sortcombo[i].selectedIndex = wert; Datei: stat_erstellen.js 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 Datei: stat_erstellen.js 19 von 71 } //die restlichen werden auf den ersten Wert gesetzt for(; i < feldcombo.length; i++) feldcombo[i].selectedIndex = 0; }D for(var i = showFeldUpTo + 1; i <= 10; i++){ for(var j = 2; j < showRow.length; j++){ showRowCol(j, i + 1, false); } visi("flipr" + (i-1), false); visi("flipl" + (i-1), false); } visi("flipr" + (i - 2), false); visi("flipr" + (i - 3), false); visi("flipl" + (i - 2), false); Seite: 10 von 10 show(); setSelect(); } ////////////////////////////////////////////////////////////////////////////// // öffnet ein PopUp-Fenster, wird hier für die Hilfefenster verwendet //---------------------------------------------------------------------------function popUp(URL) { day = new Date(); id = day.getTime(); eval("page" + id + " = window.open(URL, '" + id + "', 'toolbar=0,scrollbars=1,location=0,statusbar=0,menubar=0,resizable=1,wid } ////////////////////////////////////////////////////////////////////////////// // macht die benötigten Zeilen und Spalten sichtbar, den Rest unsichtbar //---------------------------------------------------------------------------function show(){ // bis 'showFeldUpTo' müssen alle Spalten angezeigt werden for(var i = 1; i <= showFeldUpTo; i++){ for(var j = 2; j < showRow.length; j++){ showRowCol(j, i + 1, showRow[j]); } if((i - 2) > 0) visi("flipl" + (i - 2), true); visi("flipr" + (i - 1), true); } // ggf. noch die Frage wiederherstellen if(cook_FRAGE){ document.StatistikFormular.frage.value = cook_FRAGE; } else{ document.StatistikFormular.frage.value = "Bitte geben Sie hier einen aussagekr } } Seite: 10 von 10 //HAVING-Vergleichsoperator 3 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); comparecombo[i][6].selectedIndex = wert; //HAVING-Bedigung 3 wert = cook_FELD[i].substring(0, cook_FELD[i].indexOf("|")); cook_FELD[i] = cook_FELD[i].substring(cook_FELD[i].indexOf("|") + 1); havingfelder[i][2].value = wert; havingfelder[i][1].value = wert; Datei: stat_erstellen.js 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 Datei: stat_erstellen.js Anhang Seite: 1 von 12 Seite: 1 von 12 // Array mit den Textfeldern 'aus Tabelle', wo der Tabellenname des aus// gewählten Attributs hineingeschrieben wird tabellen = new Array( document.StatistikFormular.Tabelle0, document.StatistikFormular.Tabelle1, document.StatistikFormular.Tabelle2, document.StatistikFormular.Tabelle3, document.StatistikFormular.Tabelle4, document.StatistikFormular.Tabelle5, document.StatistikFormular.Tabelle6, document.StatistikFormular.Tabelle7, document.StatistikFormular.Tabelle8, document.StatistikFormular.Tabelle9 ); // Array mit den Dropdownlisten für die Attribute aus der 4. Zeile feldcombo = new Array( document.StatistikFormular.Feld0, document.StatistikFormular.Feld1, document.StatistikFormular.Feld2, document.StatistikFormular.Feld3, document.StatistikFormular.Feld4, document.StatistikFormular.Feld5, document.StatistikFormular.Feld6, document.StatistikFormular.Feld7, document.StatistikFormular.Feld8, document.StatistikFormular.Feld9 ); // Array mit den Checkboxen für die Anzeige eines Attributs im SELECT anzeigecheck = new Array( document.StatistikFormular.Feld0anz, document.StatistikFormular.Feld1anz, document.StatistikFormular.Feld2anz, document.StatistikFormular.Feld3anz, document.StatistikFormular.Feld4anz, document.StatistikFormular.Feld5anz, document.StatistikFormular.Feld6anz, document.StatistikFormular.Feld7anz, document.StatistikFormular.Feld8anz, document.StatistikFormular.Feld9anz ); // Array mit den Dropdownlisten für die Sortierung sortcombo = new Array( document.StatistikFormular.Feld0sort, document.StatistikFormular.Feld1sort, document.StatistikFormular.Feld2sort, document.StatistikFormular.Feld3sort, document.StatistikFormular.Feld4sort, document.StatistikFormular.Feld5sort, document.StatistikFormular.Feld6sort, document.StatistikFormular.Feld7sort, document.StatistikFormular.Feld8sort, document.StatistikFormular.Feld9sort ////////////////////////////////////////////////////////////////////////////// // wird aufgerufen, wenn der BODY des Anfrageneditors geladen wird // es werden einige Felder initialisiert, die einen einfacheren Zugriff auf // die einzelnen Steuerelemente des Formulars erlauben //---------------------------------------------------------------------------function onLoadStatBody(){ checkCookie(); // falls keine Cookies erlaubt sind, gibt es eine Meldung! ////////////////////////////////////////////////////////////////////////////// // File: stat_events.js Version: $Revision: 1.4 $ // Autor: Hilmar Falkenberg $Date: 2004/10/04 21:09:05 $ // // Beschreibung: hier sind alle Funktionen, die von einem Javascript bzw. // von dem Browser Eventhandler angestoßen werden zusammengefasst //============================================================================ Datei: stat_events.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_events.js 20 von 71 Seite: 2 von 12 Seite: 2 von 12 ); // Array mit den Textfeldern für die jeweiligen Aliasnamen 'AS' aliasnamen = new Array( document.StatistikFormular.Alias0, document.StatistikFormular.Alias1, document.StatistikFormular.Alias2, document.StatistikFormular.Alias3, document.StatistikFormular.Alias4, document.StatistikFormular.Alias5, document.StatistikFormular.Alias6, document.StatistikFormular.Alias7, document.StatistikFormular.Alias8, document.StatistikFormular.Alias9 ); // Array mit den Dropdownlisten für die Aggregatfunktionen groupcombo = new Array( document.StatistikFormular.Feld0group, document.StatistikFormular.Feld1group, document.StatistikFormular.Feld2group, document.StatistikFormular.Feld3group, document.StatistikFormular.Feld4group, document.StatistikFormular.Feld5group, document.StatistikFormular.Feld6group, document.StatistikFormular.Feld7group, document.StatistikFormular.Feld8group, document.StatistikFormular.Feld9group ); // Array mit den Dropdownlisten für die Attribute aus der 6. Zeile joincombo = new Array( document.StatistikFormular.Feld0join, document.StatistikFormular.Feld1join, document.StatistikFormular.Feld2join, document.StatistikFormular.Feld3join, document.StatistikFormular.Feld4join, document.StatistikFormular.Feld5join, document.StatistikFormular.Feld6join, document.StatistikFormular.Feld7join, document.StatistikFormular.Feld8join, document.StatistikFormular.Feld9join ); // Array mit den Textfeldern 'aus Tabelle', wo der Tabellenname des aus// gewählten Attributs hineingeschrieben wird, diesmal das Verknüpfte vtabellen = new Array( document.StatistikFormular.VTabelle0, document.StatistikFormular.VTabelle1, document.StatistikFormular.VTabelle2, document.StatistikFormular.VTabelle3, document.StatistikFormular.VTabelle4, document.StatistikFormular.VTabelle5, document.StatistikFormular.VTabelle6, document.StatistikFormular.VTabelle7, document.StatistikFormular.VTabelle8, document.StatistikFormular.VTabelle9 ); // zweidimensionales Array mit den Textfeldern für die Bedingungen wherefelder = new Array( new Array(document.StatistikFormular.Where0, document.StatistikFormular.Where0Or1, document.StatistikFormular.Where0Or2), new Array(document.StatistikFormular.Where1, document.StatistikFormular.Where1Or1, document.StatistikFormular.Where1Or2), new Array(document.StatistikFormular.Where2, document.StatistikFormular.Where2Or1, document.StatistikFormular.Where2Or2), new Array(document.StatistikFormular.Where3, document.StatistikFormular.Where3Or1, document.StatistikFormular.Where3Or2), Datei: stat_events.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: stat_events.js Anhang Seite: 3 von 12 Seite: 3 von 12 ); // zweidimensionales Array mit den Textfeldern für die Gruppen-Bedingungen havingfelder = new Array( new Array(document.StatistikFormular.Having0, document.StatistikFormular.Having0Or1, document.StatistikFormular.Having0Or2), new Array(document.StatistikFormular.Having1, document.StatistikFormular.Having1Or1, document.StatistikFormular.Having1Or2), new Array(document.StatistikFormular.Having2, document.StatistikFormular.Having2Or1, document.StatistikFormular.Having2Or2), new Array(document.StatistikFormular.Having3, document.StatistikFormular.Having3Or1, document.StatistikFormular.Having3Or2), new Array(document.StatistikFormular.Having4, document.StatistikFormular.Having4Or1, document.StatistikFormular.Having4Or2), new Array(document.StatistikFormular.Having5, document.StatistikFormular.Having5Or1, document.StatistikFormular.Having5Or2), new Array(document.StatistikFormular.Having6, document.StatistikFormular.Having6Or1, document.StatistikFormular.Having6Or2), new Array(document.StatistikFormular.Having7, document.StatistikFormular.Having7Or1, document.StatistikFormular.Having7Or2), new Array(document.StatistikFormular.Having8, document.StatistikFormular.Having8Or1, document.StatistikFormular.Having8Or2), new Array(document.StatistikFormular.Having9, document.StatistikFormular.Having9Or1, document.StatistikFormular.Having9Or2) ); // zweidimensionales Array mit den Dropdownlisten für die Vergleichsoperatoren comparecombo = new Array( new Array(document.StatistikFormular.Cond00, document.StatistikFormular.Cond01, document.StatistikFormular.Cond02, document.StatistikFormular.Cond03, document.StatistikFormular.Cond04, document.StatistikFormular.Cond05, document.StatistikFormular.Cond06), new Array(document.StatistikFormular.Cond10, document.StatistikFormular.Cond11, document.StatistikFormular.Cond12, document.StatistikFormular.Cond13, document.StatistikFormular.Cond14, document.StatistikFormular.Cond15, document.StatistikFormular.Cond16), new Array(document.StatistikFormular.Where4, document.StatistikFormular.Where4Or1, document.StatistikFormular.Where4Or2), new Array(document.StatistikFormular.Where5, document.StatistikFormular.Where5Or1, document.StatistikFormular.Where5Or2), new Array(document.StatistikFormular.Where6, document.StatistikFormular.Where6Or1, document.StatistikFormular.Where6Or2), new Array(document.StatistikFormular.Where7, document.StatistikFormular.Where7Or1, document.StatistikFormular.Where7Or2), new Array(document.StatistikFormular.Where8, document.StatistikFormular.Where8Or1, document.StatistikFormular.Where8Or2), new Array(document.StatistikFormular.Where9, document.StatistikFormular.Where9Or1, document.StatistikFormular.Where9Or2) Datei: stat_events.js 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: stat_events.js 21 von 71 Seite: 4 von 12 Seite: 4 von 12 // füllen der Vergleichsoperatoren-Dropdownlisten, ebenfalls dynamisch mit Javasc // füllen der Aggregatfunktions-Dropdownliste mit den möglichen Werten // so kann der Anfrageneditor leichter um Funktionen erweitert werden (s. stat_gl for (var i = 0; i < funktionen.length; i++){ for(var j = 0; j < groupcombo.length; j++){ groupcombo[j].options[i] = new Option(funktionen[i].name, funktionen[i].val groupcombo[j].options[i].selected = (i == 2); // gruppieren als DEFAULT-Wer } } ); new Array(document.StatistikFormular.Cond20, document.StatistikFormular.Cond21, document.StatistikFormular.Cond22, document.StatistikFormular.Cond23, document.StatistikFormular.Cond24, document.StatistikFormular.Cond25, document.StatistikFormular.Cond26), new Array(document.StatistikFormular.Cond30, document.StatistikFormular.Cond31, document.StatistikFormular.Cond32, document.StatistikFormular.Cond33, document.StatistikFormular.Cond34, document.StatistikFormular.Cond35, document.StatistikFormular.Cond36), new Array(document.StatistikFormular.Cond40, document.StatistikFormular.Cond41, document.StatistikFormular.Cond42, document.StatistikFormular.Cond43, document.StatistikFormular.Cond44, document.StatistikFormular.Cond45, document.StatistikFormular.Cond46), new Array(document.StatistikFormular.Cond50, document.StatistikFormular.Cond51, document.StatistikFormular.Cond52, document.StatistikFormular.Cond53, document.StatistikFormular.Cond54, document.StatistikFormular.Cond55, document.StatistikFormular.Cond56), new Array(document.StatistikFormular.Cond60, document.StatistikFormular.Cond61, document.StatistikFormular.Cond62, document.StatistikFormular.Cond63, document.StatistikFormular.Cond64, document.StatistikFormular.Cond65, document.StatistikFormular.Cond66), new Array(document.StatistikFormular.Cond70, document.StatistikFormular.Cond71, document.StatistikFormular.Cond72, document.StatistikFormular.Cond73, document.StatistikFormular.Cond74, document.StatistikFormular.Cond75, document.StatistikFormular.Cond76), new Array(document.StatistikFormular.Cond80, document.StatistikFormular.Cond81, document.StatistikFormular.Cond82, document.StatistikFormular.Cond83, document.StatistikFormular.Cond84, document.StatistikFormular.Cond85, document.StatistikFormular.Cond86), new Array(document.StatistikFormular.Cond90, document.StatistikFormular.Cond91, document.StatistikFormular.Cond92, document.StatistikFormular.Cond93, document.StatistikFormular.Cond94, document.StatistikFormular.Cond95, document.StatistikFormular.Cond96) Datei: stat_events.js 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: stat_events.js Anhang Seite: 5 von 12 // Sortierungs-Dropdownliste // Anzeigecheckbox save = anzeigecheck[left].checked; anzeigecheck[left].checked = anzeigecheck[right].checked; anzeigecheck[right].checked = save; Seite: 5 von 12 } ////////////////////////////////////////////////////////////////////////////// // setzt bei veränderter Frage den String für den entsprechenden Cookie //---------------------------------------------------------------------------function onChangeFrage(wert){ cook_FRAGE = wert; } ////////////////////////////////////////////////////////////////////////////// // wenn eine andere Tabelle in der 2. Zeile ausgewählt wurde, müssen alle // Spalten mit den neuen Attributen gefüllt werden //---------------------------------------------------------------------------function onChangeTabellen(){ empty_feld(); // alle Spalten löschen showFeldUpTo = 1; // nur die erste Spalte anzeigen fill_feld(document.StatistikFormular, 0); // die erste Spalte mit Attributen füll visi("ROW2", true); visi("ROW3", true); visi("ROW4", true); visi("ROW5", true); visi("ROW6", true); visi("ROW9", true); show(); setSelect(); } ////////////////////////////////////////////////////////////////////////////// // wird durch die Spaltentauschen Buttons aufgerufen // es werden alle Werte einer Spalte nach und nach vertauscht. //---------------------------------------------------------------------------function onClickFlip__(left, right){ if(left >= 0 && right < 10){ // ausgewähltes Attribut var save = feldcombo[left].selectedIndex; feldcombo[left].selectedIndex = feldcombo[right].selectedIndex; feldcombo[right].selectedIndex = save; // wie wurde der Anfrageneditor gestartet? soll eine NEUE Anfrage erstellt werden // oder soll die letzte bearbeitet werden? (s. Aufruf von statistik.html) if(document.location.search && -1 != document.location.search.indexOf("neu")) neu(); else wiederherstellen(); // SQL-Klauseln initialisieren sql_select = 'SELECT * '; sql_from = 'FROM '; sql_where = null; sql_groupby = null; sql_having = null; sql_orderby = null; // so können später auch SQL-Funktionen/Prädikate wie z.B. 'between' o.ä. ergänzt for(var j = 0; j < comparecombo.length; j++){ var joinindex = 0; for (var i = 0; i < compare.length; i++){ if((i > 2 && i < 9) || i == NICHTS){ // bei der Venküpfung sind nur Verglei comparecombo[j][0].options[joinindex] = new Option(compare[i].name, comp joinindex++; } for(var k = 1; k < comparecombo[j].length; k++) comparecombo[j][k].options[i] = new Option(compare[i].name, compare[i].v } } Datei: stat_events.js 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: stat_events.js 22 von 71 Seite: 6 von 12 Seite: 6 von 12 // Vergleichsoperatorenliste save = comparecombo[left][5].selectedIndex; comparecombo[left][5].selectedIndex = comparecombo[right][5].selectedIndex; comparecombo[right][5].selectedIndex = save; // Bedingungswert save = havingfelder[left][0].value; havingfelder[left][0].value = havingfelder[right][0].value; havingfelder[right][0].value = save; // Vergleichsoperatorenliste save = comparecombo[left][4].selectedIndex; comparecombo[left][4].selectedIndex = comparecombo[right][4].selectedIndex; comparecombo[right][4].selectedIndex = save; // verwendete Funktion save = groupcombo[left].selectedIndex; groupcombo[left].selectedIndex = groupcombo[right].selectedIndex; groupcombo[right].selectedIndex = save; // Bedingungswert save = wherefelder[left][2].value; wherefelder[left][2].value = wherefelder[right][2].value; wherefelder[right][2].value = save; // Vergleichsoperatorenliste save = comparecombo[left][3].selectedIndex; comparecombo[left][3].selectedIndex = comparecombo[right][3].selectedIndex; comparecombo[right][3].selectedIndex = save; // Bedingungswert save = wherefelder[left][1].value; wherefelder[left][1].value = wherefelder[right][1].value; wherefelder[right][1].value = save; // Vergleichsoperatorenliste save = comparecombo[left][2].selectedIndex; comparecombo[left][2].selectedIndex = comparecombo[right][2].selectedIndex; comparecombo[right][2].selectedIndex = save; // Bedingungswert save = wherefelder[left][0].value; wherefelder[left][0].value = wherefelder[right][0].value; wherefelder[right][0].value = save; // Vergleichsoperatorenliste save = comparecombo[left][1].selectedIndex; comparecombo[left][1].selectedIndex = comparecombo[right][1].selectedIndex; comparecombo[right][1].selectedIndex = save; // verknüpftes Attribut save = joincombo[left].selectedIndex; joincombo[left].selectedIndex = joincombo[right].selectedIndex; joincombo[right].selectedIndex = save; // Vergleichsoperatorenliste save = comparecombo[left][0].selectedIndex; comparecombo[left][0].selectedIndex = comparecombo[right][0].selectedIndex; comparecombo[right][0].selectedIndex = save; // eingetragene Aliasnamen (Spaltenüberschriften) save = aliasnamen[left].value; aliasnamen[left].value = aliasnamen[right].value; aliasnamen[right].value = save; save = sortcombo[left].selectedIndex; sortcombo[left].selectedIndex = sortcombo[right].selectedIndex; sortcombo[right].selectedIndex = save; Datei: stat_events.js 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 Datei: stat_events.js Anhang Seite: 7 von 12 showFeldUpTo -= 1; show(); setSelect(); // Zellen-Anzeige aktualisieren // SQL-Anzeige aktualisieren Seite: 7 von 12 // Spaltentauschenleiste anzeigen (mehr als ein Attribut gewählt) oder // nicht anzeigen (ein oder kein Attribut ausgewählt) if(showFeldUpTo <= 2) showRow[2] = false; else showRow[2] = true; } // ggf. leere Spalte nach hinten durchtauschen for(var i = nr; i < showFeldUpTo; i++) onClickFlip__(i, i + 1); setSelect(); // nun noch den SQL aktualisieren } } ////////////////////////////////////////////////////////////////////////////// // wenn ein anderes Attribut ausgewählt wird, // muss ggf. eine weitere Spalte angezeigt werden oder evtl. gelöscht (leeres // Attribut ausgewählt) //---------------------------------------------------------------------------function onChangeFeld_(nr){ if(feldcombo[nr].selectedIndex > NICHTS){ // eine Spalte mehr anzeigen showFeldUpTo = (2 + nr) > showFeldUpTo ? (2 + nr) : showFeldUpTo; showFeldUpTo = 10 < showFeldUpTo ? 11 : showFeldUpTo; if(showFeldUpTo < 11) fill_feld(document.StatistikFormular, (nr + 1)); } else { // eine Spalte weniger anzeigen anzeigecheck[nr].checked = false; sortcombo[nr].selectedIndex = NICHTS; aliasnamen[nr].value = ''; comparecombo[nr][0].selectedIndex = NICHTS; comparecombo[nr][1].selectedIndex = NICHTS; comparecombo[nr][2].selectedIndex = NICHTS; comparecombo[nr][3].selectedIndex = NICHTS; comparecombo[nr][4].selectedIndex = NICHTS; comparecombo[nr][5].selectedIndex = NICHTS; comparecombo[nr][6].selectedIndex = NICHTS; joincombo[nr].selectedIndex = NICHTS; wherefelder[nr][0].value = ''; wherefelder[nr][1].value = ''; wherefelder[nr][2].value = ''; havingfelder[nr][0].value = ''; havingfelder[nr][1].value = ''; havingfelder[nr][2].value = ''; // Bedingungswert save = havingfelder[left][2].value; havingfelder[left][2].value = havingfelder[right][2].value; havingfelder[right][2].value = save; // Vergleichsoperatorenliste save = comparecombo[left][6].selectedIndex; comparecombo[left][6].selectedIndex = comparecombo[right][6].selectedIndex; comparecombo[right][6].selectedIndex = save; // Bedingungswert save = havingfelder[left][1].value; havingfelder[left][1].value = havingfelder[right][1].value; havingfelder[right][1].value = save; Datei: stat_events.js 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 Datei: stat_events.js 23 von 71 Seite: 8 von 12 Seite: 8 von 12 } ////////////////////////////////////////////////////////////////////////////// if(onoff){ show(); setSelect(); } else { // Bedingung ausgeschaltet, dann muss ggf. die nächste ODER-Zeile // ebenfalls ausgeblendet werden document.StatistikFormular.CheckBox3.checked = onoff; onCheckBox3(onoff); } } ////////////////////////////////////////////////////////////////////////////// // wird bei einem Klick auf eine Attribut-Anzeigen-Checkbox aufgerufen //---------------------------------------------------------------------------function onClickFeld_anz(nr){ if(anzeigecheck[nr].checked && feldcombo[nr].selectedIndex){ if(!aliasnamen[nr].value) // falls noch kein Alias vergeben wurde setze den Attributsnamen ein aliasnamen[nr].value = inBenutzung[feldcombo[nr].selectedIndex].name; } else{ // keine Anzeige -> kein Alias aliasnamen[nr].value = ''; anzeigecheck[nr].checked = false; } setSelect(); } ////////////////////////////////////////////////////////////////////////////// // falls andere Sortierung gewünscht ist, muss nur der SQL angepasst werden //---------------------------------------------------------------------------function onChangeFeld_sort(){ setSelect(); } ////////////////////////////////////////////////////////////////////////////// // anderer Aliasname -> gleiche Funktion wie auf Anzeigen-Checkbox klicken //---------------------------------------------------------------------------function onChangeAlias_(nr){ onClickFeld_anz(nr); } ////////////////////////////////////////////////////////////////////////////// // die Zeile für den JOIN bzw. die Verknüpfung ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox1(onoff){ showRow[5] = onoff; show(); setSelect(); } ////////////////////////////////////////////////////////////////////////////// // ändert sich der Vergleichsoperator beim JOIN -> SQL anpassen //---------------------------------------------------------------------------function onChangeCond_0(){ setSelect(); } ////////////////////////////////////////////////////////////////////////////// // ändert sich das verknüpfte Attribut beim JOIN -> SQL anpassen //---------------------------------------------------------------------------function onChangeFeld_join(){ setSelect(); } ////////////////////////////////////////////////////////////////////////////// // Bedingungen ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox2(onoff){ showRow[6] = onoff; visi("ROW7", onoff); Datei: stat_events.js 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 Datei: stat_events.js Anhang Seite: 9 von 12 Seite: 9 von 12 } ////////////////////////////////////////////////////////////////////////////// if(onoff){ show(); setSelect(); } else { // Having-Bedingung ausgeschaltet, dann muss ggf. die nächste ODER-Zeile // ebenfalls ausgeblendet werden document.StatistikFormular.CheckBox7.checked = onoff; onCheckBox7(onoff); } } ////////////////////////////////////////////////////////////////////////////// // andere Aggregatfunktion ausgewählt -> SQL anpassen //---------------------------------------------------------------------------function onChangeFeld_group(){ setSelect(); } ////////////////////////////////////////////////////////////////////////////// // Having-Bedingung ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox6(onoff){ showRow[10] = onoff; visi("ROW11", onoff); if(onoff){ show(); setSelect(); } else { // Funktionen ausgeschaltet, dann müssen ggf. die Having-Bedingungen // ebenfalls ausgeblendet werden document.StatistikFormular.CheckBox6.checked = onoff; onCheckBox6(onoff); } } ////////////////////////////////////////////////////////////////////////////// // ODER_2 ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox4(onoff){ showRow[8] = onoff; show(); setSelect(); } ////////////////////////////////////////////////////////////////////////////// // Funktionen ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox5(onoff){ showRow[9] = onoff; visi("ROW10", onoff); if(onoff){ show(); setSelect(); } else { // ODER_1 ausgeschaltet, dann muss ggf. die nächste ODER-Zeile // ebenfalls ausgeblendet werden document.StatistikFormular.CheckBox4.checked = onoff; onCheckBox4(onoff); } // ODER_1 ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox3(onoff){ showRow[7] = onoff; visi("ROW8", onoff); Datei: stat_events.js 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 Datei: stat_events.js 24 von 71 Seite: 10 von 12 // Strings werden mit ' maskiert if(!isOK && textfeld.value && datatype == "VARCHAR"){ isOK = isString(textfeld); // wird mit einer Liste (IN / NOT IN) verglichen if(comparecombo[index][condi].selectedIndex == NOTIN || comparecombo[index][condi].selectedIndex == IN){ if(!isOK && textfeld.value && datatype == "INTEGER") // nur Listen aus Integern werden z.Z. überprüft isOK = isIntList(textfeld); } Seite: 10 von 12 // wenn die Aggragatfunktion COUNT verwendet wird, muss es Integer sein if(!isOK && textfeld.value && groupcombo[index].selectedIndex == COUNT && comparecombo[index][condi].selectedIndex != NICHTS){ isOK = isInt(textfeld); } // bei IS [NOT] NULL wird nur das Feld geleert... if(comparecombo[index][condi].selectedIndex <= NOTNULL){ textfeld.value = ''; isOK = true; } // beim SUBQUERY wird nichts überprüft!!! if(comparecombo[index][condi].selectedIndex == SUBQUERY){ //in diesem Fall sollte der Benutzer schon wissen, was er tut! isOK = true; } else if(feldcombo[index].selectedIndex > STAR){ // es wurde nicht SELECT * gewählt, also Datentyp des Attributs holen var datatype = inBenutzung[feldcombo[index].selectedIndex].datatype; // ist alles leer, so ist alles OK if(null == textfeld.value || textfeld.value.length == 0) isOK = true; } ////////////////////////////////////////////////////////////////////////////// // Having-ODER_2 ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox8(onoff){ showRow[12] = onoff; show(); setSelect(); } ////////////////////////////////////////////////////////////////////////////// // überprüft ein Textfeld, ob der enthaltene Wert zu dem Datentypen des // Attributs passt und nimmt ggf. Konvertierungen vor //---------------------------------------------------------------------------function check(textfeld, index, condi) { var isOK = false; if(onoff){ show(); setSelect(); } else { // Having-ODER_1 ausgeschaltet, dann muss ggf. die nächste ODER-Zeile // ebenfalls ausgeblendet werden document.StatistikFormular.CheckBox8.checked = onoff; onCheckBox8(onoff); } // Having-ODER_1 ein-/ausschalten //---------------------------------------------------------------------------function onCheckBox7(onoff){ showRow[11] = onoff; visi("ROW12", onoff); Datei: stat_events.js 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 Datei: stat_events.js Anhang Seite: 11 von 12 Seite: 11 von 12 if(isOK) setSelect(); } ////////////////////////////////////////////////////////////////////////////// // speichert die aktuelle Anfrage //---------------------------------------------------------------------------function onClickSave(){ saveCookies(); if(cook_FELD[0].length > 0){ document.StatistikFormular.doWhat.value = "speichern"; document.StatistikFormular.submit(); } else alert("Eine leere Abfrage kann nicht gespeichert werden!"); } ////////////////////////////////////////////////////////////////////////////// // führt die aktuelle Anfrage aus //---------------------------------------------------------------------------function onClickStart(){ saveCookies(); if(document.StatistikFormular.query.value){ document.StatistikFormular.doWhat.value = "execute"; document.StatistikFormular.submit(); } else alert("Sie haben noch keine Abfrage spezifiziert!"); } ////////////////////////////////////////////////////////////////////////////// // löscht die aktuelle Anfrage (nur die gemachten Einstellungen, aber nicht // aus der DB) und bereitet den Editor für eine neue Anfrage vor //---------------------------------------------------------------------------- } else if(groupcombo[index].selectedIndex == COUNT && comparecombo[index][condi].selectedIndex != NICHTS){ // wenn die Aggragatfunktion COUNT verwendet wird, muss es Integer sein isOK = isInt(textfeld); } else if(feldcombo[index].selectedIndex == NICHTS){ // es kann erst eine Bedingung gestellt werden, wenn ein Feld // ausgewählt wurde comparecombo[index][condi].selectedIndex = NICHTS; textfeld.value = ''; alert("Wählen bitte Sie zuerst ein Feld aus,\n" + "das diese Bedingung erfüllen soll!"); feldcombo[index].focus(); } else{ textfeld.value = ''; comparecombo[index][condi].selectedIndex = NICHTS; isOK = true; } // Ganzzahlentest if(!isOK && textfeld.value && datatype == "INTEGER"){ isOK = isInt(textfeld); } // Kommazahlentest if(!isOK && textfeld.value && datatype == "FLOAT"){ isOK = isFloat(textfeld); } // ein Datum, wird in das DB-Format: 'YYYY-MM-DD' konvertiert if(!isOK && textfeld.value && datatype == "DATE"){ isOK = isValidDate(textfeld); } } Datei: stat_events.js 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 Datei: stat_events.js Seite: 12 von 12 25 von 71 Datei: stat_events.js Seite: 12 von 12 749 function onClickNew(){ 750 var ok = confirm("ACHTUNG: Alle eingegebenen Daten gehen verloren!"); 751 if(ok) 752 neu(); 753 } Datei: stat_events.js Anhang Seite: 1 von 2 SQL-Text 'FROM '; 'SELECT * '; null; null; null; null; // gibt an, wieviel Spalten angezeigt werden // wird in fill_feld() gesetzt // alle anderen werden in setSelect() // gesetzt Seite: 1 von 2 // Die implementierten Aggregatfunktionen, mit diesen wird das Array: // groupcombo[x] gefüllt var funktionen = new Array( new myOption("", "WHERE "), //0 // Array mit default-Wahrheitswerten, ob die Zeilen angezeigt werden sollen var showRow = new Array(true, //Frage true, //Tabellen + Hilfetext false, //Spalten tauschen true, //Feld true, //anzeige false, //JOIN false, //Bedingung false, //oder false, //oder false, //Funktion false, //Having false, //oder false); //oder // Arrays für die Objekt-Referenzen der Steuerelemente des Formulars var tabellen = null; var vtabellen = null; var feldcombo = null; var anzeigecheck = null; var sortcombo = null; var aliasnamen = null; var groupcombo = null; var joincombo = null; var wherefelder = null; var havingfelder = null; var comparecombo = null; var inBenutzung = null; var showFeldUpTo = 1; // Strings für den var sql_from = var sql_select = var sql_where = var sql_groupby = var sql_having = var sql_orderby = // erzeugt nur eine Optionsgruppe, damit die Attribute nach den jeweiligen // Tabellen gruppiert werden können. function OptionGroup(label){ var optGroup = document.createElement('optgroup'); optGroup.label = label; return optGroup; } // Diese Javascript-"Klasse" erzeugt die Optionsobjekte für die Attribut// dropdownlisten function myOption(n,v,typ){ this.name = n; this.value = v; this.table = ''; // wird erst bei 'fill_feld()' gesetzt!!! this.datatype = typ; } ////////////////////////////////////////////////////////////////////////////// // File: stat_globals.js Version: $Revision: 1.2 $ // Autor: Hilmar Falkenberg $Date: 2004/10/05 08:39:33 $ // // Beschreibung: In dieser Datei sind alle Gloabalen Variablen zusammenge// fasst, damit man einen bessereb Überblick hat. //============================================================================ Datei: stat_globals.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_globals.js 26 von 71 myOption("Durchschnitt ", myOption("gruppieren ", myOption("Maximum ", myOption("Minimum ", myOption("Summe ", myOption("Anzahl ", //00 //01 //02 //03 //04 //05 //06 //07 //08 //09 //10 //11 //12 Seite: 2 von 2 "#FFFF00"; "#00FF00"; "#FFFF80"; "#D9FFD9"; "#FFFF00"; "#FF0000"; "#FFFFFF"; // Farbwerte zum hervorheben der besonderen // Zellen, falls andere Farben gewünscht // sind, diese hier ändern! Seite: 2 von 2 //globale Variablen für den COOKIE-Aufbau... var cook_TABLE = ''; // bekommt die Indizes der ausgewählten Tabellen var cook_FELD = new Array('','','','','','','','','',''); var cook_CHECK = ''; // true-false, je nachdem, ob die Funktionen eingeschlatet // sind oder nicht var cook_FRAGE = ''; // naja, eben die Frage (s. ganz oben auf der HTML-Seite)m // Hintergrundfarben var COLOR_JOIN = var COLOR_GROUPBY = var COLOR_FUNKTION = var COLOR_ANZEIGEN = var COLOR_BEDINGUNG = var COLOR_SUBQUERY = var COLOR_NICHTS = //eigentlich würden sich hierfür Konstanten eignen, aber der InternetExplorer //gibt Fehlermeldungen bei dieser Syntax: //const NICHTS = 0; //Der meckert dann jedesmal, das 1. Zeichen in der nachfolgenden Zeile an!?! var NICHTS = 0; // Konstanten zum vergleichen, welcher Wert gewählt var ISNULL = 1; // wurde (s. Array compare oben) var NOTNULL = 2; var LITTLE = 3; var LEQUAL = 4; var EQUAL = 5; var GEQUAL = 6; var GREATER = 7; var NOTEQUAL = 8; var LIKE = 9; var IN = 10; var NOTIN = 11; var SUBQUERY = 12; var STAR = 1; // für SELECT * var WHERE = 0; // die Indizes der Aggregatfunktionen var AVG = 1; var GROUPBY = 2; var MAX = 3; var MIN = 4; var SUM = 5; var COUNT = 6; ""), " IS NULL"), " IS NOT NULL"), " < "), " <= "), " = "), " >= "), " > "), " <> "), " LIKE "), " IN "), " NOT IN "), " ") mit diesen wird das Array: "AVG("), //1 "GROUP BY "), //2 "MAX("), //3 "MIN("), //4 "SUM("), //5 "COUNT(") //6 // Liste der Vergleichsoperatoren, // comparecombo[x] gefüllt var compare = new Array( new myOption("", new myOption("Ist NULL", new myOption("Nicht NULL", new myOption("<", new myOption("<=", new myOption("=", new myOption(">=", new myOption(">", new myOption("!=", new myOption("Wie", new myOption("in", new myOption("nicht in", new myOption("SUBQUERY", ); ); new new new new new new Datei: stat_globals.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 Datei: stat_globals.js Anhang Seite: 1 von 5 Seite: 1 von 5 ////////////////////////////////////////////////////////////////////////////// // globales Array mit den Namen der verfügbaren Feldern für jede Tabelle // zu: new myOption("Beschriftung", "VALUE-Attribut", "Datatype") // siehe stat_globals.js // WICHTIG: die Tabellen müssen die gleiche Reihenfolge im Array haben, wie // sie in der HTML-Seite in der Auswahlliste stehen!!! //---------------------------------------------------------------------------var felder = new Array( /////////////////////////////////////////////////////////////////////////// // Tabelle: anerkennungen // Kürzel: a new Array( new myOption("Datum", "a.datum", "DATE"), new myOption("Kommentar", "a.kommentar", "VARCHAR"), new myOption("Leistpunkte", "a.leistpunkte", "FLOAT"), new myOption("Leistung", "a.leistung", "VARCHAR"), new myOption("Matrikel_nr", "a.matrikel_nr", "VARCHAR"), new myOption("Note", "a.note", "FLOAT"), new myOption("Verantwortlich", "a.verantwortlich", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: angestr_abschluss // Kürzel: aa /*********************************************************************************** // Auswahlmöglichkeiten in der 'statistik.html', in dieser Reihenfolge der // Tabellen, sollten auch die Array's in der 'felder' (s.u.) Variablen sein. //---------------------------------------------------------------------------<option value="anerkennungen a" label="Anerkennungen" >Ane <option value="angestr_abschluss aa" label="Angestr-Abschluss" >Ang <option value="diplom d" label="Diplom" >Dip <option value="diplom_pruefungen dp" label="Diplom-Pr&uuml;fungen" >Dip <option value="diplomarbeiten da" label="Diplomarbeiten" >Dip <option value="fachgebiet f" label="Fachgebiet" >Fac <option value="gruppen g" label="Gruppen" >Gru <option value="industriepraktika i" label="Industriepraktika" >Ind <option value="industriepraktika_ing ii" label="Industriepraktika (Ing)" >Ind <option value="lehrpersonal lp" label="Lehrpersonal" >Leh <option value="lehrstuhl ls" label="Lehrstuhl" >Leh <option value="pruefungsfaecher pf" label="Pr&uuml;fungsf&auml;cher" >Pr& <option value="scheine sch" label="Scheine" >Sch <option value="scheintypen scht" label="Scheintypen" >Sch <option value="studienarbeiten sa" label="Studienarbeiten" >Stu <option value="studienfaecher sf" label="Studienf&auml;cher" >Stu <option value="studierende s" label="Studierende" >Stu <option value="unterbrechungen u" label="Unterbrechungen" >Unt <option value="veranst_teilnehmer vt" label="Veranst-Teilnehmer" >Ver <option value="veranstaltungen v" label="Veranstaltungen" >Ver <option value="veranstaltungen_fachgebiet vf" label="Veranstaltungen-Fachgebiet">Ver <option value="veranstaltungstypen vtyp" label="Veranstaltungstypen" >Ver <option value="vordiplom vd" label="Vordiplom" >Vor <option value="vordiplom_pruefungen vdp" label="Vordiplom-Pr&uuml;fungen" >Vor <option value="wird_gehalten_von w" label="Wird gehalten von" >Wir <option value="zertifikat_pruefungen z" label="Zertifikat-Pr&uuml;fungen" >Zer ************************************************************************************ ////////////////////////////////////////////////////////////////////////////// // File: stat_schema.js Version: $Revision: 1.2 $ // Autor: Hilmar Falkenberg $Date: 2004/10/05 08:48:17 $ // // Beschreibung: Hier ist sozusagen das Datenbankschema nachgebildet. Die // Tabellen sind ja schon in der HTML-Seite direkt enthalten, aber die // Attribute mit angezeigtem Namen, DB-Namen und Datentyp sind hier in einem // mehrdimensionalem Array gespeichert. Aus diesem werden die Werte, dann in // fill_feld() in die Dropdownlisten dynamisch, je nachdem welche Tabellen // ausgewählt wurden, gefüllt. Zum erzeugen dieser Datei, kann das SQL-Script // javascript.sql verwendet werden, es müssen dann aber noch kleinere // Anpassungen von Hand erfolgen! //============================================================================ Datei: stat_schema.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_schema.js 27 von 71 Seite: 2 von 5 Seite: 2 von 5 new Array( new myOption("Angestr_abschluss_nr", "aa.angestr_abschluss_nr", "INTEGER"), new myOption("Bezeichnung", "aa.bezeichnung", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: diplom // Kürzel: d new Array( new myOption("Anmeldedatum", "d.anmeldedatum", "DATE") new myOption("Bemerkung", "d.bemerkung", "VARCHA new myOption("Datum_erstellung_zeugnis", "d.datum_erstellung_zeugnis", "DATE") new myOption("Datum_letzte_pruefung", "d.datum_letzte_pruefung", "DATE") new myOption("Gesamtnote", "d.gesamtnote", "FLOAT" new myOption("Kommentar", "d.kommentar", "VARCHA new myOption("Matrikel_nr", "d.matrikel_nr", "VARCHA new myOption("Nbestanden_ja_nein", "d.nbestanden_ja_nein", "VARCHA /////////////////////////////////////////////////////////////////////////// // Tabelle: diplom_pruefungen // Kürzel: dp new Array( new myOption("Datum", "dp.datum", "DATE"), new myOption("Fach_nr", "dp.fach_nr", "INTEGER"), new myOption("Kommentar", "dp.kommentar", "VARCHAR"), new myOption("1. Prüfer", "dp.lehrpersonal_nr_1", "INTEGER"), new myOption("2. Prüfer", "dp.lehrpersonal_nr_2", "INTEGER"), new myOption("Matrikel_nr", "dp.matrikel_nr", "VARCHAR"), new myOption("Note", "dp.note", "FLOAT"), new myOption("Wiederholung_ja_nein", "dp.wiederholung_ja_nein", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: diplomarbeiten // Kürzel: da new Array( new myOption("Abgabedatum", "da.abgabedatum", "DATE"), new myOption("Anmeldedatum", "da.anmeldedatum", "DATE"), new myOption("Betreuer", "da.betreuer", "VARCHAR") new myOption("Gutachter_1", "da.gutachter_1", "INTEGER") new myOption("Gutachter_2", "da.gutachter_2", "INTEGER") new myOption("Kommentar", "da.kommentar", "VARCHAR") new myOption("Lehrstuhl_nr", "da.lehrstuhl_nr", "INTEGER") new myOption("Matrikel_nr", "da.matrikel_nr", "VARCHAR") new myOption("Note", "da.note", "FLOAT"), new myOption("Thema", "da.thema", "VARCHAR") new myOption("Zurueckgegeben_ja_nein", "da.zurueckgegeben_ja_nein", "VARCHAR") /////////////////////////////////////////////////////////////////////////// // Tabelle: fachgebiet // Kürzel: f new Array( new myOption("Bezeichnung", "f.bezeichnung", "VARCHAR"), new myOption("Fachgebiet_nr", "f.fachgebiet_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: gruppen // Kürzel: g new Array( new myOption("Anzahl_akt", "g.anzahl_akt", "INTEGER"), new myOption("Anzahl_max", "g.anzahl_max", "INTEGER"), new myOption("Bemerkung", "g.bemerkung", "VARCHAR"), new myOption("Gruppe_nr", "g.gruppe_nr", "INTEGER"), new myOption("Leiter", "g.leiter", "VARCHAR"), new myOption("Semester", "g.semester", "VARCHAR"), new myOption("Veranstaltung_nr", "g.veranstaltung_nr", "VARCHAR"), new myOption("Zeit", "g.zeit", "DATE")), /////////////////////////////////////////////////////////////////////////// // Tabelle: industriepraktika // Kürzel: i new Array( new myOption("Anerkannt_ja_nein", "i.anerkannt_ja_nein", "VARCHAR"), new myOption("Datum", "i.datum", "DATE"), new myOption("Dauer", "i.dauer", "INTEGER"), new myOption("Kommentar", "i.kommentar", "VARCHAR"), Datei: stat_schema.js 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: stat_schema.js Anhang Seite: 3 von 5 Seite: 3 von 5 new myOption("Matrikel_nr", "i.matrikel_nr", "VARCHAR"), new myOption("Name_des_betriebes", "i.name_des_betriebes", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: industriepraktika_ing // Kürzel: ii new Array( new myOption("Datum_erstellt", "ii.datum_erstellt", "DATE"), new myOption("Dauer_elek_gp", "ii.dauer_elek_gp", "INTEGER"), new myOption("Dauer_fachpraxis", "ii.dauer_fachpraxis", "INTEGER"), new myOption("Dauer_mech_gp", "ii.dauer_mech_gp", "INTEGER"), new myOption("Matrikel_nr", "ii.matrikel_nr", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: lehrpersonal // Kürzel: lp new Array( new myOption("Fakultaet", "lp.fakultaet", "VARCHAR"), new myOption("Institut_ja_nein", "lp.institut_ja_nein", "VARCHAR"), new myOption("Lehrpersonal_nr", "lp.lehrpersonal_nr", "INTEGER"), new myOption("Lehrstuhl_nr", "lp.lehrstuhl_nr", "INTEGER"), new myOption("Name", "lp.name", "VARCHAR"), new myOption("Titel", "lp.titel", "VARCHAR"), new myOption("Vorname", "lp.vorname", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: lehrstuhl // Kürzel: ls new Array( new myOption("Bezeichnung", "ls.bezeichnung", "VARCHAR"), new myOption("Lehrstuhl_nr", "ls.lehrstuhl_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: pruefungsfaecher // Kürzel: pf new Array( new myOption("Bezeichnung", "pf.bezeichnung", "VARCHAR"), new myOption("Fach_nr", "pf.fach_nr", "INTEGER"), new myOption("Kommentar", "pf.kommentar", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: scheine // Kürzel: sch new Array( new myOption("Datum", "sch.datum", "DATE"), new myOption("Kommentar", "sch.kommentar", "VARCHAR"), new myOption("Matrikel_nr", "sch.matrikel_nr", "VARCHAR"), new myOption("Note", "sch.note", "FLOAT"), new myOption("Note_ja_nein", "sch.note_ja_nein", "VARCHAR"), new myOption("ScheintypNr", "sch.scheintyp_nr", "INTEGER"), new myOption("Semester", "sch.semester", "VARCHAR"), new myOption("Stundenzahl", "sch.stundenzahl", "FLOAT"), new myOption("Text_zeile_1", "sch.text_zeile_1", "VARCHAR"), new myOption("Text_zeile_2", "sch.text_zeile_2", "VARCHAR"), new myOption("Thema", "sch.thema", "VARCHAR"), new myOption("VeranstaltungNr", "sch.veranstaltung_nr", "VARCHAR"), new myOption("Wiederholung", "sch.wiederholung", "INTEGER"), new myOption("Zuordnung", "sch.zuordnung", "VARCHAR"), new myOption("Zurueckgetreten", "sch.zurueckgetreten_ja_nein", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: scheintypen // Kürzel: scht new Array( new myOption("bezeichnung", "scht.bezeichnung", "VARCHAR"), new myOption("scheintyp_nr", "scht.scheintyp_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: studienarbeiten // Kürzel: sa new Array( new myOption("Beurteilung", "sa.beurteilung", "VARCHAR"), new myOption("Datum", "sa.datum", "DATE"), new myOption("Kommentar", "sa.kommentar", "VARCHAR"), new myOption("Lehrpersonal_nr", "sa.lehrpersonal_nr", "INTEGER"), Datei: stat_schema.js 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: stat_schema.js 28 von 71 Seite: 4 von 5 Seite: 4 von 5 new myOption("Matrikel_nr", "sa.matrikel_nr", "VARCHAR"), new myOption("Thema", "sa.thema", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: studienfaecher // Kürzel: sf new Array( new myOption("Bezeichnung", "sf.bezeichnung", "VARCHAR"), new myOption("Studienfach_nr", "sf.studienfach_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: studienform // Kürzel: sfo new Array( new myOption("bezeichnung", "sfo.bezeichnung", "VARCHAR"), new myOption("studienform_nr", "sfo.studienform_nr", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: studierende // Kürzel: s new Array( new myOption("Abschlussnote", "s.abschlussnote", "FLOAT"), new myOption("Angestr_abschluss_nr", "s.angestr_abschluss_nr", "INTEGER"), new myOption("Email_institut", "s.email_institut", "VARCHAR"), new myOption("Email_privat", "s.email_privat", "VARCHAR"), new myOption("Exmatrikuliert_ja_nein", "s.exmatrikuliert_ja_nein", "VARCHAR"), new myOption("Fachsemester", "s.fachsemester", "INTEGER"), new myOption("Geburtsdatum", "s.geburtsdatum", "DATE"), new myOption("Geprueft_ja_nein", "s.geprueft_ja_nein", "VARCHAR"), new myOption("Geschlecht", "s.geschlecht", "VARCHAR"), new myOption("Hauptfach_nr", "s.hauptfach_nr", "INTEGER"), new myOption("Kommentar", "s.kommentar", "VARCHAR"), new myOption("Matrikel_nr", "s.matrikel_nr", "VARCHAR"), new myOption("Name", "s.name", "VARCHAR"), new myOption("Nebenfach_nr_1", "s.nebenfach_nr_1", "INTEGER"), new myOption("Nebenfach_nr_2", "s.nebenfach_nr_2", "INTEGER"), new myOption("Ort", "s.ort", "VARCHAR"), new myOption("Plz", "s.plz", "VARCHAR"), new myOption("Strasse", "s.strasse", "VARCHAR"), new myOption("Studienabschluss", "s.studienabschluss", "DATE"), new myOption("Studienbeginn", "s.studienbeginn", "DATE"), new myOption("StudienformNr", "s.studienform_nr", "VARCHAR"), new myOption("Telefon_1", "s.telefon_1", "VARCHAR"), new myOption("Telefon_2", "s.telefon_2", "VARCHAR"), new myOption("Vorname", "s.vorname", "VARCHAR"), new myOption("Zuletzt_bearbeitet", "s.zuletzt_bearbeitet", "DATE")), /////////////////////////////////////////////////////////////////////////// // Tabelle: unterbrechungen // Kürzel: u new Array( new myOption("Beginn", "u.beginn", "DATE"), new myOption("Ende", "u.ende", "DATE"), new myOption("Grund", "u.grund", "VARCHAR"), new myOption("Matrikel_nr", "u.matrikel_nr", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: veranst_teilnehmer // Kürzel: vt new Array( new myOption("Gruppe_nr", "vt.gruppe_nr", "INTEGER"), new myOption("Matrikel_nr", "vt.matrikel_nr", "VARCHAR"), new myOption("Semester", "vt.semester", "VARCHAR"), new myOption("Veranstaltung_nr", "vt.veranstaltung_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: veranstaltungen // Kürzel: v new Array( new myOption("Bezeichnung", "v.bezeichnung", "VARCHAR"), new myOption("Ects_schein", "v.ects_schein", "FLOAT"), new myOption("Ects_univis", "v.ects_univis", "FLOAT"), new myOption("Kommentar", "v.kommentar", "VARCHAR"), new myOption("Semester", "v.semester", "VARCHAR"), Datei: stat_schema.js 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: stat_schema.js Anhang Seite: 5 von 5 Seite: 5 von 5 new myOption("Stundenzahl", "v.stundenzahl", "FLOAT"), new myOption("Teilnehmerzahl_beginn", "v.teilnehmerzahl_beginn", "INTEGER"), new myOption("Teilnehmerzahl_ende", "v.teilnehmerzahl_ende", "INTEGER"), new myOption("Veranstaltung_nr", "v.veranstaltung_nr", "VARCHAR"), new myOption("Vtyp_nr", "v.vtyp_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: veranstaltungen_fachgebiet // Kürzel: vf new Array( new myOption("Fachgebiet_nr", "vf.fachgebiet_nr", "INTEGER"), new myOption("Lfd_nr", "vf.lfd_nr", "INTEGER"), new myOption("Semester", "vf.semester", "VARCHAR"), new myOption("Veranstaltung_nr", "vf.veranstaltung_nr", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: veranstaltungstypen // Kürzel: vtyp new Array( new myOption("Veranstaltungstyp", "vtyp.veranstaltungstyp", "VARCHAR"), new myOption("Vtyp_nr", "vtyp.vtyp_nr", "INTEGER")), /////////////////////////////////////////////////////////////////////////// // Tabelle: vordiplom // Kürzel: vd new Array( new myOption("Anmeldedatum", "vd.anmeldedatum", "DATE"), new myOption("Bemerkung", "vd.bemerkung", "VARCHAR"), new myOption("Datum_letzte_pruefung", "vd.datum_letzte_pruefung", "DATE"), new myOption("Gesamtnote", "vd.gesamtnote", "FLOAT"), new myOption("Kommentar", "vd.kommentar", "VARCHAR"), new myOption("Matrikel_nr", "vd.matrikel_nr", "VARCHAR"), new myOption("Nbestanden_ja_nein", "vd.nbestanden_ja_nein", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: vordiplom_pruefungen // Kürzel: vdp new Array( new myOption("Datum", "vdp.datum", "DATE"), new myOption("Fach_nr", "vdp.fach_nr", "INTEGER"), new myOption("Klausur_ja_nein", "vdp.klausur_ja_nein", "VARCHAR"), new myOption("Kommentar", "vdp.kommentar", "VARCHAR"), new myOption("1. Prüfer", "vdp.lehrpersonal_nr_1", "INTEGER"), new myOption("2. Prüfer", "vdp.lehrpersonal_nr_2", "INTEGER"), new myOption("Matrikel_nr", "vdp.matrikel_nr", "VARCHAR"), new myOption("Note", "vdp.note", "FLOAT"), new myOption("Wiederholung_ja_nein", "vdp.wiederholung_ja_nein", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: wird_gehalten_von // Kürzel: w new Array( new myOption("Lehrpersonal_nr", "w.lehrpersonal_nr", "INTEGER"), new myOption("Semester", "w.semester", "VARCHAR"), new myOption("Veranstaltung_nr", "w.veranstaltung_nr", "VARCHAR")), /////////////////////////////////////////////////////////////////////////// // Tabelle: zertifikat_pruefungen // Kürzel: z new Array( new myOption("Datum_zeugnis", "z.datum_zeugnis", "DATE"), new myOption("Matrikel_nr", "z.matrikel_nr", "VARCHAR"), new myOption("Pruefungsfach_1", "z.pruefungsfach_1", "INTEGER"), new myOption("Pruefungsfach_2", "z.pruefungsfach_2", "INTEGER")) Datei: stat_schema.js 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 ); Datei: stat_schema.js 29 von 71 Seite: 1 von 1 /* Hintergrundfarbe für readonly-Elemente */ .disabled { background-color:#D2D2D2; } /* Defaultlayout für anfangs nicht sichtbare Elemente */ .nonvisible { visibility:hidden; } Seite: 1 von 1 /* /////////////////////////////////////////////////////////////////////////// // File: statistik.css Version: $Revision: 1.6 $ // Autor: Hilmar Falkenberg $Date: 2004/10/05 15:47:43 $ // // Beschreibung: Cascaded Style Sheet für den Anfrageneditor //========================================================================= */ Datei: statistik.css 1 2 3 4 5 6 7 8 9 10 11 Datei: statistik.css Anhang Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Beachten Sie bitte, das gerade beim Benutzen der <em>Funktionen</em> neue Spaltenüberschriften sinnvoll sind. Z.B. sollten Sie dann ruhig <em>Summe von X</em> eingeben, um deutlich zu machen, das es sich um einen berechneten Wert handelt.</p> </td> </tr> <p>Wenn Sie sich <em>* (alle)</em> Felder ausgeben lassen, können Sie ebenfalls keine Spaltenüberschrift eingeben!</p> <tr> <td colspan="2"> <p>Mit der Spaltenüberschrift, legen Sie eben genau diese für die Ergebnisliste fest.<br /> Sie können nur für Felder die auch ausgegeben werden eine Spaltenüberschrift angeben.</p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Spaltenüberschrift</h3> </td> <title>HILFE: Spaltenüberschrift</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/alias.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu dem Texteingabefeld Spaltenüberschrift ========================================================================== --> Datei: alias.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 Datei: alias.html 30 von 71 Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Dies können Sie dazu verwenden, wenn dieses Feld nur bestimmte Kriterien erfüllen soll, d.h. einschränkende Wirkung auf das Ergebnis hat, aber nicht ausgegeben werden soll.<br /> </p> </td> </tr> <tr> <td colspan="2"> <p>Wenn Sie eine Statistik erstellen, haben Sie immer eine Ausgabe. Dazu müssen Sie ein Häkchen an dem Feld, das Sie ausgeben möchten, setzen. Ansonsten wird dieses Feld in der Ausgabe nicht berücksichtigt.<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: anzeigen</h3> </td> <title>HILFE: anzeigen</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/anzeigen.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu den Checkboxen zur Anzeige ========================================================================== --> Datei: anzeigen.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 Datei: anzeigen.html Anhang Seite: 1 von 2 Seite: 1 von 2 <li> <p><strong>Wie</strong><br /> <em>Wie</em> eignet sich ganz hervorragend zur Volltextsuche. D.h. Sie können bei einem Textfeld, den Operator <em>Wie</em> auswählen und dann auf einzelnen Teile in dem Text prüfen. Z.B. suchen Sie nach <li> <p><strong>&lt;</strong> / <strong>&lt;=</strong> / <strong>=</strong> / <strong>&gt;=</strong> / <strong>&gt;</strong> / <strong>!=</strong><br /> Dies sind die üblichen Vergleichsoperatoren, wie Sie sie aus der Schule kennen. Dabei bedeutet <strong>!=</strong> ungleich.</p> </li> <ul> <li> <p><strong>Ist NULL</strong> / <strong>Nicht NULL</strong><br /> Wenn Sie dies auswählen, wird überprüft, ob das Feld in der Datenbank leer ist, d.h. den besonderen Wert NULL enthält bzw. einfach keine Daten. Eine leere Zeichenkette, also z.B. eine Menge von Leezeichen, ist <em>ungleich</em> NULL!!!</p> </li> <p><strong>Die Vergleichsoperatoren</strong></p> <tr> <td colspan="2"> <p>Um die Bedingung nutzen zu können muss auch der entsprechende Haken gesetzt sein!<br /> Wenn Sie nur bestimmte Datensätze haben wollen, können Sie noch Bedingungen angeben, die die Datensätze erfüllen müssen, um in die Ergebnisliste aufgenommen zu werden.<br /> Eine Bedingung bezieht sich immer auf das ausgewählte Feld in dieser Spalte.<br /> Sie können keine Bedingung an das Feld &#39;<em>* (alle)</em>&#39; stellen.</p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Bedingung (oder)</h3> </td> <title>HILFE: Bedingung (oder)</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/Bedingung.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:57 $ == == Beschreibung: Hilfeseite zu den Bedingungen ========================================================================== --> Datei: Bedingung.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: Bedingung.html Seite: 2 von 2 31 von 71 Datei: Bedingung.html Seite: 2 von 2 69 <em>Matrikel_Nr Wie &#39;555%&#39;</em>, dann werden nur 70 die Studenten mit den Matrikelnummern 555000-555999 in 71 die Ergebnisliste mit aufgenommen. Oder wenn Sie nach 72 <em>Name Wie &#39;M_ller&#39;</em> suchen, erhalten Sie 73 alle mit den Namen: Müller, Möller, Miller, jedoch 74 keinen Mueller!!!<br /> 75 Also das %(Prozentzeichen) steht für 0 oder beliebig 76 viele Buchstaben und der _(Unterstrich) für genau 77 einen.</p> 78 </li> 79 80 <li> 81 <p><strong>in</strong> / <strong>nicht in</strong><br /> 82 Hier haben Sie die Möglichkeit eine ganze Liste von 83 Werten einzugeben. D.h. der Wert des ausgewählten Feldes 84 muss entweder <em>in</em> der Liste vorhanden sein, oder 85 eben <em>nicht in</em> der Liste sein.<br /> 86 Die Liste muss immer geklammert sein, also z.B.<br /> 87 <u>(1.1, 2, 3.3, 4)</u> als eine Liste von 88 (Komma)Zahlen<br /> 89 <u>(&#39;Anton&#39;, &#39;Berta&#39;, 90 &#39;Claus&#39;)</u> als Textliste<br /> 91 <u>(&#39;2001-12-24&#39;, &#39;2002-12-23&#39;)</u> als 92 Datumsliste<br /> 93 Die einzelnen Listeneinträge müssen je nach 94 Felddatentyp formatiert sein (s.u.) und sie müssen mit 95 einem Komma von einander abgetrennt sein.</p> 96 </li> 97 98 <li> 99 <p><strong>SUBQUERY</strong><br /> 100 Dies ist wohl die aller mächtigste Möglichkeit eine 101 Ergebnisliste einzuschränken. Alles was Sie hier 102 eintragen, wird <strong>ohne weitere 103 Überprüfung</strong> in die WHERE-Clause des 104 SQL-Statements mit aufgenommen!!! Sie haben hier alle 105 Möglichkeiten, die Ihnen die Datenbank zur Verfügung 106 stellt. D.h. Sie können hier z.B. Unterabfragen 107 (SUBQUERY&#39;s), oder Ausdrücke mit ANY, ALL, [NOT] 108 EXISTS, etc. erstellen.<br /> 109 Orientieren Sie sich bitte an dem vorgegebenen SQL.</p> 110 </li> 111 </ul> 112 <br /><br /> 113 114 <p><strong>Datentypen</strong><br /> 115 Je nachdem, was Sie für ein Feld ausgewählt haben, handelt es 116 sich um einen bestimmten Datentyp (<em>ganze Zahlen, 117 Kommazahlen, Text, Datum</em>).<br /> 118 Dabei ist zu beachten, das Text immer in einfachen 119 Anführungszeichen stehen muss und ggf. vorhandene 120 Anführungszeichen durch zwei Anführungszeichen ersetzt 121 werden.<br /> 122 Datumwerte können Sie auf unterschiedliche Weisen eingeben. 123 Ein Datum sollte, sofern es ein gültiges ist, automatisch in 124 die richtige Form umgewandelt werden.</p> 125 </td> 126 </tr> 127 128 <tr> 129 <td><a href="javascript:history.back();">zurück</a></td> 130 131 <td align="right"><a href="javascript:window.close();">Fenster 132 schließen</a></td> 133 </tr> 134 </table> 135 </body> 136 </html> Datei: Bedingung.html Anhang Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Besondere Bedeutung hat noch der Eintrag &#39;<em>* (alle)</em>&#39;. Wenn Sie diesen wählen und sich auch ausgeben lassen, d.h. <em>anzeigen</em> angewählt haben, so werden alle Felder von allen ausgewählten Tabellen ausgegeben!</p> </td> </tr> <p>Wenn Sie ein Feld gar nicht mehr benötigen, können Sie einfach den ersten (leeren) Eintrag auswählen, dann wird das Feld aus der Statistik entfernt.</p> <tr> <td colspan="2"> <p>In diesen Auswahllisten finden Sie gruppiert nach den Tabellen, die Sie ausgewählt haben und in alphabetischer Reihenfolge die Ihnen zur Verfügung stehenden Felder.<br /> Wählen Sie zuerst immer ein Feld aus, bevor Sie es <em>anzeigen</em> oder <em>sortieren</em> oder <em>Bedingungen</em> spezifizieren wollen.<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Feld</h3> </td> <title>HILFE: Feld</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/Felder.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu den Auswahllisten der FELDER / Attributen ========================================================================== --> Datei: Felder.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 Datei: Felder.html 32 von 71 Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Bitte vergessen Sie nicht die Statistik zu speichern!!!</p> </td> </tr> <tr> <td colspan="2"> <p>In dem Texteingabefeld &#39;Frage&#39; sollten Sie unbedingt einen eindeutigen Namen für diese Statistik vergeben.<br /> Diese Statistik können Sie dann später in der <em>Liste der gespeicherten Statistiken</em> unter genau diesem Namen / Frage wiederfinden.<br /> Sie dürfen hier auch sämtliche bekannten Sonderzeichen verwenden!<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Frage</h3> </td> <title>HILFE: Frage</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/Frage.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zum Eingabefeld: FRAGE ========================================================================== --> Datei: Frage.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 Datei: Frage.html Anhang Seite: 1 von 2 <p>Bildet die Summe über Zahlenfelder</p> <li> <strong>Summe</strong><br /> <p>/ <strong>Minimum</strong><br /> Sind beide auf alle Felder anwendbar (auch auf Textfelder!)</p> </li> <li> <strong>Maximum</strong> Seite: 1 von 2 <p>Stellt keine Funktion im eigentlichen Sinne dar, sondern alle Felder, die angezeigt werden, aber auf die keine Funktion angewendet wird, werden automatisch <em>gruppiert</em>. D.h. z.B. können Sie die Anzahl der Matrikelnummern bestimmen, und nach den Nebenfächern <em>gruppieren</em>, dann wissen Sie wieviele Studenten sich auf die verschiedenen Nebenfächer verteilen.</p> </li> <li> <strong>gruppieren</strong><br /> <p>ist berechenbar für Datum und Zahlenfelder</p> </li> <ul> <li> <strong>Durchschnitt</strong><br /> <tr> <td colspan="2"> <p>Mit diesen sogenannten <u>Aggregatfunktionen</u> ist es Ihnen möglich, z.B. eine Durchschnittsnote über alle Scheine einer<br /> Person zu bestimmen. Folgende Funktionen stehen zur Verfügung:<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Funktion</h3> </td> <title>HILFE: Funktion</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/Funktionen.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu den FUNKTIONEN ========================================================================== --> Datei: Funktionen.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: Funktionen.html Seite: 2 von 2 33 von 71 Datei: Funktionen.html Seite: 2 von 2 69 </li> 70 71 <li> 72 <strong>Anzahl</strong><br /> 73 74 <p>Zählt die <em>Anzahl</em> unterschiedlicher Werte. 75 Gibt immer eine ganze Zahl zurück.</p> 76 </li> 77 </ul> 78 </td> 79 </tr> 80 81 <tr> 82 <td><a href="javascript:history.back();">zurück</a></td> 83 84 <td align="right"><a href="javascript:window.close();">Fenster 85 schließen</a></td> 86 </tr> 87 </table> 88 </body> 89 </html> Datei: Funktionen.html Anhang Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Eine Hilfe zu den Vergleichsoperatoren und weiteren Datentypen finden Sie bei &quot;<a href="Bedingung.html">Bedingung</a>&quot;.</p> </td> </tr> <tr> <td colspan="2"> <p>Hiermit können Sie die Ergebnisliste der Funktionen noch weiter einschränken. Z.B. wenn Sie nur die Nebenfächer haben wollen, die von mehr als 10 Studenten belegt sind, dann wählen Sie die <u>Matrikelnummer</u> und <u>Nebenfachnummer</u> aus, bilden die <u>Anzahl</u> über die <u>Matrikelnummer</u>, <u>gruppieren</u> nach den <u>Nebenfächern</u> und geben als <u>Bedingung</u> für die <u>Anzahl der Matrikelnummern</u> einfach <strong>&gt;= 10</strong> ein.<br /> Beachten Sie bitte, das <em>Anzahl</em> immer eine ganze Zahl zurückgibt und <em>Durchschnitt</em> über Zahlen gebildet eine Kommazahl zurückgibt.<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Bedingung für Gruppe (oder)</h3> </td> <title>HILFE: Bedingung für Gruppe</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/GBedingung.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu den Bedingungen für eine Gruppe ========================================================================== --> Datei: GBedingung.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 Datei: GBedingung.html 34 von 71 Seite: 1 von 2 Seite: 1 von 2 <p><a href="GBedingung.html">Bedingung für Gruppe</a><br /> <a href="GBedingung.html">- oder</a><br /> </p> <p><a href="Funktionen.html">Funktion</a><br /> </p> <p><a href="Bedingung.html">Bedingung</a><br /> <a href="Bedingung.html">- oder</a><br /> </p> <td> <p><a href="join.html">verknüpfen mit</a><br /> <a href="Tabelle.html">aus Tabelle</a><br /> </p> <p><a href="anzeigen.html">anzeigen</a><br /> <a href="sortieren.html">sortieren</a><br /> <a href="alias.html">Spaltenüberschrift</a><br /> </p> </td> <p><a href="Felder.html">Feld</a><br /> <a href="Tabelle.html">aus Tabelle</a><br /> </p> <p><a href="tauschen.html">Spalten tauschen</a><br /> </p> <tr> <td valign="top"> <p><a href="Frage.html">Frage</a><br /> </p> <tr> <td> </td> </tr> <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> <body> <table border="0" width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Inhalt</h3> </td> <title>HILFE: Inhalt</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/index.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:57 $ == == Beschreibung: Die Index-Seite für die Hilfe ========================================================================== --> Datei: index.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: index.html Anhang Seite: 2 von 2 Datei: index.html Seite: 2 von 2 69 <p><a href="SQL.html">erzeugter SQL</a><br /> 70 </p> 71 </td> 72 </tr> 73 <!--tr><td></td><td valign="bottom" align="right"> 74 <a href="javascript:window.close();">Fenster schließen</a></td></tr--> 75 </table> 76 </body> 77 </html> Datei: index.html 35 von 71 Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>Sollten also Ihrer Meinung nach viel zuviele Ergebnisse geliefert werden, überprüfen Sie auf eine korrekte Verknüpfung.</p> </td> </tr> <p><strong>WARNUNG:</strong> Wenn Sie mehr als eine Tabelle auswählen und keine Verknüpfung erstellen, erhalten Sie ggf. das Kreuzprodukt beider Tabellen!!!</p> <tr> <td colspan="2"> <p>Um Verknüpfungen nutzen zu können, müssen Sie auch den Haken dazu gesetzt haben.<br /> Falls Sie zwei Tabellen ausgewählt haben und diese nun miteinander in eine Beziehung bringen möchten, z.B. alle Scheine zu einem Studenten, dann wählen Sie einmal die &#39;<u>MatrikelNr</u> &#39; aus der Tabelle &#39;<u>Studierende</u>&#39; und verknüpfen diese dann mit der &#39;<u>MatrikelNr</u>&#39; aus der Tabelle &#39;<u>Scheine</u> &#39;.<br /> Dazu sollten Sie noch den Vergleichsoperator &#39;<u>=</u>&#39; auswählen.</p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: verknüpfen mit</h3> </td> <title>HILFE: verknüpfen mit</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/join.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zum verknüpfen mit JOIN ========================================================================== --> Datei: join.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 Datei: join.html Anhang Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <p>In den Ergebnislisten selbst können Sie nur eine begrenzte Umsortierung vornehmen. Wenn Sie dort auf die Spaltenüberschrift eines Feldes klicken, wird das Ergebnis nach diesem Feld sortiert, aber nur in <strong>lexikografischer Ordnung</strong>. D.h. das z.B. Zahlen in der Reihenfolge: 1, 10, 2, 21, 3, 4, etc. sortiert werden.</p> </td> </tr> <tr> <td colspan="2"> <p>In dieser Auswahlliste, haben Sie die Möglichkeit (nur wenn das Feld auch angezeigt wird) eine auf- oder absteigende Sortierung vorzunehmen. Dabei werden Zahlen und Datum, sowie Texte in der üblichen Weise sortiert.<br /> </p> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: sortieren</h3> </td> <title>HILFE: sortieren</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/sortieren.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:57 $ == == Beschreibung: Hilfeseite zur Auswahlliste SORTIEREN ========================================================================== --> Datei: sortieren.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 Datei: sortieren.html 36 von 71 Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <tr> <td colspan="2"> <p>Dieses Feld dient nur zur Anzeige und Kontrolle für alle diejenigen, die etwas <a target="new" href="http://www.sql.org/">SQL (Structured Query Language)</a> beherrschen.<br /> </p> </td> </tr> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: erzeugter SQL</h3> </td> <title>HILFE: erzeugter SQL</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/SQL.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:57 $ == == Beschreibung: Hilfeseite zu erzeugter SQL ========================================================================== --> Datei: SQL.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 Datei: SQL.html Anhang Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <tr> <td colspan="2"> <p>Je nachdem, welches Feld Sie ausgewählt haben, erscheint der Name der dazugehörigen Tabelle. Dies dient lediglich zur Gedächtnisstütze, da manche Feldnamen sich in den verschiedenen Tabellen wiederholen. Es soll es Ihnen leichter machen, wenn Sie zwei Tabellen miteinander <em>verknüpfen</em> wollen.<br /> </p> </td> </tr> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: aus Tabelle</h3> </td> <title>HILFE: aus Tabelle</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/Tabelle.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:58 $ == == Beschreibung: Hilfeseite zu dem grau hinterlegten Feld Tabelle ========================================================================== --> Datei: Tabelle.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 Datei: Tabelle.html 37 von 71 Seite: 1 von 1 Seite: 1 von 1 <td align="right"><a href="javascript:window.close();">Fenster schließen</a></td> </tr> </table> </body> </html> <tr> <td><a href="javascript:history.back();">zurück</a></td> <tr> <td colspan="2"> <p>Falls Sie mehr als ein Feld ausgewählt haben, können Sie mit Hilfe der Buttons die Reihenfolge der Felder sehr leicht verändern.<br /> Die Felder werden in der Ergebnisliste dann in der Reihenfolge wiedergegeben, in der Sie sie in der Statistik angegeben haben.<br /> Dabei werden natürlich nur die Felder ausgegeben, bei denen Sie auch den Haken bei <em>anzeigen</em> gesetzt haben.</p> </td> </tr> <td align="right"><a href="index.html">Hilfe Inhalt</a></td> </tr> <body> <table width="370" align="center" summary=""> <tr> <td> <h3>HILFE: Spalten tauschen</h3> </td> <title>HILFE: Spalten tauschen</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ========================================================================= == File: help/tauschen.html Version: $Revision: 1.4 $ == Autor: Hilmar Falkenberg $Date: 2004/10/05 16:46:59 $ == == Beschreibung: Hilfeseite zu den SPALTEN-TAUSCHEN-BUTTONS ========================================================================== --> Datei: tauschen.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 Datei: tauschen.html Anhang Seite: 1 von 1 Seite: 1 von 1 ////////////////////////////////////////////////////////////////////////////// // löscht die Anfrage mit der STATID == nr == lfd_nr aus der Datenbank //---------------------------------------------------------------------------function deleteStat(formular, nr){ var ok = confirm("Sind Sie sicher, daß Sie die Statistik Nr." + nr + " löschen wollen?"); if(ok){ formular.doWhat.value = "delete"; formular.submit(); return true; } else return false; } ////////////////////////////////////////////////////////////////////////////// // führt die Anfrage aus und gibt das Ergebnis als HTML aus (s. Stylesheet: // stat_antwort.xsl) //---------------------------------------------------------------------------function executeStat(formular){ formular.doWhat.value = "execute"; formular.submit(); return true; } ////////////////////////////////////////////////////////////////////////////// // lädt die Anfrage in den Anfrageneditor zum bearbeiten //---------------------------------------------------------------------------function editStat(formular){ formular.doWhat.value = "edit"; formular.submit(); return true; } ////////////////////////////////////////////////////////////////////////////// // führt die Anfrage aus und gibt das Ergebnis im XML-Format zurück (s. // DocTypeDefinition: sdbdocument.dtd) //---------------------------------------------------------------------------function asXML(formular){ formular.doWhat.value = "execute"; formular.form.value = "XML"; formular.submit(); return true; } ////////////////////////////////////////////////////////////////////////////// // File: stat_verwalten.js Version: $Revision: 1.3 $ // Autor: Hilmar Falkenberg $Date: 2004/10/05 08:57:31 $ // // Beschreibung: diese Datei wird in dem Stylesheet (stat_gespeicherte.xsl) // für die Liste der gespeicherten DB-Anfragen benötigt. Es sind die // Funktionen für die Verwaltung der Anfragen implementiert, d.h. die // richtigen Aufrufparameter für das Servlet SDBStatistik, werden gesetzt //============================================================================ Datei: stat_verwalten.js 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 Datei: stat_verwalten.js 38 von 71 Seite: 1 von 3 Seite: 1 von 3 Die Beschreibung der Tabelle ********************************************************************************--> Beschreibung der ausgeführten Aktionen (update/insert/delete) ********************************************************************************--> <xsl:template match="executed"> <h3 class="highlighted"> <xsl:apply-templates /> </h3> </xsl:template> <!--**************************************************************************** Das HTML-Grundgerüst ********************************************************************************--> <xsl:template match="sdb"> <html> <head> <title> Studierenden Datenbank - gespeicherte Abfragen </title> <link rel="stylesheet" type="text/css" href="styles/general_layout.css" /> <script language="JavaScript" src="scripts/stat_verwalten.js" type="text/javascript"> </script> </head> <body> <table border="0" width="800" align="center"> <tr> <td colspan="2"> <xsl:call-template name="insertlogo" /> </td> </tr> <tr> <td align="left"> <a href="statistik.html?neu">Eine neue Statistik erstellen</a> </td> <td align="right"> <a href="Statistiken?requery=yes">Liste aktualisieren</a> </td> </tr> <tr> <td colspan="2"> <h1 style="text-align:center; margin-top:1cm; margin-bottom:1cm; Liste der zur Verfügung stehenden Abfragen</h1> </td> </tr> <tr> <td colspan="2"> <xsl:apply-templates select="executed" /> <xsl:apply-templates select="resultset/table" /> <xsl:apply-templates select="resultset/error" /> <xsl:apply-templates select="error" /> </td> </tr> </table> </body> </html> </xsl:template> <!--**************************************************************************** <?xml version="1.0" encoding="ISO-8859-1"?> <!-- $Revision: 1.5 $ $Date: 2004/09/11 19:32:47 $ --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="ISO-8859-1" indent="yes" method="html" /> <xsl:include href="logo.xsl" /> <xsl:param name="order_by_column">0</xsl:param> <!--**************************************************************************** Datei: stat_gespeicherte.xsl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_gespeicherte.xsl Anhang Seite: 2 von 3 Datei: stat_gespeicherte.xsl Seite: 2 von 3 69 <xsl:template match="table"> 70 <table border="1" cellpadding="4" cellspacing="0" width="800"> 71 <colgroup> 72 <col align="center" width="20" /> 73 <col align="center" width="50" /> 74 <col align="center" width="200" /> 75 <col align="center" width="150" /> 76 </colgroup> 77 <thead> 78 <tr class="tabelhead"> 79 <th> 80 <a><xsl:attribute 81 name="href">Statistiken?xmlparam=order_by_column:1</xsl:attribu 82 Nr</a> 83 </th> 84 <th> 85 <a><xsl:attribute 86 name="href">Statistiken?xmlparam=order_by_column:2</xsl:attribu 87 erstellt</a> 88 </th> 89 <th> 90 <a><xsl:attribute 91 name="href">Statistiken?xmlparam=order_by_column:3</xsl:attribu 92 Bezeichnung / Frage</a> 93 </th> 94 <th>Aktion</th> 95 </tr> 96 </thead> 97 <tbody> 98 <xsl:apply-templates select="../results/row" > 99 <xsl:sort select="./col[number($order_by_column)]" /> 100 </xsl:apply-templates> 101 </tbody> 102 </table> 103 <table border="0" width="800"> 104 <tr> 105 <td> 106 <a href="javascript:history.back()">zurück</a> 107 </td> 108 <td align="right"> 109 <a href="Statistiken?requery=yes">Liste aktualisieren</a> 110 </td> 111 </tr> 112 </table> 113 </xsl:template> 114 <!--**************************************************************************** 115 116 Die einzelnen Zeilen 117 ********************************************************************************--> 118 <xsl:template match="results/row"> 119 <tr> 120 <xsl:attribute name="class"> 121 <xsl:if test="0=position() mod 2">secondrow</xsl:if> 122 </xsl:attribute> 123 <form method="post" action="Statistiken"> 124 <td align="right"> 125 <xsl:value-of select="./col[1]" /> 126 </td> 127 <td align="center"> 128 <xsl:value-of select="./col[2]" /> 129 </td> 130 <td> 131 <b> 132 <xsl:value-of select="./col[3]" /> 133 </b> 134 </td> 135 <td> 136 <input type="hidden" name="STATID" > Datei: stat_gespeicherte.xsl Seite: 3 von 3 39 von 71 Datei: stat_gespeicherte.xsl Seite: 3 von 3 137 <xsl:attribute name="value"> 138 <xsl:value-of select="./col[1]" /> 139 </xsl:attribute> 140 </input> 141 <input type="hidden" name="doWhat" value="" /> 142 <input type="button" value="ausführen" 143 onClick="executeStat(this.form)" /> 144 <xsl:if test="string-length(./col[4]) > 0"> 145 <input type="button" value="bearbeiten" 146 onClick="editStat(this.form)" /> 147 </xsl:if> 148 <input type="button" value="löschen" > 149 <xsl:attribute name="onClick">deleteStat(this.form,<xsl:value-of s 150 />)</xsl:attribute> 151 </input> 152 <input type="hidden" name="form" value="" /> 153 <input type="button" value="als XML" onClick="asXML(this.form);" 154 /> 155 </td> 156 </form> 157 </tr> 158 </xsl:template> 159 </xsl:stylesheet> Datei: stat_gespeicherte.xsl Anhang Seite: 1 von 2 Seite: 1 von 2 gibt eine Navigationsleite zurück ********************************************************************************--> <xsl:template name="insertnavigation"> <table width="800" style="background-image:url(images/verlauf.jpg)" border="0" > <tr> <td align="left"> <input type="image" src="images/btn_1.gif" alt="erster Datensatz" name="nav_1" /> </td> <td align="left"> <input type="image" src="images/btn_2.gif" alt="10 Datensätze zurück" name="nav_2" /> </td> <td align="left"> <input type="image" src="images/btn_3.gif" alt="vorheriger Datensatz" name="nav_3" /> </td> <td align="center"> <input type="image" src="images/btn_4.gif" alt="gehe genau zu Datensatz Nr: " style="vertical-align:middle" name="nav_4" /> <input name="row" type="text" size="4" style="vertical-align:middle" maxlength="6"> <xsl:attribute name="value"> <xsl:value-of select="/sdb/resultset/results/row/@num" /> </xsl:attribute> </input> <font color="#FFFFFF" face="MONOSPACE"> <b> von <xsl:value-of select="/sdb/resultset/results/@count" /> <xsl:apply-templates select="row" /> </b> </font> </td> <td align="right"> <input type="image" src="images/btn_5.gif" alt="nächster Datensatz" name="nav_5" /> </td> <td align="right" > <input type="image" src="images/btn_6.gif" alt="10 Datensätze weiter" name="nav_6" /> </td> <td align="right"> <input type="image" src="images/btn_7.gif" alt="letzter Datensatz" name="nav_7" /> </td> </tr> </table> gibt die session zurück ********************************************************************************--> <xsl:template name="sessionid"> <xsl:if test="string-length(/sdb/session/text())>0">;jsessionid=<xsl:apply-tem select="/sdb/session/text()"/></xsl:if> </xsl:template> <!--**************************************************************************** gibt das Logo zurück ********************************************************************************--> <xsl:template name="insertlogo"> <img src="images/logo.jpg" alt="Studierenden Datenbank V1" border="0"> </img> </xsl:template> <!--**************************************************************************** <?xml version="1.0" encoding="ISO-8859-1"?> <!-- $Revision: 1.11 $ $Date: 2004/08/31 14:27:04 $ --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!--**************************************************************************** Datei: logo.xsl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: logo.xsl Seite: 2 von 2 40 von 71 Datei: logo.xsl Seite: 2 von 2 69 </xsl:template> 70 <!--**************************************************************************** 71 72 Darstellung evtl. Fehler 73 ********************************************************************************--> 74 <xsl:template match="error"> 75 <table bgcolor="#E9E9E9" border="2" width="800"> 76 <xsl:for-each select="error"> 77 <tr> 78 <td> 79 <h1 style="letter-spacing:3mm; text-decoration:blink; "> 80 <xsl:number count="error" format="1" level="single" />. 81 FEHLER:</h1> 82 <font style="font-family:monospace; color:red; "> 83 <xsl:value-of select="./text()" /> 84 </font> 85 </td> 86 </tr> 87 </xsl:for-each> 88 </table> 89 <a href="javascript:history.back()">zurück</a> 90 </xsl:template> 91 </xsl:stylesheet> Datei: logo.xsl Anhang Seite: 1 von 2 Seite: 1 von 2 Die Beschreibung der Tabelle ********************************************************************************--> <xsl:template match="resultset/table" > <table border="4" cellpadding="4" cellspacing="0" rules="rows" width="800"> <colgroup> <col align="right" width="10" /> <xsl:for-each select="column"> <col> <xsl:attribute name="width"> <xsl:value-of select="./@size" /> </xsl:attribute> Das HTML-Grundgerüst ********************************************************************************--> <xsl:template match="sdb"> <html> <head> <title> Studierenden Datenbank - <xsl:value-of select="formdata/frage" /></title> <link rel="stylesheet" type="text/css" href="styles/general_layout.css" /> </head> <body> <table border="0" width="800" align="center"> <tr> <td colspan="2"> <xsl:call-template name="insertlogo" /> </td> </tr> <tr> <td align="left"> <a href="statistik.html?neu">Eine neue Statistik erstellen</a> </td> <td align="right"> <a href="Statistiken?requery=yes">zu den gespeicherten Statistiken</a> </td> </tr> <tr> <td colspan="2"> <h1 style="text-align:center; margin-top:1cm; margin-bottom:1cm; <xsl:value-of select="formdata/frage" /> </h1> </td> </tr> <tr> <td colspan="2"> <xsl:apply-templates select="resultset/table" /> <xsl:apply-templates select="resultset/error" /> <xsl:apply-templates select="error" /> </td> </tr> </table> </body> </html> </xsl:template> <!--**************************************************************************** <?xml version="1.0" encoding="ISO-8859-1"?> <!-- $Revision: 1.4 $ $Date: 2004/08/31 14:27:04 $ --> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:output encoding="ISO-8859-1" indent="yes" method="html" /> <xsl:include href="logo.xsl" /> <xsl:param name="order_by_column"></xsl:param> <!--**************************************************************************** Datei: stat_antwort.xsl 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: stat_antwort.xsl Seite: 2 von 2 41 von 71 Datei: stat_antwort.xsl Seite: 2 von 2 69 </col> 70 </xsl:for-each> 71 </colgroup> 72 <tr class="tabelhead"> 73 <th align="right">#</th> 74 <xsl:for-each select="column"> 75 <th> 76 <a> 77 <xsl:attribute name="href">Statistiken?doWhat=execute&amp;xmlpa 78 select="position()" /></xsl:attribute> 79 <xsl:value-of select="./@name" /> 80 </a> 81 </th> 82 </xsl:for-each> 83 </tr> 84 <xsl:apply-templates select="../results/row" > 85 <xsl:sort select="./col[number($order_by_column)]" /> 86 </xsl:apply-templates> 87 </table> 88 <table width="800"> 89 <tr> 90 <td> 91 <a href="javascript:history.back()">zurück</a> 92 </td> 93 <td align="right"> 94 <a><xsl:attribute 95 name="href">javascript:self.print()</xsl:attribute>drucken</a> 96 </td> 97 </tr> 98 </table> 99 </xsl:template> 100 <!--**************************************************************************** 101 102 Die Beschreibung der Tabelle 103 ********************************************************************************--> 104 <xsl:template match="row"> 105 <tr> 106 <xsl:attribute name="class"> 107 <xsl:if test="0=position() mod 2">secondrow</xsl:if> 108 </xsl:attribute> 109 <td align="right"> 110 <font color="#C0C0C0"> 111 <xsl:number count="row" format="1" level="multiple" /> 112 </font> 113 </td> 114 <xsl:for-each select="col"> 115 <td> 116 <xsl:value-of select="./text()" /> 117 </td> 118 </xsl:for-each> 119 </tr> 120 </xsl:template> 121 </xsl:stylesheet> Datei: stat_antwort.xsl Anhang Seite: 1 von 2 /> /> /> /> Seite: 1 von 2 <td> <p style="text-align: right">2004-10-01 <a href="mailto:[email protected]">Hilmar Falkenberg</a> <a href="http://validator.w3.org/check?uri=referer"><img style="border:0;width:88px;height:31px" src="http://www.w3.org/Icons/valid-xhtml10" alt="Valid XHTML 1.0!" height="31" width="88" /></a></p> </td> </tr> </table> </body> <tr> <p>1. Anweisung: <textarea name="sql" cols="90" rows="7"></textarea><br 2. Anweisung: <textarea name="sql" cols="90" rows="7"></textarea><br 3. Anweisung: <textarea name="sql" cols="90" rows="7"></textarea><br 4. Anweisung: <textarea name="sql" cols="90" rows="7"></textarea><br Alle Anweisungen zu einer Transaktion zusammenfassen und <input type="submit" value="ausführen" /></p> </form> </td> </tr> <tr align="center"> <td> <form method="post" name="admin" action="Execute"> <!-- Hier könnte noch ein entsprechender Stylesheet angegeben werden, der die Ergebnisse bzw. Fehlermeldungen anzeigt. Dann sollte allerdings auch der Parameter form=xml auskommentiert werden! --> <input type="hidden" name="form" value="XML" /> <input type="hidden" name="stylesheet" value="" /> <input type="hidden" name="requery" value="yes" /> <!-- ***************************************************************** --> <tr align="center"> <td> <h3>Administratoren Seite für beliebige SQL-Anweisungen an die SDB</h3> </td> </tr> <body> <table width="800" align="center" summary="Tabelle dient nur fürs Layout"> <tr> <td><img src="images/logo.jpg" alt="Studierenden Datenbank" border="0" /> </td> </tr> <title>Administratoren Seite für beliebige SQL-Anweisungen an die SDB</title> </head> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="content-type" content="text/html; charset=ISO-8859-1" /> <meta name="author" content="Hilmar Falkenberg" /> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <!-- ======================================================================= == File: administrator.html Version: $Revision: 1.3 $ == Autor: Hilmar Falkenberg $Date: 2004/10/04 19:45:13 $ == == Beschreibung: Mit dieser Seite können bis zu vier SQL-Anweisungen in == einer Transaktion an die Studierendendatebank gesendet werden. ======================================================================== --> Datei: administrator.html 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: administrator.html 42 von 71 Datei: administrator.html 69 </html> Datei: administrator.html Anhang Seite: 2 von 2 Seite: 2 von 2 Seite: 1 von 1 /*Layout für den Tabellenkopf / * .tabelhead { background-color:# 00 C C0 C; } /*Layout für jede zweite e Zile / * .secondrow { background-color:# D9FFD9; } /*Layout für die INSERT, P D UATE, DELETE Meldungen / * .highlighted { color:# FF0000; background-color:# FFFF00; } Seite: 1 von 1 /*/////////////////////////////////////////////////////////////////////////// // File: general_layout.css Version: $Revision: 1.2 $ // Autor: Hilmar Falkenberg $Date: 2004/10/05 15:44:38 $ // // Beschreibung: a Cscaded Style Sheet für die Anzeige der Ergebnislisten //========================================================================= / * Datei: general_layout.css 1 2 3 4 5 6 7 8 9 10 11 12 13 Datei: general_layout.css 43 von 71 Seite: 1 von 1 \g \q select 'new myOption("' + trim(feld) + '","' + trim(tabelle) + '.' + trim(feld) + '","' + trim(typ) + '"),' from stat_felder order by tabelle, feld ; Seite: 1 von 1 -- dieser View soll die Tabellen darstellen, die die Benutzer zur auswahl haben -- create view stat_tabellen (name, owner) as -- select table_name, table_owner from iitables -- where system_use = 'U' -- and table_name not in ('interne_nummern','super_user','tab_status','nutzer') -- and table_name not like 'user%' -- and table_name not like 'stud%' -- and table_name not like 'stat%' -- and table_owner not in ('pra03','tomcat') --; --- hier werden alle Felder zusammengefasst, die später zur Verfügung stehen sollen -- create view stat_felder (tabelle, feld, typ, laenge, n, u, s, defaultval) as -select table_name, column_name, column_datatype, column_length, column_nulls, -column_updateable, column_system_maintained, column_default_val -from iicolumns -where table_name in (select name from stat_tabellen); --- testoutput select '<option value="' + trim(name) + '" label="' + trim(name) + '">' + trim(name) + '</option>' from stat_tabellen order by name ; Datei: javascript.sql 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 Datei: javascript.sql Anhang Seite: 1 von 1 -- zugriff auf neue Tabelle erlauben grant all on table stat_statistiken to public; commit; \g \q Seite: 1 von 1 insert into stat_statistiken (lfd_nr, datum, frage, query) values ( 3, date('now'), 'Wer sind die jüngsten Studenten?', 'SELECT s.matrikel_nr AS "Matrikel Nr.", s.name, s.vorname, s.geburtsdatum FROM s ); -- zwei einfache Abfrage einfügen insert into stat_statistiken (lfd_nr, datum, frage, query) values ( 2, date('now'), 'Wer sind die ältesten Studenten?', 'SELECT s.matrikel_nr AS "Matrikel Nr", s.name, s.vorname, s.geburtsdatum FROM st ); -- neue Tabelle anlegen create table stat_statistiken ( lfd_nr integer not null, datum date, frage varchar (100), query varchar (1000) not null, -- maximal kann es 20 Cookies geben, jeder Cookie kann maximal 20KB haben -- jedoch werden die Werte der Cookies mit der JavaScriptfunktion escape() -- noch entsprechend maskiert. Dadurch koennen ggf. auch mehr als 400KB -- an Daten entstehen. Ich bezweifele allerdings, das jemand jemals eine -- solch dermassen grosse Abfrage erstellen wird. cookie long varchar ) with page_size = 4096; -- alte Tabelle löschen -- drop table stat_statistiken; Datei: stat_statistiken.sql 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 Datei: stat_statistiken.sql 44 von 71 Datei: sdbdocument.dtd 1 <?xml version="1.0" encoding="UTF-8"?> 2 <!ELEMENT sdb (session?,formdata?,executed?,resultset*,error?)> 3 <!ELEMENT session (#PCDATA)> 4 <!ELEMENT formdata ANY> 5 <!ELEMENT executed (insert|update|delete|drop|create|grant)*> 6 <!ELEMENT insert (#PCDATA)> 7 <!ATTLIST insert count NMTOKEN #REQUIRED> 8 <!ELEMENT update (#PCDATA)> 9 <!ATTLIST update count NMTOKEN #REQUIRED> 10 <!ELEMENT delete (#PCDATA)> 11 <!ATTLIST delete count NMTOKEN #REQUIRED> 12 <!ELEMENT drop (#PCDATA)> 13 <!ELEMENT create (#PCDATA)> 14 <!ELEMENT grant (#PCDATA)> 15 <!ELEMENT resultset (statement?,table,results)> 16 <!ELEMENT statement (#PCDATA)> 17 <!ELEMENT table (column+)> 18 <!ATTLIST table columns NMTOKEN #REQUIRED> 19 <!ELEMENT column EMPTY> 20 <!ATTLIST column 21 from NMTOKEN #IMPLIED 22 label NMTOKEN #REQUIRED 23 name NMTOKEN #REQUIRED 24 size NMTOKEN #REQUIRED 25 schema NMTOKEN #IMPLIED 26 type (date|float|integer|varchar) #REQUIRED 27 writable (false|true) #REQUIRED 28 > 29 <!ELEMENT results (row*)> 30 <!ATTLIST results count NMTOKEN #REQUIRED> 31 <!ELEMENT row (col+)> 32 <!ATTLIST row num NMTOKEN #IMPLIED> 33 <!ELEMENT col (#PCDATA)> 34 <!ELEMENT error (#PCDATA|error)*> Datei: sdbdocument.dtd Anhang Seite: 1 von 1 Seite: 1 von 1 javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpSessionBindingEvent; javax.servlet.http.HttpSessionBindingListener; javax.xml.parsers.DocumentBuilder; javax.xml.parsers.DocumentBuilderFactory; javax.xml.parsers.ParserConfigurationException; org.apache.xml.serialize.OutputFormat; org.apache.xml.serialize.XMLSerializer; org.w3c.dom.DOMException; org.w3c.dom.Document; org.w3c.dom.Element; org.w3c.dom.Node; import import import import import import import import import import import import Seite: 1 von 10 /** * Objecthandle <code>execute</code> für das XML-Element: <span * class="xml">&lt;executed&gt; </span> */ /** * Objecthandle <code>error</code> für das XML-Element: <span * class="xml">&lt;error&gt; </span> */ private Element error = null; Seite: 1 von 10 /** * Ähnlich wie bei <code>doctype</code> ist dieser String für die Angabe * eines bestimmten Zeichensatzes gedacht. Defaultwert ist: "ISO-8859-1" */ private String encoding = "ISO-8859-1"; /** * Dieser String ist für eine geeignete Doctype-Definition gedacht, falls der * String nicht leer ist, wird diese dann in <code>toString()</code> in das * XML hineingeschrieben. <br /> * Eine Basis-Doctype-Definition ist <a * href="../../../web/doctypes/sdbdocument.dtd">sdbdocument.dtd </a> */ private String doctype = null; /** * Mit diesem <code>Document</code> werden alle XML-Elemente erzeugt und * auch gespeichert. */ private Document doc = null; /** * <p> * Jedes von den verwendeten Servlets <code>SDBSelect, SDBExecute, * SDBStatistik</code> * verwendet ein SDBDocument um alle Inhalte dort als XML zu speichern. * </p> * <p> * Das Dokument wird dazu an das <code>HttpSession</code> -Objekt von den * Servlets gebunden. * </p> * * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.10 $ $Date: 2004/09/23 15:31:21 $ */ public class SDBDocument implements HttpSessionBindingListener { java.io.IOException; java.io.StringWriter; java.sql.ResultSet; java.util.Enumeration; import import import import package base; Datei: SDBDocument.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBDocument.java 45 von 71 execute = null; Seite: 2 von 10 Seite: 2 von 10 /** * Fügt das XML-Element <span class="xml">&lt;formdata&gt; </span> in das * <code>Document</code> ein. * @param req Das <code>HttpServletRequest</code> aus dem alle Parameter * für das Servlet ausgelesen werden und in das <span * class="xml">&lt;formdata&gt; </span> eingefügt werden. */ public void addFormdata(HttpServletRequest req) { Element newFormdata = this.doc.createElement("formdata"); if (this.formdata != null) { this.root.replaceChild(newFormdata, this.formdata); this.formdata = newFormdata; } else { this.formdata = newFormdata; } } catch (ParserConfigurationException e) { e.printStackTrace(); } Node session = this.doc.createElement("session"); session.appendChild(this.doc.createTextNode(id)); this.root.appendChild(session); /** * Im Konstruktor wird mit einer <code>DocumentBuilderFactory</code> ein * <code>DocumentBuilder</code> erzeugt und damit dann das * <code>Document</code> doc initialisiert. Das XML-Root-Element <span * class="xml">&lt;sdb&gt; </span> wird ebenfalls erzeugt. Das <span * class="xml">&lt;session&gt; </span> Element wird als erstes Child-Element * an das Root-Element angehängt. * @param id eine JSESSIONID die in das XML-Element <span * class="xml">&lt;session&gt; </span> geschrieben wird. */ public SDBDocument(String id) { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); this.doc = builder.newDocument(); this.root = this.doc.createElement("sdb"); this.doc.appendChild(this.root); /** * Objecthandle <code>sets</code>, um auf alle eingefügten * <code>SDBResultset</code> schnellen Zugriff zu ermöglichen. */ private SDBResultset[] sets = null; /** * Objecthandle <code>root</code> für das XML-Root-Element: <span * class="xml">&lt;sdb&gt; </span> */ private Node root = null; /** * Objecthandle Liste <code>nodes</code> für die XML-Elemente: <span * class="xml">&lt;resultset&gt; </span> */ private Node[] nodes = null; /** * Objecthandle <code>formdata</code> für das XML-Element: <span * class="xml">&lt;formdata&gt; </span> */ private Element formdata = null; private Element Datei: SDBDocument.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBDocument.java Anhang Seite: 3 von 10 /** * Fügt ein XML-Element <span class="xml">&lt;resultset&gt; </span> in das * <code>Document</code> ein. Falls der String <code>sql</code> nicht * <code>null</code> ist, wird das XML-Element <span * class="xml">&lt;statement&gt; </span> in <span * class="xml">&lt;resultset&gt; </span>eingefügt. * @param rs Der <code>ResultSet</code> zum einfügen. * @param sql Der <code>String</code> für das <span * class="xml">&lt;statement&gt; </span> Element */ public void addResultSet(ResultSet rs, String sql) { // nur der 1. ResultSet muss explizit gesetzt werden if (this.sets == null) setResultSet(rs, sql); else { int size = this.sets.length; /** * Fügt ein XML-Element <span class="xml">&lt;resultset&gt; </span> in das * <code>Document</code> ein. * @param rs Der <code>ResultSet</code> zum einfügen. * @see SDBDocument#addResultSet(ResultSet, String) */ public void addResultSet(ResultSet rs) { addResultSet(rs, null); } /** * Fügt ein XML-Element <span class="xml">&lt;group&gt; </span> in das * <code>Document</code> ein. * @param g Die <code>SDBGroup</code> zum einfügen. */ public void addGroup(SDBGroup g) { this.root.appendChild(g.getGroup()); } /** * Zum manuellen setzen von dem XML-Element <span * class="xml">&lt;formdata&gt; </span> * @param name Der Name des einzufügenden Parameters * @param value Der Wert des einzufügenden Parameters * @see SDBDocument#addFormdata(HttpServletRequest) */ public void addFormdata(String name, String value) { if (this.formdata == null) { this.formdata = this.doc.createElement("formdata"); this.root.appendChild(this.formdata); } Element attrib = this.doc.createElement(name); attrib.appendChild(this.doc.createCDATASection(value)); this.formdata.appendChild(attrib); } } this.root.appendChild(this.formdata); Seite: 3 von 10 Enumeration enum = req.getParameterNames(); while (enum.hasMoreElements()) { String parameter = enum.nextElement().toString(); String[] values = req.getParameterValues(parameter); for (int i = 0; i < values.length; i++) { Element attrib = this.doc.createElement(parameter); attrib.appendChild(this.doc.createCDATASection(values[i])); this.formdata.appendChild(attrib); } } } Datei: SDBDocument.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBDocument.java 46 von 71 this.root.appendChild(this.nodes[size]); Seite: 4 von 10 return toString(); Seite: 4 von 10 /** * Gibt alle Datensätze eines Resultsets zurück * @param resultset Nummer des Resultsets * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getAll(int resultset) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getAll()); return toString(); } } /** * Gibt alle Datensätze aller Resultsets zurück * @return String Das gesamte <code>Document</code> als String * @see SDBDocument#toString() */ public String getAll() { if (hasResultSets()) for (int i = 0; i < this.sets.length; i++) refreshResultset(i, this.sets[i].getAll()); /** * Gibt den Datensatz eines Resultsets mit der absoluten Position zurück * @param resultset Nummer des Resultsets * @param absolutPosition Datensatznummer als Absolutwert * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getAbsolute(int resultset, int absolutPosition) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getAbsolute(absolutPosition)); return toString(); } /** * gibt die Anzahl der SDBResultsets zurück. * @return <code>int</code> gibt die Anzahl der <code>SDBResultset</code> * zurück. */ public int countResultSets() { if (hasResultSets()) return this.sets.length; return 0; } } } this.nodes = newnodes; this.sets = newset; newset[size] = new SDBResultset(rs, this.doc, sql); newnodes[size] = newset[size].getFirst(); for (int i = 0; i < size; i++) { newnodes[i] = this.nodes[i]; newset[i] = this.sets[i]; } SDBResultset[] newset = new SDBResultset[size + 1]; Node[] newnodes = new Node[size + 1]; Datei: SDBDocument.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: SDBDocument.java Anhang Seite: 5 von 10 /** * Gibt den nächsten Datensatz eines Resultsets zurück * @param resultset Nummer des Resultsets * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getNext(int resultset) { if (hasResultSets()) Seite: 5 von 10 /** * Gibt den letzten Datensatz eines Resultsets zurück * @param resultset Nummer des Resultsets * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getLast(int resultset) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getLast()); return toString(); } /** * Gibt den ersten Datensatz eines Resultsets zurück * @param resultset Nummer des Resultsets * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getFirst(int resultset) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getFirst()); return toString(); } /** * gibt den Encoding-Type zurück * @return <code>this.encoding</code> */ public String getEncoding() { return this.encoding; } /** * gibt die Doctype-Definition zurück * @return <code>this.doctype</code> */ public String getDoctype() { return this.doctype; } /** * gibt das <code>Document</code> zurück * @return das <code>Document</code> * @see SDBDocument#toString() */ public Document getDoc() { return this.doc; } /** * Gibt die Anzahl der Datensätze eines Resultsets zurück * @param resultset Nummer des Resultsets * @return int die Anzahl der Datensätze des Resultsets */ public int getCount(int resultset) { if (hasResultSets()) return this.sets[resultset].getCount(); return 0; } Datei: SDBDocument.java 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: SDBDocument.java 47 von 71 /** * Ist das gesamte <code>Document</code> OK? * @return boolean <code>true</code> alle Resultsets sind ok, * <code>false</code> mindestens einResultset ist nicht ok */ public boolean isValid() { boolean returnValue = true; /** * Ist ein Resultset leer? * @param resultset Nummer des Resultsets * @return boolean */ public boolean isEmpty(int resultset) { if (hasResultSets()) return this.sets[resultset].isEmpty(); return true; } /** * Wurde mindestens ein Resultset gesetzt? * @return boolean */ public boolean hasResultSets() { return this.sets != null; } Seite: 6 von 10 /** * Gibt den relativen Datensatz eines Resultsets zurück * @param resultset Nummer des Resultsets * @param relativePosition relative Position, um die der Cursor verschoben * wird. * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getRelative(int resultset, int relativePosition) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getRelative(relativePosition)); return toString(); } /** * Gibt den vorherigen Datensatz eines Resultsets zurück * @param resultset Nummer des Resultsets * @return String Das <code>Document</code> als String * @see SDBDocument#toString() */ public String getPrevious(int resultset) { if (hasResultSets()) refreshResultset(resultset, this.sets[resultset].getPrevious()); return toString(); } /** * Gibt die aktuelle Coursorposition eines Resultsets zurück * @param resultset Nummer des zu untersuchenden Resultsets * @return int die Position des Cursors */ public int getPosition(int resultset) { if (hasResultSets()) return this.sets[resultset].getPosition(); return -1; } } Seite: 6 von 10 refreshResultset(resultset, this.sets[resultset].getNext()); return toString(); Datei: SDBDocument.java 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 Datei: SDBDocument.java Anhang return returnValue; Seite: 7 von 10 } Element newError = this.doc.createElement("error"); newError.appendChild(this.doc.createTextNode(err)); this.error.appendChild(newError); /** * Setzt eine Fehlermeldung * @param err Fügt eine Fehlermeldung in das Document ein. */ public void setError(String err) { if (this.error == null) { this.error = this.doc.createElement("error"); this.root.appendChild(this.error); } /** * Setzt den Encoding-Type * @param enc zu setzender Encoding-Type */ public void setEncoding(String enc) { this.encoding = enc; } /** * Setzt den Doctype * @param dtd zu setzender Doctype */ public void setDoctype(String dtd) { this.doctype = dtd; } Seite: 7 von 10 /** * Entfernt das <span class="xml">&lt;error&gt; </span> Element aus dem * Document */ public void removeOldErrors() { if (this.error != null) this.root.removeChild(this.error); this.error = null; } /** * Ersetzt ein <span class="xml">&lt;resultset&gt; </span> * @param number Nummer des zu ersetzenden <span * class="xml">&lt;resultset&gt; </span> * @param newResultset neuer <span class="xml">&lt;resultset&gt; </span> */ private void refreshResultset(int number, Node newResultset) { try { this.root.replaceChild(newResultset, this.nodes[number]); this.nodes[number] = newResultset; } catch (DOMException e) { e.printStackTrace(); } } } if (this.sets != null) { int i = 0; while (returnValue && i < this.sets.length) returnValue = this.sets[i].isValid(); } else return false; Datei: SDBDocument.java 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 Datei: SDBDocument.java 48 von 71 Seite: 8 von 10 Seite: 8 von 10 /** * Gibt das Dokument als String im XML-Format zurück. Dabei hat jedes * Dokument in etwa folgende Struktur: * <ul> * <span class="xml">&lt;sdb&gt; </span> * <ul> * <span class="xml">&lt;session&gt; </span> <span class="data">eine * JSESSIONID </span> <span class="xml">&lt;/session&gt; </span> <br />[ * <span class="xml">&lt;formdata&gt; </span> <br /> * <ul> * [&lt;PARAMETER&gt;Daten dieses Paramters, der an das Servlet geschickt * wurde&lt;/ PARAMETER&gt;]* <br /> * </ul> * <span class="xml">&lt;/formdata&gt; </span>]? <br />[ <span * class="xml">&lt;resultset&gt; </span> <br /> * <ul>[ <span class="xml">&lt;statement&gt; </span> <span * class="data">select * from studierende </span> <span * class="xml">&lt;/statement&gt; </span>]? <br /> * <span class="xml">&lt;table columns=&quot; </span> <span * class="data">Anzahl der Spalten </span> <span class="xml">&quot;&gt; * </span> <br /> * <ul>[ <span class="xml">&lt;column name=&quot; </span> <span * class="data">Spaltenname </span> <span class="xml">&quot; size=&quot; * </span> <span class="data">Datenfeldgr&ouml;&szlig;e </span> <span * class="xml">&quot; type=&quot; </span> <span class="data">Datentyp </span> * <span class="xml">&quot; writable=&quot; </span> <span class="data">true | * false </span> <span class="xml">&quot;/&gt; </span>]+ <br /> * </ul> * <span class="xml">&lt;/table&gt; </span> <br /> } this.root.appendChild(this.nodes[0]); this.sets[0] = new SDBResultset(rs, this.doc, sql); this.nodes[0] = this.sets[0].getFirst(); /** * Setzt den ersten <code>ResultSet</code> im Document. * @param rs Erster <code>ResultSet</code> der in das Document eingefügt * wird. * @param sql Das SQL-Statement, das den <code>ResultSet</code> erzeugt * hat. * @see SDBDocument#addResultSet(ResultSet, String) */ private void setResultSet(ResultSet rs, String sql) { this.sets = new SDBResultset[1]; this.nodes = new Node[1]; } Element newExecute = this.doc.createElement(exe); if (count >= 0) newExecute.setAttribute("count", String.valueOf(count)); newExecute.appendChild(this.doc.createTextNode(msg)); this.execute.appendChild(newExecute); /** * Fügt ein <span class="xml">&lt;executed&gt; </span> in das Document ein, * bzw. ergänzt die bisherigen Meldungen. * @param exe Was wurde ausgeführt? * @param msg Welche Meldung soll angezeigt werden? * @param count Wieviele Datensätze sind betroffen? */ public void setExecute(String exe, String msg, int count) { if (this.execute == null) { this.execute = this.doc.createElement("executed"); this.root.appendChild(this.execute); } Datei: SDBDocument.java 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 Datei: SDBDocument.java Anhang Seite: 9 von 10 Seite: 9 von 10 /** * Gibt einfach alle Resourcen wieder frei. * @param arg0 wird nicht verwendet, ist vom Interface vorgegeben * @see javax.servlet.http.HttpSessionBindingListener#valueUnbound(javax.servlet. * arg0) */ /** * Nur für das Interfaces implementiert. * @param arg0 wird nicht verwendet, ist vom Interface vorgegeben * @see javax.servlet.http.HttpSessionBindingListener#valueBound(javax.servlet.ht * arg0) */ public void valueBound(HttpSessionBindingEvent arg0) { // was soll schon großartiges passieren? } } try { XMLSerializer serializer = new XMLSerializer(writer, format); serializer.serialize(this.doc); return writer.getBuffer().toString(); } catch (IOException e) { return e.toString(); } if (this.doctype != null) { format.setDoctype(null, this.doctype); format.setStandalone(false); } else format.setStandalone(true); if (this.encoding != null) format.setEncoding(this.encoding); * <span class="xml">&lt;results count=&quot; </span> <span * class="data">Anzahl der Datens&auml;tze </span> <span * class="xml">&quot;&gt; </span> <br /> * <ul>[ <span class="xml">&lt;row num=&quot; </span> <span * class="data">Datensatznummer </span> <span class="xml">&quot;&gt; </span> * <br /> * <ul>[ <span class="xml">&lt;col&gt; </span> <span * class="data">irgendwelche Daten </span> <span class="xml">&lt;/col&gt; * </span>]+ <br /> * </ul> * <span class="xml">&lt;/row&gt; </span>]* <br /> * </ul> * <span class="xml">&lt;/results&gt; </span> <br /> * </ul> * <span class="xml">&lt;/resultset&gt; </span>]* <br />[ <span * class="xml">&lt;error&gt; </span> <br /> * <ul>[ <span class="xml">&lt;error&gt; </span> <span class="data">eine * Fehlermeldung </span> <span class="xml">&lt;/error&gt; </span>]+ <br /> * </ul> * <span class="xml">&lt;/error&gt; </span>]? <br /> * </ul> * <span class="xml">&lt;/sdb&gt; </span> <br /> * </ul> * vgl. <a href="../../../web/doctypes/sdbdocument.dtd">sdbdocument.dtd </a> * @see SDBDocument#doctype * @see java.lang.Object#toString() */ public String toString() { StringWriter writer = new StringWriter(); OutputFormat format = new OutputFormat(); format.setIndenting(true); Datei: SDBDocument.java 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 Datei: SDBDocument.java 49 von 71 Datei: SDBDocument.java 613 public void valueUnbound(HttpSessionBindingEvent arg0) { 614 this.doc = null; 615 this.doctype = null; 616 this.encoding = null; 617 this.nodes = null; 618 this.root = null; 619 this.sets = null; 620 } 621 }> Datei: SDBDocument.java Anhang Seite: 10 von 10 Seite: 10 von 10 org.w3c.dom.Document; org.w3c.dom.Element; org.w3c.dom.Node; org.w3c.dom.NodeList; Seite: 1 von 2 /** * Fügt ein Element in die Liste ein. * @param element das eingefügt wird */ void addElement(Element element) { this.lastindex++; if (this.list.length <= this.lastindex) Seite: 1 von 2 /** * Standardkonstruktor, legt neues Element[] mit Kapazität = * INITIANALCAPACITY an. * @param document zum erzeugen von neuen <code>Element</code> Objekten. */ public SDBElementList(Document document) { this.doc = document; this.list = new Element[INITIANALCAPACITY]; } /** * <code>root</code>, Das Root-Element, an das die anderen Elemente als * Child angehängt werden. */ protected Element root = null; /** * <code>list</code>, Array für die Zwischenspeicherung der * <code>Element</code> Objekte */ protected Element[] list = null; /** * <code>lastindex</code>, Index für des letzten belegten Feldes im Array */ protected int lastindex = -1; /** * <code></code>, Document zum erzeugen von neuen <code>Element</code> * Objekten. */ protected Document doc = null; /** * Iinitialgröße des verwendeten Array <code>INITIANALCAPACITY</code>. * Default: 10 */ public static int INITIANALCAPACITY = 10; /** * <p> * Dynamische Liste für <code>Element</code> Objekte. * </p> * <p> * Wenn die Kapazität nicht ausreicht, wird die Liste verdoppelt. Da sie nur * gefüllt wird und nie Elemente entnommen werden, ist keine Funktion zum * Halbieren vorgesehen. Lediglich, wenn die Liste fertig gefüllt ist, kann mit * <code>trimArray()</code> die Liste auf eine optimale Größe getrimmt werden. * </p> * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.3 $ $Date: 2004/09/16 14:27:24 $ */ public class SDBElementList { import import import import package base; Datei: SDBElementList.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBElementList.java 50 von 71 this.list[this.lastindex] = element; this.list = newlist; Seite: 2 von 2 } this.list = newlist; Seite: 2 von 2 /** * Passt das Array der Liste optimal an, d.h. das Array wird so groß, wie * Elemente in der Liste gespeichert sind. */ protected void trimArray() { Element[] newlist = new Element[this.lastindex + 1]; for (int i = 0; i < newlist.length; i++) newlist[i] = this.list[i]; /** * Ist die Liste leer? * @return boolean, true->Liste ist leer, false->Liste ist nicht leer */ public boolean isEmpty() { return this.lastindex == -1; } /** * Gibt das Basis-Document zurück * @return Document, das Basis-Document */ public Document getDocument() { return this.doc; } /** * Gibt die Anzahl der Elemente zurück * @return int, Anzahl der Elemente */ public int getCount() { return this.lastindex + 1; } } /** * Vergrößert das Array um <code>size</code> * @param size größe um die das Array vergrößert wird. */ protected void enlargeArray(int size) { Element[] newlist = new Element[this.list.length + size]; for (int i = 0; i < this.lastindex; i++) newlist[i] = this.list[i]; /** * Löscht alle Child-Elements von dem Root-Element */ protected void clear() { NodeList l = this.root.getChildNodes(); int i = 0; Node n = l.item(i); while (n != null) { this.root.removeChild(n); i++; n = l.item(i); } } } enlargeArray(this.lastindex); Datei: SDBElementList.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 } Datei: SDBElementList.java Anhang Seite: 1 von 4 Seite: 1 von 4 /** * Erzeugt eine neue Gruppe mit dem Root-Element <span * class="xml">&lt;group&gt; </span>und den Datensätzen des ResultSets zur * Auswahl * @param document zum Erzeugen der XML-Elemente /** * Erzeugt eine neue Gruppe mit dem Root-Element <span * class="xml">&lt;group&gt; </span>. <br /> * Standardmäßig ist die Gruppe eine <code>SELECT</code> Gruppe, d.h. eine * Auswahlliste. * @param document zum Erzeugen der XML-Elemente */ public SDBGroup(Document document) { super(document); this.root = this.doc.createElement("group"); setType(SELECT); //wird als Defaultwert genommen } /** * <code>subgroup</code> stellt eine Untergruppe bei gruppierten * Auswahllisten dar */ private Element subgroup = null; /** * <code>multiple</code> gibt an, ob mehrfachauswahlen möglich sind */ private boolean multiple = false; /** * <code>grouped</code> gibt an, ob eine <code>SELECT</code> Auswahlliste * gruppiert sein soll */ private boolean grouped = false; /** * <code>CHECKBOX</code> entspricht dem HTML-Tag */ public static final int CHECKBOX = 3; //"checkbox"; /** * <code>RADIO</code> entspricht dem HTML-Tag */ public static final int RADIO = 2; //"radio"; /** * <code>SELECT</code> entspricht dem HTML-Tag */ public static final int SELECT = 1; //"select"; DEFAULT /** * Eine XML-Darstellung von verschiedenen Gruppen: * <p> * <code>CHECKBOX</code> 'Häckchen-Kiste' <br /> * <code>RADIO</code> 'Entweder oder' Auswahlpunkte <br /> * <code>SELECT</code> 'aufklappbare Auswahlliste' * </p> * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.3 $ $Date: 2004/09/16 14:27:23 $ */ public class SDBGroup extends SDBElementList { import org.w3c.dom.Document; import org.w3c.dom.Element; import java.sql.ResultSet; import java.sql.SQLException; package base; Datei: SDBGroup.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBGroup.java 51 von 71 Seite: 2 von 4 /** * Gibt den Gruppennamen zurück * @return der Gruppenname Seite: 2 von 4 /** * Gibt das vollständige <span class="xml">&lt;group&gt; </span>Element * zurück * @return Element das <span class="xml">&lt;group&gt; </span>Element */ public Element getGroup() { return this.root; } /** * Legt fest, für welche Spalten diese Gruppe anwendbar sein soll. * @param colname Spaltenname zu dem die Gruppe gehört */ public void forColumn(String colname) { Element col = this.doc.createElement("column"); col.setAttribute("name", colname); this.root.appendChild(col); } } if (isGrouped()) this.subgroup.appendChild(ge.getElement()); else this.root.appendChild(ge.getElement()); /** * Fügt eine Auswahloption in die Gruppe bzw. aktuelle Untergruppe ein * @param ge Auswahloption die eingefügt werden soll */ protected void addElement(SDBGroupElement ge) { super.addElement(ge.getElement()); } try { // die einzelnen Auswahlmöglichkeiten eintragen while (rs.next()) { String key = rs.getString("KEY"); String val = rs.getString("VAL"); SDBGroupElement element = new SDBGroupElement(this.doc, key, val); addElement(element); } rs.close(); rs.getStatement().close(); } catch (SQLException e) { Element err = this.doc.createElement("error"); err.appendChild(this.doc.createTextNode(e.toString())); addElement(err); } // für welche Spalten des zugehörigen Stylesheet bzw. ResultSet soll // diese Gruppe sein for (int i = 0; forColumns != null && i < forColumns.length; i++) forColumn(forColumns[i]); * @param rs mit zwei Spalten (<code>KEY</code> und <code>VALUE</code>) * @param name der Gruppe, zum zusammenhalten von Checkboxen und Radiobuttons * @param forColumns eine Stringliste, in der die Spaltennamen eingetragen * werden sollen, für die diese Gruppe eine Anwenderunterstützung sein soll. */ public SDBGroup(Document document, ResultSet rs, String name, String[] forColumns) { this(document); setName(name); Datei: SDBGroup.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBGroup.java Anhang Seite: 3 von 4 /** /** * Setzt den Namen einer Gruppe * @param namestr der neue Gruppenname */ public void setName(String namestr) { this.root.setAttribute("name", namestr); } /** * Schaltet Mehrfachauswahl ein oder aus * @param multi */ public void setMultiple(boolean multi) { this.multiple = multi; if (multi) this.root.setAttribute("multiple", "1"); else this.root.setAttribute("multiple", "0"); } Seite: 3 von 4 /** * Eröffnet eine neue Untergruppe, in die ggf. die nächsten Options-Elemente * einegefügt werden * @param group neuer Untergruppenname */ public void newSubgroup(String group) { this.grouped = true; this.root.setAttribute("grouped", "1"); this.subgroup = this.doc.createElement("subgroup"); this.subgroup.setAttribute("name", group); this.root.appendChild(this.subgroup); } /** * Gibt an, ob Mehrfachauswahlen erlaubt sind * @return true->Mehrfachauswahlen sind erlaubt, false->Mehrfachauswahlen * sind nicht erlaubt */ public boolean isMultiple() { return this.multiple; } /** * Gibt zurück, ob die Gruppe Untergruppen hat oder nicht * @return true->Gruppe hat Untergruppen, false->Gruppe hat keine * Untergruppen */ public boolean isGrouped() { return this.grouped; } /** * Gibt den Gruppentyp zurück * @return Typ der Gruppe * @see SDBGroup#CHECKBOX * @see SDBGroup#RADIO * @see SDBGroup#SELECT */ public String getType() { return this.root.getAttribute("type"); } */ public String getName() { return this.root.getAttribute("name"); } Datei: SDBGroup.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBGroup.java 52 von 71 } switch (typ) { case CHECKBOX: type = "checkbox"; break; case RADIO: type = "radio"; break; default: type = "select"; } this.root.setAttribute("type", type); * Legt den Typ einer Gruppe fest * @param typ der zu setzende Typ * @see SDBGroup#CHECKBOX * @see SDBGroup#RADIO * @see SDBGroup#SELECT */ public void setType(int typ) { String type; Datei: SDBGroup.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 } Datei: SDBGroup.java Anhang Seite: 4 von 4 Seite: 4 von 4 Seite: 1 von 2 this.root.appendChild(k); this.root.appendChild(v); /** * Setzt diese Gruppen-Option als Ausgewählt. <br /> * <span class="xml">&lt;e selected="1"&gt; </span> */ /** * Gibt diese Gruppen-Option zurück * @return Element die Gruppen-Option */ public Element getElement() { return this.root; } } k.appendChild(this.doc.createTextNode(key.trim())); v.appendChild(this.doc.createTextNode(val.trim())); Element k = this.doc.createElement("k"); Element v = this.doc.createElement("v"); Seite: 1 von 2 /** * <p> * Standardkonstruktor, erzeugt die vollständige Gruppen-Option: * </p> * <p> * <span class="xml">&lt;e&gt; </span> * <ul> * <span class="xml">&lt;k&gt; </span> <span class="data">KEY-Wert </span> * <span class="xml">&lt;/k&gt; </span> <br /> * <span class="xml">&lt;v&gt; </span> <span class="data">VALUE-Wert </span> * <span class="xml">&lt;/v&gt; </span> <br /> * </ul> * <span class="xml">&lt;/e&gt; </span> * </p> * @param document zum erzeugen der XML-Elemente * @param key Wert des Schlüsselelements als String * @param val Wert des Werteelelements als String */ public SDBGroupElement(Document document, String key, String val) { this.doc = document; this.root = this.doc.createElement("e"); /** * <code>root</code> das Root-Element <span class="xml">&lt;e&gt; </span> */ protected Element root = null; /** * <code>doc</code> zum erzeugen der Key bzw. Value Elemente */ protected Document doc = null; /** * Stellt eine XML-Gruppen-Option <span class="xml">&lt;e&gt; </span>bestehend * aus einem Key <span class="xml">&lt;k&gt; </span>und einem Value <span * class="xml">&lt;v&gt; </span> dar. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.3 $ $Date: 2004/09/16 14:27:24 $ */ public class SDBGroupElement { import org.w3c.dom.Document; import org.w3c.dom.Element; package base; Datei: SDBGroupElement.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBGroupElement.java 53 von 71 public void setSelected() { this.root.setAttribute("selected", "1"); } Datei: SDBGroupElement.java 69 70 71 72 } Datei: SDBGroupElement.java Anhang Seite: 2 von 2 Seite: 2 von 2 Seite: 1 von 2 /** * Gibt die aktuelle Cursorposition zurück * @return int, Position des Cursors Seite: 1 von 2 /** * Gibt das von der aktuellen Position aus gesehen nächste Element des * ResultSets zurück * @return Element nächstes Element des ResultSets */ public Element getNext(); /** * Gibt das letzte Element des ResultSets zurück * @return Element letztes Element des ResultSets */ public Element getLast(); /** * Gibt das erste Element des ResultSets zurück * @return Element erstes Element des ResultSets */ public Element getFirst(); /** * Gibt das Element an der aktuellen Position des Cursors im ResultSet zurück * @return Element, von der aktuellen Position */ public Element getCurrentRow(); /** * Gibt die Anzahl der Datensätze zurück * @return int die Anzahl der Datensätze */ public int getCount(); /** * Gibt ein Element mit allen Datensätzen zurück * @return Element mit allen Datensätzen */ public Element getAll(); /** * <p> * Interface für die zwischengespeicherten Resultsets * </p> * <p> * Da der verwendete JDBC-Treiber von CA Ingres nicht das vorwärts <strong>und * </strong> rückwärts durchlaufen eines Reslutsets gestattet, müssen diese für * die Funktionalität einer Navigationsleiste zwischengespeichert werden. * Klassen die dieses Interface unterstützen sollten dafür ausreichen. * </p> * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.3 $ $Date: 2004/09/16 14:27:23 $ */ public interface SDBResults { /** * Gibt das Element an der absoluten Position im ResultSet zurück * @param absolutPosition des Elements was zurückgegeben wird * @return Element, das von der absoluten Position * @throws IndexOutOfBoundsException, falls die angegebene Position * außerhalb, der Feldgrenzen liegt */ public Element getAbsolute(int absolutPosition) throws IndexOutOfBoundsException; import org.w3c.dom.Element; package base; Datei: SDBResults.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBResults.java 54 von 71 Seite: 2 von 2 /** * Gibt an, ob der ResultSet leer ist, oder nicht * @return boolean, true->leer, false->nicht leer */ public boolean isEmpty(); Seite: 2 von 2 /** * Gibt das von der aktuellen Position aus gesehen um die relative Position * versetzte Element des ResultSets zurück * @param relativePosition um die der Cursor weiterbewegt wird. * @return Element, von der relativen Position */ public Element getRelative(int relativePosition); /** * Gibt das von der aktuellen Position aus gesehen vorherige Element des * ResultSets zurück * @return Element vorherige Element des ResultSets */ public Element getPrevious(); */ public int getPosition(); Datei: SDBResults.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 } Datei: SDBResults.java Anhang Seite: 1 von 6 /** Seite: 1 von 6 /** * Standardkonstruktor, erzeugt ein neues <span class="xml">&lt;resultset&gt; * </span>Element in dem übergebenen <code>Document</code> * @param resultset aus dem die Daten gewonnen werden * @param document das die Elemente erzeugt * @param sql für das <span class="xml">&lt;statement&gt; </span> Element * @see SDBResultset#SDBResultset(ResultSet, Document) */ public SDBResultset(ResultSet resultset, Document document, String sql) { init(resultset, document, sql); } /** * Standardkonstruktor, erzeugt ein neues <span class="xml">&lt;resultset&gt; * </span>Element in dem übergebenen <code>Document</code> * @param resultset aus dem die Daten gewonnen werden * @param document das die Elemente erzeugt * @see SDBResultset#SDBResultset(ResultSet, Document, String) */ public SDBResultset(ResultSet resultset, Document document) { init(resultset, document, null); } /** * <code>valid</code> gibt an, ob der Resultset ok ist */ private boolean valid = false; /** * <code>root</code> das Root-Element <span class="xml">&lt;resultset&gt; * </span> */ private Element root = null; /** * <code>results</code> speichert den eigentlichen ResultSet */ private SDBResultsImpl results = null; /** * <code>doc</code> zum erzeugen weiterer Elemente */ private Document doc = null; /** * <code>currentnode</code> aktuelles Element, welches ggf. ausgetauscht * wird. */ private Element currentnode = null; /** * Stellt ein XML: <span class="xml">&lt;resultset&gt; </span> Element dar. * * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.4 $ $Date: 2004/09/16 14:27:24 $ */ public class SDBResultset implements SDBResults { import org.w3c.dom.Document; import org.w3c.dom.Element; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; package base; Datei: SDBResultset.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBResultset.java 55 von 71 Seite: 2 von 6 Seite: 2 von 6 /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem Datensatz mit der übergebenen Nummer). * @see base.SDBResults#getAbsolute(int) } } } catch (SQLException e) { setError(e.toString()); } column.setAttribute("writable", String.valueOf(rsmd.isDefinitelyWritable(i))); table.appendChild(column); /////////////////////////////////////////////////////////////////// // Anfangsbuchstaben großschreiben, die DB macht sonst alles klein /////////////////////////////////////////////////////////////////// String label = rsmd.getColumnLabel(i); char first = label.charAt(0); label = label.replaceFirst(String.valueOf(first), String.valueOf(Character.toUpperCase(first))); /////////////////////////////////////////////////////////////////// column.setAttribute("label", label); //Beschreibung der einzelnen Spalten des ResultSets for (int i = 1; i <= rsmd.getColumnCount(); i++) { Element column = this.doc.createElement("column"); column.setAttribute("name", rsmd.getColumnName(i)); column.setAttribute("type", rsmd.getColumnTypeName(i)); // Falls die Datenbank bzw. der JDBC-Treiber die folgenden Attribute // nicht unterstützt, werden sie auch nicht im XML aufgeführt if (rsmd.getTableName(i) != null && rsmd.getTableName(i).trim().length() > 0) { column.setAttribute("from", rsmd.getTableName(i)); } if (rsmd.getSchemaName(i) != null && rsmd.getSchemaName(i).trim().length() > 0) { column.setAttribute("schema", rsmd.getSchemaName(i)); } column.setAttribute("size", Integer.toString(rsmd.getColumnDisplaySize(i))); /** * Fügt eine Tabellenbeschreibung in das <span class="xml">&lt;resultset&gt; * </span> Element ein. * @param rs ResultSet, von dem die Metadata für die Tabellenbeschreibung * abgefragt werden */ private void addTable(ResultSet rs) { try { ResultSetMetaData rsmd = rs.getMetaData(); Element table = this.doc.createElement("table"); table.setAttribute("columns", Integer.toString(rsmd.getColumnCount())); this.root.appendChild(table); * Fügt das <span class="xml">&lt;statement&gt; </span> Element ein, falls * eine SQL-Anweisung im Konstruktor mitübergeben wurde * @param statement SQL-Select-Statement bzw. der Text für das <span * class="xml">&lt;statement&gt; </span> Element */ private void addStatement(String statement) { if (statement != null) { Element stm = this.doc.createElement("statement"); this.root.appendChild(stm); stm.appendChild(this.doc.createTextNode(statement)); } } Datei: SDBResultset.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBResultset.java Anhang Seite: 3 von 6 /** * Gibt die Position des Cursors zurück. * @see base.SDBResults#getPosition() Seite: 3 von 6 /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem nächsten Datensatz). * @see base.SDBResults#getNext() */ public Element getNext() { setResults(this.results.getNext()); return this.root; } /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem letzten Datensatz). * @see base.SDBResults#getLast() */ public Element getLast() { setResults(this.results.getLast()); return this.root; } /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem ersten Datensatz). * @see base.SDBResults#getFirst() */ public Element getFirst() { setResults(this.results.getFirst()); return this.root; } /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem aktuellen Datensatz). * @see base.SDBResults#getCurrentRow() */ public Element getCurrentRow() { setResults(this.results.getCurrentRow()); return this.root; } /** * Gibt die Anzahl der Datensätze zurück. * @see base.SDBResults#getCount() */ public int getCount() { return this.results.getCount(); } /** * Gibt alle Datensätze innerhalb eines <span class="xml">&lt;resultset&gt; * </span> Elements zurück. * @see base.SDBResults#getAll() */ public Element getAll() { setResults(this.results.getAll()); return this.root; } */ public Element getAbsolute(int absolutPosition) throws IndexOutOfBoundsException { setResults(this.results.getAbsolute(absolutPosition - 1)); return this.root; } Datei: SDBResultset.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBResultset.java 56 von 71 Seite: 4 von 6 // solange der Cursor nicht am Ende ist... while (resultset.next()) { Seite: 4 von 6 /** * <p> * Speichert die Daten eines ResultSets in einer Liste ( * <code>SDBResultsImpl</code>) als XML-Elemente. * </p> * <strong>ACHTUNG! Nebeneffekt: </strong> der übergebene ResultSet und sein * Statement werden geschlossen, da der jetzige JDBC-Treiber sowieso keine * Operation zulässt, die den Cursor zurücksetzt. Und da hier zum * zwischenspeichern der Daten der ResultSet einmal ganz durchlaufen wird, * ist der Cursor dann am Ende. * @param resultset der ResultSet, dessen Daten als XML-Elemente gespeichert * werden sollen. */ private void initResults(ResultSet resultset) { // neue ElementList anlegen this.results = new SDBResultsImpl(this.doc); if (resultset != null) { try { int colCount = resultset.getMetaData().getColumnCount(); } addStatement(statement); addTable(resultset); initResults(resultset); /** * Initialisiert das <span class="xml">&lt;resultset&gt; </span>Element, d.h. * erzeugt das Root-Element <span class="xml">&lt;resultset&gt; </span> und * fügt die Elemente <span class="xml">&lt;statement&gt; </span> und <span * class="xml">&lt;table&gt; </span> ein. Das Element <span * class="xml">&lt;results&gt; </span> mit den eigentlichen Daten wird erst * mit Aufruf einer der <code>get</code> -Methoden erzeugt. * @param resultset der Darzustellende ResultSet * @param document das Document in das der ResultSet gehört * @param statement ggf. eine SQL-Anweisung, für das <span * class="xml">&lt;statement&gt; </span> */ private void init(ResultSet resultset, Document document, String statement) { this.doc = document; this.root = this.doc.createElement("resultset"); /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück. Datensatz mit der relativen Position. * @see base.SDBResults#getRelative(int) */ public Element getRelative(int relativePosition) { setResults(this.results.getRelative(relativePosition)); return this.root; } /** * Gibt das <span class="xml">&lt;resultset&gt; </span> Element mit genau * einem Datensatz zurück (dem vorhergehenden Datensatz). * @see base.SDBResults#getPrevious() */ public Element getPrevious() { setResults(this.results.getPrevious()); return this.root; } */ public int getPosition() { return this.results.getPosition(); } Datei: SDBResultset.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: SDBResultset.java Anhang } } catch (SQLException e) { setError(e.toString()); this.valid = false; } // ACHTUNG: der ResultSet (und sein Statement) werden immer // geschlossen resultset.close(); resultset.getStatement().close(); } this.valid = true; // damit nicht zuviel Speicher verbraucht wird this.results.trimArray(); this.currentnode = this.doc.createElement("error"); Seite: 5 von 6 /** * Erzeugt eine Fehlermeldung in dem <span class="xml">&lt;resultset&gt; * </span> Element * @param msg die Meldung für das <span class="xml">&lt;error&gt; </span> * Element */ private void setError(String msg) { this.valid = false; if (this.currentnode != null) this.root.removeChild(this.currentnode); /** * Gibt zurück, ob der ResultSet ok ist, d.h. beim auslesen keine * <code>SQLException</code> aufgetreten sind. * @return Returns the valid. */ public boolean isValid() { return this.valid; } /** * Gibt zurück, ob der ResultSet leer ist * @see base.SDBResults#isEmpty() */ public boolean isEmpty() { return this.results.isEmpty(); } } Seite: 5 von 6 // füge die einzelnen Spalten in die Zeile ein -- <col></col> for (int i = 1; i <= colCount; i++) { // je nachdem, wie die Spalte heißt, wird entweder explizit // nach einem Date(), Time(), oder Object() gefragt. // So wird dann ein gutes Datum bzw. Zeitformat bei der Aus// gabe produziert. Siehe auch: SDBRow.addColumn(); // // Ingres JDBC-Treiber gibt SQL-DATE-Felder immer als // JAVA-Timestamp zurück!!! Die haben kein schönes Format. String label = resultset.getMetaData().getColumnLabel(i); if (label.toUpperCase().indexOf("DATUM") >= 0) r.addColumn(resultset.getDate(i)); else if (label.toUpperCase().indexOf("ZEIT") >= 0) r.addColumn(resultset.getTime(i)); else r.addColumn(resultset.getObject(i)); } // </row> this.results.addElement(r); // ... lege eine neue Zeile an -- <row> SDBRow r = new SDBRow(this.doc); Datei: SDBResultset.java 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: SDBResultset.java 57 von 71 Seite: 6 von 6 } this.currentnode = res; this.root.appendChild(res); Seite: 6 von 6 /** * Setzt das <span class="xml">&lt;results&gt; </span>Element auf das * übergebene. D.h. das alte wird ersetzt. * @param res neues <span class="xml">&lt;results&gt; </span>Element das * gesetzt werden soll. */ private void setResults(Element res) { if (this.currentnode != null) this.root.removeChild(this.currentnode); } this.currentnode.appendChild(this.doc.createTextNode(msg)); this.root.appendChild(this.currentnode); Datei: SDBResultset.java 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 } Datei: SDBResultset.java Anhang Seite: 1 von 3 Seite: 1 von 3 /** * Gibt das <span class="xml">&lt;results&gt; </span>Element mit allen * vorhandenen Datensätzen zurück. Löscht dabei alle alten Childelemente. * @see base.SDBResults#getAll() */ } // Anzahl der Datensätze in dem Attribut "count" von <results> festhalten this.root.setAttribute("count", String.valueOf(getCount())); return this.root; // wenn nicht leer, dann neues <row>-Element einfügen if (this.lastindex >= 0) { Element row = this.list[absolutPosition]; row.setAttribute("num", String.valueOf(absolutPosition + 1)); this.root.appendChild(row); this.position = absolutPosition; } /** * Gibt das <span class="xml">&lt;results&gt; </span>Element zurück. Löscht * dabei alle Childelemente aus <span class="xml">&lt;results&gt; </span> und * fügt nur den Datensatz mit der übergebenen Nummer ein. * @param absolutPosition die entsprechende Datensatznummer * @see base.SDBResults#getAbsolute(int) */ public Element getAbsolute(int absolutPosition) throws IndexOutOfBoundsException { clear(); // alte Childelemente löschen /** * Fügt ein <span class="xml">&lt;row&gt; </span>Element in die Liste ein. * @param row Das <span class="xml">&lt;row&gt; </span>Element in Form eines * <code>SDBRow</code> Objektes, das eingefügt werden soll * @see SDBElementList#addElement(Element) */ protected void addElement(SDBRow row) { super.addElement(row.getRow()); } /** * Standardkonstruktor, erzeugt das Root- <span class="xml">&lt;results&gt; * </span>-Element und ruft den Parent-Konstruktor auf. * @param document zum erzeugen der XML-Elemente * @see SDBElementList#SDBElementList(Document) */ public SDBResultsImpl(Document document) { super(document); this.root = this.doc.createElement("results"); } /** * <code>position</code> des Cursors */ private int position = -1; /** * Die Liste zum Zwischenspeichern eines ResultSets und gleichzeitig stellt die * Klasse das <span class="xml">&lt;results&gt; </span>Element dar. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.4 $ $Date: 2004/09/16 14:27:24 $ */ public class SDBResultsImpl extends SDBElementList implements SDBResults { import org.w3c.dom.Document; import org.w3c.dom.Element; package base; Datei: SDBResultsImpl.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBResultsImpl.java 58 von 71 return this.root; Seite: 2 von 3 Seite: 2 von 3 /** * Errechnet die Absolute Position, des Datensatzes und ruft entsprechend * <code>getAbsolute()</code> auf. Falls aus dem ResultSet hinausgelaufen * werden würde, d.h. die obere oder untere Grenze überschritten wird. Wird * entweder der erste oder letzte Datensatz zurückgegeben. /** * Das gleiche wie <code>getRelative(-1)</code> * @see base.SDBResults#getPrevious() * @see SDBResultsImpl#getRelative(int) */ public Element getPrevious() { return getRelative(-1); } /** * Gibt die Position des Cursors zurück, oder -1 falls der ResultSet leer * ist. * @see base.SDBResults#getPosition() */ public int getPosition() { return !isEmpty() ? this.position : -1; } /** * Das gleiche wie <code>getRelative(1)</code> * @see base.SDBResults#getNext() * @see SDBResultsImpl#getRelative(int) */ public Element getNext() { return getRelative(1); } /** * Das gleiche wie <code>getAbsolute(lastindex)</code> * @see base.SDBResults#getLast() * @see SDBResultsImpl#getAbsolute(int) */ public Element getLast() { return getAbsolute(this.lastindex); } /** * Das gleiche wie <code>getAbsolute(0)</code> * @see base.SDBResults#getFirst() * @see SDBResultsImpl#getAbsolute(int) */ public Element getFirst() { return getAbsolute(0); } /** * Das gleiche wie <code>getRelative(0)</code> * @see base.SDBResults#getCurrentRow() * @see SDBResultsImpl#getRelative(int) */ public Element getCurrentRow() { return getRelative(0); } } for (int i = 0; i <= this.lastindex; i++) this.root.appendChild(this.list[i]); public Element getAll() { clear(); Datei: SDBResultsImpl.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBResultsImpl.java Anhang Datei: SDBResultsImpl.java 137 * @see base.SDBResults#getRelative(int) 138 * @see SDBResultsImpl#getAbsolute(int) 139 */ 140 public Element getRelative(int relativePosition) { 141 int absolutPosition = this.position + relativePosition; 142 143 if (!isEmpty()) { 144 if (absolutPosition <= 0) 145 return getFirst(); 146 else if (absolutPosition >= this.lastindex) 147 return getLast(); 148 else 149 return getAbsolute(absolutPosition); 150 } 151 152 return null; 153 } 154 }F Datei: SDBResultsImpl.java Seite: 3 von 3 Seite: 3 von 3 59 von 71 Seite: 1 von 2 Seite: 1 von 2 /** * Gibt das Root- <span class="xml">&lt;row&gt; </span>-Element zurück * @return Element das <span class="xml">&lt;row&gt; </span>Element */ public Element getRow() { } col.appendChild(this.doc.createTextNode(value)); } this.root.appendChild(col); // nur Objekte vom Typ Date werden extra-formatiert // siehe auch SDBResultset.initResults() if (o instanceof Date) { value = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMANY).format((Date) o); } //TODO ggf. hier weitere Typkonvertierungen??? /** * Fügt ein <span class="xml">&lt;col&gt; </span>Element ein * @param o das Objekt, welches mit seiner <code>toString()</code> Methode * als Text eingefügt wird. Handelt es sich dabei um ein <code>Date</code> * Objekt, dann wird das Dtum noch folgendermaßen umformatiert: * <code>DateFormat.getDateInstance(DateFormat.MEDIUM, * Locale.GERMANY).format((Date) o);</code> */ public void addColumn(Object o) { Element col = this.doc.createElement("col"); if (o != null) { String value = o.toString().trim(); /** * Standardkonstruktor, erzeugt das Root- <span class="xml">&lt;row&gt; * </span>-Element * @param document zum erzeugen der XML-Elemente */ public SDBRow(Document document) { this.doc = document; this.root = this.doc.createElement("row"); } /** * <code>root</code> das <span class="xml">&lt;row&gt; </span>Element */ private Element root = null; /** * <code>doc</code> zum erzeugen der <span class="xml">&lt;col&gt; * </span>Elemente */ private Document doc = null; /** * Stellt ein <span class="xml">&lt;row&gt; </span>Element dar. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.4 $ $Date: 2004/09/16 14:27:23 $ */ public class SDBRow { import org.w3c.dom.Document; import org.w3c.dom.Element; import java.sql.Date; import java.text.DateFormat; import java.util.Locale; package base; Datei: SDBRow.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBRow.java Anhang return this.root; Datei: SDBRow.java 69 70 } 71 }D Datei: SDBRow.java Seite: 2 von 2 Seite: 2 von 2 60 von 71 javax.servlet.ServletException; javax.servlet.http.HttpServlet; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; javax.xml.transform.Source; javax.xml.transform.Templates; javax.xml.transform.Transformer; javax.xml.transform.TransformerFactory; javax.xml.transform.stream.StreamResult; import import import import import import import import import import Seite: 1 von 5 Seite: 1 von 5 /** * Schließt die Datenbankverbindung, wenn das Servlet 'zerstört' bzw. die * Webanwendung beendet wird. * @see javax.servlet.Servlet#destroy() */ public void destroy() { try { /** * Fügt eine Gruppe in ein sessiongebundenes Document ein. * @param g die Gruppe die eingefügt werden soll * @param s die Session in der sich das Dokument befindet, in das die Gruppe * eingefügt werden soll. */ protected void addGroup(SDBGroup g, HttpSession s) { getDocument(s).addGroup(g); } /** * Fügt die an das Servlet gesendeten Parameter in das aktuelle Dokument ein. * @param r das <code>HttpServletRequest</code> Objekt, dessen Parameter * eingefügt werden sollen. * @see SDBDocument#addFormdata(HttpServletRequest) */ protected void addFormdata(HttpServletRequest r) { HttpSession s = r.getSession(); getDocument(s).addFormdata(r); } /** * Objekthandel für die Datenbankverbindung */ private Connection db_connection; /** * Das BASIS-Servlet, von dem alle anderen SDB-Servlets erben sollten! * Initialisiert den JDBC-Treiber, stellt Datenbankverbindungen her, übernimmt * das Management für das sesseiongebunden Document, implementert die * doPost()-Methode als 'Delegate-Mehtod' an doGet(), gibt die Pfadnamen für * Stylesheets und Doc-Type-Defintions zurück, stellt Methoden zum einfügen der * empfangenen Parameter und zum erzeugen von <span class="xml">&lt;group&gt; * </span>Elementen zur Verfügung. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.9 $ $Date: 2004/09/16 14:27:23 $ */ public abstract class SDBServlet extends HttpServlet { java.io.IOException; java.io.PrintWriter; java.sql.Connection; java.sql.DriverManager; java.sql.PreparedStatement; java.sql.ResultSet; java.sql.SQLException; java.sql.Statement; import import import import import import import import package base; Datei: SDBServlet.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBServlet.java Anhang Seite: 2 von 5 return this.db_connection; Seite: 2 von 5 /** * Holt das SDBDocument aus der übergebenen Session, oder erzeugt ein neues, * falls noch keins vorhanden ist. * @param s Session in der nach dem SDBDocument gesucht wird, * @return SDBDocument das gefundene oder ein neues SDBDocument */ protected SDBDocument getDocument(HttpSession s) { /** * Gibt den Default-Pfad für XSL-Stylesheets zurück * @return String Pfad für XSL-Stylesheets */ public String getDefaultStylesheet() { return getServletContext().getRealPath("stylesheets"); } /** * Gibt den Default-Pfad für DTD's zurück * @return String Pfad für DTD's */ public String getDefaultDoctype() { return getServletContext().getRealPath("doctypes"); } } /** * gibt eine neue Datenbankverbindung zurück * @return die neue Datenbankverbindung */ protected Connection getConnection() { try { // Verbindung mit Datenbank herstellen this.db_connection = DriverManager.getConnection("jdbc:edbc://lionis:IJ7/sd } catch (SQLException e) { e.printStackTrace(); } /** * Delegatmethod: Eingaben entgegen nehmen und gleich an doGet() weiter * geben... * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletReque * javax.servlet.http.HttpServletResponse) * @see SDBServlet#doGet(HttpServletRequest, HttpServletResponse) */ public void doPost(HttpServletRequest request, HttpServletResponse response) throws java.io.IOException, ServletException { doGet(request, response); } /** * Absichtlich Abstrakte Methode, ein SDB-Servlet, was diese Methode nicht * implementiert, hätte keinen Sinn. * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletReques * javax.servlet.http.HttpServletResponse) */ public abstract void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException; } } catch (SQLException e) {// tja, was soll man da noch machen? } super.destroy(); if (this.db_connection != null) this.db_connection.close(); Datei: SDBServlet.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBServlet.java 61 von 71 Seite: 3 von 5 Seite: 3 von 5 /** * Tranformiert eine XML Source mit einem XSL Template in den * <code>Printwriter</code> * @param xmlSource die XML source, die umgewandelt werden soll * @param xslSource die XSL source, das Template, das zum umwandeln benutzt * wird * @param out ein PrintWriter auf den das Ergebnis geschrieben wird * @see Transformer#transform(javax.xml.transform.Source, * javax.xml.transform.Result) */ public void process(Source xmlSource, Source xslSource, PrintWriter out) { TransformerFactory tFactory; tFactory = TransformerFactory.newInstance(); try { Templates templates = tFactory.newTemplates(xslSource); Transformer transformer = templates.newTransformer(); transformer.transform(xmlSource, new StreamResult(out)); } catch (Exception e) { e.printStackTrace(out); } /** * Überschreibt das SDBDocument in der Session s, mit einem neuen (leeren) * SDBDocument. * @param s Session in der das neue SDBDocument gesetzt wird. * @return SDBDocument, das neu angelegte SDBDocument */ protected SDBDocument newDocument(HttpSession s) { SDBDocument doc = new SDBDocument(s.getId()); s.setAttribute("DOCUMENT", doc); return doc; } /** * Gibt an, ob in dieser Session schon ein SDBDocument ist, oder nicht * @param s Session in der nach einem SDBDocument gesucht wird * @return boolean, true->es ist ein SDBDocument vorhanden, false->kein * SDBDocument da */ protected boolean isDocumentSet(HttpSession s) { return null != (SDBDocument) s.getAttribute("DOCUMENT"); } /** * Initialisiert den Datenbanktreiber "ca.edbc.jdbc.EdbcDriver" * @see javax.servlet.GenericServlet#init() * @throws ServletException */ public void init() throws ServletException { try { // DB-Treiber initialisieren Class.forName("ca.edbc.jdbc.EdbcDriver"); } catch (Exception e) { e.printStackTrace(); } super.init(); } } if (doc == null) { doc = new SDBDocument(s.getId()); s.setAttribute("DOCUMENT", doc); } return doc; SDBDocument doc = ((SDBDocument) s.getAttribute("DOCUMENT")); Datei: SDBServlet.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBServlet.java Anhang Seite: 4 von 5 Seite: 4 von 5 /** * Fügt einen ResultSet in dem an die Session gebundenes SDBDocument ein * @param rs zu setzender ResultSet * @param s die HttpSession, wo der ResultSet in das Dokument gesetzt werden * soll. /** * Fügt einen ResultSet in dem an die Session gebundenes SDBDocument ein * @param rs zu setzender ResultSet * @param s die HttpSession, wo der ResultSet in das Dokument gesetzt werden * soll. * @see SDBServlet#setResultSet(ResultSet, HttpSession, String) */ protected void setResultSet(ResultSet rs, HttpSession s) { setResultSet(rs, s, null); } } // das XML transformieren transformer.transform(xmlSource, new StreamResult(out)); } catch (Exception e) { e.printStackTrace(out); } if (xmlparam != null) // gefundene XSL-Parameter setzen for (int i = 0; i < xmlparam.length; i++) { String[] param = xmlparam[i].split(":"); if (param != null && param.length == 2) transformer.setParameter(param[0], param[1]); else doc.setError("XML-Param: " + xmlparam[i]); } try { Templates templates = tFactory.newTemplates(xslSource); Transformer transformer = templates.newTransformer(); /** * Tranformiert eine XML Source mit einem XSL Template in den * <code>Printwriter</code>.<br /> * Zusätzlich werden noch die <code>xmlparam</code> Parameter des * <code>HttpServletRequest</code> an den XSL-Stylesheet weitergeleitet. * Ein <code>xmlparam</code> sollte dabei folgende Form haben: * <p> * xmlparam=Parameter_Name:Parameter_Wert * </p> * @param xmlSource die XML source, die umgewandelt werden soll * @param xslSource die XSL source, das Template, das zum umwandeln benutzt * wird * @param out ein PrintWriter auf den das Ergebnis geschrieben wird * @param r <code>HttpServletRequest</code> das ggf. einen oder mehrere * Parameter <code>xmlparam</code> enthält, die an den XSL-Stylesheet * weitergeleitet werden sollen * @see Transformer#transform(javax.xml.transform.Source, * javax.xml.transform.Result) */ public void process(Source xmlSource, Source xslSource, PrintWriter out, HttpServletRequest r) { TransformerFactory tFactory; tFactory = TransformerFactory.newInstance(); // durchzureichende Parameter holen String[] xmlparam = r.getParameterValues("xmlparam"); HttpSession s = r.getSession(); SDBDocument doc = getDocument(s); } Datei: SDBServlet.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: SDBServlet.java 62 von 71 Seite: 5 von 5 Seite: 5 von 5 /** * Führt die SQL-Select-Anweisung aus und fügt einen ResultSet in dem an die * Session gebundenes SDBDocument ein * @param sqlQuery die SQL-Select-Anweisung, die den ResultSet erzeugen soll * @param s die HttpSession, wo der ResultSet in das Dokument gesetzt werden * @throws SQLException bei Datenbankfehlern * @see SDBServlet#setResultSet(ResultSet, HttpSession, String) */ protected void setResultSet(String sqlQuery, HttpSession s) throws SQLException { if (sqlQuery != null && sqlQuery.trim().toUpperCase().startsWith("SELECT ")) { Connection con = getConnection(); if (con != null) { PreparedStatement stm = con.prepareStatement(sqlQuery, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); setResultSet(stm.executeQuery(), s, sqlQuery); stm.close(); con.close(); } else getDocument(s).setError( "Es konnte keine Datenbankverbindung hergestellt werden!"); } else { getDocument(s).setError("kein Query: \n" + sqlQuery); } } * @param sql Text für das <span class="xml">&lt;statment&gt; </span>Element * @see SDBDocument#addResultSet(ResultSet, String) */ protected void setResultSet(ResultSet rs, HttpSession s, String sql) { getDocument(s).addResultSet(rs, sql); } Datei: SDBServlet.java 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 } Datei: SDBServlet.java Anhang javax.servlet.ServletException; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; javax.xml.transform.Source; javax.xml.transform.stream.StreamSource; java.io.IOException; java.io.PrintWriter; java.io.StringReader; java.sql.SQLException; java.util.Enumeration; Seite: 1 von 7 Seite: 1 von 7 /** * Dieses Servlet kann mit einer Reihe von Parametern gesteuert werden. Es * eignet sich lediglich zur Anzeige nicht jedoch zum Ändern von Daten. * Entsprechend den Anforderungen für Navigationsleisten bietet es die * Möglichkeit, immer nur einen Datensatz oder aber alle anzuzeigen. * <h4>Parameterliste zur Steuerung der Servlets</h4> * <ul> * <li><strong>Parameter: requery </strong> <br /> * Wird der Parameter "requery" an das Servlet gesendet, wird ein neues * SDBDocument angelegt. Diese Funktionalität ist notwendig, weil sonst im Laufe * einer Session immer mehr <span class="xml">&lt;resultset&gt; </span> Elemente * in dem SDBDocument gespeichert werden würden und daher in den Stylesheets * nicht ermittelt werden könnte, welcher Resultset wo angezeigt werden soll. * Aus diesem Grund sollte bei einem Wechsel zwischen zwei verschiedenen * Eingabemasken immer auch ein "requery" an das Servlet gesendet werden, es sei * denn, es werden zwei <span class="xml">&lt;resultset&gt; </span>Elemente * gewünscht. So kann z.B. in einer ersten Eingabemaske ein Student ausgewählt * und in einer folgenden seine erworbenen Scheine zusätzlich aufgelistet * werden. Der Wert des Parameters ist ohne Bedeutung, da nur überprüft wird, ob * er vorhanden ist. Ist das der Fall, wird ein neues SDBDocument angelegt. Ist * er nicht an das Servlet gesendet worden, wird das SDBDocument von der * aktuellen Session weiterverwendet.</li> * <li><strong>Parameter: query </strong> <br /> * An das Servlet können ein oder mehrere "queries" geschickt werden. Jeder * String, der als "query" an ein Servlet geschickt wird, wird darauf getestet, * ob er mit SELECT anfängt. In diesem Fall wird versucht, eine * Datenbankverbindung herzustellen und die Select-Anweisung auszuführen. Wenn * dies gelingt, wird ein <span class="xml">&lt;resultset&gt; </span>Element in * das aktuelle SDBDocument eingefügt, anderenfalls werden entsprechende * Fehlermeldungen ( <span class="xml">&lt;error&gt; </span> Elemente)erzeugt. * </li> * <li><strong>Parameter: nav_[1-7] </strong> <br /> * Alle Parameter, die mit nav_ beginnen, werden dahingehend überprüft, ob * hinter dem Unterstrich eine Ziffer folgt. Die Ziffern haben dabei folgende * Bedeutungen: * <ul> * 1: Der erste Datensatz wird angezeigt. <br /> * 2: Ausgehend von der aktuellen Position wird um zehn Datensätze * zurückgerückt. <br /> * 3: Ausgehend von der aktuellen Position wird um einen Datensatz * zurückgerückt. <br /> * 4: Ist zusätzlich der Parameter row vorhanden und eine Zahl zwischen 1 und * der Anzahl der Datensätze eingetragen, wird zu dem Datensatz mit dieser * Nummer gesprungen. <br /> * 5: Ausgehend von der aktuellen Position wird um zehn Datensätze vorgerückt. * <br /> * 6: Ausgehend von der aktuellen Position wird um einen Datensatz vorgerückt. * <br /> * 7: Der letzte Datensatz wird angezeigt <br /> * </ul> import base.SDBDocument; import base.SDBServlet; import import import import import import import import import import import package servlet; Datei: SDBSelect.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBSelect.java Seite: 2 von 7 63 von 71 Datei: SDBSelect.java Seite: 2 von 7 69 * Falls keine Ziffer zwischen 1 und 7 hinter dem Unterstrich steht, werden alle 70 * Datensätze angezeigt.</li> 71 * <li><strong>Parameter: stylesheet </strong> <br /> 72 * Mit dem Parameter stylesheet wird dem Servlet mitgeteilt, welchen Stylesheet 73 * es verwenden soll, um aus den XML-Daten des SDBDocuments eine z.B. HMTL-Seite 74 * zu erzeugen.</li> 75 * <li><strong>Parameter: form </strong> <br /> 76 * Dieser Parameter soll die Einstellung verschiedener Ausgabeformate 77 * ermöglichen. Zur Zeit werden aber nur zwei Formate unterstützt. Das 78 * Standardformat ist HTML und wird immer verwendet, auch wenn dieser Parameter 79 * nicht gesetzt wird. Wenn <code>form=xml</code> an das Servlet gesendet 80 * wird, wird der XML-String eines SDBDocuments unverändert gelassen. In der 81 * <code>doGet()</code> -Methode läßt sich vor der Datenausgabe leicht jedes 82 * andere Format einstellen. Da die javax.servlet.http-Technologie es nicht 83 * zulässt, allein durch Angabe eines anderen Stylesheets das Ausgabeformat 84 * einzustellen, muss dieses zusätzlich immer mit der Methode 85 * <code>HttpServletResponse.setContentType()</code> gesetzt werden.</li> 86 * <li><strong>Parameter: xmlparam </strong> <br /> 87 * Dieser Parameter gestattet es, an einen Stylesheet selbst wiederum Parameter 88 * weiterzugeben. Diese Technik wird zum Beispiel bei den Statistiken verwendet, 89 * um ein schnelles einfaches Umsortieren der Ergebnislisten zu ermöglichen. 90 * Dazu wird <code>xmlparam=order_by_column:1</code> an das Servlet gesendet, 91 * dieses setzt anschließend in der <code>process()</code> -Methode den 92 * entsprechenden XSL-Parameter <code>order_by_column</code> auf den Wert 1. 93 * In einem Stylesheet kann dann auf den Wert zugegriffen werden und wie in 94 * diesem Beispiel nach der 1. Spalte sortiert werden.</li> 95 * <ul> 96 * 97 * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> 98 * @version $Revision: 1.7 $ $Date: 2004/09/16 14:27:24 $ 99 */ 100 public class SDBSelect extends SDBServlet { 101 /** 102 * Verarbeitet die in der Klassenbeschreibung (s.o.) angegebenen Parameter. 103 * Funktionsweise: 104 * <ul> 105 * 1. Session anlegen / wiederfinden. <br /> 106 * 2. bei "requery" ggf. ein neues Document anlegen (incl. <span 107 * class="xml">&lt;session&gt; </span>Element). <br /> 108 * 3. evtl. vorhandene alte Fehlermeldung aus dem Document löschen. <br /> 109 * 4. alle Parameter die an das Servlet gesendet wurden in das <span 110 * class="xml">&lt;formdata&gt; </span>Element einfügen. <br /> 111 * 5. alle übergebenen "query" ausführen und in das Document die 112 * entsprechenden <span class="xml">&lt;resultset&gt; </span>Elemente 113 * einfügen. 6. ggf. zu bestimmten Datensätzen durch den Parameter nav_[1-7] 114 * navigieren. <br /> 115 * 7. Stylesheet aus dem entsprechenden Verzeichnis laden. <br /> 116 * 8. je nach angegebenen Ausgabeformat XML-transformieren 117 * </ul> 118 * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletReques 119 * javax.servlet.http.HttpServletResponse) 120 */ 121 public void doGet(HttpServletRequest request, HttpServletResponse response) 122 throws IOException, ServletException { 123 Source xsltSource = null, xmlSource = null; 124 String stylesheet = null, xml = ""; 125 126 PrintWriter out = response.getWriter(); 127 128 // session feststellen 129 HttpSession session = request.getSession(true); 130 131 // ggf. neues SDBDocument anlegen 132 if (request.getParameter("requery") != null) 133 newDocument(session); 134 135 // evtl. alte Fehlermeldungen aus dem SDBDocument löschen 136 getDocument(session).removeOldErrors(); Datei: SDBSelect.java Anhang out.flush(); if ("XML".equalsIgnoreCase(request.getParameter("form"))) { // SDBDocument als XML ausgeben response.setContentType("text/xml; charset=ISO-8859-1"); out.print(showAllRecords(session)); } else { // XML des SDBDocuments mit angegebenem Stylesheet transformieren. xsltSource = new StreamSource(getDefaultStylesheet() + "/" + stylesheet); response.setContentType("text/html; charset=ISO-8859-1"); if (request.getParameter("xmlparam") != null) // ggf. noch mit XSL-Parametern transformieren process(xmlSource, xsltSource, out, request); else process(xmlSource, xsltSource, out); } // richtigen Stylesheet (je nach Parameterwert "stylesheet") auswählen stylesheet = request.getParameter("stylesheet"); if (stylesheet == null || !stylesheet.endsWith(".xsl")) stylesheet = "/einzelansicht.xsl"; // XML-String in eine StreamSource umwandeln xmlSource = new StreamSource(new StringReader(xml)); // ggf. zu bestimmten Datensatz navigieren if (isDocumentSet(session)) xml = navigate(request); else xml = "Fehler: konnte kein Document in dieser Session anlegen bzw. finden!" // die "query"s setzen setQuerys(request); /** * Gleiche Funktion wie <code>getFirstRecord(s, 0)</code> Seite: 3 von 7 /** * Gibt das SDBDcoument als String zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu dem Datensatz mit der aboluten Position * gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @param abs_pos Datensatznummer zu der gesprungen wird. * @return String das SDBDocument aus der Session * @see SDBDocument#getAbsolute(int, int) */ protected String getAbsolutRecord(HttpSession s, int resNumber, int abs_pos) { return getDocument(s).getAbsolute(resNumber, abs_pos); } /** * Gleiche Funktion wie <code>getAbsolutRecord(s, 0, abs_pos)</code> * @param s aktuelle Session * @param abs_pos Datensatznummer zu der gesprungen wird. * @return String das SDBDocument aus der Session * @see SDBSelect#getAbsolutRecord(HttpSession, int, int) */ protected String getAbsolutRecord(HttpSession s, int abs_pos) { return getAbsolutRecord(s, 0, abs_pos); } } Seite: 3 von 7 // alle an das Servlet gesendeten Parameter in das SDBDcoument einfügen addFormdata(request); Datei: SDBSelect.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBSelect.java 64 von 71 Seite: 4 von 7 /** * Gleiche Funktion wie <code>getPreviousRecord(s, 0)</code> * @param s die aktuelle Session * @return String das SDBDocument aus der Session Seite: 4 von 7 /** * Gibt das SDBDocument der Session zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu dem nächsten Datensatz gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @return String das SDBDocument aus der Session * @see SDBDocument#getNext(int) */ protected String getNextRecord(HttpSession s, int resNumber) { return getDocument(s).getNext(resNumber); } /** * Gleiche Funktion wie <code>getNextRecord(s, 0)</code> * @param s die aktuelle Session * @return String das SDBDocument aus der Session * @see SDBSelect#getNextRecord(HttpSession, int) */ protected String getNextRecord(HttpSession s) { return getNextRecord(s, 0); } /** * Gibt das SDBDocument der Session zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu dem letzten Datensatz gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @return String das SDBDocument aus der Session * @see SDBDocument#getLast(int) */ protected String getLastRecord(HttpSession s, int resNumber) { return getDocument(s).getLast(resNumber); } /** * Gleiche Funktion wie <code>getLastRecord(s, 0)</code> * @param s die aktuelle Session * @return String das SDBDocument aus der Session * @see SDBSelect#getLastRecord(HttpSession, int) */ protected String getLastRecord(HttpSession s) { return getLastRecord(s, 0); } /** * Gibt das SDBDocument der Session zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu dem ersten Datensatz gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @return String das SDBDocument aus der Session * @see SDBDocument#getFirst(int) */ protected String getFirstRecord(HttpSession s, int resNumber) { return getDocument(s).getFirst(resNumber); } * @param s die aktuelle Session * @return String das SDBDocument aus der Session * @see SDBSelect#getFirstRecord(HttpSession, int) */ protected String getFirstRecord(HttpSession s) { return getFirstRecord(s, 0); } Datei: SDBSelect.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: SDBSelect.java Anhang Seite: 5 von 7 Seite: 5 von 7 /** * Sucht nach einem Parameter <code>nav_[1-7]</code>. Wird ein solcher * gefunden, wird je nach Zahl (s.u.) in dem ersten ResultSet des * SDBDocuments zu dem entsprechenden Datensatz navigiert und nur dieser * angezeigt. * <ul> * nav_1: Der erste Datensatz wird angezeigt. <br /> * nav_2: Ausgehend von der aktuellen Position wird um zehn Datensätze * zurückgerückt. <br /> * nav_3: Ausgehend von der aktuellen Position wird um einen Datensatz * zurückgerückt. <br /> * nav_4: Ist zusätzlich der Parameter row vorhanden und eine Zahl zwischen 1 * und der Anzahl der Datensätze eingetragen, wird zu dem Datensatz mit * dieser Nummer gesprungen. <br /> * nav_5: Ausgehend von der aktuellen Position wird um zehn Datensätze * vorgerückt. <br /> * nav_6: Ausgehend von der aktuellen Position wird um einen Datensatz * vorgerückt. <br /> * nav_7: Der letzte Datensatz wird angezeigt <br /> * </ul> * Falls keiner dieser Parameter angegeben wurde, werden alle ResultSets mit * allen Datensätzen angezeigt. * @param r <code>HttpServletRequest</code> aus der doGet()-Methode * @return String das SDBDocument aus der Session */ protected String navigate(HttpServletRequest r) { HttpSession s = r.getSession(); /** * Gibt das SDBDocument der Session zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu der relativen Datensatz-Position gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @param rel_pos relative Position zu der gesprungen wird. * @return String das SDBDocument aus der Session * @see SDBDocument#getRelative(int, int) */ protected String getRelativeRecord(HttpSession s, int resNumber, int rel_pos) { return getDocument(s).getRelative(resNumber, rel_pos); } /** * Gleiche Funktion wie <code>getRelativeRecord(s, 0, rel_pos)</code> * @param s die aktuelle Session * @param rel_pos relative Position zu der gesprungen wird. * @return String das SDBDocument aus der Session */ protected String getRelativeRecord(HttpSession s, int rel_pos) { return getRelativeRecord(s, 0, rel_pos); } /** * Gibt das SDBDocument der Session zurück, dabei wird in dem ResultSet mit * der übergebenen Nummer zu dem vorhergehenden Datensatz gesprungen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @return String das SDBDocument aus der Session * @see SDBDocument#getPrevious(int) */ protected String getPreviousRecord(HttpSession s, int resNumber) { return getDocument(s).getPrevious(resNumber); } * @see SDBSelect#getPreviousRecord(HttpSession, int) */ protected String getPreviousRecord(HttpSession s) { return getPreviousRecord(s, 0); } Datei: SDBSelect.java 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: SDBSelect.java 65 von 71 Seite: 6 von 7 /** * Gibt das SDBDocument mit allen ResultSets und jeweils allen Datensätzen * zurück * @param s die aktuelle Session * @return String das SDBDocument aus der Session * @see SDBDocument#getAll() */ protected String showAll(HttpSession s) { return getDocument(s).getAll(); } } // ist der Parameter an das Servlet gesendet worden? if (query != null && query.length > 0) for (int i = 0; i < query.length; i++) { // jeden "query"-String auf ein 'SELECT ' am Anfang überprüfen if (query[i].trim().length() >= 0 && query[i].toUpperCase().startsWith("SELECT ")) { try { // Query ausführen und ResultSet erzeugen setResultSet(query[i], s); } catch (SQLException e) { doc.setError(e.toString()); } } else doc.setError("Query: " + query[i]); } /** * Führt die einzelnen SQL-Select-Anweisungen, die in den Parametern "query" * an das Servlet gesendet wurden aus und erzeugt jeweils ein <span * class="xml">&lt;resultset&gt; </span>Element in dem SDBDocument der * aktuellen Session. * @param r <code>HttpServletRequest</code> aus der doGet()-Methode * @see SDBServlet#setResultSet(String, HttpSession) */ protected void setQuerys(HttpServletRequest r) { String[] query = r.getParameterValues("query"); HttpSession s = r.getSession(); SDBDocument doc = getDocument(s); } Seite: 6 von 7 while (e.hasMoreElements()) { String nav = e.nextElement().toString(); if (nav.startsWith("nav_")) switch (nav.charAt(4)) { // nav_X X==4. Position case '1': return getFirstRecord(s); case '2': return getRelativeRecord(s, -10); case '3': return getPreviousRecord(s); case '4': int number = Integer.parseInt(r.getParameter("row")); return getAbsolutRecord(s, number); case '5': return getNextRecord(s); case '6': return getRelativeRecord(s, 10); case '7': return getLastRecord(s); } } return getDocument(s).getAll(); Enumeration e = r.getParameterNames(); Datei: SDBSelect.java 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 Datei: SDBSelect.java Anhang Seite: 7 von 7 Seite: 7 von 7 /** * Gibt das SDBDocument zurück und den ResultSet mit der übergebenen Nummer * dabei mit allen Datensätzen. * @param s die aktuelle Session * @param resNumber Nummer des ResultSets * @return String das SDBDocument aus der Session * @see SDBDocument#getAll(int) */ protected String showAllRecords(HttpSession s, int resNumber) { return getDocument(s).getAll(resNumber); } /** * Gibt das SDBDocument zurück und den ersten ResultSet dabei mit allen * Datensätzen. Die gleiche Funktion wie <code>showAllRecords(s, 0)</code> * @param s die aktuelle Session * @return String das SDBDocument aus der Session * @see SDBSelect#showAllRecords(HttpSession, int) */ protected String showAllRecords(HttpSession s) { return showAllRecords(s, 0); } Datei: SDBSelect.java 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 }} Datei: SDBSelect.java 66 von 71 base.*; java.io.*; java.sql.*; javax.servlet.*; javax.servlet.http.*; javax.xml.transform.*; javax.xml.transform.stream.*; Seite: 1 von 3 // Ausgabeformat festlegen und entsprechend ausgeben if ("XML".equalsIgnoreCase(request.getParameter("form"))) { // den Stylesheet holen stylesheet = request.getParameter("stylesheet"); if (stylesheet == null || !stylesheet.endsWith(".xsl")) stylesheet = "/einzelansicht.xsl"; // aus dem String des SDBDocuments eine Source erzeugen xmlSource = new StreamSource(new StringReader(xml)); Seite: 1 von 3 if (isDocumentSet(session)) xml = navigate(request); // Navigationsleiste anwenden else xml = "Fehler: konnte kein Document in dieser Session anlegen bzw. finden!" setQuerys(request); // ggf. noch Select-Anweisungen ausführen execute(request); // SQL-Anweisungen ausführen addFormdata(request); // hinzufügen der gesendeten Parameter // ggf. alte Fehlermeldungen löschen, gerade wenn kein neues Document // angelegt wurde!! getDocument(session).removeOldErrors(); // ggf. neues SDBDocument anlegen und das alte damit verwerfen if (request.getParameter("requery") != null) newDocument(session); // aktuelle Session erkennen HttpSession session = request.getSession(true); PrintWriter out = response.getWriter(); /** * Mit diesem Servlet können alle Datenbankoperationen ausgeführt werden, die * der JDBC-Treiber zulässt. Es ist speziell für * <code>INSERT, UPDATE, DELETE</code> Operationen gedacht. Es werden aber * genausogut auch <code>CREATE TABLE, DROP TABLE, GRANT...</code> Operationen * unterstützt. Ansonsten ist die Funktionsweise die gleiche wie bei dem * Servlet: <code>SDBSelect</code> * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.4 $ $Date: 2004/09/23 15:31:21 $ */ public class SDBExecute extends SDBSelect { /** * Funktioniert genauso wie bei <code>SDBSelect</code>, nur das nach dem * <span class="xml">&lt;formdata&gt; </span>Element die in dem Parameter * "sql" übergebenen Datenbankanweisungen ausgeführt werden und das * entsprechende <span class="xml">&lt;executed&gt; </span>Element erzeugt * wird. * @see SDBSelect#doGet(HttpServletRequest, HttpServletResponse) */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { Source xsltSource = null, xmlSource = null; String stylesheet = null, xml = ""; import import import import import import import package servlet; Datei: SDBExecute.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBExecute.java Anhang out.flush(); Seite: 2 von 3 Seite: 2 von 3 if (what.equals("insert")) message = count + " Datensätze eingefügt"; else if (what.equals("update")) message = count + " Datensätze überschrieben"; else if (what.equals("delete")) message = count + " Datensätze gelöscht"; else message = sql[i].substring(0, (sql[i].length() > 30 ? 30 : sql[i].length())).trim(). // die SQL-Anweisungen nach und nach ausführen for (int i = 0; i < sql.length; i++) { if (sql[i].trim().length() > 0) { try { Statement stm = con.createStatement( ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); if (stm.execute(sql[i])) { // ggf. eine Ergebnisliste erzeugen setResultSet(stm.getResultSet(), s); } else { // oder eine Meldung, über die durchgeführte Aktion // erzeugen String what = sql[i].substring(0, sql[i].indexOf(' ')).trim( int count = stm.getUpdateCount(); String message = null; // SQL-Parameterliste checken if (sql != null && sql.length > 0) try { // Datenbankeinstellungen vornehmen con.setAutoCommit(false); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // Datenbankverbindung aufbauen Connection con = getConnection(); if (con == null) { doc.setError("Es konnte keine Datenbankverbindung hergestellt werden!"); return; } /** * Sucht in der Parameterliste des mitgegebenen * <code>HttpServletRequest</code> nach "sql", alle diese Parameter werden * in einer Transaktion in der Reihenfolge wie sie an das Servlet geschickt * wurden ausgeführt. * @param r das <code>HttpServletRequest</code> in dem nach SQLs gesucht * wird. */ protected void execute(HttpServletRequest r) { String[] sql = r.getParameterValues("sql"); HttpSession s = r.getSession(); SDBDocument doc = getDocument(s); boolean error = false; } } else { xsltSource = new StreamSource(getDefaultStylesheet() + "/" + stylesheet); response.setContentType("text/html; charset=ISO-8859-1"); process(xmlSource, xsltSource, out); } response.setContentType("text/xml; charset=ISO-8859-1"); out.print(showAllRecords(session)); Datei: SDBExecute.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBExecute.java 67 von 71 } catch (SQLException e) { while (e != null) { doc.setError(e.toString()); e = e.getNextException(); } error = true; } doc.setExecute(what, message, count); } stm.close(); con.close(); } catch (SQLException e) { doc.setError(e.toString()); try { con.rollback(); con.close(); } catch (SQLException e2) { doc.setError(e2.toString()); } } } } if (!error) con.commit(); //keine Fehler -> commit else con.rollback(); // bei Fehlern -> rollback Datei: SDBExecute.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 } 168 }r Datei: SDBExecute.java Anhang Seite: 3 von 3 Seite: 3 von 3 javax.servlet.ServletException; javax.servlet.http.Cookie; javax.servlet.http.HttpServletRequest; javax.servlet.http.HttpServletResponse; javax.servlet.http.HttpSession; javax.xml.transform.Source; javax.xml.transform.stream.StreamSource; import import import import import import import Seite: 1 von 8 Seite: 1 von 8 for (int i = 0; theCookies != null && i < this.cookie.length;) { index = theCookies.indexOf("::::"); if (index < 0) break; name = theCookies.substring(0, index); /** * Konstruktor, bei dem die Cookies aus dem übergebenen * <code>String</code> extrahiert werden. * @param theCookies aus dem die <code>Cookies</code> geholt werden. */ public StatCookie(String theCookies) { String name, value; int index; /** * Konstruktor, bei dem die Cookies aus dem übergebenen * <code>HttpServletRequest</code> geholt werden. * @param request aus dem die <code>Cookies</code> geholt werden. */ public StatCookie(HttpServletRequest request) { this.cookie = request.getCookies(); } /** * Das Servlet zum Verwalten und Ausführen der Datenbankanfragen, die mit dem * Anfrageneditor erstellt wurden. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision: 1.8 $ $Date: 2004/09/16 14:27:24 $ */ public final class SDBStatistik extends SDBSelect { /** * Klasse zum umwandeln der Cookies in einen zusammenhängenden String und * wieder zurück. * @author <a href="mailto:[email protected]">Hilmar Falkenberg </a> * @version $Revision$ $Date$ */ private class StatCookie { /** * Array <code>cookie</code> für maximal 20 Cookies, mehr sind in * Browsern nicht erlaubt (vgl. HTTP-Standard)! <br /> * Cookies für den Anfrageneditor: TABLE, FELD[0-9], CHECK, FUNKT, FRAGE */ private Cookie[] cookie = new Cookie[20]; import base.SDBDocument; java.io.IOException; java.io.InputStream; java.io.InputStreamReader; java.io.PrintWriter; java.io.StringBufferInputStream; java.io.StringReader; java.sql.Connection; java.sql.PreparedStatement; java.sql.ResultSet; java.sql.SQLException; java.sql.Statement; import import import import import import import import import import import package servlet; Datei: SDBStatistik.java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 Datei: SDBStatistik.java 68 von 71 /** * Die Stringdarstellung eines StatCookies ist: <br /> * <strong>cookie_NAME1::::cookie_WERT1####cookie_NAME2::::cookie_WERT3 * ... </strong> <br /> * @see java.lang.Object#toString() */ public String toString() { StringBuffer buf = new StringBuffer(); for (int i = 0; i < this.cookie.length && this.cookie[i] != null; i++) { buf.append(this.cookie[i].getName() + "::::" + this.cookie[i].getValue() + "####"); } return buf.toString(); } Seite: 2 von 8 /** * Löscht eine Datenbankanfrage aus der Tabelle pra03.stat_statistiken. Dazu * muss ein Parameter <code>STATID</code> an das Servlet übergeben worden * sein, in ihm muss die eindeutige Datenbankanfragen-Nummer (lfd_nr) * enthalten sein, die gelöscht werden soll. <br /> * Anschließend wir die Liste mit den gespeicherten Anfragen angezeigt. * @param request weitergereicht von <code>doGet()</code> * @param response weitergereicht von <code>doGet()</code> * @throws IOException * @see SDBStatistik#doGet(HttpServletRequest, HttpServletResponse) /** * Wandelt einen <code>InputStream</code> in einen <code>String</code> um * @param in <code>InputStream</code> der umgewandelt werden soll * @return die Daten des InputStreams als String * @throws IOException */ public static String toString(InputStream in) throws IOException { char[] charBuffer = new char[1024]; int bytesRead; InputStreamReader isr = new InputStreamReader(in); StringBuffer sb = new StringBuffer(); while (-1 != (bytesRead = isr.read(charBuffer, 0, charBuffer.length))) { sb.append(charBuffer, 0, bytesRead); } in.close(); isr.close(); return sb.toString(); } } } Seite: 2 von 8 /** * Setzt beim Client die Cookies, die sich in dem Array * <code>cookie</code> befinden. * @param response Client-Antwort-Objekt */ public void addCookies(HttpServletResponse response) { for (int i = 0; i < this.cookie.length && this.cookie[i] != null; i++) { response.addCookie(this.cookie[i]); } } } theCookies = theCookies.substring(index + 4); index = theCookies.indexOf("####"); if (index < 0) break; value = theCookies.substring(0, index); theCookies = theCookies.substring(index + 4); if (name != null && value != null) { this.cookie[i++] = new Cookie(name, value); } Datei: SDBStatistik.java 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 Datei: SDBStatistik.java Anhang Seite: 3 von 8 Seite: 3 von 8 /** * Sucht nach dem Parameter: "doWhat" * <ul> * <li><strong>speichern/save </strong> <br /> * <br /> * Mit diesem Wert wird das Servlet dazu veranlasst, die Cookies auszulesen. * Je nachdem, ob eine STATID als Parameter mit übergeben wurde, wird ein * insert (keine STATID) oder ein update (mit entsprechender STATID) auf der * Tabelle pra03.stat_statistiken vorgenommen. Anschließend wird die Liste * der gespeicherten Anfragen mit einem Hinweis dargestellt, ob das Speichern * erfolgreich war.</li> * <li><strong>bearbeiten/edit </strong> <br /> * Wird einer dieser beiden Werte an das Servlet gesendet, ist ein * zusätzlicher Parameter STATID unablässig. Es wird dann der Datensatz mit * der entsprechenden lfd_nr aus der Tabelle pra03.stat_statistiken gelesen * und die Cookies aus dem long-varchar-Feld werden wieder hergestellt, so * dass nach einem HttpServletResponse.sendRedirect("statistik.html") eine } // Liste der gespeicherten Anfragen erzeugen liste(request, response); } } else doc.setError("Es wurde keine Anfrage gelöscht, weil keine STATID übergeben } catch (SQLException e) { doc.setError(e.toString()); } stm.close(); con.commit(); con.close(); if (stm.execute()) setResultSet(stm.getResultSet(), session); else { int count = stm.getUpdateCount(); doc.setExecute("delete", "Abfrage Nr: " + statid + " - wurde erfolgreich gelöscht", count); } // Anfrage löschen String sql = "DELETE FROM pra03.stat_statistiken WHERE lfd_nr = ?"; PreparedStatement stm = con.prepareStatement(sql); stm.setInt(1, statid); // ist eine STATID übergeben worden? if (statid != 0) { Connection con = getConnection(); if (con == null) { doc.setError("Es konnte keine Datenbankverbindung hergestellt werden!"); } else { try { con.setAutoCommit(false); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); // neues Document anlegen SDBDocument doc = newDocument(session); addFormdata(request); */ private void delete(HttpServletRequest request, HttpServletResponse response) throws IOException { // STATID holen int statid = getStatId(request); HttpSession session = request.getSession(true); Datei: SDBStatistik.java 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 Datei: SDBStatistik.java 69 von 71 Seite: 4 von 8 Seite: 4 von 8 if (statid != 0) { try { // Anfrage aus der Tabelle pra03.stat_statistiken laden Connection con = getConnection(); Statement stm = con.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); String sql = "SELECT cookie, frage from pra03.stat_statistiken WHERE lfd + statid; ResultSet rs = stm.executeQuery(sql); /** * Lädt eine Anfrage aus der Datenbank in den Anfrageneditor. Dazu wird der * Parameter STATID benötigt, d.h. die Nummer der Anfrage, die bearbeitet * werden soll. * @param request weitergereicht von <code>doGet()</code> * @param response weitergereicht von <code>doGet()</code> * @throws IOException * @see SDBStatistik#doGet(HttpServletRequest, HttpServletResponse) */ private void edit(HttpServletRequest request, HttpServletResponse response) throws IOException { // Anfragennummer feststellen int statid = getStatId(request); } if (doWhat.equalsIgnoreCase("speichern") || doWhat.equalsIgnoreCase("save")) { save(request, response); } else if (doWhat.equalsIgnoreCase("bearbeiten") || doWhat.equalsIgnoreCase("edit")) { edit(request, response); } else if (doWhat.equalsIgnoreCase("ausführen") || doWhat.equalsIgnoreCase("execute")) { execute(request, response); } else if (doWhat.equalsIgnoreCase("löschen") || doWhat.equalsIgnoreCase("delete")) { delete(request, response); } else liste(request, response); * Bearbeitung in dem Anfrageneditor vorgenommen werden kann.</li> * <li><strong>ausführen/execute </strong> <br /> * Diese Werte steuern das Servlet so, dass entweder die aktuelle Anfrage * gemäß der Eingabe in dem Anfrageneditor ausgeführt wird oder eine aus der * Liste der gespeicherten Datenbankanfragen ausgewählte Anfrage. Dazu wird * diese aus der Tabelle pra03.stat_statistiken zuerst ausgelesen und dann * ausgeführt.</li> * <li><strong>löschen/delete </strong> <br /> * Der Aufruf des Servlets mit diesen Werten wird nur von der Seite mit den * gespeicherten Datenbankanfragen vorgenommen und führt dazu, dass die * Datenbankanfrage mit der lfd_nr (entspricht mitgesendeter STATID) gelöscht * wird. Anschließend wird wieder die Liste mit den gespeicherten Anfragen * mit einem Hinweis dargestellt, ob das Löschen erfolgreich war.</li> * <li><strong>keiner der obigen Werte wurde als "doWhat" an das Servlet * gesendet </strong> <br />, dann wird die Lsite mit den bisher * gespeicherten Anfragen dargestellt.</li> * </ul> * @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletReques * javax.servlet.http.HttpServletResponse) */ public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { String doWhat = request.getParameter("doWhat") + ""; Datei: SDBStatistik.java 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 Datei: SDBStatistik.java Anhang Seite: 5 von 8 // um welche Anfrage handelt es sich int statid = getStatId(request); SDBDocument doc = newDocument(session); try { // Wurde eine Anfrage mitgesendet? String query = request.getParameter("query"); if (statid != 0 && query == null) { // keine Anfrage ("query") übergeben, dafür aber eine STATID Connection con = getConnection(); if (con == null) { doc.setError("Es konnte keine Datenbankverbindung hergestellt werd } else { // Anfrage mit der ldf_nr = STATID aus der Datenbank laden String sql = "select frage, query from pra03.stat_statistiken wher + statid; // soll nach einer Spalte umsortiert werden? String neuSortieren = request.getParameter("xmlparam"); if (neuSortieren == null || !neuSortieren.startsWith("order_by_column")) { PrintWriter out = response.getWriter(); HttpSession session = request.getSession(true); /** * Führt entweder die aktuell im Anfrageneditor befindliche Anfrage aus, oder * holt die Anfrage mit der übergebenen STATID aus der Datenbank und führt * diese aus. * @param request weitergereicht von <code>doGet()</code> * @param response weitergereicht von <code>doGet()</code> * @throws IOException * @see SDBStatistik#doGet(HttpServletRequest, HttpServletResponse) */ private void execute(HttpServletRequest request, HttpServletResponse response) throws IOException { } SDBDocument doc = getDocument(request.getSession()); doc.setError(e.toString()); response.setContentType("text/html; charset=ISO-8859-1"); Source xmlSource = new StreamSource(new StringReader(doc.toString())); Source xsltSource = new StreamSource(getDefaultStylesheet() + "/stat_gespeicherte.xsl"); process(xmlSource, xsltSource, response.getWriter()); } } // zur Anfrageneditor-HTML-Seite wechseln response.sendRedirect(response.encodeRedirectURL("statistik.html")); // // // // // // // // } catch (SQLException e) { // was soll man hier schon noch großes tun? // Die Fehlermeldungen werden eh nicht angezeigt! rs.close(); stm.close(); con.close(); } Seite: 5 von 8 // Cookies beim Client setzen cookie.addCookies(response); response.addCookie(new Cookie("STATID", String.valueOf(statid))); if (rs.next()) { // long varchar Feld in Cookies umwandeln StatCookie cookie = new StatCookie( toString(rs.getAsciiStream(1))); Datei: SDBStatistik.java 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 Datei: SDBStatistik.java 70 von 71 } catch (SQLException e) { doc.setError(e.toString()); } } out.flush(); if (request.getParameter("xmlparam") != null) process(xmlSource, xsltSource, out, request); else process(xmlSource, xsltSource, out); Seite: 6 von 8 /** * Erzeugt die Liste mit den bisher gespeicherten Datenbankanfragen. Dabei /** * Gibt die an das Servlet gesendete STATID zurück * @param request weitergereicht von <code>doGet()</code> * @return int die an das Servlet gesendete STATID */ private int getStatId(HttpServletRequest request) { try { return Integer.parseInt(request.getParameter("STATID")); } catch (NumberFormatException e) { return 0; } } } // Anfrage ausführen und <resultset> Element erzeugen doc.addResultSet(stm.executeQuery(sql), sql); con.close(); if ("XML".equalsIgnoreCase(request.getParameter("form"))) { // ggf. das Ergebnis als XML darstellen response.setContentType("text/xml; charset=ISO-8859-1"); out.print(showAllRecords(session)); } else { // ansonsten wird der standard Stylesheet "stat_antwort.xsl" verwendet Source xmlSource = new StreamSource(new StringReader( showAllRecords(session))); Source xsltSource = new StreamSource(getDefaultStylesheet() + "/stat_antwort.xsl"); response.setContentType("text/html; charset=ISO-8859-1"); } Seite: 6 von 8 // konnte die Anfrage geladen werden? PreparedStatement stm = con.prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY); ResultSet rs = stm.executeQuery(); if (rs.next()) { String frage = rs.getString(1); doc.addFormdata("frage", frage); sql = rs.getString(2); } else doc.addFormdata("frage", "Das hat leider nicht funkioniert!"); rs.close(); } } else { // die übergebene Anfrage direkt ausführen String frage = request.getParameter("frage"); doc.addFormdata("frage", frage); setResultSet(query, session); } Datei: SDBStatistik.java 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 Datei: SDBStatistik.java Anhang Seite: 7 von 8 out.flush(); SDBDocument doc = newDocument(session); addFormdata(request); StatCookie cookie = new StatCookie(request); Seite: 7 von 8 /** * Speichert die Datenbankanfrage in der Tabelle pra03.stat_statistiken, die * gerade in dem Anfrageneditor bearbeitet wird. Dazu wird entweder eine neue * lfd_nr / STATID erzeugt und ein INSERT durchgeführt, falls es sich um eine * neue Anfrage handelt. Oder es wird die Anfrage mit der in dem Parameter * STATID, übergebenen lfd_nr ein UPDATE durchgeführt. <br /> * Anschließend wir die Liste mit den gespeicherten Anfragen angezeigt. * @param request weitergereicht von <code>doGet()</code> * @param response weitergereicht von <code>doGet()</code> * @throws IOException * @see SDBStatistik#doGet(HttpServletRequest, HttpServletResponse) */ private void save(HttpServletRequest request, HttpServletResponse response) throws IOException { HttpSession session = request.getSession(true); } // Ausgabe der Liste, ggf. mit Umordnungsparameter if (request.getParameter("xmlparam") != null) process(xmlSource, xsltSource, out, request); else process(xmlSource, xsltSource, out); // Sourcen für die Transformierung vorbereiten, ... Source xmlSource = new StreamSource(new StringReader( getDocument(session).getAll())); // ... dabei wird immer der Stylesheet "stat_gespeicherte.xsl" verwendet Source xsltSource = new StreamSource(getDefaultStylesheet() + "/stat_gespeicherte.xsl"); response.setContentType("text/html; charset=ISO-8859-1"); String neuSortieren = request.getParameter("xmlparam"); // soll evtl. nur neu sortiert werden? Dann braucht kein neuer Resultset // erzeugt werden if (neuSortieren == null || !neuSortieren.startsWith("order_by_column")) try { String sql = "select lfd_nr, datum, frage, cookie from pra03.stat_statis setResultSet(sql, session); } catch (SQLException e) { doc.setError(e.toString()); } // ggf. ein neues Document anlegen? if (request.getParameter("requery") != null) doc = newDocument(session); * berücksichtigte Parameter: "requery", "xmlparam". <br /> * Das "query" ist fest (Liste der gespeicherten Anfragen). Passender * "stylesheet" ist ebenfalls fest. Die Liste wird immer im HTML-Format * ausgegeben und nicht als XML, daher kein "form" Parameter! * @param request weitergereicht von <code>doGet()</code> * @param response weitergereicht von <code>doGet()</code> * @throws IOException * @see SDBStatistik#doGet(HttpServletRequest, HttpServletResponse) */ private void liste(HttpServletRequest request, HttpServletResponse response) throws IOException { PrintWriter out = response.getWriter(); HttpSession session = request.getSession(true); // altes Document holen SDBDocument doc = getDocument(session); Datei: SDBStatistik.java 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 Datei: SDBStatistik.java 71 von 71 Seite: 8 von 8 } // Liste der gespeicherten Anfragen erzeugen liste(request, response); } catch (SQLException e) { doc.setError(e.toString()); } stm.close(); con.commit(); con.close(); Seite: 8 von 8 // UPDATE bzw. INSERT - Anweisung ausführen if (stm.execute()) setResultSet(stm.getResultSet(), session); else { int count = stm.getUpdateCount(); if (count > 0) doc.setExecute(update ? "update" : "insert", frage + " - wurde erfolgreich gespeichert", count); } // zu speichernde Werte in die SQL-Anweisung einsetzen PreparedStatement stm = con.prepareStatement(sql); stm.setString(1, frage); stm.setString(2, query); String strCookie = cookie.toString(); stm.setAsciiStream(3, new StringBufferInputStream(strCookie), strCookie.length()); Connection con = getConnection(); if (con == null) { doc.setError("Es konnte keine Datenbankverbindung hergestellt werden!"); } else { try { con.setAutoCommit(false); con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); String frage = request.getParameter("frage"); String query = request.getParameter("query"); // UPDATE oder INSERT - Anweisung vorbereiten if (!update) { sql = "INSERT INTO pra03.stat_statistiken (lfd_nr, datum, frage, query, coo + "SELECT IFNULL(MAX(lfd_nr),0) + 1, DATE('now'), ?, SQUEEZE(?), ? FR } else { sql = "UPDATE pra03.stat_statistiken SET datum = DATE('now'), " + "frage = ?, query = SQUEEZE(?), cookie = ? WHERE lfd_nr = " + statid; } // evtl. vorhandene STATID holen int statid = getStatId(request); boolean update = (statid != 0); String sql; Datei: SDBStatistik.java 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 } 534 }f Datei: SDBStatistik.java Anhang