\set ECHO none
\pset format unaligned

-- provenance() inside a scalar SubLink is a scope-local, INERT token
-- fetch: it resolves to that subquery's own provenance token and returns
-- it as a plain uuid value, WITHOUT coupling the subquery's relations into
-- the outer row's lineage.  This is the basis of the conditioning
-- operator's evidence.  The inner query may be arbitrarily complex (joins,
-- grouping, HAVING): its provenance() resolves to the genuine token of
-- that scope.  Only an EXPR scalar `(SELECT provenance() FROM …)` is inert;
-- EXISTS / IN / quantified forms are boolean predicates, not value
-- fetches, and stay rejected.

CREATE TABLE isub(id int, v text);
INSERT INTO isub VALUES (1,'a'),(2,'b'),(3,'c');
SELECT add_provenance('isub');
DO $$ BEGIN PERFORM set_prob(provenance(), 0.5) FROM isub; END $$;

-- No coupling: the outer row's provenance stays the BARE row token, so
-- its probability is .5 (= P(id=1)), not .25 (= P(id=1 AND id=2)); the
-- fetched evidence token is id=2's own token (probability .5) and is
-- distinct from the row's.
CREATE TABLE r1 AS
  SELECT t1.id,
         provenance() AS row_tok,
         (SELECT provenance() FROM isub t2 WHERE t2.id = 2) AS ev_tok
  FROM isub t1 WHERE t1.id = 1;
SELECT remove_provenance('r1');
SELECT round(probability_evaluate(row_tok)::numeric, 3) AS p_row,
       round(probability_evaluate(ev_tok)::numeric, 3)  AS p_ev,
       row_tok <> ev_tok AS distinct_tokens
FROM r1;
DROP TABLE r1;

-- Correlated per-row evidence (the conditioning shape): every row keeps
-- its bare token and fetches its own neighbour's token inertly.
CREATE TABLE r2 AS
  SELECT t1.id,
         provenance() AS row_tok,
         (SELECT provenance() FROM isub t2 WHERE t2.id = t1.id + 1) AS ev_tok
  FROM isub t1;
SELECT remove_provenance('r2');
SELECT id,
       round(probability_evaluate(row_tok)::numeric, 3) AS p_row,
       CASE WHEN ev_tok IS NULL THEN NULL
            ELSE round(probability_evaluate(ev_tok)::numeric, 3) END AS p_ev
FROM r2 ORDER BY id;
DROP TABLE r2;

-- Inert fetch in WHERE position: still no coupling (row stays bare, p .5).
CREATE TABLE r3 AS
  SELECT t1.id, provenance() AS row_tok
  FROM isub t1
  WHERE t1.id = 1
    AND (SELECT provenance() FROM isub t2 WHERE t2.id = 2) IS NOT NULL;
SELECT remove_provenance('r3');
SELECT round(probability_evaluate(row_tok)::numeric, 3) AS p_row FROM r3;
DROP TABLE r3;

-- Arbitrarily complex inner query: a 2-table join resolves to the genuine
-- joint token (a times gate), p = .5 * .5 = .25, still uncoupled from the
-- outer row (which stays bare at .5).
CREATE TABLE r4 AS
  SELECT t1.id, provenance() AS row_tok,
         (SELECT provenance() FROM isub a JOIN isub b ON b.id = a.id + 1
           WHERE a.id = 1) AS ev_tok
  FROM isub t1 WHERE t1.id = 1;
SELECT remove_provenance('r4');
SELECT round(probability_evaluate(row_tok)::numeric, 3) AS p_row,
       round(probability_evaluate(ev_tok)::numeric, 3)  AS p_ev
FROM r4;
DROP TABLE r4;

-- Grouped + HAVING inner query is inert too: it resolves to that group's
-- HAVING-gated token (a cmp gate), evaluable, uncoupled from the row.
CREATE TABLE r5 AS
  SELECT t1.id, provenance() AS row_tok,
         (SELECT provenance() FROM isub GROUP BY v HAVING count(*) >= 1
           LIMIT 1) AS ev_tok
  FROM isub t1 WHERE t1.id = 1;
SELECT remove_provenance('r5');
SELECT round(probability_evaluate(ev_tok)::numeric, 3) AS p_ev FROM r5;
DROP TABLE r5;

-- Still rejected: provenance() in EXISTS (a boolean predicate, not a value
-- fetch -- an inert fetch cannot honour its probabilistic semantics).
SELECT 1 AS bad WHERE EXISTS (SELECT provenance() FROM isub WHERE id = 2);

SELECT remove_provenance('isub');
DROP TABLE isub;
