\set ECHO none
\pset format unaligned
SET search_path TO provsql_test,provsql;

SET provsql.where_provenance = on;

/* Where-provenance under a multi-table join.
 *
 * The bug this test guards against: when the planner builds the project
 * gate over a TIMES (join) of distinct base tables, each output column's
 * position must be the column's offset in the *concatenated* locator
 * vector produced by WhereCircuit::evaluate(TIMES), not the column's
 * varattno within its own table.  Otherwise a column from the second
 * (or later) join input lands inside the first input's range and the
 * locator reports the wrong table:column.
 */
CREATE TABLE wpj_left  (l1 int, l2 text, l3 int);
INSERT INTO wpj_left  VALUES (1,'a',10),(2,'b',20),(3,'c',30);
SELECT add_provenance('wpj_left');

CREATE TABLE wpj_right (r1 int, r2 text);
INSERT INTO wpj_right VALUES (1,'one'),(2,'two'),(3,'three');
SELECT add_provenance('wpj_right');

/* Output columns, in order:
 *   1. l3       – wpj_left, varattno 3
 *   2. r2       – wpj_right, varattno 2
 *   3. l2       – wpj_left, varattno 2
 *   4. wprov    – function expression (no source)
 *
 * The where-provenance for column 2 (r2) must report wpj_right::2,
 * not wpj_left::2 (which is what the buggy varattno-without-offset
 * code would report).
 */
CREATE TABLE wpj_result AS
  SELECT l3, r2, l2,
    regexp_replace(where_provenance(provenance()),':[0-9a-f-]*:','::','g') AS wprov
  FROM wpj_left JOIN wpj_right ON l1 = r1
  ORDER BY l3;

SELECT remove_provenance('wpj_result');
SELECT * FROM wpj_result;
DROP TABLE wpj_result;

DROP TABLE wpj_left;
DROP TABLE wpj_right;

/* Where-provenance over a relation with a NULL-valued data column.
 *
 * The bug this guards against: identify_token tested "result IS NOT NULL"
 * on the whole matched record, but "RECORD IS NOT NULL" is true only when
 * *every* field is non-null. A provenance-tracked table with any NULL data
 * column (here wpn.c, always NULL) therefore never matched, so its input
 * gates were left with table_name = NULL / nb_columns = -1, and
 * where_provenance crashed with an opaque "construction from null" error.
 * After the fix the row is identified via its (always non-null) provsql
 * column and the locator points at the right table:column.
 */
CREATE TABLE wpn (a int, b int, c int);
INSERT INTO wpn VALUES (1,10,NULL),(2,20,NULL),(3,30,NULL);
SELECT add_provenance('wpn');

CREATE TABLE wpn_other (k int, v text);
INSERT INTO wpn_other VALUES (1,'one'),(2,'two'),(3,'three');
SELECT add_provenance('wpn_other');

CREATE TABLE wpn_result AS
  SELECT a, v,
    regexp_replace(where_provenance(provenance()),':[0-9a-f-]*:','::','g') AS wprov
  FROM wpn JOIN wpn_other ON a = k
  ORDER BY a;

SELECT remove_provenance('wpn_result');
SELECT * FROM wpn_result;
DROP TABLE wpn_result;

DROP TABLE wpn;
DROP TABLE wpn_other;

/* An input gate that belongs to no provenance-tracked relation (e.g. a
 * table that was dropped, or one outside the search_path) must yield a
 * clear error rather than the opaque "construction from null". */
SELECT create_gate(public.uuid_generate_v5(uuid_ns_provsql(), 'wpj-orphan'::text), 'input');
SELECT where_provenance(public.uuid_generate_v5(uuid_ns_provsql(), 'wpj-orphan'::text));
