27#include "catalog/pg_type.h"
28#include "utils/uuid.h"
29#include "utils/lsyscache.h"
39#include <unordered_map>
67 const std::set<gate_t> &inputs,
71 std::unordered_map<gate_t, bool> provenance_mapping;
72 initialize_provenance_mapping<bool>(constants, c, provenance_mapping, [](
const char *v) {
99 text *result = (text *) palloc(VARHDRSZ + out.size());
100 SET_VARSIZE(result, VARHDRSZ + out.size());
101 memcpy(VARDATA(result), out.c_str(), out.size());
102 PG_RETURN_TEXT_P(result);
118 const std::set<gate_t> &inputs,
121 std::unordered_map<gate_t, semiring::why_provenance_t> provenance_mapping;
123 initialize_provenance_mapping<semiring::why_provenance_t>(
131 provsql_error(
"Complex Why-semiring values for input tuples not currently supported.");
132 single.insert(std::string(v));
133 result.insert(std::move(single));
143 std::ostringstream oss;
145 bool firstOuter =
true;
146 for (
const auto &inner : prov) {
147 if (!firstOuter) oss <<
",";
150 bool firstInner =
true;
151 for (
const auto &label : inner) {
152 if (!firstInner) oss <<
",";
160 std::string out = oss.str();
161 text *result = (text *) palloc(VARHDRSZ + out.size());
162 SET_VARSIZE(result, VARHDRSZ + out.size());
163 memcpy(VARDATA(result), out.c_str(), out.size());
164 PG_RETURN_TEXT_P(result);
181 const std::set<gate_t> &inputs,
185 std::unordered_map<gate_t, std::string> provenance_mapping;
186 initialize_provenance_mapping<std::string>(
187 constants, c, provenance_mapping,
189 return std::string(v);
200 text *result = (text *) palloc(VARHDRSZ + s.size());
201 SET_VARSIZE(result, VARHDRSZ + s.size());
202 memcpy(VARDATA(result), s.c_str(), s.size());
203 PG_RETURN_TEXT_P(result);
220 const std::set<gate_t> &inputs,
224 std::unordered_map<gate_t, unsigned> provenance_mapping;
225 initialize_provenance_mapping<unsigned>(constants, c, provenance_mapping, [](
const char *v) {
235 PG_RETURN_INT32((int32) out);
246 if (SPI_connect() != SPI_OK_CONNECT)
249 char *table_name = get_rel_name(table);
255 constexpr size_t nb_max_uuid_value = 10000000;
257 StringInfoData join_query;
258 initStringInfo(&join_query);
259 bool drop_table =
false;
267 if(uuids.size() == 0) {
268 appendStringInfo(&join_query,
269 "SELECT value, provenance FROM \"%s\" WHERE 'f'", table_name);
270 }
else if(uuids.size() <= nb_max_uuid_value) {
271 appendStringInfo(&join_query,
272 "SELECT value, provenance FROM \"%s\" t JOIN (VALUES", table_name);
275 appendStringInfo(&join_query,
"%s('%s'::uuid)", first?
"":
",", u.c_str());
279 appendStringInfo(&join_query,
") AS u(id) ON t.provenance=u.id");
281 const char *create_temp_table =
"CREATE TEMP TABLE tmp_uuids(id uuid);";
282 if (SPI_exec(create_temp_table, 0) != SPI_OK_UTILITY) {
288 constexpr size_t batch_size = 1000;
290 for (
size_t offset = 0; offset < uuids.size(); offset += batch_size) {
291 StringInfoData insert_query;
292 initStringInfo(&insert_query);
293 appendStringInfo(&insert_query,
"INSERT INTO tmp_uuids VALUES ");
295 size_t end = std::min(offset + batch_size, uuids.size());
296 for (
size_t i = offset; i < end; ++i) {
297 appendStringInfo(&insert_query,
"('%s')%s", uuids[i].c_str(), (i + 1 == end) ?
"" :
",");
300 int retval=SPI_exec(insert_query.data, 0);
301 pfree(insert_query.data);
303 if(retval != SPI_OK_INSERT) {
310 appendStringInfo(&join_query,
311 "SELECT value, provenance FROM \"%s\" t JOIN tmp_uuids u ON t.provenance = u.id", table_name);
314 if (SPI_exec(join_query.data, 0) != SPI_OK_SELECT) {
347 std::vector<std::string> inputs_uuid;
348 std::transform(inputs.begin(), inputs.end(), std::back_inserter(inputs_uuid), [&c](
auto x) {
356 return pec_why(constants, c, g, inputs, drop_table);
365 throw CircuitException(
"Unknown element type for provenance_evaluate_compiled");
372 Datum token = PG_GETARG_DATUM(0);
374 Oid table = PG_GETARG_OID(1);
376 text *t = PG_GETARG_TEXT_P(2);
377 std::string
semiring(VARDATA(t),VARSIZE(t)-VARHDRSZ);
379 Oid type = get_fn_expr_argtype(fcinfo->flinfo, 3);
382 }
catch(
const std::exception &e) {
385 provsql_error(
"provenance_evaluate_compiled: Unknown exception");
Boolean-expression (lineage formula) semiring.
Boolean semiring ({false, true}, ∨, ∧, false, true).
BooleanCircuit getBooleanCircuit(pg_uuid_t token, gate_t &gate)
Build a BooleanCircuit from the mmap store rooted at token.
GenericCircuit getGenericCircuit(pg_uuid_t token)
Build a GenericCircuit from the mmap store rooted at token.
gate_t
Strongly-typed gate identifier.
Counting semiring (ℕ, +, ×, 0, 1).
Why-provenance semiring (set of witness sets).
Boolean circuit for provenance formula evaluation.
virtual std::string toString(gate_t g) const override
Return a textual description of gate g for debugging.
Exception type thrown by circuit operations on invalid input.
gate_t getGate(const uuid &u)
Return (or create) the gate associated with UUID u.
In-memory provenance circuit with semiring-generic evaluation.
S::value_type evaluate(gate_t g, std::unordered_map< gate_t, typename S::value_type > &provenance_mapping, S semiring) const
Evaluate the sub-circuit rooted at gate g over semiring semiring.
const std::set< gate_t > & getInputs() const
Return the set of input (leaf) gates.
The Boolean semiring over bool.
The counting semiring over unsigned.
void provsql_try_having_why(GenericCircuit &c, gate_t g, std::unordered_map< gate_t, semiring::why_provenance_t > &mapping)
Evaluate the HAVING sub-circuit at g over the Why-provenance semiring.
void provsql_try_having_counting(GenericCircuit &c, gate_t g, std::unordered_map< gate_t, unsigned > &mapping)
Evaluate the HAVING sub-circuit at g over the Counting semiring.
void provsql_try_having_boolean(GenericCircuit &c, gate_t g, std::unordered_map< gate_t, bool > &mapping)
Evaluate the HAVING sub-circuit at g over the Boolean semiring.
void provsql_try_having_formula(GenericCircuit &c, gate_t g, std::unordered_map< gate_t, std::string > &mapping)
Evaluate the HAVING sub-circuit at g over the Formula semiring.
Provenance evaluation helpers for HAVING-clause circuits.
std::set< label_set > why_provenance_t
Why-provenance value: the full set of all witnesses.
std::set< label_t > label_set
A witness: a set of labels that collectively justify one derivation.
static Datum provenance_evaluate_compiled_internal(pg_uuid_t token, Oid table, const std::string &semiring, Oid type)
Core implementation of compiled provenance evaluation.
static Datum pec_varchar(const constants_t &constants, GenericCircuit &c, gate_t g, const std::set< gate_t > &inputs, const std::string &semiring, bool drop_table)
Evaluate a varchar semiring provenance for a circuit.
static Datum pec_boolexpr(const constants_t &constants, BooleanCircuit &bc, gate_t root)
Evaluate the Boolean-expression semiring provenance for a circuit.
const char * drop_temp_table
DROP TABLE statement for the per-query temporary provenance mapping table.
bool join_with_temp_uuids(Oid table, const std::vector< std::string > &uuids)
Join a provenance mapping table with a set of UUIDs using SPI.
static Datum pec_why(const constants_t &constants, GenericCircuit &c, gate_t g, const std::set< gate_t > &inputs, bool drop_table)
Evaluate the Why-provenance semiring for a circuit.
static Datum pec_bool(const constants_t &constants, GenericCircuit &c, gate_t g, const std::set< gate_t > &inputs, const std::string &semiring, bool drop_table)
Evaluate the Boolean semiring provenance for a circuit.
Datum provenance_evaluate_compiled(PG_FUNCTION_ARGS)
PostgreSQL-callable wrapper for provenance_evaluate_compiled().
static Datum pec_int(const constants_t &constants, GenericCircuit &c, gate_t g, const std::set< gate_t > &inputs, const std::string &semiring, bool drop_table)
Evaluate an integer semiring provenance for a circuit.
Template helper for populating provenance mappings from SPI results.
#define provsql_error(fmt,...)
Report a fatal ProvSQL error and abort the current transaction.
Shared-memory segment and inter-process pipe management.
constants_t get_constants(bool failure_if_not_possible)
Retrieve the cached OID constants for the current database.
Core types, constants, and utilities shared across ProvSQL.
string uuid2string(pg_uuid_t uuid)
Format a pg_uuid_t as a std::string.
Structure to store the value of various constants.
Oid OID_TYPE_VARCHAR
OID of the VARCHAR TYPE.
Oid OID_TYPE_INT
OID of the INT TYPE.
Oid OID_TYPE_BOOL
OID of the BOOL TYPE.