<!DOCTYPE article PUBLIC "-//NLM//DTD JATS (Z39.96) Journal Archiving and Interchange DTD v1.0 20120330//EN" "JATS-archivearticle1.dtd">
<article xmlns:xlink="http://www.w3.org/1999/xlink">
  <front>
    <journal-meta />
    <article-meta>
      <title-group>
        <article-title>Where- und Why-Provenance für syntaktisch reiches SQL durch Kombination von Programmanalysetechniken</article-title>
      </title-group>
      <contrib-group>
        <contrib contrib-type="author">
          <string-name>Tobias Müller</string-name>
          <xref ref-type="aff" rid="aff0">0</xref>
        </contrib>
        <aff id="aff0">
          <label>0</label>
          <institution>Universität Tübingen Tübingen</institution>
          ,
          <country country="DE">Deutschland</country>
        </aff>
      </contrib-group>
      <pub-date>
        <year>2015</year>
      </pub-date>
      <fpage>84</fpage>
      <lpage>89</lpage>
      <abstract>
        <p>Das hier vorgestellte Verfahren ermöglicht die Analyse der Data Provenance von beliebigen SQL-Queries. Von der ebenfalls hier skizzierten Implementierung des Verfahrens werden unter anderem unterstützt: Subqueries, Aggregierungen, rekursive Queries und Window Functions. Eingabequeries werden zunächst in eine imperative Programmiersprache übersetzt. Der Programmcode wird mit einem neuen Verfahren analysiert, das auf bekannte Techniken aus dem Bereich der Programmanalyse aufbaut: Program Slicing, Kontrollflussanalyse und abstrakte Interpretation. Dadurch erhält man eine Berechnung von Where- und Why-Provenance auf der Granularitätsebene einzelner Tabellenzellen.</p>
      </abstract>
    </article-meta>
  </front>
  <body>
    <sec id="sec-1">
      <title>Categories and Subject Descriptors</title>
      <sec id="sec-1-1">
        <title>Languages</title>
        <p>Data provenance, SQL, program analysis</p>
      </sec>
    </sec>
    <sec id="sec-2">
      <title>EINFÜHRUNG</title>
      <p>
        Wir stellen einen neuen Ansatz für die Analyse der Data
Provenance [
        <xref ref-type="bibr" rid="ref5">5</xref>
        ] von SQL-Queries vor sowie eine
prototypische Implementierung davon. Der hier präsentierte Ansatz
erlaubt eine Analyse beliebiger (lesender) SQL-Queries. Die
algebraische Ebene wird nicht berührt, wodurch auch keine
algebraischen Restriktionen auftreten. Zum Beispiel ist [
        <xref ref-type="bibr" rid="ref1">1</xref>
        ]
eingeschränkt auf eine positive relationale Algebra.
      </p>
      <p>Die theoretische Anwendbarkeit auf beliebige Queries wird
dadurch erreicht, dass wir Eingabequeries zuerst in eine
imperative (Turing-vollständige) Programmiersprache
überset1.1</p>
    </sec>
    <sec id="sec-3">
      <title>Data Provenance</title>
      <p>2.</p>
    </sec>
    <sec id="sec-4">
      <title>BEISPIEL-QUERIES</title>
      <p>Im Folgenden werden zwei Beispiel-Queries und die
Ergebnisse der mit unserer Implementierung durchgeführten
Provenance-Analyse vorgestellt. Die erste Query greift ein
Beispiel aus der Literatur auf und die zweite wurde gewählt,
um die Mächtigkeit unseres Ansatzes zu demonstrieren.
agencies</p>
      <p>name based_in phone
t1 BayTours San Francisco 415-1200
t2 HarborCruz Santa Cruz 831-3000
externaltours</p>
      <p>name destination type
t3 BayTours San Francisco cable car
t4 BayTours Santa Cruz bus
t5 BayTours Santa Cruz boat
t6 BayTours Monterey boat
t7 HarborCruz Monterey boat
t8 HarborCruz Carmel train
price
$50
$100
$250
$400
$200
$90</p>
      <sec id="sec-4-1">
        <title>Abbildung 1: Bootstouren-Beispiel: Where- und</title>
      </sec>
      <sec id="sec-4-2">
        <title>Why-Provenance sind markiert mit sowie .</title>
      </sec>
      <sec id="sec-4-3">
        <title>Falls beides zutrifft, wird verwendet. Tupel sind</title>
        <p>mit ti bezeichnet.</p>
        <p>SELECT e.name, a.phone
FROM agencies AS a,</p>
        <p>externaltours AS e
