ProvSQL SQL API
Adding support for provenance and uncertainty management to PostgreSQL databases
Loading...
Searching...
No Matches

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 (random_variable, random_variable) only; mixed shapes such as rv + 2 or 2.5 > rv resolve through the implicit casts from INTEGER / NUMERIC / double precision to random_variable declared above.

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 gate_arith via provenance_arith and return a new random_variable wrapping its UUID.

Comparison operators are placeholders that return BOOLEAN and raise if executed – the BOOLEAN return type is required so that PostgreSQL accepts WHERE rv > 2 at parse-analyze. The planner hook intercepts every such OpExpr (matched by opfuncid against constants_t::OID_FUNCTION_RV_CMP) and rewrites it into a provenance_cmp call whose UUID is conjoined into the tuple's provsql column via provenance_times. Code that needs a gate_cmp UUID directly (without going through the planner hook) uses the rv_cmp_* family below, which call provenance_cmp with the matching float8-comparator OID.

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 sum aggregate that takes a random_variable per row and returns the random_variable representing the (provenance-weighted) sum.

Lives in the provsql schema so a sum(random_variable) call resolves to it without colliding with the built-in NUMERIC sum overloads in pg_catalog.

Direct calls outside a provenance-tracked query treat each row's contribution unconditionally (no per-row Boolean selector). When the planner hook sees a provsql.sum Aggref over a provenance-tracked query, it wraps the per-row argument x in provsql.mixture(prov_token, x, provsql.as_random(0)) so the aggregate's effective semantics become \(\mathrm{SUM}(x) = \sum_i \mathbf{1}\{\varphi_i\} \cdot X_i\), the natural extension of semimodule-provenance to RV-valued M.

The internal state is the array of UUIDs of the per-row mixtures. The final function builds a single gate_arith PLUS over them (or returns as_random(0) for an empty group, the additive identity). Sharing on provenance_arith's v5 hash means two sum invocations over the same set of rows collide on the same gate.

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)

Detailed Description

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.

Source code
provsql.sql line 2111

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.

Source code
provsql.sql line 2131

Cast an AGG_TOKEN to its TEXT representation

Source code
provsql.sql line 2136

Extract the UUID from an AGG_TOKEN (implicit cast to UUID)

Source code
provsql.sql line 2148

Implicit PostgreSQL cast from AGG_TOKEN to UUID (delegates to agg_token_uuid())

Source code
provsql.sql line 2157

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.

Parameters
tokenUUID 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).
Source code
provsql.sql line 2176

Cast an AGG_TOKEN to NUMERIC (extracts the aggregate value, loses provenance)

Source code
provsql.sql line 2189

Cast an AGG_TOKEN to DOUBLE PRECISION (extracts the aggregate value, loses provenance)

Source code
provsql.sql line 2194

Cast an AGG_TOKEN to INTEGER (extracts the aggregate value, loses provenance)

Source code
provsql.sql line 2199

Cast an AGG_TOKEN to bigint (extracts the aggregate value, loses provenance)

Source code
provsql.sql line 2204

Cast an AGG_TOKEN to TEXT (extracts the aggregate value, loses provenance)

Source code
provsql.sql line 2209

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).

Source code
provsql.sql line 2237

Bundle a provenance gate UUID with a running value into an AGG_TOKEN (inverse of the agg_token_uuid / agg_token_value accessors).

Source code
provsql.sql line 2244

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).

Source code
provsql.sql line 2254

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.

Source code
provsql.sql line 2277 AGG_TOKEN <op> AGG_TOKEN

AGG_TOKEN + AGG_TOKEN (gate_arith PLUS).

Source code
provsql.sql line 2291

AGG_TOKEN - AGG_TOKEN (gate_arith MINUS).

Source code
provsql.sql line 2298

AGG_TOKEN * AGG_TOKEN (gate_arith TIMES).

Source code
provsql.sql line 2305

