ProvSQL C/C++ API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches
having_semantics.cpp
Go to the documentation of this file.
1/**
2 * @file having_semantics.cpp
3 * @brief Helper definitions for HAVING-clause provenance evaluation.
4 *
5 * Defines the small non-template helpers declared in
6 * @c provsql_having_detail in @c having_semantics.hpp. The actual
7 * possible-worlds enumeration logic is the @c provsql_having() template
8 * in the header.
9 */
10extern "C" {
11#include "postgres.h"
12#include "utils/lsyscache.h"
13}
14
15#include <string>
16#include <unordered_set>
17#include <vector>
18
19#include "having_semantics.hpp"
20
22
23namespace {
24// Parse int from string
25int parse_int_strict(const std::string &s, bool &ok) {
26 ok = false;
27 if (s.empty()) return 0;
28 size_t idx = 0;
29 try {
30 int v = std::stoi(s, &idx);
31 if (idx != s.size()) return 0;
32 ok = true;
33 return v;
34 } catch (...) {
35 return 0;
36 }
37}
38
39// Parse double from string
40double parse_double_strict(const std::string &s, bool &ok) {
41 ok = false;
42 if (s.empty()) return 0.0;
43 size_t idx = 0;
44 try {
45 double v = std::stod(s, &idx);
46 if (idx != s.size()) return 0.0;
47 ok = true;
48 return v;
49 } catch (...) {
50 return 0.0;
51 }
52}
53} // namespace
54
55// Map a cmp gate's Postgres operator to subset.cpp's ComparisonOperator
57 return cmpOpFromOid(c.getInfos(cmp_gate).first, ok);
58}
59
60// Flip operator for "C op agg" <=> "agg flip(op) C"
72
75 gate_t semimod_gate,
76 int &m_out,
77 gate_t &k_gate_out)
78{
79 if (c.getGateType(semimod_gate) != gate_semimod) return false;
80
81 const auto &w = c.getWires(semimod_gate);
82 if (w.size() != 2) return false;
83
84 if (c.getGateType(w[1]) != gate_value) return false;
85 bool ok = false;
86 m_out = parse_int_strict(c.getExtra(w[1]), ok);
87 if (!ok) return false;
88
89 k_gate_out = w[0];
90 return true;
91}
92
93// Extract constant C from possible encodings:
94// - gate_value("C")
95// - gate_semimod(C, gate_one)
96// - gate_semimod(gate_one, C)
97bool extract_constant_C(GenericCircuit &c, gate_t x, int &C_out) {
98 if (c.getGateType(x) != gate_semimod)
99 return false;
100
101 const auto &w = c.getWires(x);
102 if (w.size() != 2)
103 return false;
104
105 if (c.getGateType(w[0]) != gate_one)
106 return false;
107
108 if (c.getGateType(w[1]) != gate_value)
109 return false;
110
111 bool ok = false;
112 int v = parse_int_strict(c.getExtra(w[1]), ok);
113 if (!ok)
114 return false;
115
116 C_out = v;
117 return true;
118}
119
120// Float8 sibling of extract_constant_C: parses a gate_value's extra as
121// double precision instead of int. Used by the continuous-distributions
122// path where the right-hand side of a gate_cmp is a float literal.
124 if (c.getGateType(x) != gate_value)
125 return false;
126
127 bool ok = false;
128 double v = parse_double_strict(c.getExtra(x), ok);
129 if (!ok)
130 return false;
131
132 C_out = v;
133 return true;
134}
135
136// Collect cmp gates in the prov circuit
137std::vector<gate_t> collect_sp_cmp_gates(GenericCircuit &c, gate_t start) {
138 std::vector<gate_t> out;
139 std::vector<gate_t> stack;
140 stack.push_back(start);
141
142 std::unordered_set<gate_t> seen;
143
144 while (!stack.empty()) {
145 gate_t cur = stack.back();
146 stack.pop_back();
147
148 if (!seen.insert(cur).second) continue;
149
150 if (c.getGateType(cur) == gate_cmp) {
151 const auto &cw = c.getWires(cur);
152 if (cw.size() == 2) {
153 gate_t L = cw[0];
154 gate_t R = cw[1];
155
156 int tmpC = 0;
157 bool is_candidate =
158 (c.getGateType(L) == gate_agg && extract_constant_C(c, R, tmpC)) ||
159 (c.getGateType(R) == gate_agg && extract_constant_C(c, L, tmpC));
160
161 if (is_candidate)
162 out.push_back(cur);
163 }
164 }
165
166 const auto &w = c.getWires(cur);
167 for (gate_t ch : w) stack.push_back(ch);
168 }
169 return out;
170}
171
172} // namespace provsql_having_detail
ComparisonOperator cmpOpFromOid(Oid op_oid, bool &ok)
Map a PostgreSQL comparison-operator OID to a ComparisonOperator.
ComparisonOperator
SQL comparison operators used in gate_cmp circuit gates.
Definition Aggregation.h:38
@ LT
Less than (<).
Definition Aggregation.h:42
@ GT
Greater than (>).
Definition Aggregation.h:44
@ LE
Less than or equal (<=).
Definition Aggregation.h:41
@ NE
Not equal (<>).
Definition Aggregation.h:40
@ GE
Greater than or equal (>=).
Definition Aggregation.h:43
gate_t
Strongly-typed gate identifier.
Definition Circuit.h:49
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
Definition Circuit.h:140
gateType getGateType(gate_t g) const
Return the type of gate g.
Definition Circuit.h:130
In-memory provenance circuit with semiring-generic evaluation.
std::string getExtra(gate_t g) const
Return the string extra for gate g.
std::pair< unsigned, unsigned > getInfos(gate_t g) const
Return the integer annotation pair for gate g.
Provenance evaluation helper for HAVING-clause circuits.
bool extract_constant_C(GenericCircuit &c, gate_t x, int &C_out)
bool extract_constant_double(GenericCircuit &c, gate_t x, double &C_out)
ComparisonOperator flip_op(ComparisonOperator op)
std::vector< gate_t > collect_sp_cmp_gates(GenericCircuit &c, gate_t start)
bool semimod_extract_M_and_K(GenericCircuit &c, gate_t semimod_gate, int &m_out, gate_t &k_gate_out)
ComparisonOperator map_cmp_op(GenericCircuit &c, gate_t cmp_gate, bool &ok)