WHERE a.name = e.name
AND e.type = b’oat’
output</p>
        <p>name phone
HarborCruz 831-3000
BayTours 415-1200
BayTours 1 415-1200
2
(a) SFW-Query (b) Ergebnis</p>
      </sec>
      <sec id="sec-4-4">
        <title>Abbildung 2: Welche Agenturen bieten Bootstouren an?</title>
        <p>2.1</p>
      </sec>
    </sec>
    <sec id="sec-5">
      <title>Bootstouren</title>
      <p>
        Diese Beispiel-Query stammt aus [
        <xref ref-type="bibr" rid="ref4">4</xref>
        ] und reproduziert die
dort gefundene Data Provenance. In Abbildung 1 sind die
Eingabetabellen dargestellt: agencies enthält Stammdaten
von Reiseveranstaltern und externaltours enthält deren
angebotene Touren. Die Query in Abbildung 2(a) findet
diejenigen Veranstalter, die Bootstouren im Angebot haben.
Die Ausgaberelation steht in Abbildung 2(b).
      </p>
      <p>Zelle 1 ist hier als Where-abhängig von t5: BayTours
markiert. Ein Blick auf die SQL-Query (SELECT e.name)
bestätigt dieses Ergebnis: denn hier werden Werte aus der
Eingabetabelle ins Resultat kopiert. Dies entspricht den
Kriterien von Where-Provenance, wie wir sie in Abschnitt 1
angegeben haben.</p>
      <p>Die Markierungen zeigen außerdem Why-Abhängigkeiten
von t1: BayTours , t5: BayTours und t5: boat . Diese drei
Werte werden im WHERE-Teil der SQL-Query für die
Joinund Filterkriterien benutzt.</p>
      <p>1 und 2 zeigen, dass die wertemäßig nicht
unterscheidbaren BayTours und BayTours anhand ihrer jeweiligen
Provenance (t5 oder t6) unterscheidbar werden.</p>
      <p>3 veranschaulicht, dass Data Provenance entgegen der
wörtlichen Bedeutung auch in Vorwärts-Richtung
funktioniert. Die Farbmarkierungen besagen, dass t1: 415-1200
mit zwei Werten von der Ausgabetabelle auf Werteebene
zusammenhängt. Konkret wird hier die Telefonnummer zwei
Mal kopiert.
2.2</p>
    </sec>
    <sec id="sec-6">
      <title>Endlicher Automat</title>
      <p>Die hier vorgestellte Provenance-Analyse einer rekursiven
Query ist nach dem Wissen der Autoren mit keiner anderen
existierenden Implementierung möglich. Die Query besteht
auch aus einer Anzahl von Funktionsaufrufen.
Interessante Ausschnitte des Ergebnisses unserer Provenance-Analyse
werden erneut mit farbigen Markierungen dargestellt.</p>
      <p>Abbildung 3(a) zeigt die Eingaberelationen. compounds
enthält chemische Summenformeln und ihre Bezeichnungen.
In Tabelle fsm ist ein endlicher Automat codiert, der die
Syntax dieser Formeln überprüfen kann.</p>
      <p>Die SQL-Query in Abbildung 3(b) führt diesen
Automaten aus. Da alle Formeln in compounds parallel verarbeitet
werden, existieren mehrere Automaten parallel. In jedem
Schritt eines Automaten wird das erste Zeichen einer
Formel abgeschnitten und der entsprechende Zustandsübergang
durchgeführt. Aktueller Zustand und “Restformel” sind in
der Tabelle run gespeichert, die bei jedem Schritt der
Automaten neu berechnet wird. In Abbildung 3(c) sind zwei
Versionen von run abgebildet: direkt nach der
Initialisierung (step: 0) und nach drei Schritten (step: 3). Wenn die
Formeln vollständig verzehrt sind, beendet sich der rekursive
Teil der Query. Als Endresultat werden die
Ableitungsschritte für citrate (siehe Abbildung 3(d)) zurückgegeben.</p>
      <p>Die Where-Provenance von 4 zeigt an, von welchen
Werten O73- abgeleitet wurde. Dazu zählt erst einmal die
vollständige Summenformel t9: C6H5O73- . Aber auch alle
Zwischenzustände werden von der Analyse erfasst, wie anhand
der Markierungen in Abbildung 3(c) zu erkennen ist.</p>
      <p>Die interessantesten Why-Abhängigkeiten von 4 sind
innerhalb der Tupel t12 und t13 zu finden. Das sind nämlich
gerade die Kanten des Automaten, die besucht wurden, um
O73- abzuleiten.
compounds
compound
t9 citrate
t11 hydronium HC36HO1+2O6
t10 glucose
formula</p>
      <p>C6H5O73t12