AGG_TOKEN / AGG_TOKEN (gate_arith DIV).

Source code
provsql.sql line 2312

Unary -AGG_TOKEN (gate_arith NEG).

Source code
provsql.sql line 2319 AGG_TOKEN <op> NUMERIC

AGG_TOKEN + NUMERIC (gate_arith PLUS, constant lifted to a value gate).

Source code
provsql.sql line 2327

AGG_TOKEN - NUMERIC.

Source code
provsql.sql line 2334

AGG_TOKEN * NUMERIC.

Source code
provsql.sql line 2341

AGG_TOKEN / NUMERIC.

Source code
provsql.sql line 2348 NUMERIC <op> AGG_TOKEN

NUMERIC + AGG_TOKEN.

Source code
provsql.sql line 2356

NUMERIC - AGG_TOKEN.

Source code
provsql.sql line 2363

NUMERIC * AGG_TOKEN.

Source code
provsql.sql line 2370

NUMERIC / AGG_TOKEN.

Source code
provsql.sql line 2377 Operator declarations

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.

Source code
provsql.sql line 2422

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.

Source code
provsql.sql line 2467

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.

Source code
provsql.sql line 2492

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.

Source code
provsql.sql line 2511

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.

Source code
provsql.sql line 2527

SQL operator AGG_TOKEN < NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2538

SQL operator NUMERIC < AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2546

SQL operator AGG_TOKEN <= NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2555

SQL operator NUMERIC <= AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2563

SQL operator AGG_TOKEN = NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2572

SQL operator NUMERIC = AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2580

SQL operator AGG_TOKEN <> NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2589

SQL operator NUMERIC <> AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2597

SQL operator AGG_TOKEN >= NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2606

SQL operator NUMERIC >= AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2614

SQL operator AGG_TOKEN > NUMERIC (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2623

SQL operator NUMERIC > AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2631

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).

Source code
provsql.sql line 2648

SQL operator AGG_TOKEN < AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2659

SQL operator AGG_TOKEN <= AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2664

SQL operator AGG_TOKEN > AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2669

SQL operator AGG_TOKEN >= AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2674

SQL operator AGG_TOKEN = AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2679

SQL operator AGG_TOKEN <> AGG_TOKEN (placeholder rewritten at plan time)

Source code
provsql.sql line 2684

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.

Source code
provsql.sql line 2696

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.

Source code
provsql.sql line 2712

SQL operator AGG_TOKEN = TEXT (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2723

SQL operator TEXT = AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2731

SQL operator AGG_TOKEN <> TEXT (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2740

SQL operator TEXT <> AGG_TOKEN (placeholder rewritten by ProvSQL at plan time)

Source code
provsql.sql line 2748

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.

Function Documentation

◆ as_random() [1/3]

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.

See also
Wikipedia: Degenerate distribution (Dirac point mass)
Source code
provsql.sql line 3274

◆ as_random() [2/3]

random_variable update_provenance::as_random ( INTEGER c)

as_random for INTEGER (delegates to the float8 form).

Source code
provsql.sql line 3274

◆ as_random() [3/3]

random_variable update_provenance::as_random ( NUMERIC c)

as_random for NUMERIC (delegates to the float8 form).

Source code
provsql.sql line 3274

◆ avg()

VOID update_provenance::avg ( random_variable )

◆ avg_rv_ffunc()

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".

Source code
provsql.sql line 3891

◆ CAST() [1/3]

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.

◆ CAST() [2/3]

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).

◆ CAST() [3/3]

CREATE update_provenance::CAST ( UUID AS random_variable)

◆ CAST(INTEGER AS RANDOM_VARIABLE)()

random_variable update_provenance::CAST(INTEGER AS RANDOM_VARIABLE) ( INTEGER )

Implicit cast INTEGER -> random_variable.

Source code
provsql.sql line 3323

◆ CAST(NUMERIC AS RANDOM_VARIABLE)()

random_variable update_provenance::CAST(NUMERIC AS RANDOM_VARIABLE) ( NUMERIC )

Implicit cast NUMERIC -> random_variable.

Source code
provsql.sql line 3327

◆ categorical()

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.
  • Each probs[i] must be finite, in [0, 1], and the array must sum to 1 within 1e-9.
  • Each 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.

See also
mixture for the Bernoulli-weighted choice constructor.
Wikipedia: Categorical distribution
Source code
provsql.sql line 3155

◆ erlang()

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.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Erlang distribution
Source code
provsql.sql line 2974

◆ exponential()

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.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Exponential distribution
Source code
provsql.sql line 2932

◆ is_finite_float8()

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).

