• +49-(0)721-402485-12
Ihre Experten für XML, XQuery und XML-Datenbanken

Statische Analyse

Die erste Phase der Auswertung wird "Statische Analyse" genannt, weil sie nur von der Anweisung und dem statischen Kontext, aber nicht von den verarbeiteten Daten abhängt. Ein XQuery-Hauptmodul wird zunächst analysiert ("parse"). Der XQuery-Prolog wird benutzt, um den statischen Kontext zu erweitern und zu verändern. Die eigentliche Anfrage wird in einen Operatorbaum, d. h. eine interne Darstellung, überführt. Dabei wird geprüft, ob alle Typnamen, Namensraumpräfixe, Funktionsnamen und Variablennamen, die nicht in der Anfrage selbst definiert werden, im statischen Kontext vorliegen. Ist dies nicht der Fall, ist die Anfrage fehlerhaft und wird nicht weiter verarbeitet.

Statische Typprüfung

Im Rahmen der statischen Analyse kann eine XQuery-Implementierung bereits konstante Ausdrücke berechnen und einige Typzuweisungen und -prüfungen vornehmen (statische Typanalyse). So kann die folgende Anfrage schon in der statischen Analyse mit einem Fehler zurückgewiesen werden, weil die zu vergleichenden Variablen $i und $j einen inkompatiblen Typ haben:

import schema namespace x="http://example.org/x"
for $i in (1 to 3)
for $j as element(*, xs:string) in doc("Beispiel.xml")//x:Zahl
where $i gt $j
return
($i, "ist größer als", $j)

Ebenso würde ein Fehler erzeugt, wenn in der importierten Schemadefinition kein Element Zahl aus dem Namensraum "http://example.org/x" definiert ist oder wenn dieses nicht zu dem Typ element(*, xs:string) passt, weil es z. B. komplexen Inhalt hat. Man bemerkt hier, dass die statische Analyse konservativ ist, wenn es um die Beurteilung der Typsicherheit geht. Die Anfrage könnte ohne statische Typprüfung durchaus erfolgreich bearbeitet werden, ohne dass ein Typfehler auftritt, wenn nämlich in dem Dokument Beispiel.xml kein Element x:Zahl auftritt. In diesem Fall liefert die Anfrage eine leere Sequenz.

Das Verhalten der statischen Typprüfung kann auf den ersten Blick erstaunlich sein. So wird folgende Anfrage einen statischen Typfehler liefern, wenn im Schema das Vorkommen der Elemente Bonus und Gehalt nicht auf höchstens 1 begrenzt ist:

for $a in fn:collection("Angestellte")
return $a/Gehalt + $a/Bonus

Gerade bei statischer Typprüfung erweist sich die typeswitch-Anweisung als hilfreich ([Katz04] und [MBC+04]). Die Anweisung

typeswitch ($Angestellter)
case $a as element(*, Arzt_T) return $a/Fähigkeit
case $k as element(*, Pfleger_T) return $k/Zertifikat

wird die statische Typprüfung problemlos bestehen, während die folgende Anweisung, die bezüglich ihres dynamischen Verhaltens identisch zu der obigen ist, an der statischen Typprüfung scheitern wird:

if ($Angestellter instance of element(*, Arzt_T)
then $Angestellter/Fähigkeit
else if ($Angestellter instance of element(*, Pfleger_T)
then $Angestellter/Zertifikat

Das liegt daran, dass die Ableitungsregeln, wie sie in definiert sind, nicht beweisen können, dass auf das Element Zertifikat nur zugegriffen wird, wenn $Angestellter vom Typ Pfleger_T ist. In einer XQuery-Implementierung, die statische Typprüfung unterstützt, ist daher nur die erste Anfrageformulierung möglich. Die treat as-Anweisung wurde nur wegen der statischen Typprüfung eingeführt. Sie sichert einen Typ zu, so dass sich die statische Typprüfung darauf verlassen kann (dafür wird gegebenenfalls in der dynamischen Ausführung ein Fehler erzeugt, wenn die Zusicherung nicht zutrifft). So kann die obige Anfrage noch gerettet werden:

if ($Angestellter instance of element(*, Arzt_T)
then ($Angestellter treat as Arzt_T)/Fähigkeit
else if ($Angestellter instance of element(*, Pfleger_T)
then ($Angestellter treat as Pfleger_T)/Zertifikat

Statische Typprüfung ist besonders dann hilfreich, wenn Daten aus einem bekannten und definierten Eingabeschema in ein bekanntes und definiertes Ausgabeschema umgeformt werden sollen. Allerdings muss man sehr diszipliniert mit Typen umgehen, um keine unangenehmen Überraschungen zu erleben. Schon folgende triviale Anfrage liefert einen statischen Typfehler:

let $x as xs:decimal := 1
let $y as xs:integer := $x*2
return $y

Die Variable $x hat zwar einen Wert, der zum Typ xs:integer passt, wird aber von der statischen Typprüfung nicht zur Zuweisung an $y zugelassen, weil ihre Typannotation xs:decimal ist.

In Szenarien, in denen dieselbe XQuery-Anfrage mehrfach ausgeführt werden soll, ist zu erwarten, dass die XQuery-Implementierung ein Prepare/Execute-Modell anbietet, bei dem eine Anfrage nur einmal übersetzt (und damit der statischen Analyse unterzogen) wird, aber mehrfach ausgeführt wird (ggf. mit anderen Variablenwerten). Dann lohnt sich ein höherer Aufwand in der statischen Analyse besonders, denn dadurch kann oft der Aufwand während der dynamischen Ausführung reduziert werden.

 

Quelle: "XQuery – Grundlagen und fortgeschrittene Methoden", dpunkt-Verlag, Heidelberg (2004)

<< zurückvor >>