t13
t14
t15
t16
t17
t18
fsm
source
0
1
1
1
2
2
3</p>
      <p>labels
A..Za..z
A..Za..z0..9
0..9
+0..9
+A..Za..z
target final
1 false
1 true
2 true
3 true
2 false
3 false
1 true</p>
      <p>WITH RECURSIVE
run(compound, step, state, formula) AS (</p>
      <p>SELECT compound, 0, 0, formula
FROM compounds
UNION ALL
SELECT this.compound,
this.step + 1 AS step,
edge.target AS state,
right(this.formula, -1) AS formula
FROM run AS this,</p>
      <p>fsm AS edge
WHERE length(this.formula) &gt; 0
AND this.state = edge.source
AND strpos(edge.labels,</p>
      <p>left(this.formula, 1)) &gt; 0
)
SELECT r.step, r.state, r.formula
FROM run AS r
WHERE r.compound = c’itrate’
run
compound step state formula
citrate 0 0
C6H5O73glucose 0 50 C6H12O6
hydronium 0 0 H3O+
.
.</p>
      <p>.</p>
      <p>run
compound step state formula
citrate 3 1
5O73glucose 3 1 12O6
hydronium 3 1 +
output
step state formula
0 0
C6H5O731 1
6H5O732 1
H5O733 1
5O734 1
O735 1 73- 4
6 1
37 2
8 3
1 def query(agencies , externaltours ):
2 #FROM clause: read source tables
3 rows = []
4 for tupVar2 in agencies:
5 for tupVar3 in externaltours:
6 rs = {"tupVar2": tupVar2 ,
7 "tupVar3": tupVar3 ,
8 "tmp": {},
9 }
10 rows.append(rs)
11 #WHERE clause: compute where predicate
12 rowIdx = 0
13 while rowIdx &lt; len(rows):
14 rs = rows[rowIdx]
15 col4 = rs["tupVar2"]["name"]
16 col5 = rs["tupVar3"]["name"]
17 res6 = col4 == col5
18 col7 = rs["tupVar3"]["type"]
19 val8 = "boat"
20 res9 = col7 == val8
21 res10 = res6 and res9
22 rs["tmp"]["where"] = res10
23 rowIdx = rowIdx + 1
24 #WHERE clause: apply where predicate
25 filtered = []
26 for rs in rows:
27 if rs["tmp"]["where"]:
28 filtered.append(rs)
29 rows = filtered
30 #SELECT clause: compute result columns
31 rowIdx = 0
32 while rowIdx &lt; len(rows):
33 rs = rows[rowIdx]
34 col11 = rs["tupVar3"]["name"]
35 col12 = rs["tupVar2"]["phone"]
36 rs["tmp"]["eval0"] = col11
37 rs["tmp"]["eval1"] = col12
38 rowIdx = rowIdx + 1
39 #SELECT clause: assemble result table
40 ship = []
41 for rs in rows:
42 row = {}
43 row["name"] = rs["tmp"]["eval0"]
44 row["phone"] = rs["tmp"]["eval1"]
45 ship.append(row)
46 return ship</p>
      <sec id="sec-6-1">
        <title>Listing 1: Übersetzung der Bootstouren-Query. Es findet (noch) keine Code-Optimierung statt.</title>
        <p>Zuletzt wird mit 5 noch die Einsicht transportiert, dass
die Schrittzahl des Automaten keinerlei Einfluss auf die
Ableitung von citrate hat. Die Markierungen zeigen lediglich
eine Where-Provenance zwischen den Schritten 0 bis 8
an, die auf das Inkrementieren zurückzuführen ist. Es gibt
keine Why-Provenance, das heißt keine (versehentliche)
Beeinflussung des Endresultats durch die Schrittzählung.</p>
      </sec>
    </sec>
    <sec id="sec-7">
      <title>3. SQL-ÜBERSETZUNG</title>
      <p>Die zu analysierenden SQL-Queries werden in unserer
Implementierung zunächst in Python-Programme übersetzt.
Python hat als Zwischensprache den Vorteil, sehr
leichtgewichtig und daher für die weitere Analyse gut zugänglich</p>
      <sec id="sec-7-1">
        <title>Abbildung 4: Hauptelemente der Provenance</title>
      </sec>
      <sec id="sec-7-2">
        <title>Analyse</title>
        <p>zu sein. Es wird außerdem von Kooperationspartnern