Source code
provsql.sql line 2826

◆ mixture() [1/2]

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.

Warning
VOLATILE is load-bearing for the same reason as normal and the other RV constructors – folding under STABLE / IMMUTABLE would collapse two independent draws into one shared gate.
See also
Wikipedia: Mixture distribution
Source code
provsql.sql line 3039

◆ mixture() [2/2]

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.

See also
Wikipedia: Mixture distribution
Source code
provsql.sql line 3039

◆ normal()

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.
  • When 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).
Warning
The VOLATILE marking is load-bearing and must not be weakened. Each call mints a fresh uuid_generate_v4 token because two calls to normal(0, 1) are independent random variables; if PostgreSQL were allowed to fold the function (which it would under STABLE / IMMUTABLE), two calls in the same query would share a UUID and collapse into a single dependent RV, silently breaking the c-table semantics. Same warning applies to uniform and exponential below.
See also
Wikipedia: Normal distribution
Source code
provsql.sql line 2860

◆ product()

VOID update_provenance::product ( random_variable )

◆ product_rv_ffunc()

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.

Source code
provsql.sql line 3988

◆ random_variable_cmp_oid()

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).

Source code
provsql.sql line 3425

◆ random_variable_cmp_placeholder()

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.

Source code
provsql.sql line 3445

◆ random_variable_cond()

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)".

Source code
provsql.sql line 3646

◆ random_variable_cond_predicate()

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.

Source code
provsql.sql line 3696

◆ random_variable_div()

random_variable update_provenance::random_variable_div ( random_variable a,
random_variable b )

random_variable / random_variable (gate_arith DIV).

Source code
provsql.sql line 3396

◆ random_variable_eq()

BOOLEAN update_provenance::random_variable_eq ( random_variable a,
random_variable b )

◆ random_variable_eq_random_variable()

BOOLEAN update_provenance::random_variable_eq_random_variable ( random_variable left,
random_variable right )

◆ random_variable_ge()

BOOLEAN update_provenance::random_variable_ge ( random_variable a,
random_variable b )

◆ random_variable_ge_random_variable()

BOOLEAN update_provenance::random_variable_ge_random_variable ( random_variable left,
random_variable right )

◆ random_variable_gt()

BOOLEAN update_provenance::random_variable_gt ( random_variable a,
random_variable b )

◆ random_variable_gt_random_variable()

BOOLEAN update_provenance::random_variable_gt_random_variable ( random_variable left,
random_variable right )

◆ random_variable_in()

random_variable update_provenance::random_variable_in ( CSTRING )

Input function for the random_variable type.

Source code
provsql.sql line 2783

◆ random_variable_le()

BOOLEAN update_provenance::random_variable_le ( random_variable a,
random_variable b )

◆ random_variable_le_random_variable()

BOOLEAN update_provenance::random_variable_le_random_variable ( random_variable left,
random_variable right )

◆ random_variable_lt()

BOOLEAN update_provenance::random_variable_lt ( random_variable a,
random_variable b )

◆ random_variable_lt_random_variable()

BOOLEAN update_provenance::random_variable_lt_random_variable ( random_variable left,
random_variable right )

Prefix unary minus on random_variable.

