![]() |
ProvSQL SQL API
Adding support for provenance and uncertainty management to PostgreSQL databases
|
Input function for the AGG_TOKEN type (parses TEXT representation). More...
Topics | |
| Aggregate provenance | |
Per-row helper: wrap an RV in mixture(prov, rv, as_random(0)). | |
Functions | |
| random_variable | random_variable_in (CSTRING) |
| Input function for the random_variable type. | |
| CSTRING | random_variable_out (random_variable) |
| Output function for the random_variable type. | |
| random_variable | random_variable_make (UUID tok) |
| Build a random_variable from a UUID (internal). | |
| CREATE | CAST (random_variable AS UUID) WITHOUT FUNCTION AS ASSIGNMENT |
| Binary-coercible cast random_variable -> UUID. | |
| CREATE | CAST (UUID AS random_variable) WITHOUT FUNCTION |
| BOOL | is_finite_float8 (DOUBLE PRECISION x) |
Internal: true iff x is a finite (non-NaN, non-±∞) float8. | |
| random_variable | normal (DOUBLE PRECISION mu, DOUBLE PRECISION sigma) |
| Construct a normal-distribution random variable. | |
| random_variable | uniform (DOUBLE PRECISION a, DOUBLE PRECISION b) |
| Construct a uniform-distribution random variable on [a, b]. | |
| random_variable | exponential (DOUBLE PRECISION lambda) |
| Construct an exponential-distribution random variable with rate λ | |
| random_variable | erlang (INTEGER k, DOUBLE PRECISION lambda) |
Construct an Erlang-distribution random variable, sum of k i.i.d. | |
| random_variable | mixture (UUID p, random_variable x, random_variable y) |
| Construct a probabilistic-mixture random variable. | |
| random_variable | mixture (DOUBLE PRECISION p_value, random_variable x, random_variable y) |
Ad-hoc mixture constructor that mints a fresh anonymous gate_input Bernoulli with probability p_value. | |
| random_variable | categorical (DOUBLE_PRECISION[] probs, DOUBLE_PRECISION[] outcomes) |
| Categorical-RV constructor over explicit (probabilities, values) arrays. | |
| random_variable | as_random (DOUBLE PRECISION c) |
| Lift a deterministic constant into a random_variable. | |
| CREATE | CAST (DOUBLE PRECISION AS random_variable) WITH FUNCTION as_random(DOUBLE PRECISION) AS IMPLICIT |
| Implicit cast DOUBLE PRECISION -> random_variable (lifts a scalar literal to a constant RV). | |
| random_variable | as_random (INTEGER c) |
as_random for INTEGER (delegates to the float8 form). | |
| random_variable | as_random (NUMERIC c) |
as_random for NUMERIC (delegates to the float8 form). | |
| random_variable | CAST(INTEGER AS RANDOM_VARIABLE) (INTEGER) |
| Implicit cast INTEGER -> random_variable. | |
| random_variable | CAST(NUMERIC AS RANDOM_VARIABLE) (NUMERIC) |
| Implicit cast NUMERIC -> random_variable. | |
Arithmetic and comparison on random_variable | |
Each binary operator below is declared on This avoids the resolution ambiguity that would arise if both (rv, NUMERIC) and (rv, rv) overloads were declared while implicit casts also existed. Arithmetic operators build a Comparison operators are placeholders that return | |
| random_variable | random_variable_plus (random_variable a, random_variable b) |
random_variable + random_variable (gate_arith PLUS). | |
| random_variable | random_variable_minus (random_variable a, random_variable b) |
random_variable - random_variable (gate_arith MINUS). | |
| random_variable | random_variable_times (random_variable a, random_variable b) |
random_variable * random_variable (gate_arith TIMES). | |
| random_variable | random_variable_div (random_variable a, random_variable b) |
random_variable / random_variable (gate_arith DIV). | |
| random_variable | random_variable_neg (random_variable a) |
Unary -random_variable (gate_arith NEG). | |
| oid | random_variable_cmp_oid (TEXT sym) |
| Internal helper: float8-comparator OID for a given symbol. | |
| BOOLEAN | random_variable_cmp_placeholder (random_variable a, random_variable b) |
| Placeholder body shared by every random_variable_* comparison procedure. | |
| BOOLEAN | random_variable_lt (random_variable a, random_variable b) |
| BOOLEAN | random_variable_le (random_variable a, random_variable b) |
| BOOLEAN | random_variable_eq (random_variable a, random_variable b) |
| BOOLEAN | random_variable_ne (random_variable a, random_variable b) |
| BOOLEAN | random_variable_ge (random_variable a, random_variable b) |
| BOOLEAN | random_variable_gt (random_variable a, random_variable b) |
| UUID | rv_cmp_lt (random_variable a, random_variable b) |
Build a gate_cmp for a < b and return its UUID. | |
| UUID | rv_cmp_le (random_variable a, random_variable b) |
Build a gate_cmp for a ≤ b and return its UUID. | |
| UUID | rv_cmp_eq (random_variable a, random_variable b) |
Build a gate_cmp for a = b and return its UUID. | |
| UUID | rv_cmp_ne (random_variable a, random_variable b) |
Build a gate_cmp for a <> b and return its UUID. | |
| UUID | rv_cmp_ge (random_variable a, random_variable b) |
Build a gate_cmp for a ≥ b and return its UUID. | |
| UUID | rv_cmp_gt (random_variable a, random_variable b) |
Build a gate_cmp for a > b and return its UUID. | |
| BOOLEAN | random_variable_op_random_variable (random_variable left, random_variable right) |
| BOOLEAN | random_variable_lt_random_variable (random_variable left, random_variable right) |
Prefix unary minus on random_variable. | |
| BOOLEAN | random_variable_le_random_variable (random_variable left, random_variable right) |
| BOOLEAN | random_variable_eq_random_variable (random_variable left, random_variable right) |
| BOOLEAN | random_variable_ne_random_variable (random_variable left, random_variable right) |
| BOOLEAN | random_variable_ge_random_variable (random_variable left, random_variable right) |
| BOOLEAN | random_variable_gt_random_variable (random_variable left, random_variable right) |
| random_variable | random_variable_cond (random_variable rv, UUID cond) |
Condition a random variable on an event: "X | C". | |
| BOOLEAN | random_variable_op_uuid (random_variable left, UUID right) |
| random_variable | random_variable_cond_predicate (random_variable rv, BOOLEAN predicate) |
Placeholder for "X | (predicate)" – conditioning a random variable on a Boolean comparison written naturally. | |
| BOOLEAN | random_variable_op_boolean (random_variable left, BOOLEAN right) |
| UUID | rv_conditioned_target (UUID token) |
| Unpack the target of a random-variable conditioning gate. | |
| UUID | rv_conditioned_prov (UUID token, UUID prov) |
Combine a conditioning gate's event with an explicit prov. | |
Aggregates over random_variable | |
An overload of the standard Lives in the Direct calls outside a provenance-tracked query treat each row's contribution unconditionally (no per-row Boolean selector). When the planner hook sees a The internal state is the array of UUIDs of the per-row mixtures. The final function builds a single | |
| random_variable | rv_aggregate_semimod (UUID prov, random_variable rv) |
Per-row helper: wrap an RV in mixture(prov, rv, as_random(0)). | |
| UUID[] | sum_rv_sfunc (UUID[] state, random_variable rv) |
State-transition function for sum(random_variable). | |
| random_variable | sum_rv_ffunc (UUID[] state) |
Final function for sum(random_variable): build a gate_arith PLUS root. | |
| VOID | sum (random_variable) |
| random_variable | avg_rv_ffunc (UUID[] state) |
Final function for avg(random_variable). | |
| VOID | avg (random_variable) |
| random_variable | product_rv_ffunc (UUID[] state) |
Final function for product(random_variable). | |
| VOID | product (random_variable) |
Input function for the AGG_TOKEN type (parses TEXT representation).
Custom type random_variable: a thin wrapper around a provenance gate UUID, used to expose continuous probabilistic c-tables in SQL.
Output function for the AGG_TOKEN type
Default: produces the human-friendly "value (*)" form, where value is the running aggregate state.
When the provsql.aggtoken_text_as_uuid GUC is on, returns the underlying provenance UUID instead. UI layers (notably ProvSQL Studio) flip this on per session so aggregate cells expose the circuit root UUID for click-through; the "value (*)" display string is recovered via provsql.agg_token_value_text(UUID).
Marked STABLE rather than IMMUTABLE because the chosen output shape now depends on a GUC that the same session can flip at runtime.
Cast an AGG_TOKEN to its TEXT representation
Extract the UUID from an AGG_TOKEN (implicit cast to UUID)
Implicit PostgreSQL cast from AGG_TOKEN to UUID (delegates to agg_token_uuid())
Recover the "value (*)" display string for an aggregation gate
Companion helper to the provsql.aggtoken_text_as_uuid GUC. With the GUC on, an AGG_TOKEN cell prints as the underlying provenance UUID, which is convenient for tooling that wants to click through to the circuit but loses the human-readable aggregate value. This function takes such a UUID and returns the original "value (*)" string by reading the gate's extra (set by aggregate evaluation for agg gates, and by agg_arith_make for the arith gates that AGG_TOKEN arithmetic mints). Returns NULL if token does not resolve to an agg or arith gate.
| token | UUID of an agg gate (typically obtained from an AGG_TOKEN cell when aggtoken_text_as_uuid is on, or via a manual UUID cast otherwise). |
Cast an AGG_TOKEN to NUMERIC (extracts the aggregate value, loses provenance)
Cast an AGG_TOKEN to DOUBLE PRECISION (extracts the aggregate value, loses provenance)
Cast an AGG_TOKEN to INTEGER (extracts the aggregate value, loses provenance)
Cast an AGG_TOKEN to bigint (extracts the aggregate value, loses provenance)
Cast an AGG_TOKEN to TEXT (extracts the aggregate value, loses provenance)
Assignment cast from AGG_TOKEN to NUMERIC (extracts the scalar value, dropping provenance). ASSIGNMENT, not IMPLICIT: provenance- preserving arithmetic on aggregates is provided by the native AGG_TOKEN operators below, so an implicit NUMERIC coercion would only silently steal s + 1 away from them (and reroute it differently depending on whether provsql is in search_path). Write s::NUMERIC to opt into the lossy scalar. Arithmetic on aggregates (AGG_TOKEN) Mirrors the random_variable arithmetic surface: the operators build a gate_arith over the operand provenance UUIDs (via provenance_arith, info1 = PROVSQL_ARITH_*), so the arithmetic is recorded symbolically in the circuit and can be resolved when a comparison (gate_cmp) over the result is evaluated. Unlike random_variable (a bare UUID), an AGG_TOKEN also carries a running scalar value, so each operator additionally computes the resulting value and bundles it back with the new gate.
Running value of an AGG_TOKEN as NUMERIC, without the provenance-loss warning the public cast emits (internal use).
Bundle a provenance gate UUID with a running value into an AGG_TOKEN (inverse of the agg_token_uuid / agg_token_value accessors).
Lift a scalar NUMERIC constant into a gate_value leaf and return its UUID, so it can be a child of a gate_arith (the agg-side analogue of as_random for random_variable).
Mint (or reuse) the gate_arith for an AGG_TOKEN arithmetic result and return the AGG_TOKEN carrying it.
Also records the computed scalar in the gate's extra – exactly what aggregate evaluation does for agg gates – so agg_token_value_text can recover the "value (*)" display from the bare UUID (as ProvSQL Studio does for result cells under provsql.aggtoken_text_as_uuid). The gate UUID is deterministic in (op, children), so re-recording the (identical) value is idempotent.
AGG_TOKEN + AGG_TOKEN (gate_arith PLUS).
AGG_TOKEN - AGG_TOKEN (gate_arith MINUS).
AGG_TOKEN * AGG_TOKEN (gate_arith TIMES).
AGG_TOKEN / AGG_TOKEN (gate_arith DIV).
Unary -AGG_TOKEN (gate_arith NEG).
AGG_TOKEN + NUMERIC (gate_arith PLUS, constant lifted to a value gate).
AGG_TOKEN - NUMERIC.
AGG_TOKEN * NUMERIC.
AGG_TOKEN / NUMERIC.
NUMERIC + AGG_TOKEN.
NUMERIC - AGG_TOKEN.
NUMERIC * AGG_TOKEN.
NUMERIC / AGG_TOKEN.
Assignment cast from AGG_TOKEN to DOUBLE PRECISION
Assignment cast from AGG_TOKEN to INTEGER
Assignment cast from AGG_TOKEN to bigint
Assignment cast from AGG_TOKEN to TEXT (extracts value, not UUID)
Condition a discrete aggregate's distribution on an event: "SUM(x) | C".
Mirrors random_variable_cond for the AGG_TOKEN carrier: returns a conditioned AGG_TOKEN that flows onward, its provenance token wrapped in the composable two-child gate_conditioned [agg_target, condition] while its running value is preserved. The moment / support dispatchers unpack it (agg_conditioned_target + rv_conditioned_prov) and route through the existing agg_raw_moment with the condition conjoined into the prov argument, so expected(SUM(x)|C) / variance(SUM(x)|C) report the conditional aggregate distribution. Nested conditioning folds.
Placeholder for "SUM(x) | (predicate)" on an AGG_TOKEN.
Lets the conditioning event be a natural Boolean predicate (e.g. "SUM(x) | (SUM(x) > 5)") instead of a hand-built gate. Never executes: the planner converts the Boolean operand into a condition gate and emits agg_token_cond.
Unpack the target of a conditioned AGG_TOKEN.
For a "SUM(x) | C" whose provenance token is the two-child gate_conditioned [agg_target, condition] returns the AGG_TOKEN over agg_target (same running value); for any other AGG_TOKEN returns it unchanged. The conditioning event itself is recovered separately via rv_conditioned_prov on the token's UUID.
Placeholder comparison of AGG_TOKEN with NUMERIC
This function is never actually called; it exists so the SQL parser accepts comparison operators between AGG_TOKEN and NUMERIC values. The ProvSQL query rewriter replaces these comparisons at plan time.
Placeholder comparison of NUMERIC with AGG_TOKEN
Symmetric to agg_token_comp_numeric; never actually called. The ProvSQL query rewriter replaces these comparisons at plan time.
SQL operator AGG_TOKEN < NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC < AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN <= NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC <= AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN = NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC = AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN <> NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC <> AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN >= NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC >= AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN > NUMERIC (placeholder rewritten by ProvSQL at plan time)
SQL operator NUMERIC > AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
Placeholder comparison of two AGG_TOKEN values (the diagonal)
Never actually called; lets the parser accept AGG_TOKEN <op> AGG_TOKEN (e.g. sum(x) > sum(y) on materialised tokens), which the ProvSQL rewriter lowers to a gate_cmp at plan time. Declaring this diagonal also disambiguates s = s2 (otherwise "operator is not unique", because both AGG_TOKEN -> UUID and AGG_TOKEN -> NUMERIC casts apply).
SQL operator AGG_TOKEN < AGG_TOKEN (placeholder rewritten at plan time)
SQL operator AGG_TOKEN <= AGG_TOKEN (placeholder rewritten at plan time)
SQL operator AGG_TOKEN > AGG_TOKEN (placeholder rewritten at plan time)
SQL operator AGG_TOKEN >= AGG_TOKEN (placeholder rewritten at plan time)
SQL operator AGG_TOKEN = AGG_TOKEN (placeholder rewritten at plan time)
SQL operator AGG_TOKEN <> AGG_TOKEN (placeholder rewritten at plan time)
Placeholder comparison of AGG_TOKEN with TEXT
This function is never actually called; it exists so the SQL parser accepts comparison operators between AGG_TOKEN and TEXT values. The ProvSQL query rewriter replaces these comparisons at plan time.
Placeholder comparison of TEXT with AGG_TOKEN
Symmetric to agg_token_comp_text; never actually called. The ProvSQL query rewriter replaces these comparisons at plan time.
SQL operator AGG_TOKEN = TEXT (placeholder rewritten by ProvSQL at plan time)
SQL operator TEXT = AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
SQL operator AGG_TOKEN <> TEXT (placeholder rewritten by ProvSQL at plan time)
SQL operator TEXT <> AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)
Custom type random_variable: a thin wrapper around a provenance gate UUID, used to expose continuous probabilistic c-tables in SQL. The UUID indexes either a gate_rv (an actual distribution) or a gate_value (a zero-variance constant produced by provsql.as_random). Binary-coercible with UUID (same 16-byte layout), so an rv-typed expression flows directly into any function expecting a UUID at zero runtime cost.
Constructors live in this group: provsql.normal(μ, σ), provsql.uniform(a, b), provsql.exponential(λ), provsql.erlang(k, λ), and provsql.as_random(c). Operator overloads (+ - * / and the six comparators) are defined further below, alongside direct rv_cmp_* UUID constructors for callers that want a gate_cmp token without going through the planner hook.
The UUID indexes either a gate_rv (an actual distribution) or a gate_value (a zero-variance constant produced by provsql.as_random). Binary-coercible with UUID (same 16-byte layout), so an rv-typed expression flows directly into any function expecting a UUID at zero runtime cost.
Constructors live in this group: provsql.normal(μ, σ), provsql.uniform(a, b), provsql.exponential(λ), provsql.erlang(k, λ), and provsql.as_random(c). Operator overloads (+ - * / and the six comparators) are defined further below, alongside direct rv_cmp_* UUID constructors for callers that want a gate_cmp token without going through the planner hook.
| random_variable update_provenance::as_random | ( | DOUBLE PRECISION | c | ) |
Lift a deterministic constant into a random_variable.
Creates a gate_value carrying the constant's TEXT form so that comparisons against a random_variable column produce the same circuit shape regardless of whether the operand is an actual RV or a literal constant.
Marked IMMUTABLE: the gate UUID is derived deterministically from the constant via the same v5 convention as provenance_semimod's inline value gate (concat('value', CAST(c AS VARCHAR))), so as_random(2) always resolves to the same gate, and any other code path that already creates a value gate for the same constant (e.g. provenance_semimod) shares the UUID. create_gate is idempotent on already-mapped tokens, so repeat invocations are harmless.
| random_variable update_provenance::as_random | ( | INTEGER | c | ) |
as_random for INTEGER (delegates to the float8 form).
| random_variable update_provenance::as_random | ( | NUMERIC | c | ) |
as_random for NUMERIC (delegates to the float8 form).
| VOID update_provenance::avg | ( | random_variable | ) |
| random_variable update_provenance::avg_rv_ffunc | ( | UUID[] | state | ) |
Final function for avg(random_variable).
Builds the natural lift of "AVG = SUM / COUNT" into the random_variable algebra:
\[ \mathrm{AVG}(x) \;=\; \frac{\sum_i \mathbf{1}\{\varphi_i\} \cdot X_i} {\sum_i \mathbf{1}\{\varphi_i\}} \]
realised as gate_arith(DIV, num, denom) where num is the sum(random_variable) gate over the per-row mixtures and denom is the sum(random_variable) gate over the same provenance gates weighted by a per-row as_random(1) – exactly the SQL pattern "@c sum(x) @c / @c sum(as_random(1))" emitted as a single random_variable token.
Reuses sum_rv_sfunc as the state-transition function so the array of per-row UUIDs is collected identically to sum(random_variable). In a provenance-tracked query the planner-hook rewriter routes RV-returning aggregates through make_rv_aggregate_expression, which wraps each per-row argument in mixture(prov_i, x_i, as_random(0)); the FFUNC then recovers prov_i from each mixture's first child to construct the matching mixture(prov_i, as_random(1), as_random(0)) for the denominator. Outside a tracked query the per-row UUIDs are plain RV roots, in which case each row contributes an unconditional as_random(1) to the denominator – the natural extension of "no provenance =
every row counts" used elsewhere in the extension.
Empty group: returns NULL, matching the standard SQL AVG convention. This differs from sum(random_variable), which returns the additive identity as_random(0) for an empty group; for AVG the multiplicative identity is not the right answer and the caller has no way to disambiguate "0 rows" from "rows that
sum to 0".
| CREATE update_provenance::CAST | ( | DOUBLE PRECISION AS | random_variable | ) |
Implicit cast DOUBLE PRECISION -> random_variable (lifts a scalar literal to a constant RV).
Lets users write WHERE reading > 2.5::float8 instead of WHERE reading > provsql.as_random(2.5); the planner-hook rewriter then sees a uniform random_variable on both sides. Sibling casts below cover INTEGER and NUMERIC literals so plain WHERE reading > 2 and WHERE reading > 2.5 also work; PostgreSQL's operator resolution does not chain casts across more than one step, so each NUMERIC-source type needs its own direct cast.
| CREATE update_provenance::CAST | ( | random_variable AS | UUID | ) |
Binary-coercible cast random_variable -> UUID.
A random_variable is byte-for-byte a pg_uuid_t (alignment char, length 16), so WITHOUT FUNCTION lets PostgreSQL reinterpret the bytes at zero runtime cost. The cast is ASSIGNMENT (not IMPLICIT): an implicit cross-domain cast would silently reroute a comparison such as v < w to UUID < UUID (raw byte comparison) whenever provsql is not in search_path, since operators are resolved through search_path but casts are not. Demoting to ASSIGNMENT turns that silent wrong result into a clean parse error. Passing a random_variable to a UUID-taking function now needs an explicit v::UUID (function resolution never applies assignment casts).
| CREATE update_provenance::CAST | ( | UUID AS | random_variable | ) |
| random_variable update_provenance::CAST(INTEGER AS RANDOM_VARIABLE) | ( | INTEGER | ) |
Implicit cast INTEGER -> random_variable.
| random_variable update_provenance::CAST(NUMERIC AS RANDOM_VARIABLE) | ( | NUMERIC | ) |
Implicit cast NUMERIC -> random_variable.
| random_variable update_provenance::categorical | ( | DOUBLE_PRECISION[] | probs, |
| DOUBLE_PRECISION[] | outcomes ) |
Categorical-RV constructor over explicit (probabilities, values) arrays.
Builds a categorical-form gate_mixture directly: a fresh gate_input "key" anchor and one gate_mulinput per outcome with positive mass, all sharing the key. The wires [key, mul_1, ..., mul_n] are what downstream evaluators (Expectation, MonteCarloSampler, AnalyticEvaluator, RangeCheck) recognise via isCategoricalMixture and treat as a scalar RV with the categorical distribution probs over outcomes.
Validation:
probs and outcomes must be non-null, same length, length ≥ 1.probs[i] must be finite, in [0, 1], and the array must sum to 1 within 1e-9.outcomes[i] must be finite.Each call mints a fresh key gate and a fresh set of mulinputs, so two calls to categorical with the same arrays are independent categorical RVs. The marking is VOLATILE accordingly.
Degenerate case: a categorical with exactly one positive-mass outcome reduces to as_random(v) at construction (the block would just be a single mulinput, which is operationally a Dirac point mass). Two such calls share the gate_value UUID via the v5 convention as_random already uses.
mixture for the Bernoulli-weighted choice constructor. | random_variable update_provenance::erlang | ( | INTEGER | k, |
| DOUBLE PRECISION | lambda ) |
Construct an Erlang-distribution random variable, sum of k i.i.d.
exponentials with shared rate lambda
The Erlang distribution is the sum of k independent Exp(λ) random variables (equivalently the gamma with INTEGER shape). It is the natural closure of i.i.d. exponentials under addition, and is materialised here as a single gate_rv so the analytic CDF and closed-form moments fire directly (rather than the sampler having to draw and sum k exponential leaves per Monte-Carlo iteration).
Validation:
k must be ≥ 1. The degenerate k=1 case is silently routed through exponential so erlang(1, λ) shares its gate with exponential(λ).lambda must be finite and strictly positive.| random_variable update_provenance::exponential | ( | DOUBLE PRECISION | lambda | ) |
Construct an exponential-distribution random variable with rate λ
Validation:
lambda must be finite and strictly positive. No degenerate form exists for the exponential distribution, so there is no silent route through as_random.| BOOL update_provenance::is_finite_float8 | ( | DOUBLE PRECISION | x | ) |
Internal: true iff x is a finite (non-NaN, non-±∞) float8.
PostgreSQL's isnan is defined for NUMERIC only, not for DOUBLE PRECISION; we use the inequality form, which works because PG defines NaN = NaN as TRUE for floats (so NaN <> 'NaN'::float8 is FALSE).
| random_variable update_provenance::mixture | ( | DOUBLE PRECISION | p_value, |
| random_variable | x, | ||
| random_variable | y ) |
Ad-hoc mixture constructor that mints a fresh anonymous gate_input Bernoulli with probability p_value.
Sugar over the mixture(UUID, x, y) form: when the caller doesn't care about reusing the Bernoulli token elsewhere in the circuit (which is the common case – "give me a 0.3 / 0.7 weighted GMM,
I don't need to share the coin"), this overload creates the underlying gate_input on the fly with a fresh uuid_generate_v4() token, pins p_value via set_prob, and threads everything into the UUID-keyed constructor.
Each call mints a NEW Bernoulli, so two calls to mixture(0.5, X, Y) are independent mixtures whose branch selections are uncorrelated. When coupling is desired (e.g. two mixtures sharing a coin), use the mixture(UUID, x, y) form with a user-managed gate_input token.
STABLE / IMMUTABLE would collapse two independent draws into one shared gate.| random_variable update_provenance::mixture | ( | UUID | p, |
| random_variable | x, | ||
| random_variable | y ) |
Construct a probabilistic-mixture random variable.
Returns a random_variable whose distribution is a Bernoulli mixture of two scalar RV roots: with probability P(p = true) the mixture samples x, with the complementary probability it samples y. The mixing token p is a gate_input Bernoulli whose probability has been pinned with set_prob, and the same p can be shared with other branches of the circuit – the Monte-Carlo sampler's per-iteration cache couples every reference to the same draw, so users can build joint conditional structures (e.g. mixture(p, X1, Y1) + mixture(p, X2, Y2) samples X1 + X2 with prob π and Y1 + Y2 with prob 1-π).
x and y may be any scalar RV root: a base gate_rv (normal / uniform / exponential / erlang), a gate_value Dirac (as_random), a gate_arith expression, or another mixture. N-ary mixtures are built by composition – mixture(p1, A, mixture(p2, B, C)) realises a 3-component mixture with effective weights π1, (1-π1)·π2, (1-π1)·(1-π2).
Validation:
p must point to a Boolean gate (input, mulinput, update, plus, times, monus, project, eq, cmp, zero, one). Compound Boolean gates derive their probability from their atoms via the active probability-evaluation method; a bare gate_input's probability is whatever set_prob pinned (set_prob is responsible for keeping it in [0, 1]).x and y must be scalar RV roots; aggregate / Boolean roots are rejected at construction.Two calls to mixture with the same (p, x, y) operands collapse to the same gate_mixture node by v5-hash, exactly like arith(PLUS, X, Y). Draw independence is controlled by p: sharing p couples branch selection across consumers via the sampler's bool_cache_; minting independent Bernoullis (e.g. via the mixture(p_value, …) overload) decouples them.
| random_variable update_provenance::normal | ( | DOUBLE PRECISION | mu, |
| DOUBLE PRECISION | sigma ) |
Construct a normal-distribution random variable.
Creates a fresh gate_rv with "normal:μ,σ" stored in the gate's extra field, and returns a random_variable pointing at it.
Validation:
mu and sigma must be finite (no NaN, no ±Infinity).sigma must be non-negative.sigma is zero the distribution degenerates to the Dirac at mu; the call is silently routed through as_random(mu), producing a gate_value rather than a zero-variance gate_rv. This keeps the sampler / moment / boundcheck paths free of σ=0 special cases and lets normal(x, 0) share its gate with as_random(x).uniform and exponential below.| VOID update_provenance::product | ( | random_variable | ) |
| random_variable update_provenance::product_rv_ffunc | ( | UUID[] | state | ) |
Final function for product(random_variable).
Multiplicative analogue of sum(random_variable):
\[ \mathrm{PRODUCT}(x) \;=\; \prod_i \big(\mathbf{1}\{\varphi_i\} \cdot X_i + \mathbf{1}\{\neg\varphi_i\} \cdot 1\big) \;=\; \prod_{i : \varphi_i} X_i \]
realised as gate_arith(TIMES, mixtures) over per-row contributions whose else-branch is as_random(1) (the multiplicative identity), so rows whose provenance is false contribute 1 to the product instead of 0.
The C-side wrap shared with sum / avg always builds mixture(prov_i, X_i, as_random(0)); the PRODUCT FFUNC patches each mixture's else-branch to as_random(1) by reconstructing the mixture with the corrected else-arg. Going through provsql.mixture (rather than create_gate directly) keeps the gate v5-hash consistent with any other mixture sharing the same (prov_i, X_i, as_random(1)) triple.
Reuses sum_rv_sfunc as the state-transition function. Empty group: returns the multiplicative identity as_random(1) – the natural counterpart to sum(random_variable)'s empty-group as_random(0).
Singleton group: returns the single patched child directly without minting a useless single-child gate_arith TIMES root.
Direct (untracked) call: state entries are raw RV uuids rather than mixtures; pass them through unchanged so PRODUCT degenerates to the straight RV product over all rows, the natural "no provenance = every row counts" behaviour.
| oid update_provenance::random_variable_cmp_oid | ( | TEXT | sym | ) |
Internal helper: float8-comparator OID for a given symbol.
Wraps the '<sym>(DOUBLE PRECISION,DOUBLE PRECISION)'::regoperator lookup so the per-comparator functions read uniformly. Marked IMMUTABLE because the resolved OID is fixed at catalog level (the float8 comparators are core PG and never re-installed).
| BOOLEAN update_provenance::random_variable_cmp_placeholder | ( | random_variable | a, |
| random_variable | b ) |
Placeholder body shared by every random_variable_* comparison procedure.
Raises with a uniform message.
| random_variable update_provenance::random_variable_cond | ( | random_variable | rv, |
| UUID | cond ) |
Condition a random variable on an event: "X | C".
Returns a conditioned distribution that flows onward like any other random_variable: it can be stored, re-conditioned, and queried with expected / variance / moment / support, which then report the conditional distribution. cond is a Boolean-event provenance token, typically a comparison over the variable itself ("X | rv_cmp_gt(X,
as_random(3))" – a truncation) or any external event.
Unlike the UUID carrier's terminal cond, the random-variable form is a composable two-child gate_conditioned [target, condition]: the moment / support dispatchers unpack it and route through the existing conditional evaluator (rv_moment over the joint of the target and the condition). Nested conditioning folds: "(X|A)|B = X|(A∧B)".
| random_variable update_provenance::random_variable_cond_predicate | ( | random_variable | rv, |
| BOOLEAN | predicate ) |
Placeholder for "X | (predicate)" – conditioning a random variable on a Boolean comparison written naturally.
Lets one write "X | (X > 3)" instead of "X | rv_cmp_gt(X, as_random(3))". Never executes: the ProvSQL planner hook rewrites the Boolean operand (a combination of random_variable comparisons) into the corresponding condition gate and emits random_variable_cond. Reaching it at runtime means the rewriter was inactive or the predicate was not a random_variable comparison.
| random_variable update_provenance::random_variable_div | ( | random_variable | a, |
| random_variable | b ) |
random_variable / random_variable (gate_arith DIV).
| BOOLEAN update_provenance::random_variable_eq | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_eq_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| BOOLEAN update_provenance::random_variable_ge | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_ge_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| BOOLEAN update_provenance::random_variable_gt | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_gt_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| random_variable update_provenance::random_variable_in | ( | CSTRING | ) |
Input function for the random_variable type.
| BOOLEAN update_provenance::random_variable_le | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_le_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| BOOLEAN update_provenance::random_variable_lt | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_lt_random_variable | ( | random_variable | left, |
| random_variable | right ) |
Prefix unary minus on random_variable.
| random_variable update_provenance::random_variable_make | ( | UUID | tok | ) |
Build a random_variable from a UUID (internal).
| random_variable update_provenance::random_variable_minus | ( | random_variable | a, |
| random_variable | b ) |
random_variable - random_variable (gate_arith MINUS).
| BOOLEAN update_provenance::random_variable_ne | ( | random_variable | a, |
| random_variable | b ) |
| BOOLEAN update_provenance::random_variable_ne_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| random_variable update_provenance::random_variable_neg | ( | random_variable | a | ) |
Unary -random_variable (gate_arith NEG).
| BOOLEAN update_provenance::random_variable_op_boolean | ( | random_variable | left, |
| BOOLEAN | right ) |
| BOOLEAN random_variable_op_random_variable | ( | random_variable | left, |
| random_variable | right ) |
| BOOLEAN update_provenance::random_variable_op_uuid | ( | random_variable | left, |
| UUID | right ) |
| CSTRING update_provenance::random_variable_out | ( | random_variable | ) |
Output function for the random_variable type.
| random_variable update_provenance::random_variable_plus | ( | random_variable | a, |
| random_variable | b ) |
random_variable + random_variable (gate_arith PLUS).
| random_variable update_provenance::random_variable_times | ( | random_variable | a, |
| random_variable | b ) |
random_variable * random_variable (gate_arith TIMES).
| random_variable update_provenance::rv_aggregate_semimod | ( | UUID | prov, |
| random_variable | rv ) |
Per-row helper: wrap an RV in mixture(prov, rv, as_random(0)).
Internal helper used by the planner-hook rewriter to lift a sum(random_variable) argument into its provenance-aware form. Encodes one row's contribution to the SUM as a Bernoulli mixture over the row's provenance: with probability P(prov) the mixture samples rv, otherwise it samples the additive identity as_random(0). Exposed as a regular SQL function so the planner can construct a FuncExpr by name without needing to disambiguate mixture / as_random overloads at OID-lookup time.
| UUID update_provenance::rv_cmp_eq | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a = b and return its UUID.
| UUID update_provenance::rv_cmp_ge | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a ≥ b and return its UUID.
| UUID update_provenance::rv_cmp_gt | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a > b and return its UUID.
| UUID update_provenance::rv_cmp_le | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a ≤ b and return its UUID.
| UUID update_provenance::rv_cmp_lt | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a < b and return its UUID.
| UUID update_provenance::rv_cmp_ne | ( | random_variable | a, |
| random_variable | b ) |
Build a gate_cmp for a <> b and return its UUID.
| UUID update_provenance::rv_conditioned_prov | ( | UUID | token, |
| UUID | prov ) |
Combine a conditioning gate's event with an explicit prov.
For a two-child gate_conditioned [target, condition] returns "condition ∧ prov"; otherwise returns prov unchanged. Lets a stored "X | C" be queried as expected(X|C) (prov defaulting to one) or have an extra condition conjoined as expected(X|C, extra_prov).
| UUID update_provenance::rv_conditioned_target | ( | UUID | token | ) |
Unpack the target of a random-variable conditioning gate.
For a two-child gate_conditioned [target, condition] (the "X | C" shape) returns target; for any other token returns it unchanged. Used by the moment / support dispatchers to route a conditioned distribution through the existing conditional evaluator.
| VOID update_provenance::sum | ( | random_variable | ) |
| random_variable update_provenance::sum_rv_ffunc | ( | UUID[] | state | ) |
Final function for sum(random_variable): build a gate_arith PLUS root.
Empty group (state = '{}'): return as_random(0), the additive identity, so SUM over zero rows is the deterministic scalar 0 – matches the AGG_TOKEN convention in agg_raw_moment.
Singleton group: return the single child directly without minting a useless single-child gate_arith.
Otherwise: build gate_arith(PLUS, state) via provenance_arith.
| UUID[] update_provenance::sum_rv_sfunc | ( | UUID[] | state, |
| random_variable | rv ) |
State-transition function for sum(random_variable).
Appends the input RV's UUID to the running array. NULL inputs are skipped (matching standard SUM semantics). The aggregate's INITCOND is '{}' so the FINALFUNC always runs even on an empty group, which is what lets us return as_random(0) (the additive identity) for an empty SUM rather than NULL.
| random_variable update_provenance::uniform | ( | DOUBLE PRECISION | a, |
| DOUBLE PRECISION | b ) |
Construct a uniform-distribution random variable on [a, b].
Validation:
a and b must be finite.a must be ≤ b (reversed bounds are rejected).a; the call is silently routed through as_random(a) for the same reason as normal with sigma = 0.