eingesetzt. Ein Nachteil von Python ist die schlechtere
Performance (gegenüber Sprachen wie C). Es gibt jedoch keinen
Hinderungsgrund, die mit Hilfe von Python erarbeiteten
Techniken der Provenance-Analyse nicht auf andere Sprachen wie
LLVM zu übertragen.</p>
        <p>
          Damit würden wir einem aktuellen Forschungstrend in der
Datenbank-Community folgen, SQL nicht länger mit dem
Volcano-Iterator-Model zu implementieren, sondern Queries
just-in-time zu kompilieren (siehe [
          <xref ref-type="bibr" rid="ref9">9</xref>
          ]).
        </p>
        <p>Aus Platzgründen wird der von uns verwendete
Übersetzer nur anhand eines Beispiels vorgestellt. Listing 1 zeigt,
wie die Übersetzung von Query 2(a) aussieht. Je Query oder
Sub-Query wird eine eigene Python-Funktion erzeugt. Die
Argumente und Rückgabewerte sind Tabellen, die in
Python als Listen von Dictionaries implementiert sind. Die
SQL-Klauseln einer Query werden in eine Reihenfolge
gebracht, die eine Berechnung im imperativen Paradigma
erlaubt: SFW wird beispielsweise zu FWS.</p>
      </sec>
    </sec>
    <sec id="sec-8">
      <title>4. PROVENANCE-ANALYSE</title>
    </sec>
    <sec id="sec-9">
      <title>IN ZWEI STUFEN</title>
      <p>Wie in Abbildung 4 dargestellt, teilt sich die
ProvenanceAnalyse im Wesentlichen auf zwei Schritte auf: 1
Kontrollflussanalyse (dynamisch, zur Laufzeit) und 2 abstrakte
Interpretation (statisch, zur Kompilierzeit).</p>
      <p>Die Kontrollflussanalyse ist dafür zuständig, alle für den
Kontrollfluss benötigten Prädikate zu bestimmen und deren
Werte zu speichern. Beispielsweise würde bei der
Ausführung einer if-Anweisung die zugehörige
Kontrollflussinformation darin bestehen, ob entweder der if- oder der
elseRumpf ausgeführt wird. Die Information kann durch einen
einzelnen booleschen Wert codiert werden.</p>
      <p>In Phase 2 findet die eigentliche Provenance-Analyse
statt. Hier wird das Kontrollfluss-Log benutzt, um den
tatsächlichen Ausführungspfad nachvollziehen zu können, den
das Programm zur Laufzeit genommen hat.</p>
      <p>In Abschnitt 4.1 wird die Motivation für die soeben
skizzierte Struktur geschildert sowie ein Bezug zu Ergebnissen
der theoretischen Informatik hergestellt, die einer
Programmanalyse harte Grenzen setzt. Abschnitt 5 erläutert die
beiden Analyseschritte genauer sowie deren Implementierung in
Python.</p>
    </sec>
    <sec id="sec-10">
      <title>4.1 Linearisierung</title>
      <p>Eine rein statische Provenance-Analyse ist im
Allgemeinen für Python-Programme nicht möglich, denn Python ist
eine Turing-vollständige Programmiersprache. Der Satz von
Rice besagt, dass nicht-triviale Laufzeiteigenschaften (wie
Data Provenance) für allgemeine Turing-Maschinen nicht
algorithmisch entscheidbar sind.</p>
      <p>Um den Konsequenzen des Satzes von Rice zu entgehen,
ändert dieses Verfahren die Voraussetzungen. Wie in
Abbildung 4 dargestellt, wird der zur Laufzeit
aufgezeichnete Kontrollfluss an die abstrakte Interpretation übergeben.
Zu Kontrollflussanweisungen zählen unter anderem if- und
while-Anweisungen. Für diese Konstrukte besteht das
zugehörige Kontrollfluss-Log lediglich aus einer Folge von
booleschen Werten:
• Wird entweder if oder else ausgeführt?
• Wird der Rumpf von while (nochmal) ausgeführt oder
wird die Schleife beendet?</p>
      <p>Dieses Log steht also während der statischen Analyse zur
Verfügung. Das heißt, die statische Analyse weiß für
jedes if x:, ob es in Wirklichkeit entweder ein if True: oder
if False: ist - je nachdem, ob True oder False im Log steht.</p>
      <p>Mit dem Kontrollfluss-Log findet deshalb eine
