16#ifndef PROVSQL_HAVING_SEMANTICS_HPP
17#define PROVSQL_HAVING_SEMANTICS_HPP
45template <
typename SemiringT,
typename MapT>
50 SemiringT S = SemiringT{})
56 if (cmp_gates.empty())
59 auto pw_from_cmp_gate = [&](
gate_t cmp_gate,
typename SemiringT::value_type &pw_out) ->
bool {
60 const auto &cw = c.
getWires(cmp_gate);
61 if (cw.size() != 2)
return false;
68 if (!okop)
return false;
76 const auto &children = c.
getWires(agg_side);
78 std::vector<long> mvals;
79 mvals.reserve(children.size());
81 std::vector<typename SemiringT::value_type> kvals;
82 kvals.reserve(children.size());
84 for (
gate_t ch : children) {
91 auto kval = c.
evaluate<SemiringT>(k_gate, mapping, S);
94 kvals.push_back(std::move(kval));
101 bool all_one_mvals =
true;
102 for (
int m : mvals) {
103 if (m != 1) { all_one_mvals =
false;
break; }
111 if (worlds.empty()) {
116 std::vector<typename SemiringT::value_type> disjuncts;
117 disjuncts.reserve(worlds.size());
119 const size_t n = kvals.size();
121 for (
auto mask : worlds) {
122 std::vector<typename SemiringT::value_type> present;
123 std::vector<typename SemiringT::value_type> missing;
127 for (
size_t i = 0; i < n; ++i) {
129 if(kvals[i]!=S.one())
130 present.push_back(kvals[i]);
140 if(kvals[i]!=S.zero())
141 missing.push_back(kvals[i]);
145 auto present_prod = S.times(present);
147 if (missing.empty()) {
148 disjuncts.push_back(std::move(present_prod));
150 auto missing_sum = S.plus(missing);
151 auto monus_factor = S.monus(S.one(), missing_sum);
152 auto term = monus_factor;
153 if(present_prod!=S.one())
154 term = S.times(std::vector<typename SemiringT::value_type>{present_prod, monus_factor});
155 disjuncts.push_back(std::move(term));
159 pw_out = S.plus(disjuncts);
164 return build_from(L, R, op);
167 return build_from(R, L,
flip_op(op));
172 for (
gate_t cmp_gate : cmp_gates) {
173 typename SemiringT::value_type pw;
174 if (!pw_from_cmp_gate(cmp_gate, pw))
177 mapping[cmp_gate] = std::move(pw);
AggregationOperator getAggregationOperator(Oid oid)
Map a PostgreSQL aggregate function OID to an AggregationOperator.
AggregationOperator
SQL aggregation functions tracked by ProvSQL.
@ COUNT
COUNT(*) or COUNT(expr) → integer.
@ SUM
SUM → integer or float.
ComparisonOperator
SQL comparison operators used in gate_cmp circuit gates.
@ LE
Less than or equal (<=).
@ GE
Greater than or equal (>=).
gate_t
Strongly-typed gate identifier.
Template implementation of GenericCircuit::evaluate().
std::vector< gate_t > & getWires(gate_t g)
Return a mutable reference to the child-wire list of gate g.
gateType getGateType(gate_t g) const
Return the type of gate g.
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.
std::pair< unsigned, unsigned > getInfos(gate_t g) const
Return the integer annotation pair for gate g.
void provsql_having(GenericCircuit &c, gate_t g, MapT &mapping, SemiringT S=SemiringT{})
Rewrite HAVING comparison gates in the circuit by enumerating possible worlds.
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)
std::vector< mask_t > enumerate_valid_worlds(const std::vector< long > &values, int constant, ComparisonOperator op, AggregationOperator agg_kind, bool absorptive, bool &upset)
Enumerate all subsets of n tuples satisfying an aggregate predicate.
Enumerate tuple subsets satisfying an aggregate HAVING predicate.