Source code
provsql.sql line 3582

◆ random_variable_make()

random_variable update_provenance::random_variable_make ( UUID tok)

Build a random_variable from a UUID (internal).

Source code
provsql.sql line 2800

◆ random_variable_minus()

random_variable update_provenance::random_variable_minus ( random_variable a,
random_variable b )

random_variable - random_variable (gate_arith MINUS).

Source code
provsql.sql line 3372

◆ random_variable_ne()

BOOLEAN update_provenance::random_variable_ne ( random_variable a,
random_variable b )

◆ random_variable_ne_random_variable()

BOOLEAN update_provenance::random_variable_ne_random_variable ( random_variable left,
random_variable right )

◆ random_variable_neg()

random_variable update_provenance::random_variable_neg ( random_variable a)

Unary -random_variable (gate_arith NEG).

Source code
provsql.sql line 3408

◆ random_variable_op_boolean()

BOOLEAN update_provenance::random_variable_op_boolean ( random_variable left,
BOOLEAN right )

◆ random_variable_op_random_variable()

BOOLEAN random_variable_op_random_variable ( random_variable left,
random_variable right )

◆ random_variable_op_uuid()

BOOLEAN update_provenance::random_variable_op_uuid ( random_variable left,
UUID right )

◆ random_variable_out()

CSTRING update_provenance::random_variable_out ( random_variable )

Output function for the random_variable type.

Source code
provsql.sql line 2788

◆ random_variable_plus()

random_variable update_provenance::random_variable_plus ( random_variable a,
random_variable b )

random_variable + random_variable (gate_arith PLUS).

Source code
provsql.sql line 3360

◆ random_variable_times()

random_variable update_provenance::random_variable_times ( random_variable a,
random_variable b )

random_variable * random_variable (gate_arith TIMES).

Source code
provsql.sql line 3384

◆ rv_aggregate_semimod()

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.

Source code
provsql.sql line 3792

◆ rv_cmp_eq()

UUID update_provenance::rv_cmp_eq ( random_variable a,
random_variable b )

Build a gate_cmp for a = b and return its UUID.

Source code
provsql.sql line 3511

◆ rv_cmp_ge()

UUID update_provenance::rv_cmp_ge ( random_variable a,
random_variable b )

Build a gate_cmp for a ≥ b and return its UUID.

Source code
provsql.sql line 3531

◆ rv_cmp_gt()

UUID update_provenance::rv_cmp_gt ( random_variable a,
random_variable b )

Build a gate_cmp for a > b and return its UUID.

Source code
provsql.sql line 3541

◆ rv_cmp_le()

UUID update_provenance::rv_cmp_le ( random_variable a,
random_variable b )

Build a gate_cmp for a ≤ b and return its UUID.

Source code
provsql.sql line 3501

◆ rv_cmp_lt()

UUID update_provenance::rv_cmp_lt ( random_variable a,
random_variable b )

Build a gate_cmp for a < b and return its UUID.

Source code
provsql.sql line 3491

◆ rv_cmp_ne()

UUID update_provenance::rv_cmp_ne ( random_variable a,
random_variable b )

Build a gate_cmp for a <> b and return its UUID.

Source code
provsql.sql line 3521

◆ rv_conditioned_prov()

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).

Source code
provsql.sql line 3738

◆ rv_conditioned_target()

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.

Source code
provsql.sql line 3720

◆ sum()

VOID update_provenance::sum ( random_variable )

◆ sum_rv_ffunc()

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.

Source code
provsql.sql line 3831

◆ sum_rv_sfunc()

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.

Source code
provsql.sql line 3808

◆ uniform()

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).
  • When a = b the distribution is the Dirac at a; the call is silently routed through as_random(a) for the same reason as normal with sigma = 0.
Warning
VOLATILE is load-bearing; see the warning on normal.
See also
Wikipedia: Continuous uniform distribution
Source code
provsql.sql line 2897