Linearisierung des Python-Programms statt. Die Abfolge der
Anweisungen im Programm ist statisch festgelegt, weil der
Kontrollfluss festgelegt ist. Kontrollfluss-Konstrukte verhalten
sich nun transparent und im einfachsten Fall besteht die
restliche Analyse des Programms nur noch darin,
Zuweisungen an Variablen zu betrachten.</p>
      <p>Dadurch liegt in 2 keine Turing-Vollständigkeit mehr
vor. Der Satz von Rice gilt nicht mehr und eine
ProvenanceAnalyse ist (quasi-statisch) möglich.</p>
      <p>Das Beispiel in Abschnitt 5 wird das verdeutlichen.
4.2</p>
    </sec>
    <sec id="sec-11">
      <title>Granularität und Auflösung</title>
      <p>
        Als Granularität (oder level of detail) wird in [
        <xref ref-type="bibr" rid="ref7">7</xref>
        ]
bezeichnet, was die kleinstmöglichen Datenstrukturen sind, die in
einer Provenance-Analyse berücksichtigt werden. Meist sind
das entweder Tupel oder Tabellenzellen. In dem hier
besprochenen Ansatz besteht die Granularität in Zellen.
      </p>
      <p>Orthogonal dazu wollen wir den Begriff Auflösung
verwenden, um damit die Größe der Programmfragmente zu
bezeichnen, für die am Ende der Analyse eine Data
Provenane ausgegeben wird.</p>
      <p>Beispielsweise könnte es in einer niedrigen Auflösung so
sein, dass das Programm nur als Ganzes analysiert wird.
Das heißt, die Data Provenance bezieht sich gerade auf die
Ein/Ausgabedaten des Programms selbst und zeigt an, wie
die Ausgabedaten von den Eingabedaten abhängig sind.
Eine andere Variante bestünde darin, für jeden einzelnen
Ausdruck in diesem Programm eine Data Provenance
auszugeben. Das heißt, für einen Ausdruck wie b+c wird als Ergebnis
die Abhängigkeit von den Einzelwerten b sowie c
ausgegeben. Hier ist die Auflösung sehr hoch.</p>
      <p>Von uns wurde als Auflösung die Ebene von
Funktionsaufrufen benutzerdefinierter Funktionen gewählt. Im
Ergebnis der Provenance-Analyse sind deshalb die Parameter und
Rückgabewerte von Funktionsaufrufen aufgeführt sowie die
dazugehörende Data Provenance.</p>
    </sec>
    <sec id="sec-12">
      <title>5. IMPLEMENTIERUNG</title>
      <p>Als Grundlage für die Implementierung der
ProvenanceAnalyse dient CPython in Version 3.4. Dabei handelt es sich
um die stabile und zum Zeitpunkt des Schreibens dieses
Artikels aktuelle Referenzimplementation von Python. Intern
übersetzt sie Quelltext in Bytecode, der anschließend in der
zugehörigen virtuellen Maschine (VM) ausgeführt wird. Als
Zwischenschritt während der Übersetzung erzeugt CPython
einen Abstract Syntax Tree (AST), auf dessen Basis wir das
Analyseverfahren implementiert haben.</p>
      <p>In Abbildung 5 ist dargestellt, wie die einzelnen
PythonKomponenten zusammenarbeiten. Mit weißem Hintergrund
dargestellt sind die ein/ausgehenden Datensätze
(Relationen) sowie der Python Programmcode, der analysiert
wer</p>
      <sec id="sec-12-1">
        <title>Abbildung 5:</title>
      </sec>
      <sec id="sec-12-2">
        <title>Implementierung</title>
      </sec>
      <sec id="sec-12-3">
        <title>Komponenten der</title>
      </sec>
      <sec id="sec-12-4">
        <title>Python</title>
        <p>den soll. Grau hinterlegt sind Komponenten der
CPythonImplementierung selbst, die unmodifiziert verwendet
werden. In schwarz ist, was wir zusätzlich implementiert haben.</p>
        <p>Während der Analyse wird das zu einem AST
