ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
WhereCircuit.cpp
Go to the documentation of this file.
1/**
2 * @file WhereCircuit.cpp
3 * @brief WhereCircuit method implementations and where-provenance evaluation.
4 *
5 * Implements:
6 * - Gate creation methods: @c setGate(), @c setGateInput(),
7 * @c setGateProjection(), @c setGateEquality().
8 * - @c toString(): human-readable gate representation for debugging.
9 * - @c evaluate(): recursive DFS that computes the set of @c Locator
10 * values for each output column position, propagating provenance
11 * through TIMES (Cartesian product), PLUS (union), PROJECT
12 * (column selection), and EQ (equijoin merging) gates.
13 * - @c WhereCircuit::Locator::operator<() and @c toString().
14 */
15#include "WhereCircuit.h"
16
17extern "C" {
18#include "provsql_utils.h"
19#include <unistd.h>
20}
21
22#include <cassert>
23#include <string>
24#include <fstream>
25#include <sstream>
26#include <cstdlib>
27
28using namespace std;
29
31{
32 return Circuit::setGate(u, type);
33}
34
35gate_t WhereCircuit::setGateProjection(const uuid &u, vector<int> &&infos)
36{
37 auto id = setGate(u, WhereGate::PROJECT);
38 projection_info[id]=infos;
39 return id;
40}
41
42gate_t WhereCircuit::setGateEquality(const uuid &u, int pos1, int pos2)
43{
44 auto id = setGate(u, WhereGate::EQ);
45 equality_info[id]=make_pair(pos1,pos2);
46 return id;
47}
48
49gate_t WhereCircuit::setGateInput(const uuid &u, string table, int nb_columns)
50{
51 auto id = setGate(u, WhereGate::IN);
52 input_token[id]=u;
53 input_info[id]=make_pair(table, nb_columns);
54 return id;
55}
56
58{
59 std::string op;
60 string result;
61
62 switch(getGateType(g)) {
63 case WhereGate::IN:
64 return input_info.find(g)->second.first+":"+to_string(input_info.find(g)->second.second)+":"+input_token.find(g)->second;
66 op="?";
67 break;
69 op="⊗";
70 break;
71 case WhereGate::PLUS:
72 op="⊕";
73 break;
75 op="Π[";
76 {
77 bool first=true;
78 for(auto i : projection_info.find(g)->second) {
79 if(!first)
80 op+=",";
81 op+=to_string(i);
82 first=false;
83 }
84 }
85 op+="]";
86 break;
87 case WhereGate::EQ:
88 op="=["+to_string(equality_info.find(g)->second.first)+","+to_string(equality_info.find(g)->second.second)+"]";
89 }
90
91 for(auto s: getWires(g)) {
93 result = op;
94 else if(!result.empty())
95 result+=" "+op+" ";
96 result+=toString(s);
97 }
98
99 return "("+result+")";
100}
101
102vector<set<WhereCircuit::Locator>> WhereCircuit::evaluate(gate_t g) const
103{
104 vector<set<Locator>> v;
105
106 switch(getGateType(g)) {
107 case WhereGate::IN:
108 {
109 string table=input_info.find(g)->second.first;
110 uuid tid=input_token.find(g)->second;
111 int nb_columns=input_info.find(g)->second.second;
112 for(int i=0;i<nb_columns;++i) {
113 set<Locator> s;
114 s.insert(Locator(table,tid,i+1));
115 v.push_back(s);
116 }
117 }
118 break;
119
120 case WhereGate::TIMES:
121 if(getWires(g).empty())
122 throw CircuitException("No wire connected to ⊗ gate");
123
124 for(auto g2 : getWires(g)) {
125 if(v.empty())
126 v=evaluate(g2);
127 else {
128 vector<set<Locator>> w=evaluate(g2);
129 v.insert(v.end(), w.begin(), w.end());
130 }
131 }
132 break;
133
134 case WhereGate::PLUS:
135 if(getWires(g).empty())
136 throw CircuitException("No wire connected to ⊕ gate");
137
138 for(auto g2 : getWires(g)) {
139 if(v.empty())
140 v=evaluate(g2);
141 else {
142 vector<set<Locator>> w=evaluate(g2);
143 if(w.size()!=v.size())
144 throw CircuitException("Incompatible inputs for ⊕ gate");
145
146 for(size_t k=0;k<v.size();++k) {
147 v[k].insert(w[k].begin(), w[k].end());
148 }
149 }
150 }
151 break;
152
154 if(getWires(g).size()!=1)
155 throw CircuitException("Not exactly one wire connected to Π gate");
156
157 {
158 vector<set<Locator>> w=evaluate(*getWires(g).begin());
159 vector<int> positions=projection_info.find(g)->second;
160 for(auto i : positions) {
161 if(i==0)
162 v.push_back(set<Locator>());
163 else
164 v.push_back(w[i-1]);
165 }
166 }
167 break;
168
169 case WhereGate::EQ:
170 if(getWires(g).size()!=1)
171 throw CircuitException("Not exactly one wire connected to = gate");
172
173 v=evaluate(*getWires(g).begin());
174 {
175 pair<int,int> positions=equality_info.find(g)->second;
176 v[positions.first-1].insert(v[positions.second-1].begin(), v[positions.second-1].end());
177 v[positions.second-1].insert(v[positions.first-1].begin(), v[positions.first-1].end());
178 }
179 break;
180
181 default:
182 throw CircuitException("Wrong type of gate");
183 }
184
185 return v;
186}
187
189{
190 if(this->table<that.table)
191 return true;
192 if(this->tid<that.tid)
193 return true;
194 return this->position<that.position;
195}
196
198{
199 return table + ":" + tid + ":" +to_string(position);
200}
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:48
std::string to_string(gate_t g)
Convert a gate_t to its decimal string representation.
Definition Circuit.h:249
Where-provenance circuit tracking column-level data origin.
WhereGate
Gate types for a where-provenance circuit.
@ PROJECT
Projection gate recording which attributes are kept.
@ EQ
Equijoin gate recording the joined attribute pair.
@ PLUS
Sum (disjunction) of child where-provenance sets.
@ TIMES
Product (conjunction) of child where-provenance sets.
@ IN
Input gate for a single base-relation tuple.
@ UNDETERMINED
Placeholder; should not appear in a complete circuit.
Exception type thrown by circuit operations on invalid input.
Definition Circuit.h:205
std::string uuid
UUID type used in this circuit (always std::string).
Definition Circuit.h:64
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:139
WhereGate getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:129
virtual gate_t setGate(const uuid &u, gateType type)
Create or update the gate associated with UUID u.
Definition Circuit.hpp:73
std::unordered_map< gate_t, std::pair< int, int > > equality_info
Joined attribute pair (pos1, pos2) for EQ gates.
std::unordered_map< gate_t, uuid > input_token
UUID of the source tuple for each IN gate.
std::unordered_map< gate_t, std::pair< std::string, int > > input_info
(table name, nb_columns) for each IN gate
std::unordered_map< gate_t, std::vector< int > > projection_info
Projected attribute positions for PROJECT gates.
gate_t setGateInput(const uuid &u, std::string table, int nb_columns)
Create an input gate for a specific table row.
gate_t setGateEquality(const uuid &u, int pos1, int pos2)
Create an equality (equijoin) gate for two attribute positions.
gate_t setGate(const uuid &u, WhereGate type) override
Create or update the gate associated with UUID u.
std::string toString(gate_t g) const override
Return a textual description of gate g for debugging.
gate_t setGateProjection(const uuid &u, std::vector< int > &&infos)
Create a projection gate with column mapping.
std::vector< std::set< Locator > > evaluate(gate_t g) const
Evaluate the where-provenance circuit at gate g.
Core types, constants, and utilities shared across ProvSQL.
Describes the origin of a single attribute value.
std::string toString() const
Return a human-readable representation of this locator.
bool operator<(Locator that) const
Lexicographic ordering for use in std::set.
int position
Zero-based column index within the tuple.
std::string table
Name of the source relation.
uuid tid
UUID (row token) of the source tuple.