kompilierte Eingabeprogramm zwei Mal verarbeitet. In Schritt 1
wird es zunächst instrumentiert. Dabei werden zusätzliche
Python-Anweisungen eingefügt, die einerseits die
vorhandene Funktionalität nicht verändern und andererseits für
das Schreiben des Kontrollfluss-Log zuständig sind. Das so
modifizierte Programm wird zu Bytecode kompiliert und
anschließend mit der VM ausgeführt. Während der
Ausführung werden Eingabe/Ausgabedaten gelesen/geschrieben
sowie das Kontrollfluss-Log produziert. Schritt 1 wird in
Abschnitt 5.1 genauer beschrieben.</p>
        <p>In Schritt 2 wird das unmodifizierte (nicht
instrumentierte) Eingabeprogramm erneut hergenommen und mit
Hilfe des Kontrollfluss-Logs die eigentliche Provenance-Analyse
durchgeführt. Eine genaue Beschreibung dieses Teils folgt in
Abschnitt 5.2. Bemerkenswert ist, dass hier keine
Eingabedaten benötigt werden. Die abstrakte Interpretation findet
auf symbolischer Ebene statt, das heißt es wird lediglich
ermittelt, wie die im Programm benutzten Variablen
voneinander abhängig sind. Dies genügt, um sowohl Why- als
auch Where-Provenance zu berechnen.
5.1</p>
      </sec>
    </sec>
    <sec id="sec-13">
      <title>Instrumentierung</title>
      <p>Allgemein gesprochen müssen diejenigen
Sprachkonstrukte instrumentiert werden, deren Verhalten bezüglich Data
Provenance sich nicht durch rein statische Analyse
bestimmen lässt. Bisher instrumentieren wir zwei Kategorien von
Sprachkonstrukten: (i) Kontrollfluss und (ii) Indexzugriff.</p>
      <p>Listing 2 zeigt ein bereits instrumentiertes
Programmfragment, das je ein Beispiel für beide Fälle enthält. Die
Funktion dow() erhält als Argumente den Wochentag als
Zahlenwert (num = 0...6) und eine Liste mit Namen von
Wochentagen. Sie liefert eine String-Repräsentation zurück.
Sie unterstützt außerdem zwei verschiedene
Datumsformate: Wochenbeginn am Montag (fmt = True) oder am Sonntag
(fmt = False).
6</p>
    </sec>
    <sec id="sec-14">
      <title>Abstrakte Interpretation</title>
      <p>Nachdem die Kontrollfluss-Logs erzeugt worden sind, kann
jetzt die eigentliche Ableitung der Data Provenance
stattfinden. Dazu werden wie in Abbildung 5 dargestellt, lediglich
das Eingabeprogramm zusammen mit den Logs verwendet.
Daten sind an dieser Phase nicht beteiligt. Dementsprechend
werden auch keine Berechnungen von Werten ausgeführt,
was Systemressourcen spart.</p>
      <p>Die abstrakte Interpretation wird durchgeführt, indem alle
Anweisungen des Programms in derselben Reihenfolge
nachvollzogen werden, in der sie auch zur Laufzeit ausgeführt
wurden. Die richtige Reihenfolge einzuhalten ist dank des
aufgezeichneten Kontrollflusses sehr einfach. Immer dann,
wenn eine Kontrollflussentscheidung benötigt wird (zum
Beispiel: if- oder else-Block ausführen), kann diese Information
im Kontrollfluss-Log nachgeschlagen werden.</p>
      <p>Where-Provenance.</p>
      <p>Während die Anweisungen nacheinander interpretiert
wer1 days = [(),(),() ,
2 () ,() ,() ,()]
3 def dow(num , fmt , days ):
4 if fmt: #fmt: True
5 pos = (num +()) % ()
6 else:
7 pos = num
8 res = days[pos] #pos: 5
9 return res
10 dow((), (), days) #returns: ()</p>
      <sec id="sec-14-1">
        <title>Listing 3: Pseudocode aus Sicht der abstrakten</title>
      </sec>
      <sec id="sec-14-2">
        <title>Interpretation.</title>
        <p>den, wird eine Variablenumgebung gepflegt und mit jeder
interpretierten Anweisung gegebenenfalls aktualisiert. Die
Umgebung beinhaltet alle derzeit sichtbaren Variablen
zusammen mit ihren jeweiligen Abhängigkeiten von den
Eingabedaten.</p>
        <p>Der Aufbau dieser Umgebung ist ein inkrementeller
Prozess. Jede Zuweisung einer Variablen, wie zum Beispiel in
a = b, wird eine entsprechende Aktualisierung der
Umgebung nach sich ziehen. In diesem Beispiel müssten alle
Abhängigkeiten von b nach a kopiert werden.</p>
        <p>Auf diese Weise wird die Umgebung ständig aktuell
gehalten und referenziert in ihren Abhängigkeiten stets die
Eingabedaten. Am Ende der Analyse braucht nur noch die
gewünschte Variable, zum Beispiel res, in der Umgebung
nachgeschlagen zu werden.</p>
        <p>Why-Provenance.</p>
        <p>Die Ausführung von Anweisungen in einem if- oder
elseRumpf sind abhängig vom zugehörigen Prädikat des
if/elseKonstrukts. Diese Abhängigkeit modellieren wir als
WhyProvenance.</p>
        <p>In der Analyse wird dazu eine Menge an Abhängigkeiten
gepflegt, die dem Kontrollfluss selbst zugeordnet ist. Bei
Eintritt in den Rumpf einer if-Anweisung wird dem
Kontrollfluss eine Abhängigkeit vom Prädikat dieser if-Anweisung
zugeordnet. Allen Zuweisungen, die in diesem Rumpf
ausgeführt werden, werden dann wiederum die Abhängigkeiten
des Kontrollflusses in Form von Why-Provenance
hinzugefügt.</p>
        <p>Nachdem der if-Rumpf abgearbeitet ist, werden die
Abhängigkeiten des Kontrollflusses wieder zurückgesetzt. Ob
if- oder else-Rumpf ausgeführt werden, macht hier keinen
Unterschied: in beiden Fällen gilt dasselbe Prädikat. Die
Interpretation von Schleifen funktioniert analog.</p>
        <p>Beispiel-Analyse.</p>
        <p>In Listing 3 ist abgedruckt, wie sich das aus dem
Instrumentierungsschritt bereits bekannte Programmfragment in
Schritt 2 der Provenance-Analyse darstellen würde. Alle
vorkommenden atomaren Werte sind durch () ersetzt
worden. Code in dieser Form wird nicht erzeugt, doch das
Listing veranschaulicht, auf welcher Basis die abstrakte
Interpretation arbeitet.</p>
        <p>Anhand dieses Beispiels wird nun dargestellt, wie die
Ableitung der Data Provenance funktioniert. Das Ergebnis
dieser Analyse besteht gemäß der gewählten Granularität und
Auflösung (siehe Abschnitt 4.2) darin, wie die Variable res
von den Funktionsparametern abhängig ist.</p>
        <p>Um die Analyse zu initialisieren, werden die in den
Funk</p>
        <sec id="sec-14-2-1">
          <title>Abhängigkeiten Kontrollfluss Variablen Zeile</title>
          <p>3 (dow()) num: 7e
fmt: 8e
4 (if fmt:) 8y num: 7e
fmt: 8e
5 (pos=) 8y num: 7e
fmt: 8e
pos: 8y, 7e
8 (res=) num: 7e
fmt: 8e
pos: 8y, 7e
res: 8y, 7y, 5e</p>
        </sec>
      </sec>
      <sec id="sec-14-3">
        <title>Tabelle 1: Ableitung der Provenance</title>
        <p>Wir versprechen uns eine Performanceverbesserung von
dieser neuen Implementierung.</p>
        <p>
          Als weitere Implementierung ist LLVM geplant, um
mittels [
          <xref ref-type="bibr" rid="ref9">9</xref>
          ] kompilierte Queries analysieren zu können.
        </p>
        <p>
          Habitat [
          <xref ref-type="bibr" rid="ref8">8</xref>
          ] ist ein SQL-Debugger, der eingesetzt wird, um
potentiell fehlerhafte Queries direkt auf SQL-Sprachebene
zu untersuchen. Dazu wird die verdächtige Query von
Habitat instrumentiert und vom RDBMS ausgeführt. Die
instrumentierte Query beobachtet (= zeichnet auf), wie die
potentiell fehlerhafte Ergebnisrelation berechnet wird und
präsentiert dem Benutzer diese Beobachtungen. Bei großen
Eingabetabellen besteht das Problem, dass man vielleicht
nur an der Beobachtung der Berechnung eines einzelnen
Ergebnistupels interessiert ist, aber auch tausende andere
Tupel zusätzlich beobachtet. Um genau die für ein bestimmtes
Ergebnistupel relevanten Eingabetupel herauszufinden, ist
Data Provenance genau das richtige Werkzeug. Eine
Kombination von diesen beiden Techniken wird von uns
angestrebt.
        </p>
      </sec>
    </sec>
  </body>
  <back>
    <ref-list>
      <ref id="ref1">
        <mixed-citation>
          [1]
          <string-name>
            <given-names>Y.</given-names>
            <surname>Amsterdamer</surname>
          </string-name>
          ,
          <string-name>
            <given-names>D.</given-names>
            <surname>Deutch</surname>
          </string-name>
          , and
          <string-name>
            <given-names>V.</given-names>
            <surname>Tannen</surname>
          </string-name>
          .
          <article-title>Provenance for Aggregate Queries</article-title>
          .
          <source>In Proc. PODS</source>
          , pages
          <fpage>153</fpage>
          -
          <lpage>164</lpage>
          . ACM,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref2">
        <mixed-citation>
          [2]
          <string-name>
            <given-names>P.</given-names>
            <surname>Buneman</surname>
          </string-name>
          ,
          <string-name>
            <given-names>S.</given-names>
            <surname>Khanna</surname>
          </string-name>
          , and
          <string-name>
            <given-names>W.-C.</given-names>
            <surname>Tan</surname>
          </string-name>
          .
          <article-title>Why and Where: A Characterization of Data Provenance</article-title>
          .
          <source>In Proc. ICDT</source>
          , pages
          <fpage>316</fpage>
          -
          <lpage>330</lpage>
          . Springer,
          <year>2001</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref3">
        <mixed-citation>
          [3]
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          .
          <source>Program Slicing and Data Provenance. IEEE Data Engineering Bulletin</source>
          ,
          <volume>30</volume>
          (
          <issue>4</issue>
          ):
          <fpage>22</fpage>
          -
          <lpage>28</lpage>
          ,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref4">
        <mixed-citation>
          [4]
          <string-name>
            <given-names>J.</given-names>
            <surname>Cheney</surname>
          </string-name>
          ,
          <string-name>
            <given-names>L.</given-names>
            <surname>Chiticariu</surname>
          </string-name>
          , and
          <string-name>
            <given-names>W.-C.</given-names>
            <surname>Tan</surname>
          </string-name>
          . Provenance in Databases: Why, How, and
          <string-name>
            <surname>Where</surname>
          </string-name>
          . Foundations and Trends in Databases,
          <volume>1</volume>
          (
          <issue>4</issue>
          ),
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref5">
        <mixed-citation>
          [5]
          <string-name>
            <given-names>Y.</given-names>
            <surname>Cui</surname>
          </string-name>
          ,
          <string-name>
            <given-names>J.</given-names>
            <surname>Widom</surname>
          </string-name>
          , and
          <string-name>
            <given-names>J.</given-names>
            <surname>Wiener</surname>
          </string-name>
          .
          <article-title>Tracing the Lineage of View Data in a Warehousing Environment</article-title>
          .
          <source>ACM TODS</source>
          ,
          <volume>25</volume>
          (
          <issue>2</issue>
          ),
          <year>2000</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref6">
        <mixed-citation>
          [6]
          <string-name>
            <given-names>B.</given-names>
            <surname>Glavic</surname>
          </string-name>
          and
          <string-name>
            <given-names>G.</given-names>
            <surname>Alonso</surname>
          </string-name>
          .
          <article-title>Provenance for Nested Subqueries</article-title>
          .
          <source>In Proc. EDBT</source>
          , pages
          <fpage>982</fpage>
          -
          <lpage>993</lpage>
          . ACM,
          <year>2009</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref7">
        <mixed-citation>
          [7]
          <string-name>
            <given-names>B.</given-names>
            <surname>Glavic</surname>
          </string-name>
          and
          <string-name>
            <given-names>K.</given-names>
            <surname>Dittrich</surname>
          </string-name>
          .
          <article-title>Data Provenance: A Categorization of Existing Approaches</article-title>
          . In BTW, volume
          <volume>7</volume>
          , pages
          <fpage>227</fpage>
          -
          <lpage>241</lpage>
          . Citeseer,
          <year>2007</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref8">
        <mixed-citation>
          [8]
          <string-name>
            <given-names>T.</given-names>
            <surname>Grust</surname>
          </string-name>
          and
          <string-name>
            <given-names>J.</given-names>
            <surname>Rittinger</surname>
          </string-name>
          .
          <article-title>Observing SQL Queries in their Natural Habitat</article-title>
          .
          <source>ACM TODS</source>
          ,
          <volume>38</volume>
          (
          <issue>1</issue>
          ),
          <year>2013</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref9">
        <mixed-citation>
          [9]
          <string-name>
            <given-names>T.</given-names>
            <surname>Neumann</surname>
          </string-name>
          .
          <article-title>Efficiently Compiling Efficient Query Plans for Modern Hardware</article-title>
          .
          <source>In Proc. VLDB</source>
          ,
          <year>2011</year>
          .
        </mixed-citation>
      </ref>
      <ref id="ref10">
        <mixed-citation>
          [10]
          <string-name>
            <given-names>M.</given-names>
            <surname>Weiser</surname>
          </string-name>
          .
          <source>Program Slicing. IEEE Transactions on Software Engineering</source>
          , SE-
          <volume>10</volume>
          (
          <issue>4</issue>
          ),
          <year>1984</year>
          .
        </mixed-citation>
      </ref>
    </ref-list>
  </back>
</article>