/* <begin connected objects> */
/*
This file is auto generated by pgrx.

The ordering of items is not stable, it is driven by a dependency graph.
*/
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lib.rs:114

DO $pgcontext_schema_guard$
DECLARE
    target_owner oid;
    delegated_create boolean;
BEGIN
    SELECT namespace.nspowner,
           EXISTS (
               SELECT 1
                 FROM pg_catalog.aclexplode(
                          coalesce(
                              namespace.nspacl,
                              pg_catalog.acldefault('n', namespace.nspowner)
                          )
                      ) AS privilege
                WHERE privilege.privilege_type = 'CREATE'
                  AND privilege.grantee <> namespace.nspowner
           )
      INTO target_owner, delegated_create
      FROM pg_catalog.pg_namespace AS namespace
     WHERE namespace.nspname = 'pgcontext';

    IF target_owner IS DISTINCT FROM CURRENT_USER::pg_catalog.regrole::oid THEN
        RAISE EXCEPTION 'pgcontext schema must be owned by the extension installer'
            USING ERRCODE = '42501';
    END IF;
    IF delegated_create THEN
        RAISE EXCEPTION 'pgcontext schema must not delegate CREATE privilege'
            USING ERRCODE = '42501';
    END IF;
END
$pgcontext_schema_guard$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog_schema.rs:3
-- requires:
--   pgcontext_bootstrap


CREATE TABLE pgcontext._collections (
    collection_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_name text NOT NULL UNIQUE,
    owner_role oid NOT NULL,
    config_revision bigint NOT NULL DEFAULT 1 CHECK (config_revision > 0),
    source_table_oid oid,
    source_schema_name text,
    source_table_name text,
    strict_mode boolean NOT NULL DEFAULT false,
    max_dimensions int4 CHECK (max_dimensions IS NULL OR max_dimensions > 0),
    max_vectors int4 CHECK (max_vectors IS NULL OR max_vectors > 0),
    max_points bigint CHECK (max_points IS NULL OR max_points > 0),
    max_filter_nodes int4 CHECK (max_filter_nodes IS NULL OR max_filter_nodes > 0),
    max_search_limit int4 CHECK (max_search_limit IS NULL OR max_search_limit > 0),
    max_candidate_budget int4 CHECK (max_candidate_budget IS NULL OR max_candidate_budget > 0),
    query_timeout_ms int4 CHECK (query_timeout_ms IS NULL OR query_timeout_ms > 0),
    max_index_memory_bytes bigint CHECK (
        max_index_memory_bytes IS NULL OR max_index_memory_bytes > 0
    ),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(), updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK (
        (source_table_oid IS NULL AND source_schema_name IS NULL AND source_table_name IS NULL)
        OR
        (source_table_oid IS NOT NULL AND source_schema_name IS NOT NULL AND source_table_name IS NOT NULL)
    )
);

CREATE TABLE pgcontext._collection_vectors (
    vector_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    vector_name text NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    vector_column_name text NOT NULL,
    vector_attnum int2 NOT NULL,
    hnsw_index_oid oid,
    dimensions int4 NOT NULL CHECK (dimensions > 0),
    metric text NOT NULL CHECK (metric IN ('l2', 'inner_product', 'cosine', 'l1', 'hamming', 'jaccard')),
    hnsw_options jsonb NOT NULL DEFAULT '{}'::jsonb CHECK (pg_catalog.jsonb_typeof(hnsw_options) = 'object'),
    quantization_options jsonb NOT NULL DEFAULT '{}'::jsonb CHECK (pg_catalog.jsonb_typeof(quantization_options) = 'object'),
    status text NOT NULL DEFAULT 'ready' CHECK (status IN ('ready', 'building', 'disabled', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(), updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, vector_name),
    UNIQUE (collection_id, vector_column_name)
);

CREATE TABLE pgcontext._collection_sparse_vectors (
    sparse_vector_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    vector_name text NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    vector_column_name text NOT NULL,
    vector_attnum int2 NOT NULL,
    dimensions int4 NOT NULL CHECK (dimensions > 0),
    metric text NOT NULL CHECK (metric IN ('l2', 'inner_product', 'cosine', 'l1', 'hamming', 'jaccard')),
    storage_options jsonb NOT NULL DEFAULT '{}'::jsonb CHECK (pg_catalog.jsonb_typeof(storage_options) = 'object'),
    index_options jsonb NOT NULL DEFAULT '{}'::jsonb CHECK (pg_catalog.jsonb_typeof(index_options) = 'object'),
    status text NOT NULL DEFAULT 'ready' CHECK (status IN ('ready', 'building', 'disabled', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(), updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, vector_name),
    UNIQUE (collection_id, vector_column_name)
);

CREATE TABLE pgcontext._collection_points (
    point_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_key text NOT NULL,
    deleted_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, source_key)
);

CREATE TABLE pgcontext._collection_source_revisions (
    collection_id bigint PRIMARY KEY REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_version bigint NOT NULL DEFAULT 1 CHECK (source_version > 0),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);

CREATE FUNCTION pgcontext._initialize_collection_source_revision()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    INSERT INTO pgcontext._collection_source_revisions (collection_id)
    VALUES (NEW.collection_id)
    ON CONFLICT (collection_id) DO NOTHING;
    RETURN NEW;
END;
$$;

CREATE TRIGGER pgcontext_initialize_collection_source_revision
AFTER INSERT ON pgcontext._collections
FOR EACH ROW
EXECUTE FUNCTION pgcontext._initialize_collection_source_revision();

CREATE TABLE pgcontext._collection_aliases (
    alias_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    alias_name text NOT NULL UNIQUE,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);

CREATE TABLE pgcontext._collection_payload_columns (
    payload_column_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    filter_key text NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    column_name text NOT NULL,
    column_attnum int2 NOT NULL,
    jsonb_path text[],
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, filter_key),
    UNIQUE NULLS NOT DISTINCT (collection_id, column_name, jsonb_path)
);

CREATE TABLE pgcontext._query_stats (
    query_stat_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    cohort text NOT NULL CHECK (cohort <> ''),
    query_kind text NOT NULL CHECK (query_kind IN ('search', 'search_filtered', 'candidate_recheck', 'hybrid')),
    result_count bigint NOT NULL CHECK (result_count >= 0),
    candidate_count bigint CHECK (candidate_count IS NULL OR candidate_count >= 0),
    rows_rechecked bigint NOT NULL DEFAULT 0 CHECK (rows_rechecked >= 0),
    rows_pruned bigint NOT NULL DEFAULT 0 CHECK (rows_pruned >= 0),
    recall_threshold double precision CHECK (recall_threshold IS NULL OR (recall_threshold >= 0 AND recall_threshold <= 1)),
    recall_achieved double precision CHECK (recall_achieved IS NULL OR (recall_achieved >= 0 AND recall_achieved <= 1)),
    latency_bucket text NOT NULL DEFAULT 'Unspecified' CHECK (latency_bucket IN ('Lt1Ms', 'Lt10Ms', 'Lt100Ms', 'Lt1S', 'Gte1S', 'Unspecified')),
    lifecycle_state text NOT NULL DEFAULT 'Unspecified' CHECK (lifecycle_state IN ('Unspecified', 'Exact', 'Indexed', 'Fallback', 'IndexNotReady', 'IndexCorrupt', 'ArtifactMissing')),
    strategy text NOT NULL DEFAULT 'unspecified' CHECK (
        pg_catalog.octet_length(strategy) BETWEEN 1 AND 64
        AND strategy ~ '^[a-z0-9_]+$'
    ),
    visits bigint NOT NULL DEFAULT 0 CHECK (visits >= 0),
    filter_candidates bigint NOT NULL DEFAULT 0 CHECK (filter_candidates >= 0),
    candidates bigint NOT NULL DEFAULT 0 CHECK (candidates >= 0),
    rechecks bigint NOT NULL DEFAULT 0 CHECK (rechecks >= 0),
    stages bigint NOT NULL DEFAULT 0 CHECK (stages >= 0),
    expansions bigint NOT NULL DEFAULT 0 CHECK (expansions >= 0),
    adaptive_prefix_dimensions int4 CHECK (adaptive_prefix_dimensions > 0),
    adaptive_termination text CHECK (
        adaptive_termination IN (
            'exhaustive', 'empty_corpus', 'candidate_budget',
            'comparison_budget', 'recheck_budget', 'memory_budget',
            'expansion_budget'
        )
    ),
    completion text NOT NULL DEFAULT 'unspecified' CHECK (
        completion IN ('unspecified', 'complete', 'cancelled', 'budget_exhausted', 'error')
    ),
    latency_ms double precision NOT NULL CHECK (latency_ms >= 0),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);

CREATE TABLE pgcontext._embedding_profiles (
    embedding_profile_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    profile_name text NOT NULL CHECK (
        pg_catalog.octet_length(profile_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(profile_name) <> ''
        AND profile_name !~ '[[:cntrl:]]'
    ),
    source_schema_name text NOT NULL CHECK (pg_catalog.btrim(source_schema_name) <> ''),
    source_table_name text NOT NULL CHECK (pg_catalog.btrim(source_table_name) <> ''),
    source_column_name text NOT NULL CHECK (pg_catalog.btrim(source_column_name) <> ''),
    source_attnum int2 NOT NULL CHECK (source_attnum > 0),
    source_type_name text NOT NULL CHECK (source_type_name IN ('vector', 'halfvec', 'sparsevec', 'bitvec', 'int8vec', 'uint8vec')),
    source_typmod int4 NOT NULL CHECK (source_typmod BETWEEN 1 AND 16000),
    source_version_column_name text,
    source_version_attnum int2,
    embedding_version_column_name text,
    embedding_version_attnum int2,
    hnsw_schema_name text NOT NULL CHECK (pg_catalog.btrim(hnsw_schema_name) <> ''),
    hnsw_index_name text NOT NULL CHECK (pg_catalog.btrim(hnsw_index_name) <> ''),
    hnsw_opclass text NOT NULL CHECK (pg_catalog.btrim(hnsw_opclass) <> ''),
    representation text NOT NULL CHECK (representation IN ('dense', 'half', 'sparse', 'bit', 'int8', 'uint8')),
    dimensions int4 NOT NULL CHECK (dimensions BETWEEN 1 AND 16000),
    normalization text NOT NULL CHECK (normalization IN ('none', 'unit_l2')),
    metric text NOT NULL CHECK (metric IN ('l2', 'inner_product', 'cosine', 'l1', 'hamming', 'jaccard')),
    provider text NOT NULL CHECK (pg_catalog.btrim(provider) <> ''),
    model text NOT NULL CHECK (pg_catalog.btrim(model) <> ''),
    revision text NOT NULL CHECK (pg_catalog.btrim(revision) <> ''),
    input_template text NOT NULL CHECK (pg_catalog.btrim(input_template) <> ''),
    output_template text NOT NULL CHECK (pg_catalog.btrim(output_template) <> ''),
    bit_order text CHECK (bit_order IN ('msb_first', 'lsb_first')),
    byte_order text CHECK (byte_order IN ('msb_first', 'lsb_first')),
    scale double precision CHECK (scale IS NULL OR (scale > 0 AND scale < 'Infinity'::double precision)),
    zero_point int4,
    configuration_hash text NOT NULL CHECK (configuration_hash ~ '^[0-9a-f]{16}$' AND configuration_hash <> '0000000000000000'),
    matryoshka_prefixes int4[],
    -- Only `active` and `draining` serve queries. A profile registers into
    -- `shadow` or `active`; every later move is a validated transition.
    lifecycle text NOT NULL DEFAULT 'active'
        CHECK (lifecycle IN ('shadow', 'active', 'draining', 'retired', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, profile_name),
    -- A declared Matryoshka policy must certify 1..=8 prefixes below the full
    -- dimension, and only for a representation and metric whose coordinates
    -- stay interpretable at a cut point. Strict ascent is enforced by the typed
    -- `MatryoshkaPolicy` constructor: a CHECK cannot contain the subquery that
    -- a pairwise comparison would need, and adding an extension-owned function
    -- to a CHECK would entangle dump/restore ordering.
    CHECK (matryoshka_prefixes IS NULL OR (
        pg_catalog.cardinality(matryoshka_prefixes) BETWEEN 1 AND 8
        AND representation IN ('dense', 'half')
        AND metric IN ('l2', 'inner_product', 'cosine')
        AND matryoshka_prefixes[1] > 0
        AND matryoshka_prefixes[pg_catalog.cardinality(matryoshka_prefixes)] < dimensions
    )),
    UNIQUE (collection_id, source_column_name, revision),
    CHECK (source_type_name = CASE representation
        WHEN 'dense' THEN 'vector'
        WHEN 'half' THEN 'halfvec'
        WHEN 'sparse' THEN 'sparsevec'
        WHEN 'bit' THEN 'bitvec'
        WHEN 'int8' THEN 'int8vec'
        WHEN 'uint8' THEN 'uint8vec'
    END),
    CHECK (source_typmod = dimensions),
    CHECK (
        (source_version_column_name IS NULL
            AND source_version_attnum IS NULL
            AND embedding_version_column_name IS NULL
            AND embedding_version_attnum IS NULL)
        OR
        (pg_catalog.btrim(source_version_column_name) <> ''
            AND source_version_attnum > 0
            AND pg_catalog.btrim(embedding_version_column_name) <> ''
            AND embedding_version_attnum > 0
            AND source_version_column_name <> embedding_version_column_name
            AND source_version_attnum <> embedding_version_attnum)
    ),
    CHECK (
        (representation = 'bit'
            AND metric IN ('hamming', 'jaccard')
            AND bit_order IS NOT NULL
            AND byte_order IS NOT NULL
            AND scale IS NULL
            AND zero_point IS NULL)
        OR
        (representation <> 'bit'
            AND metric IN ('l2', 'inner_product', 'cosine', 'l1')
            AND bit_order IS NULL
            AND byte_order IS NULL
            AND (
                (representation = 'int8' AND (
                    (scale IS NULL AND zero_point IS NULL)
                    OR (scale IS NOT NULL AND zero_point IS NOT NULL AND zero_point BETWEEN -128 AND 127)
                ))
                OR
                (representation = 'uint8' AND (
                    (scale IS NULL AND zero_point IS NULL)
                    OR (scale IS NOT NULL AND zero_point IS NOT NULL AND zero_point BETWEEN 0 AND 255)
                ))
                OR
                (representation NOT IN ('int8', 'uint8') AND scale IS NULL AND zero_point IS NULL)
            ))
    )
);

-- An embedding profile's *contract* is immutable: representation, dimensions,
-- metric, templates, bindings, and hash describe a model that already produced
-- stored vectors, so changing one would silently reinterpret existing data.
-- `lifecycle` is different in kind -- it records whether that fixed contract is
-- currently serving -- so it is the one column an update may touch, and only
-- along a legal transition.
--
-- The contract comparison neutralizes `lifecycle` in both row images and then
-- compares the rows as text. Comparing whole rows rather than listing protected
-- columns means a column added later is protected by default; comparing text
-- rather than jsonb also catches changes jsonb normalizes away, such as an
-- array rewritten with different dimension bounds.
--
-- The transition table is duplicated from `context-core::ProfileLifecycle` on
-- purpose: the Rust table governs the SQL-facing API, and this one governs
-- direct catalog writes, so the invariant survives a superuser bypassing the
-- API.
CREATE FUNCTION pgcontext._reject_embedding_profile_mutation()
RETURNS trigger
LANGUAGE plpgsql
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    frozen_old pgcontext._embedding_profiles := OLD;
    frozen_new pgcontext._embedding_profiles := NEW;
BEGIN
    frozen_old.lifecycle := '';
    frozen_new.lifecycle := '';
    IF frozen_new::text IS DISTINCT FROM frozen_old::text THEN
        RAISE EXCEPTION USING
            ERRCODE = '55000',
            MESSAGE = 'embedding profiles are immutable; register a new profile revision';
    END IF;

    IF NEW.lifecycle = OLD.lifecycle THEN
        RAISE EXCEPTION USING
            ERRCODE = '22023',
            MESSAGE = pg_catalog.format(
                'embedding profile cannot move from %s to %s', OLD.lifecycle, NEW.lifecycle
            );
    END IF;

    IF NOT (
        (OLD.lifecycle = 'shadow' AND NEW.lifecycle IN ('active', 'failed', 'retired'))
        OR (OLD.lifecycle = 'active' AND NEW.lifecycle IN ('draining', 'failed'))
        OR (OLD.lifecycle = 'draining' AND NEW.lifecycle IN ('retired', 'active', 'failed'))
        OR (OLD.lifecycle = 'failed' AND NEW.lifecycle IN ('shadow', 'retired'))
    ) THEN
        RAISE EXCEPTION USING
            ERRCODE = '22023',
            MESSAGE = pg_catalog.format(
                'embedding profile cannot move from %s to %s', OLD.lifecycle, NEW.lifecycle
            );
    END IF;

    RETURN NEW;
END;
$$;

-- Catalog write for the one mutable column. Retrieval and registration run
-- SECURITY INVOKER, so a non-superuser collection member holds no privilege on
-- this private table; the write is performed as the extension owner after an
-- explicit owner-role check, exactly like the other catalog writers here.
CREATE FUNCTION pgcontext._set_embedding_profile_lifecycle(
    p_collection_id bigint,
    p_profile_name text,
    p_lifecycle text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied for collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    UPDATE pgcontext._embedding_profiles
       SET lifecycle = p_lifecycle
     WHERE collection_id = p_collection_id
       AND profile_name = p_profile_name;
END;
$$;

CREATE TRIGGER embedding_profiles_immutable
BEFORE UPDATE ON pgcontext._embedding_profiles
FOR EACH ROW EXECUTE FUNCTION pgcontext._reject_embedding_profile_mutation();

CREATE TABLE pgcontext._embedding_migrations (
    migration_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_embedding_profile_id bigint NOT NULL REFERENCES pgcontext._embedding_profiles(embedding_profile_id),
    target_embedding_profile_id bigint NOT NULL REFERENCES pgcontext._embedding_profiles(embedding_profile_id),
    status text NOT NULL CHECK (status IN ('planned', 'running', 'completed', 'failed')),
    total_points bigint NOT NULL CHECK (total_points >= 0),
    processed_points bigint NOT NULL DEFAULT 0 CHECK (processed_points >= 0),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK (processed_points <= total_points),
    CHECK (source_embedding_profile_id <> target_embedding_profile_id)
);

CREATE TABLE pgcontext._build_jobs (
    build_job_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    artifact_kind text NOT NULL CHECK (
        artifact_kind IN ('index', 'segment', 'sparse_index', 'mmap', 'certification')
    ),
    artifact_name text NOT NULL CHECK (artifact_name <> ''),
    target_name text NOT NULL CHECK (target_name <> ''),
    job_kind text NOT NULL DEFAULT 'artifact_build' CHECK (
        job_kind IN ('artifact_build', 'compaction', 'projection_backfill', 'certification')
    ),
    status text NOT NULL CHECK (
        status IN ('planned', 'running', 'cancel_requested', 'cancelled', 'validating', 'publishing', 'completed', 'failed', 'abandoned')
    ),
    backend_pid int4,
    backend_identity text,
    attempt int4 NOT NULL DEFAULT 1 CHECK (attempt > 0),
    total_units bigint NOT NULL CHECK (total_units >= 0),
    processed_units bigint NOT NULL DEFAULT 0 CHECK (processed_units >= 0),
    last_source_point_id bigint NOT NULL DEFAULT 0 CHECK (last_source_point_id >= 0),
    source_high_water bigint NOT NULL DEFAULT 0 CHECK (source_high_water >= 0),
    config_revision bigint,
    source_version bigint CHECK (source_version IS NULL OR source_version > 0),
    lease_expires_at timestamptz,
    validation_passed boolean,
    validation_findings int4 CHECK (validation_findings IS NULL OR validation_findings >= 0),
    published_generation bigint CHECK (published_generation IS NULL OR published_generation > 0),
    supervised boolean NOT NULL DEFAULT false,
    cancel_requested boolean NOT NULL DEFAULT false,
    error_message text,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    completed_at timestamptz,
    CHECK (processed_units <= total_units),
    CHECK (NOT supervised OR job_kind IN ('certification', 'compaction'))
);

CREATE FUNCTION pgcontext._reject_build_job_progress_regression()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    IF NEW.processed_units < OLD.processed_units THEN
        RAISE EXCEPTION 'build job progress cannot go backwards: % < %',
            NEW.processed_units,
            OLD.processed_units
            USING ERRCODE = '22023';
    END IF;
    RETURN NEW;
END;
$$;

CREATE TRIGGER pgcontext_build_jobs_no_progress_regression
BEFORE UPDATE OF processed_units ON pgcontext._build_jobs
FOR EACH ROW
EXECUTE FUNCTION pgcontext._reject_build_job_progress_regression();

CREATE FUNCTION pgcontext._enforce_build_job_terminal_state()
RETURNS trigger
LANGUAGE plpgsql
AS $$
BEGIN
    IF NEW.status IN ('running', 'cancel_requested', 'validating', 'publishing') THEN
        IF NEW.backend_pid IS NULL THEN
            RAISE EXCEPTION 'active build job % must record backend_pid',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
        IF NEW.backend_identity IS NULL THEN
            RAISE EXCEPTION 'active build job % must record backend_identity',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
        IF NEW.completed_at IS NOT NULL THEN
            RAISE EXCEPTION 'active build job % cannot retain completed_at',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
        IF NEW.lease_expires_at IS NULL THEN
            RAISE EXCEPTION 'active build job % must record lease_expires_at',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
    END IF;
    IF NEW.status IN ('completed', 'failed', 'cancelled', 'abandoned') THEN
        IF NEW.backend_pid IS NOT NULL OR NEW.backend_identity IS NOT NULL THEN
            RAISE EXCEPTION 'terminal build job % cannot retain backend ownership',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
        IF NEW.completed_at IS NULL THEN
            RAISE EXCEPTION 'terminal build job % must record completed_at',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
        IF NEW.lease_expires_at IS NOT NULL THEN
            RAISE EXCEPTION 'terminal build job % cannot retain a lease',
                NEW.status
                USING ERRCODE = '22023';
        END IF;
    END IF;
    IF NEW.status IN ('validating', 'publishing', 'completed') AND NEW.processed_units <> NEW.total_units THEN
        RAISE EXCEPTION 'completed build job progress must equal total: % <> %',
            NEW.processed_units,
            NEW.total_units
            USING ERRCODE = '22023';
    END IF;
    RETURN NEW;
END;
$$;

CREATE TRIGGER pgcontext_build_jobs_terminal_state
BEFORE INSERT OR UPDATE OF status, backend_pid, backend_identity, lease_expires_at, completed_at, processed_units, total_units
ON pgcontext._build_jobs
FOR EACH ROW
EXECUTE FUNCTION pgcontext._enforce_build_job_terminal_state();

CREATE UNIQUE INDEX pgcontext_build_jobs_one_active_target
    ON pgcontext._build_jobs (collection_id, artifact_kind, artifact_name, target_name)
 WHERE status IN ('planned', 'running', 'cancel_requested', 'validating', 'publishing');

CREATE TABLE pgcontext._build_deltas (
    delta_sequence bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    build_job_id bigint NOT NULL REFERENCES pgcontext._build_jobs(build_job_id) ON DELETE CASCADE,
    point_id bigint NOT NULL REFERENCES pgcontext._collection_points(point_id) ON DELETE CASCADE,
    operation text NOT NULL CHECK (operation IN ('upsert', 'delete')),
    source_version bigint NOT NULL CHECK (source_version > 0),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (build_job_id, source_version, point_id)
);

CREATE FUNCTION pgcontext._capture_build_point_delta()
RETURNS trigger
LANGUAGE plpgsql
AS $$
DECLARE
    delta_operation text;
    next_source_version bigint;
BEGIN
    INSERT INTO pgcontext._collection_source_revisions (
        collection_id, source_version, updated_at
    )
    VALUES (NEW.collection_id, 1, pg_catalog.now())
    ON CONFLICT (collection_id) DO UPDATE
       SET source_version = pgcontext._collection_source_revisions.source_version + 1,
           updated_at = pg_catalog.now()
    RETURNING source_version INTO STRICT next_source_version;
    delta_operation := CASE WHEN NEW.deleted_at IS NULL THEN 'upsert' ELSE 'delete' END;
    INSERT INTO pgcontext._build_deltas (
        build_job_id, point_id, operation, source_version
    )
    SELECT jobs.build_job_id, NEW.point_id, delta_operation, next_source_version
      FROM pgcontext._build_jobs AS jobs
     WHERE jobs.collection_id = NEW.collection_id
       AND (
           jobs.status IN ('running', 'cancel_requested', 'validating', 'publishing')
           OR (jobs.supervised AND jobs.status = 'planned')
       )
    ON CONFLICT (build_job_id, source_version, point_id) DO UPDATE
       SET operation = EXCLUDED.operation;
    RETURN NEW;
END;
$$;

CREATE TRIGGER pgcontext_capture_build_point_delta
AFTER INSERT OR UPDATE OF deleted_at ON pgcontext._collection_points
FOR EACH ROW
EXECUTE FUNCTION pgcontext._capture_build_point_delta();

CREATE TABLE pgcontext._generation_build_rows (
    build_job_id bigint NOT NULL REFERENCES pgcontext._build_jobs(build_job_id) ON DELETE CASCADE,
    point_id bigint NOT NULL,
    source_key text NOT NULL,
    PRIMARY KEY (build_job_id, point_id)
);

CREATE TABLE pgcontext._artifact_segments (
    artifact_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    build_job_id bigint NOT NULL REFERENCES pgcontext._build_jobs(build_job_id) ON DELETE RESTRICT,
    artifact_kind text NOT NULL CHECK (artifact_kind IN ('segment', 'mmap')),
    artifact_name text NOT NULL CHECK (artifact_name <> ''),
    target_name text NOT NULL CHECK (target_name <> ''),
    generation bigint NOT NULL CHECK (generation > 0),
    segment_kind text NOT NULL CHECK (segment_kind IN ('hnsw_graph')),
    format_version int4 NOT NULL CHECK (format_version = 2),
    payload_bytes bigint NOT NULL CHECK (payload_bytes >= 0),
    checksum bigint NOT NULL,
    config_revision bigint,
    relative_path text,
    lifecycle_state text NOT NULL DEFAULT 'validated' CHECK (lifecycle_state IN ('validated', 'file_materialized', 'rebuild_required', 'retired')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK (lifecycle_state <> 'file_materialized' OR relative_path IS NOT NULL),
    UNIQUE (collection_id, artifact_kind, artifact_name, target_name, generation)
);

CREATE FUNCTION pgcontext.current_vector_config_revision(collection bigint)
RETURNS bigint
LANGUAGE sql
STABLE
AS $$
    SELECT config_revision
      FROM pgcontext._collections
     WHERE collection_id = $1
$$;

CREATE TABLE pgcontext._artifact_reader_pins (
    artifact_id bigint NOT NULL REFERENCES pgcontext._artifact_segments(artifact_id) ON DELETE CASCADE,
    backend_pid int4 NOT NULL,
    backend_identity text NOT NULL,
    pin_count int4 NOT NULL CHECK (pin_count > 0),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (artifact_id, backend_pid, backend_identity)
);

CREATE TABLE pgcontext._generation_manifests (
    generation bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    build_job_id bigint NOT NULL UNIQUE REFERENCES pgcontext._build_jobs(build_job_id) ON DELETE RESTRICT,
    publication_alias text NOT NULL CHECK (publication_alias <> ''),
    source_version bigint NOT NULL CHECK (source_version > 0),
    config_revision bigint NOT NULL CHECK (config_revision > 0),
    lifecycle_state text NOT NULL DEFAULT 'staged' CHECK (
        lifecycle_state IN ('staged', 'validated', 'published', 'retiring', 'retired', 'rebuild_required')
    ),
    validation_passed boolean,
    validation_findings int4 CHECK (validation_findings IS NULL OR validation_findings >= 0),
    total_payload_bytes bigint NOT NULL DEFAULT 0 CHECK (total_payload_bytes >= 0),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK ((validation_passed IS NULL) = (validation_findings IS NULL)),
    CHECK (lifecycle_state NOT IN ('validated', 'published', 'retiring', 'retired') OR validation_passed)
);

CREATE TABLE pgcontext._generation_artifacts (
    generation bigint NOT NULL REFERENCES pgcontext._generation_manifests(generation) ON DELETE CASCADE,
    artifact_kind text NOT NULL CHECK (artifact_kind IN (
        'hnsw_segment', 'hnsw_delta', 'hnsw_directory', 'ivf_centroids',
        'ivf_postings', 'quantized_codes', 'chunk_projection',
        'vector_projection', 'graph_projection', 'community_summary',
        'certification_evidence'
    )),
    artifact_name text NOT NULL CHECK (artifact_name <> ''),
    payload_bytes bigint NOT NULL CHECK (payload_bytes >= 0),
    checksum_algorithm text NOT NULL DEFAULT 'pg_hashtextextended_hex_v1' CHECK (
        checksum_algorithm = 'pg_hashtextextended_hex_v1'
    ),
    checksum bigint NOT NULL,
    payload bytea NOT NULL,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (generation, artifact_kind, artifact_name),
    CONSTRAINT generation_artifact_payload_length_check CHECK (
        payload_bytes = pg_catalog.octet_length(payload)
    ),
    CONSTRAINT generation_artifact_payload_checksum_check CHECK (
        checksum_algorithm = 'pg_hashtextextended_hex_v1'
        AND checksum = pg_catalog.hashtextextended(pg_catalog.encode(payload, 'hex'), 0)
    )
);

CREATE TABLE pgcontext._generation_aliases (
    collection_id bigint NOT NULL REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    publication_alias text NOT NULL CHECK (publication_alias <> ''),
    generation bigint NOT NULL UNIQUE REFERENCES pgcontext._generation_manifests(generation) ON DELETE RESTRICT,
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (collection_id, publication_alias)
);

CREATE TABLE pgcontext._generation_reader_pins (
    generation bigint NOT NULL REFERENCES pgcontext._generation_manifests(generation) ON DELETE CASCADE,
    backend_pid int4 NOT NULL,
    backend_identity text NOT NULL,
    pin_count int4 NOT NULL CHECK (pin_count > 0),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (generation, backend_pid, backend_identity)
);

CREATE FUNCTION pgcontext._publish_generation(target_generation bigint)
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
    target_collection bigint;
    target_alias text;
    previous_generation bigint;
BEGIN
    SELECT collection_id, publication_alias
      INTO target_collection, target_alias
      FROM pgcontext._generation_manifests
     WHERE generation = target_generation
       AND lifecycle_state IN ('validated', 'published')
       AND validation_passed
     FOR UPDATE;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'generation % is not validated for publication', target_generation
            USING ERRCODE = '55000';
    END IF;
    IF NOT EXISTS (
        SELECT 1 FROM pgcontext._generation_artifacts WHERE generation = target_generation
    ) THEN
        RAISE EXCEPTION 'generation % has no artifact inventory', target_generation
            USING ERRCODE = '55000';
    END IF;

    -- A collection row always exists for a valid manifest and provides a
    -- transaction-scoped serialization point even when an alias has never
    -- been published before.
    PERFORM 1
      FROM pgcontext._collections
     WHERE collection_id = target_collection
     FOR UPDATE;

    SELECT generation
      INTO previous_generation
      FROM pgcontext._generation_aliases
     WHERE collection_id = target_collection
       AND publication_alias = target_alias
     FOR UPDATE;

    IF previous_generation IS NOT NULL AND previous_generation <> target_generation THEN
        DELETE FROM pgcontext._generation_reader_pins AS pins
         WHERE pins.generation = previous_generation
           AND NOT EXISTS (
               SELECT 1
                 FROM pg_catalog.pg_stat_activity AS activity
                WHERE activity.pid = pins.backend_pid
                  AND pg_catalog.to_char(
                          activity.backend_start AT TIME ZONE 'UTC',
                          'YYYY-MM-DD"T"HH24:MI:SS.US'
                      ) = pins.backend_identity
           );
        UPDATE pgcontext._generation_manifests
           SET lifecycle_state = CASE
                   WHEN EXISTS (
                       SELECT 1
                         FROM pgcontext._generation_reader_pins AS pins
                        WHERE pins.generation = previous_generation
                   ) THEN 'retiring'
                   ELSE 'retired'
               END,
               updated_at = pg_catalog.now()
         WHERE generation = previous_generation
           AND lifecycle_state = 'published';
    END IF;

    INSERT INTO pgcontext._generation_aliases (collection_id, publication_alias, generation)
    VALUES (target_collection, target_alias, target_generation)
    ON CONFLICT (collection_id, publication_alias) DO UPDATE
       SET generation = EXCLUDED.generation,
           updated_at = pg_catalog.now();

    UPDATE pgcontext._generation_manifests
       SET lifecycle_state = 'published', updated_at = pg_catalog.now()
     WHERE generation = target_generation;
END;
$$;

CREATE FUNCTION pgcontext._pin_generation(
    target_collection bigint,
    target_alias text
)
RETURNS bigint
LANGUAGE plpgsql
AS $$
DECLARE
    target_generation bigint;
    backend_identity_value text;
BEGIN
    SELECT aliases.generation
      INTO target_generation
      FROM pgcontext._generation_aliases AS aliases
      JOIN pgcontext._generation_manifests AS manifests USING (generation)
     WHERE aliases.collection_id = target_collection
       AND aliases.publication_alias = target_alias
       AND manifests.lifecycle_state = 'published'
     FOR SHARE OF aliases, manifests;
    IF NOT FOUND THEN
        RETURN NULL;
    END IF;
    SELECT pg_catalog.to_char(
               activity.backend_start AT TIME ZONE 'UTC',
               'YYYY-MM-DD"T"HH24:MI:SS.US'
           )
      INTO STRICT backend_identity_value
      FROM pg_catalog.pg_stat_activity AS activity
     WHERE activity.pid = pg_catalog.pg_backend_pid();
    INSERT INTO pgcontext._generation_reader_pins (
        generation, backend_pid, backend_identity, pin_count
    )
    VALUES (
        target_generation, pg_catalog.pg_backend_pid(), backend_identity_value, 1
    )
    ON CONFLICT (generation, backend_pid, backend_identity) DO UPDATE
       SET pin_count = pgcontext._generation_reader_pins.pin_count + 1,
           updated_at = pg_catalog.now();
    RETURN target_generation;
END;
$$;

CREATE FUNCTION pgcontext._unpin_generation(target_generation bigint)
RETURNS void
LANGUAGE plpgsql
AS $$
DECLARE
    backend_identity_value text;
BEGIN
    SELECT pg_catalog.to_char(
               activity.backend_start AT TIME ZONE 'UTC',
               'YYYY-MM-DD"T"HH24:MI:SS.US'
           )
      INTO STRICT backend_identity_value
      FROM pg_catalog.pg_stat_activity AS activity
     WHERE activity.pid = pg_catalog.pg_backend_pid();
    UPDATE pgcontext._generation_reader_pins
       SET pin_count = pin_count - 1,
           updated_at = pg_catalog.now()
     WHERE generation = target_generation
       AND backend_pid = pg_catalog.pg_backend_pid()
       AND backend_identity = backend_identity_value
       AND pin_count > 1;
    IF NOT FOUND THEN
        DELETE FROM pgcontext._generation_reader_pins
         WHERE generation = target_generation
           AND backend_pid = pg_catalog.pg_backend_pid()
           AND backend_identity = backend_identity_value;
        IF NOT FOUND THEN
            RAISE EXCEPTION 'generation % is not pinned by this backend', target_generation
                USING ERRCODE = '55000';
        END IF;
    END IF;
    UPDATE pgcontext._generation_manifests AS manifests
       SET lifecycle_state = 'retired', updated_at = pg_catalog.now()
     WHERE manifests.generation = target_generation
       AND manifests.lifecycle_state = 'retiring'
       AND NOT EXISTS (
           SELECT 1
             FROM pgcontext._generation_reader_pins AS pins
            WHERE pins.generation = manifests.generation
       );
END;
$$;

-- Intentionally unfiltered pre-authorization lookup. Callers need this minimal
-- collection/alias name, owner-role, and source-binding summary to resolve a
-- collection before checking membership. It must not expose source-table
-- identity, source keys, vectors, payload metadata, or operational state.
CREATE VIEW pgcontext._collection_acl AS
SELECT collection_id,
       collection_name,
       owner_role,
       source_table_oid IS NOT NULL AS has_source_table
  FROM pgcontext._collections
UNION ALL
SELECT collections.collection_id,
       aliases.alias_name AS collection_name,
       collections.owner_role,
       collections.source_table_oid IS NOT NULL AS has_source_table
  FROM pgcontext._collection_aliases AS aliases
  JOIN pgcontext._collections AS collections USING (collection_id);

CREATE VIEW pgcontext._visible_collection_vectors
WITH (security_barrier = true) AS
SELECT vectors.*
  FROM pgcontext._collection_vectors AS vectors
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_embedding_profiles
WITH (security_barrier = true) AS
SELECT profiles.*
  FROM pgcontext._embedding_profiles AS profiles
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_sparse_vectors
WITH (security_barrier = true) AS
SELECT vectors.*
  FROM pgcontext._collection_sparse_vectors AS vectors
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_points
WITH (security_barrier = true) AS
SELECT points.*
  FROM pgcontext._collection_points AS points
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_query_stats
WITH (security_barrier = true) AS
SELECT stats.*
  FROM pgcontext._query_stats AS stats
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_payload_columns
WITH (security_barrier = true) AS
SELECT payload_columns.*
  FROM pgcontext._collection_payload_columns AS payload_columns
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_build_jobs
WITH (security_barrier = true) AS
SELECT jobs.*
  FROM pgcontext._build_jobs AS jobs
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_artifact_segments
WITH (security_barrier = true) AS
SELECT artifacts.*,
       collections.collection_name
  FROM pgcontext._artifact_segments AS artifacts
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_limits
WITH (security_barrier = true) AS
SELECT collection_id,
       strict_mode,
       max_dimensions,
       max_vectors,
       max_points,
       max_filter_nodes,
       max_search_limit,
       max_candidate_budget,
       query_timeout_ms,
       max_index_memory_bytes
  FROM pgcontext._collections
 WHERE pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collections
WITH (security_barrier = true) AS
SELECT collection_id,
       collection_name,
       owner_role,
       source_table_oid,
       source_schema_name,
       source_table_name
  FROM pgcontext._collections
 WHERE pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER');

GRANT SELECT ON pgcontext._collection_acl TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_vectors TO PUBLIC;
GRANT SELECT ON pgcontext._visible_embedding_profiles TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_sparse_vectors TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_points TO PUBLIC;
GRANT SELECT ON pgcontext._visible_query_stats TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_payload_columns TO PUBLIC;
GRANT SELECT ON pgcontext._visible_build_jobs TO PUBLIC;
GRANT SELECT ON pgcontext._visible_artifact_segments TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_limits TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collections TO PUBLIC;

-- Drift self-healing writes. Retrieval functions run SECURITY INVOKER so that
-- source-table SELECT/RLS is enforced against the caller, which means a
-- non-superuser collection member holds no direct privilege on the private
-- catalog tables. When a dump/restore or table rewrite changes a source
-- table's oid, the query path detects the drift and refreshes the stored
-- metadata through these SECURITY DEFINER helpers so the write succeeds as the
-- extension owner.
--
-- Security: these helpers accept only identifying keys, never a caller-supplied
-- oid or attnum. Each re-derives the authoritative oid/attnum from pg_catalog
-- using the schema, table, and column names already stored in the private
-- catalog, so a call can only ever set the true current binding of the
-- already-registered source table. This is deliberate: accepting an oid would
-- let a collection member repoint _collections.source_table_oid at an unrelated
-- table they control, and the SECURITY DEFINER payload/backfill paths check
-- privileges by that oid while mutating the real table by name -- a
-- confused-deputy escalation. Each helper also re-checks owner-role membership
-- on SESSION_USER (defence in depth for direct calls) and pins search_path.
CREATE FUNCTION pgcontext._refresh_collection_source_table(
    p_collection_id bigint
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied to refresh collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    UPDATE pgcontext._collections AS collections
       SET source_table_oid = source_class.oid,
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.oid = source_class.relnamespace
     WHERE collections.collection_id = p_collection_id
       AND source_namespace.nspname = collections.source_schema_name
       AND source_class.relname = collections.source_table_name
       AND source_class.relkind IN ('r', 'p');
END;
$$;

CREATE FUNCTION pgcontext._refresh_vector_source_binding(
    p_collection_id bigint,
    p_vector_column_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied to refresh collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    UPDATE pgcontext._collection_vectors AS vectors
       SET source_table_oid = source_class.oid,
           vector_attnum = source_attribute.attnum,
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.oid = source_class.relnamespace
      JOIN pg_catalog.pg_attribute AS source_attribute
        ON source_attribute.attrelid = source_class.oid
     WHERE vectors.collection_id = p_collection_id
       AND vectors.vector_column_name = p_vector_column_name
       AND source_namespace.nspname = vectors.source_schema_name
       AND source_class.relname = vectors.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND source_attribute.attname = vectors.vector_column_name
       AND source_attribute.attnum > 0
       AND NOT source_attribute.attisdropped;
END;
$$;

CREATE FUNCTION pgcontext._refresh_sparse_vector_source_binding(
    p_collection_id bigint,
    p_vector_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied to refresh collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    UPDATE pgcontext._collection_sparse_vectors AS sparse_vectors
       SET source_table_oid = source_class.oid,
           vector_attnum = source_attribute.attnum,
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.oid = source_class.relnamespace
      JOIN pg_catalog.pg_attribute AS source_attribute
        ON source_attribute.attrelid = source_class.oid
     WHERE sparse_vectors.collection_id = p_collection_id
       AND sparse_vectors.vector_name = p_vector_name
       AND source_namespace.nspname = sparse_vectors.source_schema_name
       AND source_class.relname = sparse_vectors.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND source_attribute.attname = sparse_vectors.vector_column_name
       AND source_attribute.attnum > 0
       AND NOT source_attribute.attisdropped;
END;
$$;

CREATE FUNCTION pgcontext._refresh_payload_source_bindings(
    p_collection_id bigint
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied to refresh collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    UPDATE pgcontext._collection_payload_columns AS payload_columns
       SET source_table_oid = source_class.oid,
           column_attnum = source_attribute.attnum,
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.oid = source_class.relnamespace
      JOIN pg_catalog.pg_attribute AS source_attribute
        ON source_attribute.attrelid = source_class.oid
     WHERE payload_columns.collection_id = p_collection_id
       AND source_namespace.nspname = payload_columns.source_schema_name
       AND source_class.relname = payload_columns.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND source_attribute.attname = payload_columns.column_name
       AND source_attribute.attnum > 0
       AND NOT source_attribute.attisdropped;
END;
$$;

SELECT pg_catalog.pg_extension_config_dump('pgcontext._collections', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._collection_vectors', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._collection_sparse_vectors', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._collection_points', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._collection_aliases', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._collection_payload_columns', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._query_stats', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._embedding_profiles', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._embedding_migrations', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._build_jobs', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._build_deltas', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._artifact_segments', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._generation_manifests', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._generation_artifacts', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._generation_aliases', '');
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am/mapped_lifecycle.rs:38
-- requires:
--   pgcontext_bootstrap


CREATE FUNCTION pgcontext._mapped_hnsw_sql_drop()
RETURNS event_trigger
AS 'MODULE_PATHNAME', 'pgcontext_hnsw_mapped_sql_drop'
LANGUAGE C;

CREATE EVENT TRIGGER pgcontext_mapped_hnsw_sql_drop
    ON sql_drop
    EXECUTE FUNCTION pgcontext._mapped_hnsw_sql_drop();
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first_catalog_schema.rs:3
-- requires:
--   create_catalog_tables


CREATE TABLE pgcontext._exact_first_registrations (
    exact_first_registration_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    registration_revision bigint NOT NULL DEFAULT 1 CHECK (registration_revision > 0),
    registration_system_identifier bigint NOT NULL,
    registration_database_oid oid NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    source_key_column_name text NOT NULL,
    source_key_attnum int2 NOT NULL CHECK (source_key_attnum > 0),
    source_key_type_oid oid NOT NULL,
    source_key_typmod int4 NOT NULL,
    source_key_collation_oid bigint NOT NULL CHECK (source_key_collation_oid BETWEEN 0 AND 4294967295),
    source_key_index_oid oid NOT NULL,
    specification_version text NOT NULL CHECK (specification_version = 'exact_first_registration_v1'),
    specification_sha256 bytea NOT NULL CHECK (pg_catalog.octet_length(specification_sha256) = 32),
    readiness_state text NOT NULL DEFAULT 'exact_only'
        CHECK (readiness_state IN ('exact_only','building','indexed','stale','degraded')),
    readiness_reason text NOT NULL DEFAULT 'current_exact_path'
        CHECK (readiness_reason IN (
            'current_exact_path','build_active','optimization_ready',
            'source_relation_changed','source_key_changed','source_column_changed',
            'configuration_changed','exact_path_unavailable','build_failed',
            'build_cancelled','optimization_corrupt','resource_limit','recall_rejected'
        )),
    current_plan_revision bigint CHECK (current_plan_revision IS NULL OR current_plan_revision > 0),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id)
);

CREATE TABLE pgcontext._exact_first_columns (
    exact_first_registration_id bigint NOT NULL
        REFERENCES pgcontext._exact_first_registrations(exact_first_registration_id)
        ON DELETE CASCADE,
    binding_ordinal int2 NOT NULL CHECK (binding_ordinal BETWEEN 0 AND 255),
    binding_name text NOT NULL,
    binding_kind text NOT NULL CHECK (binding_kind IN (
        'dense','half','sparse','int8','uint8','bit','vector_array',
        'lexical','tsvector','fuzzy','filter','payload'
    )),
    column_name text NOT NULL,
    column_attnum int2 NOT NULL CHECK (column_attnum > 0),
    column_type_oid oid NOT NULL,
    column_typmod int4 NOT NULL,
    column_collation_oid bigint NOT NULL CHECK (column_collation_oid BETWEEN 0 AND 4294967295),
    dimensions int4 CHECK (dimensions IS NULL OR dimensions > 0),
    metric text CHECK (metric IS NULL OR metric IN (
        'l2','inner_product','cosine','l1','hamming','jaccard'
    )),
    text_configuration_oid oid,
    normalization text,
    configuration_revision bigint NOT NULL DEFAULT 1 CHECK (configuration_revision > 0),
    PRIMARY KEY (exact_first_registration_id, binding_ordinal),
    UNIQUE (exact_first_registration_id, binding_name)
);

CREATE TABLE pgcontext._exact_first_plans (
    exact_first_plan_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    exact_first_registration_id bigint NOT NULL
        REFERENCES pgcontext._exact_first_registrations(exact_first_registration_id)
        ON DELETE CASCADE,
    plan_revision bigint NOT NULL CHECK (plan_revision > 0),
    registration_revision bigint NOT NULL CHECK (registration_revision > 0),
    plan_sha256 bytea NOT NULL CHECK (pg_catalog.octet_length(plan_sha256) = 32),
    apply_policy text NOT NULL CHECK (apply_policy IN (
        'recommend_only','exact_only','enqueue','apply_foreground'
    )),
    recommendation text NOT NULL,
    evidence jsonb NOT NULL CHECK (pg_catalog.jsonb_typeof(evidence) = 'object'),
    generated_ddl text,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (exact_first_registration_id, plan_revision),
    UNIQUE (exact_first_registration_id, plan_sha256)
);

CREATE TABLE pgcontext._exact_first_plan_jobs (
    exact_first_plan_id bigint PRIMARY KEY
        REFERENCES pgcontext._exact_first_plans(exact_first_plan_id) ON DELETE CASCADE,
    build_job_id bigint NOT NULL UNIQUE
        REFERENCES pgcontext._build_jobs(build_job_id) ON DELETE CASCADE,
    status text NOT NULL DEFAULT 'queued' CHECK (status IN (
        'queued','building','validating','cancel_requested','cancelled','failed'
    )),
    attempt int4 NOT NULL DEFAULT 0 CHECK (attempt BETWEEN 0 AND 3),
    lease_token bigint,
    lease_expires_at timestamptz,
    worker_id text CHECK (worker_id IS NULL OR pg_catalog.octet_length(worker_id) BETWEEN 1 AND 128),
    error_code text CHECK (error_code IS NULL OR pg_catalog.octet_length(error_code) BETWEEN 1 AND 64),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);

CREATE TABLE pgcontext._exact_first_targets (
    exact_first_target_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    exact_first_registration_id bigint NOT NULL
        REFERENCES pgcontext._exact_first_registrations(exact_first_registration_id)
        ON DELETE CASCADE,
    exact_first_plan_id bigint NOT NULL
        REFERENCES pgcontext._exact_first_plans(exact_first_plan_id) ON DELETE CASCADE,
    index_oid oid,
    index_fingerprint_sha256 bytea NOT NULL
        CHECK (pg_catalog.octet_length(index_fingerprint_sha256) = 32),
    lifecycle_state text NOT NULL CHECK (lifecycle_state IN (
        'shadow','current','retiring','retired','failed'
    )),
    structurally_validated boolean NOT NULL DEFAULT false,
    recall_bps int4 CHECK (recall_bps BETWEEN 0 AND 10000),
    published_at timestamptz,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);

CREATE UNIQUE INDEX exact_first_targets_one_current
    ON pgcontext._exact_first_targets (exact_first_registration_id)
    WHERE lifecycle_state = 'current';

CREATE TABLE pgcontext._exact_first_invalid_samples (
    exact_first_registration_id bigint NOT NULL
        REFERENCES pgcontext._exact_first_registrations(exact_first_registration_id)
        ON DELETE CASCADE,
    sample_ordinal int2 NOT NULL CHECK (sample_ordinal BETWEEN 0 AND 63),
    binding_ordinal int2,
    reason_code text NOT NULL CHECK (pg_catalog.octet_length(reason_code) BETWEEN 1 AND 64),
    source_key_sha256 bytea CHECK (pg_catalog.octet_length(source_key_sha256) = 32),
    observed_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (exact_first_registration_id, sample_ordinal)
);

CREATE VIEW pgcontext._visible_exact_first_registrations
WITH (security_barrier = true) AS
SELECT registrations.*
  FROM pgcontext._exact_first_registrations AS registrations
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_exact_first_columns
WITH (security_barrier = true) AS
SELECT columns.*
  FROM pgcontext._exact_first_columns AS columns
  JOIN pgcontext._exact_first_registrations AS registrations
    USING (exact_first_registration_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_exact_first_plans
WITH (security_barrier = true) AS
SELECT plans.*,
       CASE WHEN EXISTS (
                SELECT 1
                  FROM pgcontext._exact_first_targets AS targets
                  JOIN pg_catalog.pg_index AS target_index
                    ON target_index.indexrelid = targets.index_oid
                 WHERE targets.exact_first_plan_id = plans.exact_first_plan_id
                   AND targets.lifecycle_state = 'current'
                   AND targets.structurally_validated
                   AND target_index.indisvalid
                   AND target_index.indisready
                   AND target_index.indislive
            ) THEN 'published'
            ELSE COALESCE(plan_jobs.status, 'frozen') END AS status,
       plan_jobs.build_job_id, COALESCE(plan_jobs.attempt, 0) AS attempt,
       plan_jobs.lease_token, plan_jobs.lease_expires_at,
       plan_jobs.worker_id, plan_jobs.error_code, plan_jobs.updated_at
  FROM pgcontext._exact_first_plans AS plans
  LEFT JOIN pgcontext._exact_first_plan_jobs AS plan_jobs USING (exact_first_plan_id)
  JOIN pgcontext._exact_first_registrations AS registrations
    USING (exact_first_registration_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_exact_first_targets
WITH (security_barrier = true) AS
SELECT targets.*
  FROM pgcontext._exact_first_targets AS targets
  JOIN pgcontext._exact_first_registrations AS registrations
    USING (exact_first_registration_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_exact_first_invalid_samples
WITH (security_barrier = true) AS
SELECT samples.exact_first_registration_id,
       samples.sample_ordinal,
       samples.binding_ordinal,
       samples.reason_code,
       samples.observed_at
  FROM pgcontext._exact_first_invalid_samples AS samples
  JOIN pgcontext._exact_first_registrations AS registrations
    USING (exact_first_registration_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

REVOKE ALL ON pgcontext._exact_first_registrations FROM PUBLIC;
REVOKE ALL ON pgcontext._exact_first_columns FROM PUBLIC;
REVOKE ALL ON pgcontext._exact_first_plans FROM PUBLIC;
REVOKE ALL ON pgcontext._exact_first_plan_jobs FROM PUBLIC;
REVOKE ALL ON pgcontext._exact_first_targets FROM PUBLIC;
REVOKE ALL ON pgcontext._exact_first_invalid_samples FROM PUBLIC;
GRANT SELECT ON pgcontext._visible_exact_first_registrations TO PUBLIC;
GRANT SELECT ON pgcontext._visible_exact_first_columns TO PUBLIC;
GRANT SELECT ON pgcontext._visible_exact_first_plans TO PUBLIC;
GRANT SELECT ON pgcontext._visible_exact_first_targets TO PUBLIC;
GRANT SELECT ON pgcontext._visible_exact_first_invalid_samples TO PUBLIC;

SELECT pg_catalog.pg_extension_config_dump('pgcontext._exact_first_registrations', '');
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._exact_first_registrations_exact_first_registration_id_seq', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._exact_first_columns', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._exact_first_plans', '');
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._exact_first_plans_exact_first_plan_id_seq', '');
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_catalog_schema.rs:8
-- requires:
--   create_catalog_tables


CREATE TABLE pgcontext._collection_lexical_sources (
    lexical_source_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_name text NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    document_mode text NOT NULL
        CHECK (document_mode IN ('fields', 'stored_vector')),
    stored_vector_column_name text,
    stored_vector_attnum int2,
    configuration_oid oid NOT NULL,
    configuration_schema_name text NOT NULL,
    configuration_name text NOT NULL,
    ranker text NOT NULL CHECK (ranker IN ('ts_rank', 'ts_rank_cd')),
    normalization int4 NOT NULL DEFAULT 0
        CHECK (normalization BETWEEN 0 AND 63),
    rank_weight_d real NOT NULL DEFAULT 0.1
        CHECK (rank_weight_d BETWEEN 0.0 AND 1.0),
    rank_weight_c real NOT NULL DEFAULT 0.2
        CHECK (rank_weight_c BETWEEN 0.0 AND 1.0),
    rank_weight_b real NOT NULL DEFAULT 0.4
        CHECK (rank_weight_b BETWEEN 0.0 AND 1.0),
    rank_weight_a real NOT NULL DEFAULT 1.0
        CHECK (rank_weight_a BETWEEN 0.0 AND 1.0),
    row_tsquery_name text,
    row_tsquery_column_name text,
    row_tsquery_attnum int2,
    index_oid oid,
    index_name text,
    index_am_name text CHECK (index_am_name IN ('gin', 'gist')),
    index_definition text,
    index_is_lossy boolean NOT NULL DEFAULT false,
    registration_revision bigint NOT NULL DEFAULT 1
        CHECK (registration_revision > 0),
    status text NOT NULL DEFAULT 'ready'
        CHECK (status IN ('ready', 'stale', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, source_name),
    CHECK ((document_mode = 'stored_vector') = (stored_vector_column_name IS NOT NULL)),
    CHECK ((stored_vector_column_name IS NULL) = (stored_vector_attnum IS NULL)),
    CHECK ((row_tsquery_name IS NULL) = (row_tsquery_column_name IS NULL)),
    CHECK ((row_tsquery_column_name IS NULL) = (row_tsquery_attnum IS NULL)),
    CHECK ((index_oid IS NULL) = (index_name IS NULL)),
    CHECK ((index_oid IS NULL) = (index_am_name IS NULL)),
    CHECK ((index_oid IS NULL) = (index_definition IS NULL))
);

CREATE TABLE pgcontext._collection_lexical_fields (
    lexical_source_id bigint NOT NULL
        REFERENCES pgcontext._collection_lexical_sources(lexical_source_id)
        ON DELETE CASCADE,
    field_ordinal int4 NOT NULL CHECK (field_ordinal > 0),
    column_name text NOT NULL,
    column_attnum int2 NOT NULL,
    column_type_oid oid NOT NULL,
    column_collation_oid oid NOT NULL DEFAULT 0,
    json_path text[],
    weight text NOT NULL DEFAULT 'D' CHECK (weight IN ('A', 'B', 'C', 'D')),
    PRIMARY KEY (lexical_source_id, field_ordinal),
    CHECK (json_path IS NULL OR pg_catalog.cardinality(json_path) BETWEEN 1 AND 16)
);

CREATE TABLE pgcontext._collection_fuzzy_sources (
    fuzzy_source_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_name text NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    text_column_name text NOT NULL,
    text_attnum int2 NOT NULL,
    text_type_oid oid NOT NULL,
    text_collation_oid oid NOT NULL DEFAULT 0,
    trgm_extension_oid oid NOT NULL,
    trgm_schema_name text NOT NULL,
    index_oid oid,
    index_name text,
    index_am_name text CHECK (index_am_name IN ('gin', 'gist')),
    index_definition text,
    registration_revision bigint NOT NULL DEFAULT 1
        CHECK (registration_revision > 0),
    status text NOT NULL DEFAULT 'ready'
        CHECK (status IN ('ready', 'stale', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, source_name),
    CHECK ((index_oid IS NULL) = (index_name IS NULL)),
    CHECK ((index_oid IS NULL) = (index_am_name IS NULL)),
    CHECK ((index_oid IS NULL) = (index_definition IS NULL))
);

REVOKE ALL ON TABLE pgcontext._collection_lexical_sources FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._collection_lexical_fields FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._collection_fuzzy_sources FROM PUBLIC;

CREATE VIEW pgcontext._visible_collection_lexical_sources
WITH (security_barrier = true) AS
SELECT sources.*
  FROM pgcontext._collection_lexical_sources AS sources
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_lexical_fields
WITH (security_barrier = true) AS
SELECT fields.*
  FROM pgcontext._collection_lexical_fields AS fields
  JOIN pgcontext._collection_lexical_sources AS sources USING (lexical_source_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_collection_fuzzy_sources
WITH (security_barrier = true) AS
SELECT sources.*
  FROM pgcontext._collection_fuzzy_sources AS sources
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

GRANT SELECT ON pgcontext._visible_collection_lexical_sources TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_lexical_fields TO PUBLIC;
GRANT SELECT ON pgcontext._visible_collection_fuzzy_sources TO PUBLIC;

-- Catalog writes. The SQL-facing lexical functions run SECURITY INVOKER so the
-- caller's source-table SELECT, RLS, and index-creation privileges apply. These
-- helpers perform the private-catalog write as the extension owner.
--
-- Security: no helper accepts a caller-supplied oid or attnum. Every oid is
-- re-derived from pg_catalog using the names the caller already proved access
-- to, each helper re-checks owner-role membership on SESSION_USER, and each
-- pins search_path.
CREATE FUNCTION pgcontext._require_collection_owner(p_collection_id bigint)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections
         WHERE collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'permission denied for collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;
END;
$$;

CREATE FUNCTION pgcontext._register_lexical_source(
    p_collection_id bigint,
    p_source_name text,
    p_document_mode text,
    p_stored_vector_column text,
    p_configuration_schema text,
    p_configuration_name text,
    p_ranker text,
    p_normalization int4,
    p_rank_weights real[],
    p_columns text[],
    p_weights text[],
    p_json_paths text[]
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_schema text;
    source_table text;
    source_oid oid;
    configuration_oid oid;
    stored_attnum int2;
    new_source_id bigint;
    ordinal int4;
    column_name text;
    path_text text;
    path_components text[];
    attribute_row record;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);

    SELECT collections.source_schema_name, collections.source_table_name, source_class.oid
      INTO source_schema, source_table, source_oid
      FROM pgcontext._collections AS collections
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.nspname = collections.source_schema_name
      JOIN pg_catalog.pg_class AS source_class
        ON source_class.relnamespace = source_namespace.oid
       AND source_class.relname = collections.source_table_name
       AND source_class.relkind IN ('r', 'p')
     WHERE collections.collection_id = p_collection_id;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'collection % has no resolvable source table', p_collection_id
            USING ERRCODE = '42P01';
    END IF;
    IF NOT pg_catalog.has_table_privilege(SESSION_USER, source_oid, 'SELECT') THEN
        RAISE EXCEPTION 'permission denied for source table %.%', source_schema, source_table
            USING ERRCODE = '42501';
    END IF;

    SELECT configuration.oid
      INTO configuration_oid
      FROM pg_catalog.pg_ts_config AS configuration
      JOIN pg_catalog.pg_namespace AS namespace
        ON namespace.oid = configuration.cfgnamespace
     WHERE namespace.nspname = p_configuration_schema
       AND configuration.cfgname = p_configuration_name;
    IF configuration_oid IS NULL THEN
        RAISE EXCEPTION 'text search configuration does not exist: %.%',
            p_configuration_schema, p_configuration_name
            USING ERRCODE = '42704';
    END IF;

    IF p_document_mode = 'stored_vector' THEN
        SELECT attribute.attnum
          INTO stored_attnum
          FROM pg_catalog.pg_attribute AS attribute
         WHERE attribute.attrelid = source_oid
           AND attribute.attname = p_stored_vector_column
           AND attribute.attnum > 0
           AND NOT attribute.attisdropped
           AND pg_catalog.format_type(attribute.atttypid, NULL) = 'tsvector';
        IF stored_attnum IS NULL THEN
            RAISE EXCEPTION 'stored lexical document column is missing or is not tsvector: %',
                p_stored_vector_column
                USING ERRCODE = '42703';
        END IF;
    END IF;

    INSERT INTO pgcontext._collection_lexical_sources (
        collection_id, source_name, source_table_oid, source_schema_name,
        source_table_name, document_mode, stored_vector_column_name,
        stored_vector_attnum, configuration_oid, configuration_schema_name,
        configuration_name, ranker, normalization,
        rank_weight_d, rank_weight_c, rank_weight_b, rank_weight_a
    )
    VALUES (
        p_collection_id, p_source_name, source_oid, source_schema,
        source_table, p_document_mode,
        CASE WHEN p_document_mode = 'stored_vector' THEN p_stored_vector_column END,
        stored_attnum, configuration_oid, p_configuration_schema,
        p_configuration_name, p_ranker, p_normalization,
        p_rank_weights[1], p_rank_weights[2], p_rank_weights[3], p_rank_weights[4]
    )
    RETURNING lexical_source_id INTO new_source_id;

    IF p_document_mode = 'fields' THEN
        FOR ordinal IN 1 .. pg_catalog.cardinality(p_columns) LOOP
            column_name := p_columns[ordinal];
            SELECT attribute.attnum, attribute.atttypid, attribute.attcollation
              INTO attribute_row
              FROM pg_catalog.pg_attribute AS attribute
             WHERE attribute.attrelid = source_oid
               AND attribute.attname = column_name
               AND attribute.attnum > 0
               AND NOT attribute.attisdropped;
            IF NOT FOUND THEN
                RAISE EXCEPTION 'lexical field column is missing: %', column_name
                    USING ERRCODE = '42703';
            END IF;
            path_text := p_json_paths[ordinal];
            IF path_text IS NULL OR path_text = '' THEN
                path_components := NULL;
            ELSE
                path_components := pg_catalog.string_to_array(path_text, '.');
                IF pg_catalog.format_type(attribute_row.atttypid, NULL)
                       NOT IN ('json', 'jsonb') THEN
                    RAISE EXCEPTION 'lexical JSON path requires a json or jsonb column: %',
                        column_name
                        USING ERRCODE = '42804';
                END IF;
            END IF;
            INSERT INTO pgcontext._collection_lexical_fields (
                lexical_source_id, field_ordinal, column_name, column_attnum,
                column_type_oid, column_collation_oid, json_path, weight
            )
            VALUES (
                new_source_id, ordinal, column_name, attribute_row.attnum,
                attribute_row.atttypid, attribute_row.attcollation,
                path_components, pg_catalog.upper(p_weights[ordinal])
            );
        END LOOP;
    END IF;

    RETURN new_source_id;
END;
$$;

CREATE FUNCTION pgcontext._register_lexical_tsquery(
    p_collection_id bigint,
    p_source_name text,
    p_tsquery_name text,
    p_column_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_oid oid;
    column_attnum int2;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT source_table_oid INTO source_oid
      FROM pgcontext._collection_lexical_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'lexical source is not registered: %', p_source_name
            USING ERRCODE = '42704';
    END IF;
    SELECT attribute.attnum INTO column_attnum
      FROM pg_catalog.pg_attribute AS attribute
     WHERE attribute.attrelid = source_oid
       AND attribute.attname = p_column_name
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped
       AND pg_catalog.format_type(attribute.atttypid, NULL) = 'tsquery';
    IF column_attnum IS NULL THEN
        RAISE EXCEPTION 'registered row tsquery column is missing or is not tsquery: %',
            p_column_name
            USING ERRCODE = '42703';
    END IF;
    UPDATE pgcontext._collection_lexical_sources
       SET row_tsquery_name = p_tsquery_name,
           row_tsquery_column_name = p_column_name,
           row_tsquery_attnum = column_attnum,
           registration_revision = registration_revision + 1,
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
END;
$$;

CREATE FUNCTION pgcontext._attach_lexical_index(
    p_collection_id bigint,
    p_source_name text,
    p_index_schema text,
    p_index_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_oid oid;
    index_row record;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT source_table_oid INTO source_oid
      FROM pgcontext._collection_lexical_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'lexical source is not registered: %', p_source_name
            USING ERRCODE = '42704';
    END IF;

    SELECT index_class.oid AS index_oid,
           access_method.amname AS amname,
           index.indisvalid AS indisvalid,
           index.indislive AS indislive,
           index.indpred IS NULL AS is_full,
           index.indrelid AS indrelid,
           pg_catalog.pg_get_indexdef(index.indexrelid) AS definition
      INTO index_row
      FROM pg_catalog.pg_class AS index_class
      JOIN pg_catalog.pg_namespace AS index_namespace
        ON index_namespace.oid = index_class.relnamespace
      JOIN pg_catalog.pg_index AS index
        ON index.indexrelid = index_class.oid
      JOIN pg_catalog.pg_am AS access_method
        ON access_method.oid = index_class.relam
     WHERE index_namespace.nspname = p_index_schema
       AND index_class.relname = p_index_name;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'index does not exist: %.%', p_index_schema, p_index_name
            USING ERRCODE = '42704';
    END IF;
    IF index_row.indrelid <> source_oid THEN
        RAISE EXCEPTION 'index %.% is not defined on the registered source relation',
            p_index_schema, p_index_name
            USING ERRCODE = '42809';
    END IF;
    IF index_row.amname NOT IN ('gin', 'gist') THEN
        RAISE EXCEPTION 'lexical index access method must be gin or gist, found %',
            index_row.amname
            USING ERRCODE = '0A000';
    END IF;
    IF NOT index_row.is_full THEN
        RAISE EXCEPTION 'lexical index must not be partial: %.%', p_index_schema, p_index_name
            USING ERRCODE = '0A000';
    END IF;
    IF NOT index_row.indisvalid OR NOT index_row.indislive THEN
        RAISE EXCEPTION 'lexical index is not valid and live: %.%', p_index_schema, p_index_name
            USING ERRCODE = '55000';
    END IF;

    UPDATE pgcontext._collection_lexical_sources
       SET index_oid = index_row.index_oid,
           index_name = p_index_name,
           index_am_name = index_row.amname,
           index_definition = index_row.definition,
           index_is_lossy = (index_row.amname = 'gist'),
           registration_revision = registration_revision + 1,
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
END;
$$;

CREATE FUNCTION pgcontext._detach_lexical_index(
    p_collection_id bigint,
    p_source_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    UPDATE pgcontext._collection_lexical_sources
       SET index_oid = NULL,
           index_name = NULL,
           index_am_name = NULL,
           index_definition = NULL,
           index_is_lossy = false,
           registration_revision = registration_revision + 1,
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
END;
$$;

CREATE FUNCTION pgcontext._drop_lexical_source(
    p_collection_id bigint,
    p_source_name text
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    removed bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    DELETE FROM pgcontext._collection_lexical_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
    GET DIAGNOSTICS removed = ROW_COUNT;
    RETURN removed > 0;
END;
$$;

CREATE FUNCTION pgcontext._register_fuzzy_source(
    p_collection_id bigint,
    p_source_name text,
    p_column_name text
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_schema text;
    source_table text;
    source_oid oid;
    attribute_row record;
    extension_row record;
    new_source_id bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);

    SELECT collections.source_schema_name, collections.source_table_name, source_class.oid
      INTO source_schema, source_table, source_oid
      FROM pgcontext._collections AS collections
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.nspname = collections.source_schema_name
      JOIN pg_catalog.pg_class AS source_class
        ON source_class.relnamespace = source_namespace.oid
       AND source_class.relname = collections.source_table_name
       AND source_class.relkind IN ('r', 'p')
     WHERE collections.collection_id = p_collection_id;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'collection % has no resolvable source table', p_collection_id
            USING ERRCODE = '42P01';
    END IF;
    IF NOT pg_catalog.has_table_privilege(SESSION_USER, source_oid, 'SELECT') THEN
        RAISE EXCEPTION 'permission denied for source table %.%', source_schema, source_table
            USING ERRCODE = '42501';
    END IF;

    SELECT extension.oid AS extension_oid, namespace.nspname AS schema_name
      INTO extension_row
      FROM pg_catalog.pg_extension AS extension
      JOIN pg_catalog.pg_namespace AS namespace
        ON namespace.oid = extension.extnamespace
     WHERE extension.extname = 'pg_trgm';
    IF NOT FOUND THEN
        RAISE EXCEPTION 'fuzzy sources require the pg_trgm extension'
            USING ERRCODE = '42704';
    END IF;

    SELECT attribute.attnum, attribute.atttypid, attribute.attcollation
      INTO attribute_row
      FROM pg_catalog.pg_attribute AS attribute
     WHERE attribute.attrelid = source_oid
       AND attribute.attname = p_column_name
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'fuzzy source text column is missing: %', p_column_name
            USING ERRCODE = '42703';
    END IF;
    IF attribute_row.atttypid <> 'pg_catalog.text'::pg_catalog.regtype THEN
        RAISE EXCEPTION 'fuzzy source column must be text: %', p_column_name
            USING ERRCODE = '42804';
    END IF;

    INSERT INTO pgcontext._collection_fuzzy_sources (
        collection_id, source_name, source_table_oid, source_schema_name,
        source_table_name, text_column_name, text_attnum, text_type_oid,
        text_collation_oid,
        trgm_extension_oid, trgm_schema_name
    )
    VALUES (
        p_collection_id, p_source_name, source_oid, source_schema, source_table,
        p_column_name, attribute_row.attnum, attribute_row.atttypid,
        attribute_row.attcollation,
        extension_row.extension_oid, extension_row.schema_name
    )
    RETURNING fuzzy_source_id INTO new_source_id;
    RETURN new_source_id;
END;
$$;

CREATE FUNCTION pgcontext._attach_fuzzy_index(
    p_collection_id bigint,
    p_source_name text,
    p_index_schema text,
    p_index_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_oid oid;
    index_row record;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT source_table_oid INTO source_oid
      FROM pgcontext._collection_fuzzy_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'fuzzy source is not registered: %', p_source_name
            USING ERRCODE = '42704';
    END IF;

    SELECT index_class.oid AS index_oid,
           access_method.amname AS amname,
           index.indisvalid AS indisvalid,
           index.indislive AS indislive,
           index.indpred IS NULL AS is_full,
           index.indrelid AS indrelid,
           pg_catalog.pg_get_indexdef(index.indexrelid) AS definition
      INTO index_row
      FROM pg_catalog.pg_class AS index_class
      JOIN pg_catalog.pg_namespace AS index_namespace
        ON index_namespace.oid = index_class.relnamespace
      JOIN pg_catalog.pg_index AS index
        ON index.indexrelid = index_class.oid
      JOIN pg_catalog.pg_am AS access_method
        ON access_method.oid = index_class.relam
     WHERE index_namespace.nspname = p_index_schema
       AND index_class.relname = p_index_name;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'index does not exist: %.%', p_index_schema, p_index_name
            USING ERRCODE = '42704';
    END IF;
    IF index_row.indrelid <> source_oid THEN
        RAISE EXCEPTION 'index %.% is not defined on the registered source relation',
            p_index_schema, p_index_name
            USING ERRCODE = '42809';
    END IF;
    IF index_row.amname NOT IN ('gin', 'gist') THEN
        RAISE EXCEPTION 'fuzzy index access method must be gin or gist, found %',
            index_row.amname
            USING ERRCODE = '0A000';
    END IF;
    IF NOT index_row.is_full THEN
        RAISE EXCEPTION 'fuzzy index must not be partial: %.%', p_index_schema, p_index_name
            USING ERRCODE = '0A000';
    END IF;
    IF NOT index_row.indisvalid OR NOT index_row.indislive THEN
        RAISE EXCEPTION 'fuzzy index is not valid and live: %.%', p_index_schema, p_index_name
            USING ERRCODE = '55000';
    END IF;

    UPDATE pgcontext._collection_fuzzy_sources
       SET index_oid = index_row.index_oid,
           index_name = p_index_name,
           index_am_name = index_row.amname,
           index_definition = index_row.definition,
           registration_revision = registration_revision + 1,
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
END;
$$;

CREATE FUNCTION pgcontext._detach_fuzzy_index(
    p_collection_id bigint,
    p_source_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    UPDATE pgcontext._collection_fuzzy_sources
       SET index_oid = NULL,
           index_name = NULL,
           index_am_name = NULL,
           index_definition = NULL,
           registration_revision = registration_revision + 1,
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
END;
$$;

CREATE FUNCTION pgcontext._drop_fuzzy_source(
    p_collection_id bigint,
    p_source_name text
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    removed bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    DELETE FROM pgcontext._collection_fuzzy_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name;
    GET DIAGNOSTICS removed = ROW_COUNT;
    RETURN removed > 0;
END;
$$;

-- Dump/restore OID refresh. Every identity is re-derived from the stable names
-- already stored in the private catalog. A row whose stable names no longer
-- resolve to a compatible object is marked stale rather than silently rebound,
-- and a row an operator has marked failed is never reactivated by a refresh.
CREATE FUNCTION pgcontext._refresh_lexical_catalog_oids(p_collection_id bigint)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    refreshed bigint := 0;
    touched bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);

    UPDATE pgcontext._collection_lexical_sources AS sources
       SET source_table_oid = source_class.oid,
           configuration_oid = configuration.oid,
           status = 'ready',
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class,
           pg_catalog.pg_namespace AS source_namespace,
           pg_catalog.pg_ts_config AS configuration,
           pg_catalog.pg_namespace AS configuration_namespace
     WHERE sources.collection_id = p_collection_id
       AND sources.status <> 'failed'
       AND source_namespace.oid = source_class.relnamespace
       AND source_namespace.nspname = sources.source_schema_name
       AND source_class.relname = sources.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND configuration_namespace.oid = configuration.cfgnamespace
       AND configuration_namespace.nspname = sources.configuration_schema_name
       AND configuration.cfgname = sources.configuration_name;
    GET DIAGNOSTICS touched = ROW_COUNT;
    refreshed := refreshed + touched;

    UPDATE pgcontext._collection_lexical_sources AS sources
       SET stored_vector_attnum = attribute.attnum
      FROM pg_catalog.pg_attribute AS attribute
     WHERE sources.collection_id = p_collection_id
       AND sources.stored_vector_column_name IS NOT NULL
       AND attribute.attrelid = sources.source_table_oid
       AND attribute.attname = sources.stored_vector_column_name
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped;

    UPDATE pgcontext._collection_lexical_fields AS fields
       SET column_attnum = attribute.attnum,
           column_type_oid = attribute.atttypid,
           column_collation_oid = attribute.attcollation
      FROM pgcontext._collection_lexical_sources AS sources,
           pg_catalog.pg_attribute AS attribute
     WHERE fields.lexical_source_id = sources.lexical_source_id
       AND sources.collection_id = p_collection_id
       AND attribute.attrelid = sources.source_table_oid
       AND attribute.attname = fields.column_name
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped;

    UPDATE pgcontext._collection_lexical_sources AS sources
       SET index_oid = index_class.oid,
           index_definition = pg_catalog.pg_get_indexdef(index_class.oid),
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS index_class
      JOIN pg_catalog.pg_namespace AS index_namespace
        ON index_namespace.oid = index_class.relnamespace
     WHERE sources.collection_id = p_collection_id
       AND sources.index_name IS NOT NULL
       AND index_class.relname = sources.index_name
       AND index_namespace.nspname = sources.source_schema_name
       AND index_class.relkind = 'i';

    UPDATE pgcontext._collection_fuzzy_sources AS sources
       SET source_table_oid = source_class.oid,
           text_attnum = attribute.attnum,
           text_type_oid = attribute.atttypid,
           text_collation_oid = attribute.attcollation,
           trgm_extension_oid = extension.oid,
           trgm_schema_name = extension_namespace.nspname,
           status = 'ready',
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS source_class,
           pg_catalog.pg_namespace AS source_namespace,
           pg_catalog.pg_attribute AS attribute,
           pg_catalog.pg_extension AS extension,
           pg_catalog.pg_namespace AS extension_namespace
     WHERE source_namespace.oid = source_class.relnamespace
       AND attribute.attrelid = source_class.oid
       AND extension.extname = 'pg_trgm'
       AND extension_namespace.oid = extension.extnamespace
       AND sources.collection_id = p_collection_id
       AND source_namespace.nspname = sources.source_schema_name
       AND source_class.relname = sources.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND attribute.attname = sources.text_column_name
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped
       AND attribute.atttypid = 'pg_catalog.text'::pg_catalog.regtype
       AND sources.status <> 'failed';
    GET DIAGNOSTICS touched = ROW_COUNT;
    refreshed := refreshed + touched;

    UPDATE pgcontext._collection_fuzzy_sources AS sources
       SET index_oid = index_class.oid,
           index_definition = pg_catalog.pg_get_indexdef(index_class.oid),
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_class AS index_class
      JOIN pg_catalog.pg_namespace AS index_namespace
        ON index_namespace.oid = index_class.relnamespace
     WHERE sources.collection_id = p_collection_id
       AND sources.index_name IS NOT NULL
       AND index_class.relname = sources.index_name
       AND index_namespace.nspname = sources.source_schema_name
       AND index_class.relkind = 'i';

    -- Anything that did not re-resolve is marked stale so query preparation
    -- fails closed instead of trusting an OID the restore invalidated.
    UPDATE pgcontext._collection_lexical_sources AS sources
       SET status = 'stale',
           updated_at = pg_catalog.now()
     WHERE sources.collection_id = p_collection_id
       AND sources.status = 'ready'
       AND NOT EXISTS (
           SELECT 1
             FROM pg_catalog.pg_class AS source_class
             JOIN pg_catalog.pg_namespace AS source_namespace
               ON source_namespace.oid = source_class.relnamespace
            WHERE source_class.oid = sources.source_table_oid
              AND source_namespace.nspname = sources.source_schema_name
              AND source_class.relname = sources.source_table_name
              AND source_class.relkind IN ('r', 'p')
       );

    UPDATE pgcontext._collection_fuzzy_sources AS sources
       SET status = 'stale',
           updated_at = pg_catalog.now()
     WHERE sources.collection_id = p_collection_id
       AND sources.status = 'ready'
       AND NOT EXISTS (
           SELECT 1
             FROM pg_catalog.pg_class AS source_class
             JOIN pg_catalog.pg_namespace AS source_namespace
               ON source_namespace.oid = source_class.relnamespace
             JOIN pg_catalog.pg_attribute AS attribute
               ON attribute.attrelid = source_class.oid
              AND attribute.attname = sources.text_column_name
              AND attribute.attnum > 0
              AND NOT attribute.attisdropped
              AND attribute.atttypid = 'pg_catalog.text'::pg_catalog.regtype
            WHERE source_class.oid = sources.source_table_oid
              AND source_namespace.nspname = sources.source_schema_name
              AND source_class.relname = sources.source_table_name
              AND source_class.relkind IN ('r', 'p')
       );

    RETURN refreshed;
END;
$$;

SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_lexical_sources',
    ''
);
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_lexical_sources_lexical_source_id_seq',
    ''
);
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_lexical_fields',
    ''
);
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_fuzzy_sources',
    ''
);
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_fuzzy_sources_fuzzy_source_id_seq',
    ''
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/semantic_rerank_catalog_schema.rs:3
-- requires:
--   create_catalog_tables
--   create_lexical_catalog_tables


CREATE TABLE pgcontext._semantic_rerank_sources (
    rerank_source_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_name text NOT NULL CHECK (
        pg_catalog.octet_length(source_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(source_name) <> ''
        AND source_name !~ '[[:cntrl:]]'
    ),
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    source_key_attnum int2 NOT NULL CHECK (source_key_attnum > 0),
    source_key_type_oid oid NOT NULL,
    source_key_collation_oid oid NOT NULL DEFAULT 0,
    source_key_type_schema text NOT NULL,
    source_key_type_name text NOT NULL,
    text_column_name text NOT NULL,
    text_attnum int2 NOT NULL CHECK (text_attnum > 0),
    text_type_oid oid NOT NULL,
    text_collation_oid oid NOT NULL DEFAULT 0,
    text_collation_schema text NOT NULL,
    text_collation_name text NOT NULL,
    source_version_column_name text NOT NULL,
    source_version_attnum int2 NOT NULL CHECK (source_version_attnum > 0),
    source_version_type_oid oid NOT NULL,
    content_hash_rule text NOT NULL DEFAULT 'sha256_utf8_v1'
        CHECK (content_hash_rule = 'sha256_utf8_v1'),
    registration_revision bigint NOT NULL DEFAULT 1
        CHECK (registration_revision > 0),
    status text NOT NULL DEFAULT 'ready'
        CHECK (status IN ('ready', 'stale', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, source_name)
);

CREATE TABLE pgcontext._semantic_rerank_requests (
    request_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    rerank_source_id bigint NOT NULL
        REFERENCES pgcontext._semantic_rerank_sources(rerank_source_id) ON DELETE CASCADE,
    session_user_oid oid NOT NULL,
    source_registration_revision bigint NOT NULL CHECK (source_registration_revision > 0),
    filter_binding_sha256 bytea NOT NULL
        CHECK (pg_catalog.octet_length(filter_binding_sha256) = 32),
    model_name text NOT NULL CHECK (
        pg_catalog.octet_length(model_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(model_name) <> ''
        AND model_name !~ '[[:cntrl:]]'
    ),
    model_revision bigint NOT NULL CHECK (model_revision > 0),
    query_text text NOT NULL CHECK (
        pg_catalog.octet_length(query_text) BETWEEN 1 AND 65536
        AND query_text !~ E'\\x00'
    ),
    filter_json jsonb,
    failure_policy text NOT NULL
        CHECK (failure_policy IN ('require_reranker', 'allow_fused_fallback')),
    allow_partial boolean NOT NULL DEFAULT false,
    expires_at_micros bigint NOT NULL CHECK (expires_at_micros > 0),
    status text NOT NULL DEFAULT 'prepared'
        CHECK (status IN ('prepared', 'finalized')),
    response_sha256 bytea,
    final_status text CHECK (
        final_status IN ('reranked', 'degraded_reranker', 'partial_reranked')
    ),
    degraded_reason text CHECK (
        degraded_reason IS NULL OR (
            pg_catalog.octet_length(degraded_reason) BETWEEN 1 AND 64
            AND degraded_reason ~ '^[a-z0-9_]+$'
        )
    ),
    final_result jsonb,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    finalized_at timestamptz,
    CHECK ((status = 'prepared') = (final_result IS NULL)),
    CHECK ((status = 'prepared') = (response_sha256 IS NULL)),
    CHECK ((status = 'prepared') = (final_status IS NULL))
);

CREATE TABLE pgcontext._semantic_rerank_candidates (
    request_id bigint NOT NULL
        REFERENCES pgcontext._semantic_rerank_requests(request_id) ON DELETE CASCADE,
    occurrence_id bigint NOT NULL CHECK (occurrence_id > 0),
    point_id bigint NOT NULL CHECK (point_id > 0),
    source_version bigint NOT NULL CHECK (source_version > 0),
    content_digest bytea NOT NULL CHECK (pg_catalog.octet_length(content_digest) = 32),
    fused_rank int4 NOT NULL CHECK (fused_rank > 0),
    fused_score double precision NOT NULL CHECK (
        fused_score > '-Infinity'::double precision
        AND fused_score < 'Infinity'::double precision
    ),
    contributions jsonb NOT NULL CHECK (pg_catalog.jsonb_typeof(contributions) = 'array'),
    metadata jsonb NOT NULL CHECK (pg_catalog.jsonb_typeof(metadata) = 'array'),
    PRIMARY KEY (request_id, occurrence_id),
    UNIQUE (request_id, point_id)
);

REVOKE ALL ON TABLE pgcontext._semantic_rerank_sources FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._semantic_rerank_requests FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._semantic_rerank_candidates FROM PUBLIC;

CREATE VIEW pgcontext._visible_semantic_rerank_sources
WITH (security_barrier = true) AS
SELECT sources.*
  FROM pgcontext._semantic_rerank_sources AS sources
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

CREATE VIEW pgcontext._visible_semantic_rerank_requests
WITH (security_barrier = true) AS
SELECT requests.*
  FROM pgcontext._semantic_rerank_requests AS requests
 WHERE requests.session_user_oid = SESSION_USER::pg_catalog.regrole::oid;

CREATE VIEW pgcontext._visible_semantic_rerank_candidates
WITH (security_barrier = true) AS
SELECT candidates.*
  FROM pgcontext._semantic_rerank_candidates AS candidates
  JOIN pgcontext._semantic_rerank_requests AS requests USING (request_id)
 WHERE requests.session_user_oid = SESSION_USER::pg_catalog.regrole::oid;

GRANT SELECT ON pgcontext._visible_semantic_rerank_sources TO PUBLIC;
GRANT SELECT ON pgcontext._visible_semantic_rerank_requests TO PUBLIC;
GRANT SELECT ON pgcontext._visible_semantic_rerank_candidates TO PUBLIC;

CREATE FUNCTION pgcontext._register_semantic_rerank_source(
    p_collection_id bigint,
    p_source_name text,
    p_text_column text,
    p_source_version_column text
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_schema text;
    source_table text;
    source_oid oid;
    key_row record;
    text_row record;
    version_row record;
    registered_id bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT collections.source_schema_name,
           collections.source_table_name,
           source_class.oid
      INTO source_schema, source_table, source_oid
      FROM pgcontext._collections AS collections
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.nspname = collections.source_schema_name
      JOIN pg_catalog.pg_class AS source_class
        ON source_class.relnamespace = source_namespace.oid
       AND source_class.relname = collections.source_table_name
       AND source_class.relkind IN ('r', 'p')
     WHERE collections.collection_id = p_collection_id;
    IF source_oid IS NULL THEN
        RAISE EXCEPTION 'semantic rerank source table is unavailable'
            USING ERRCODE = '42P01';
    END IF;
    IF NOT pg_catalog.has_table_privilege(SESSION_USER, source_oid, 'SELECT') THEN
        RAISE EXCEPTION 'permission denied for semantic rerank source'
            USING ERRCODE = '42501';
    END IF;

    SELECT attribute.attnum,
           attribute.atttypid,
           attribute.attcollation,
           type_namespace.nspname AS type_schema,
           type.typname AS type_name
      INTO key_row
      FROM pg_catalog.pg_attribute AS attribute
      JOIN pg_catalog.pg_type AS type ON type.oid = attribute.atttypid
      JOIN pg_catalog.pg_namespace AS type_namespace ON type_namespace.oid = type.typnamespace
      JOIN pg_catalog.pg_index AS index
        ON index.indrelid = attribute.attrelid
       AND index.indisprimary
       AND index.indisvalid
       AND index.indisready
       AND index.indislive
       AND index.indnkeyatts = 1
       AND index.indnatts = 1
       AND index.indkey[0] = attribute.attnum
     WHERE attribute.attrelid = source_oid
       AND attribute.attname = 'id'
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped;
    IF key_row.attnum IS NULL THEN
        RAISE EXCEPTION 'semantic rerank source requires a single-column primary key named id'
            USING ERRCODE = '55000';
    END IF;

    SELECT attribute.attnum,
           attribute.atttypid,
           attribute.attcollation,
           collation_namespace.nspname AS collation_schema,
           text_collation.collname AS collation_name
      INTO text_row
      FROM pg_catalog.pg_attribute AS attribute
      JOIN pg_catalog.pg_collation AS text_collation
        ON text_collation.oid = attribute.attcollation
      JOIN pg_catalog.pg_namespace AS collation_namespace
        ON collation_namespace.oid = text_collation.collnamespace
     WHERE attribute.attrelid = source_oid
       AND attribute.attname = p_text_column
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped
       AND attribute.atttypid = 'pg_catalog.text'::pg_catalog.regtype;
    IF text_row.attnum IS NULL THEN
        RAISE EXCEPTION 'semantic rerank text column is missing or is not text'
            USING ERRCODE = '42703';
    END IF;

    SELECT attribute.attnum, attribute.atttypid
      INTO version_row
      FROM pg_catalog.pg_attribute AS attribute
     WHERE attribute.attrelid = source_oid
       AND attribute.attname = p_source_version_column
       AND attribute.attnum > 0
       AND NOT attribute.attisdropped
       AND attribute.atttypid = 'pg_catalog.int8'::pg_catalog.regtype;
    IF version_row.attnum IS NULL THEN
        RAISE EXCEPTION 'semantic rerank source version column is missing or is not bigint'
            USING ERRCODE = '42703';
    END IF;

    INSERT INTO pgcontext._semantic_rerank_sources (
        collection_id, source_name, source_table_oid,
        source_schema_name, source_table_name,
        source_key_attnum, source_key_type_oid, source_key_collation_oid,
        source_key_type_schema, source_key_type_name,
        text_column_name, text_attnum, text_type_oid, text_collation_oid,
        text_collation_schema, text_collation_name,
        source_version_column_name, source_version_attnum,
        source_version_type_oid, content_hash_rule, registration_revision, status
    ) VALUES (
        p_collection_id, p_source_name, source_oid,
        source_schema, source_table,
        key_row.attnum, key_row.atttypid, key_row.attcollation,
        key_row.type_schema, key_row.type_name,
        p_text_column, text_row.attnum, text_row.atttypid, text_row.attcollation,
        text_row.collation_schema, text_row.collation_name,
        p_source_version_column, version_row.attnum,
        version_row.atttypid, 'sha256_utf8_v1', 1, 'ready'
    )
    ON CONFLICT (collection_id, source_name) DO UPDATE
       SET source_table_oid = EXCLUDED.source_table_oid,
           source_schema_name = EXCLUDED.source_schema_name,
           source_table_name = EXCLUDED.source_table_name,
           source_key_attnum = EXCLUDED.source_key_attnum,
           source_key_type_oid = EXCLUDED.source_key_type_oid,
           source_key_collation_oid = EXCLUDED.source_key_collation_oid,
           source_key_type_schema = EXCLUDED.source_key_type_schema,
           source_key_type_name = EXCLUDED.source_key_type_name,
           text_column_name = EXCLUDED.text_column_name,
           text_attnum = EXCLUDED.text_attnum,
           text_type_oid = EXCLUDED.text_type_oid,
           text_collation_oid = EXCLUDED.text_collation_oid,
           text_collation_schema = EXCLUDED.text_collation_schema,
           text_collation_name = EXCLUDED.text_collation_name,
           source_version_column_name = EXCLUDED.source_version_column_name,
           source_version_attnum = EXCLUDED.source_version_attnum,
           source_version_type_oid = EXCLUDED.source_version_type_oid,
           content_hash_rule = EXCLUDED.content_hash_rule,
           registration_revision = pgcontext._semantic_rerank_sources.registration_revision +
               CASE WHEN
                   pgcontext._semantic_rerank_sources.source_table_oid IS DISTINCT FROM
                       EXCLUDED.source_table_oid
                   OR pgcontext._semantic_rerank_sources.source_key_attnum IS DISTINCT FROM
                       EXCLUDED.source_key_attnum
                   OR pgcontext._semantic_rerank_sources.source_key_type_oid IS DISTINCT FROM
                       EXCLUDED.source_key_type_oid
                   OR pgcontext._semantic_rerank_sources.source_key_collation_oid IS DISTINCT FROM
                       EXCLUDED.source_key_collation_oid
                   OR pgcontext._semantic_rerank_sources.text_column_name IS DISTINCT FROM
                       EXCLUDED.text_column_name
                   OR pgcontext._semantic_rerank_sources.text_attnum IS DISTINCT FROM
                       EXCLUDED.text_attnum
                   OR pgcontext._semantic_rerank_sources.text_type_oid IS DISTINCT FROM
                       EXCLUDED.text_type_oid
                   OR pgcontext._semantic_rerank_sources.text_collation_oid IS DISTINCT FROM
                       EXCLUDED.text_collation_oid
                   OR pgcontext._semantic_rerank_sources.source_version_column_name IS DISTINCT FROM
                       EXCLUDED.source_version_column_name
                   OR pgcontext._semantic_rerank_sources.source_version_attnum IS DISTINCT FROM
                       EXCLUDED.source_version_attnum
                   OR pgcontext._semantic_rerank_sources.source_version_type_oid IS DISTINCT FROM
                       EXCLUDED.source_version_type_oid
               THEN 1 ELSE 0 END,
           status = 'ready',
           updated_at = pg_catalog.now()
    RETURNING rerank_source_id INTO registered_id;
    RETURN registered_id;
END;
$$;

CREATE FUNCTION pgcontext._refresh_semantic_rerank_source(
    p_collection_id bigint,
    p_source_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._semantic_rerank_sources%ROWTYPE;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT * INTO registration
      FROM pgcontext._semantic_rerank_sources
     WHERE collection_id = p_collection_id
       AND source_name = p_source_name;
    IF NOT FOUND THEN
        RETURN;
    END IF;

    UPDATE pgcontext._semantic_rerank_sources AS sources
       SET source_table_oid = source_class.oid,
           source_key_attnum = key_attribute.attnum,
           source_key_type_oid = key_attribute.atttypid,
           source_key_collation_oid = key_attribute.attcollation,
           source_key_type_schema = key_type_namespace.nspname,
           source_key_type_name = key_type.typname,
           text_attnum = text_attribute.attnum,
           text_type_oid = text_attribute.atttypid,
           text_collation_oid = text_attribute.attcollation,
           source_version_attnum = version_attribute.attnum,
           source_version_type_oid = version_attribute.atttypid,
           registration_revision = sources.registration_revision +
               CASE WHEN source_class.oid IS DISTINCT FROM registration.source_table_oid
                          OR key_attribute.attnum IS DISTINCT FROM registration.source_key_attnum
                          OR key_attribute.atttypid IS DISTINCT FROM registration.source_key_type_oid
                          OR key_attribute.attcollation IS DISTINCT FROM registration.source_key_collation_oid
                          OR text_attribute.attnum IS DISTINCT FROM registration.text_attnum
                          OR text_attribute.atttypid IS DISTINCT FROM registration.text_type_oid
                          OR text_attribute.attcollation IS DISTINCT FROM registration.text_collation_oid
                          OR version_attribute.attnum IS DISTINCT FROM registration.source_version_attnum
                          OR version_attribute.atttypid IS DISTINCT FROM registration.source_version_type_oid
                    THEN 1 ELSE 0 END,
           status = 'ready',
           updated_at = pg_catalog.now()
      FROM pg_catalog.pg_namespace AS source_namespace,
           pg_catalog.pg_class AS source_class,
           pg_catalog.pg_attribute AS key_attribute,
           pg_catalog.pg_type AS key_type,
           pg_catalog.pg_namespace AS key_type_namespace,
           pg_catalog.pg_attribute AS text_attribute,
           pg_catalog.pg_collation AS text_collation,
           pg_catalog.pg_namespace AS text_collation_namespace,
           pg_catalog.pg_attribute AS version_attribute
     WHERE sources.rerank_source_id = registration.rerank_source_id
       AND source_namespace.nspname = sources.source_schema_name
       AND source_class.relnamespace = source_namespace.oid
       AND source_class.relname = sources.source_table_name
       AND source_class.relkind IN ('r', 'p')
       AND key_attribute.attrelid = source_class.oid
       AND key_attribute.attname = 'id'
       AND key_attribute.attnum > 0
       AND NOT key_attribute.attisdropped
       AND EXISTS (
           SELECT 1
             FROM pg_catalog.pg_index AS primary_index
            WHERE primary_index.indrelid = source_class.oid
              AND primary_index.indisprimary
              AND primary_index.indisvalid
              AND primary_index.indisready
              AND primary_index.indislive
              AND primary_index.indnkeyatts = 1
              AND primary_index.indnatts = 1
              AND primary_index.indkey[0] = key_attribute.attnum
       )
       AND key_type.oid = key_attribute.atttypid
       AND key_type_namespace.oid = key_type.typnamespace
       AND key_type_namespace.nspname = sources.source_key_type_schema
       AND key_type.typname = sources.source_key_type_name
       AND text_attribute.attrelid = source_class.oid
       AND text_attribute.attname = sources.text_column_name
       AND text_attribute.atttypid = 'pg_catalog.text'::pg_catalog.regtype
       AND text_attribute.attnum > 0
       AND NOT text_attribute.attisdropped
       AND text_collation.oid = text_attribute.attcollation
       AND text_collation_namespace.oid = text_collation.collnamespace
       AND text_collation_namespace.nspname = sources.text_collation_schema
       AND text_collation.collname = sources.text_collation_name
       AND version_attribute.attrelid = source_class.oid
       AND version_attribute.attname = sources.source_version_column_name
       AND version_attribute.atttypid = 'pg_catalog.int8'::pg_catalog.regtype
       AND version_attribute.attnum > 0
       AND NOT version_attribute.attisdropped;

    IF NOT FOUND THEN
        UPDATE pgcontext._semantic_rerank_sources
           SET status = 'stale', updated_at = pg_catalog.now()
         WHERE rerank_source_id = registration.rerank_source_id;
    END IF;
END;
$$;

CREATE FUNCTION pgcontext._insert_semantic_rerank_request(
    p_collection_id bigint,
    p_rerank_source_id bigint,
    p_registration_revision bigint,
    p_filter_binding_sha256 bytea,
    p_model_name text,
    p_model_revision bigint,
    p_query_text text,
    p_filter_json jsonb,
    p_failure_policy text,
    p_allow_partial boolean,
    p_expires_at_micros bigint,
    p_candidates jsonb
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    new_request_id bigint;
    expected_count int4;
    inserted_count int4;
    now_micros bigint;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    now_micros := pg_catalog.floor(
        pg_catalog.extract('epoch', pg_catalog.clock_timestamp()) * 1000000
    )::bigint;
    IF p_model_name IS NULL
       OR p_query_text IS NULL
       OR p_model_revision IS NULL
       OR p_failure_policy IS NULL
       OR p_allow_partial IS NULL
       OR p_expires_at_micros IS NULL
       OR p_candidates IS NULL
       OR p_filter_binding_sha256 IS NULL
       OR pg_catalog.octet_length(p_filter_binding_sha256) <> 32
       OR pg_catalog.octet_length(p_model_name) NOT BETWEEN 1 AND 128
       OR pg_catalog.octet_length(p_query_text) NOT BETWEEN 1 AND 65536
       OR p_model_revision <= 0
       OR p_expires_at_micros <= now_micros
       OR p_expires_at_micros > now_micros + 60000000
       OR p_failure_policy NOT IN ('require_reranker', 'allow_fused_fallback')
       OR pg_catalog.pg_column_size(p_candidates) > 4194304
       OR pg_catalog.octet_length(p_candidates::text) > 4194304
       OR (
           p_filter_json IS NOT NULL
           AND (
               pg_catalog.pg_column_size(p_filter_json) > 262144
               OR pg_catalog.octet_length(p_filter_json::text) > 262144
           )
       )
    THEN
        RAISE EXCEPTION 'semantic rerank request exceeds its storage contract'
            USING ERRCODE = '54000';
    END IF;
    IF NOT EXISTS (
        SELECT 1 FROM pgcontext._semantic_rerank_sources
         WHERE rerank_source_id = p_rerank_source_id
           AND collection_id = p_collection_id
           AND registration_revision = p_registration_revision
           AND status = 'ready'
    ) THEN
        RAISE EXCEPTION 'semantic rerank source registration changed'
            USING ERRCODE = '55000';
    END IF;
    IF pg_catalog.jsonb_typeof(p_candidates) <> 'array' THEN
        RAISE EXCEPTION 'semantic rerank candidates must be an array'
            USING ERRCODE = '22023';
    END IF;
    expected_count := pg_catalog.jsonb_array_length(p_candidates);
    IF expected_count NOT BETWEEN 1 AND 512 THEN
        RAISE EXCEPTION 'semantic rerank candidate count is outside 1..=512'
            USING ERRCODE = '54000';
    END IF;

    INSERT INTO pgcontext._semantic_rerank_requests (
        collection_id, rerank_source_id, session_user_oid,
        source_registration_revision, filter_binding_sha256, model_name, model_revision,
        query_text, filter_json, failure_policy, allow_partial, expires_at_micros
    ) VALUES (
        p_collection_id, p_rerank_source_id, SESSION_USER::pg_catalog.regrole::oid,
        p_registration_revision, p_filter_binding_sha256, p_model_name, p_model_revision,
        p_query_text, p_filter_json, p_failure_policy, p_allow_partial,
        p_expires_at_micros
    ) RETURNING request_id INTO new_request_id;

    INSERT INTO pgcontext._semantic_rerank_candidates (
        request_id, occurrence_id, point_id, source_version, content_digest,
        fused_rank, fused_score, contributions, metadata
    )
    SELECT new_request_id,
           candidate.occurrence_id,
           candidate.point_id,
           candidate.source_version,
           pg_catalog.decode(candidate.content_digest, 'hex'),
           candidate.fused_rank,
           candidate.fused_score,
           candidate.contributions,
           candidate.metadata
      FROM pg_catalog.jsonb_to_recordset(p_candidates) AS candidate(
          occurrence_id bigint,
          point_id bigint,
          source_version bigint,
          content_digest text,
          fused_rank int4,
          fused_score double precision,
          contributions jsonb,
          metadata jsonb
      );
    GET DIAGNOSTICS inserted_count = ROW_COUNT;
    IF inserted_count <> expected_count THEN
        RAISE EXCEPTION 'semantic rerank candidate set is incomplete'
            USING ERRCODE = '22023';
    END IF;
    RETURN new_request_id;
END;
$$;

CREATE FUNCTION pgcontext._finalize_semantic_rerank_request(
    p_request_id bigint,
    p_response_sha256 bytea,
    p_final_status text,
    p_degraded_reason text,
    p_final_result jsonb
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    IF p_response_sha256 IS NULL
       OR p_final_status IS NULL
       OR p_final_result IS NULL
       OR pg_catalog.octet_length(p_response_sha256) <> 32
       OR p_final_status NOT IN ('reranked', 'degraded_reranker', 'partial_reranked')
       OR pg_catalog.pg_column_size(p_final_result) > 4194304
       OR (
           p_degraded_reason IS NOT NULL
           AND pg_catalog.octet_length(p_degraded_reason) NOT BETWEEN 1 AND 64
       )
    THEN
        RAISE EXCEPTION 'semantic rerank finalization exceeds its storage contract'
            USING ERRCODE = '54000';
    END IF;
    UPDATE pgcontext._semantic_rerank_requests
       SET status = 'finalized',
           response_sha256 = p_response_sha256,
           final_status = p_final_status,
           degraded_reason = p_degraded_reason,
           final_result = p_final_result,
           finalized_at = pg_catalog.now()
     WHERE request_id = p_request_id
       AND session_user_oid = SESSION_USER::pg_catalog.regrole::oid
       AND status = 'prepared';
    RETURN FOUND;
END;
$$;

CREATE FUNCTION pgcontext._cleanup_semantic_rerank_requests(p_limit int4)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    deleted bigint;
BEGIN
    IF p_limit NOT BETWEEN 1 AND 10000 THEN
        RAISE EXCEPTION 'semantic rerank cleanup limit must be 1..=10000'
            USING ERRCODE = '22023';
    END IF;
    WITH victims AS (
        SELECT request_id
          FROM pgcontext._semantic_rerank_requests
         WHERE session_user_oid = SESSION_USER::pg_catalog.regrole::oid
           AND (
               expires_at_micros <= pg_catalog.floor(
                   pg_catalog.extract('epoch', pg_catalog.clock_timestamp()) * 1000000
               )::bigint
               OR status = 'finalized'
           )
         ORDER BY request_id
         LIMIT p_limit
         FOR UPDATE SKIP LOCKED
    ), deleted_rows AS (
        DELETE FROM pgcontext._semantic_rerank_requests AS requests
         USING victims
         WHERE requests.request_id = victims.request_id
         RETURNING 1
    )
    SELECT pg_catalog.count(*) INTO deleted FROM deleted_rows;
    RETURN deleted;
END;
$$;

SELECT pg_catalog.pg_extension_config_dump('pgcontext._semantic_rerank_sources', '');
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._semantic_rerank_sources_rerank_source_id_seq', ''
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership_catalog.rs:7
-- requires:
--   pgcontext_bootstrap


CREATE TABLE pgcontext._pgvector_ownership_conversions (
    conversion_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    owner_role oid NOT NULL,
    source_table_oid oid NOT NULL,
    source_schema_name name NOT NULL,
    source_table_name name NOT NULL,
    source_column_name name NOT NULL,
    source_attnum int2 NOT NULL CHECK (source_attnum > 0),
    source_type_oid oid NOT NULL,
    source_type_name text NOT NULL CHECK (source_type_name <> ''),
    source_typmod int4 NOT NULL CHECK (source_typmod >= -1),
    shadow_column_name name NOT NULL,
    shadow_attnum int2 CHECK (shadow_attnum IS NULL OR shadow_attnum > 0),
    backup_column_name name NOT NULL,
    trigger_name name NOT NULL,
    index_name name NOT NULL,
    mode text NOT NULL CHECK (mode IN ('fast', 'restricted_online')),
    metric text NOT NULL CHECK (metric IN ('l2', 'inner_product', 'cosine', 'l1')),
    status text NOT NULL DEFAULT 'planned' CHECK (
        status IN (
            'planned',
            'backfilling',
            'index_pending',
            'ready',
            'cutover',
            'completed',
            'rolled_back',
            'failed'
        )
    ),
    dependency_manifest text[] NOT NULL DEFAULT ARRAY[]::text[],
    validation_attestations text[] NOT NULL DEFAULT ARRAY[]::text[],
    total_rows bigint NOT NULL DEFAULT 0 CHECK (total_rows >= 0),
    processed_rows bigint NOT NULL DEFAULT 0 CHECK (processed_rows >= 0),
    mismatch_count bigint NOT NULL DEFAULT 0 CHECK (mismatch_count >= 0),
    backfill_cursor text NOT NULL DEFAULT '(0,0)',
    source_checksum text,
    shadow_checksum text,
    error_message text,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    started_at timestamptz,
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    completed_at timestamptz,
    CHECK (source_schema_name <> ''),
    CHECK (source_table_name <> ''),
    CHECK (source_column_name <> ''),
    CHECK (shadow_column_name <> backup_column_name),
    CHECK (trigger_name <> index_name),
    CHECK (processed_rows <= total_rows),
    CHECK (completed_at IS NULL OR status IN ('completed', 'rolled_back'))
);

CREATE UNIQUE INDEX pgcontext_pgvector_ownership_conversions_active_source
    ON pgcontext._pgvector_ownership_conversions (source_table_oid, source_attnum)
    WHERE status IN (
        'planned',
        'backfilling',
        'index_pending',
        'ready',
        'cutover',
        'failed'
    );

REVOKE ALL ON TABLE pgcontext._pgvector_ownership_conversions FROM PUBLIC;

CREATE VIEW pgcontext._visible_pgvector_ownership_conversions
WITH (security_barrier = true) AS
SELECT conversions.*
  FROM pgcontext._pgvector_ownership_conversions AS conversions
 WHERE pg_catalog.pg_has_role(SESSION_USER, conversions.owner_role, 'MEMBER');

GRANT SELECT ON pgcontext._visible_pgvector_ownership_conversions TO PUBLIC;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:4
-- BuildJobStatus
CREATE TYPE BuildJobStatus AS ENUM (
	'Planned',
	'Running',
	'CancelRequested',
	'Cancelled',
	'Validating',
	'Publishing',
	'Completed',
	'Failed',
	'Abandoned'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:27
-- EmbeddingMigrationStatus
CREATE TYPE EmbeddingMigrationStatus AS ENUM (
	'Planned',
	'Running',
	'Completed',
	'Failed'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:166
-- IndexAdvisorRecommendation
CREATE TYPE IndexAdvisorRecommendation AS ENUM (
	'NoAction',
	'CreateBtreeIndex',
	'CreateGinIndex',
	'AnalyzeTable',
	'AvoidCandidateMaterialization',
	'TuneHnswSettings'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:105
-- IndexDiagnosticStatus
CREATE TYPE IndexDiagnosticStatus AS ENUM (
	'Ready',
	'IndexNotReady',
	'IndexCorrupt',
	'UnsupportedAccessMethod'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:94
-- IndexLifecycleStatus
CREATE TYPE IndexLifecycleStatus AS ENUM (
	'Ready',
	'Building',
	'Invalid'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:129
-- IndexMemoryEstimateStatus
CREATE TYPE IndexMemoryEstimateStatus AS ENUM (
	'Projected',
	'UnsupportedAccessMethod',
	'UnavailableStatistics'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:140
-- OptimizationStatus
CREATE TYPE OptimizationStatus AS ENUM (
	'Indexed',
	'ExactOnly',
	'MissingArtifacts',
	'StaleCatalog'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:59
-- QueryCohortStatus
CREATE TYPE QueryCohortStatus AS ENUM (
	'Observed'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:83
-- QueryExplainStatus
CREATE TYPE QueryExplainStatus AS ENUM (
	'Ready',
	'Fallback',
	'Policy'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:66
-- QueryLatencyBucket
CREATE TYPE QueryLatencyBucket AS ENUM (
	'Lt1Ms',
	'Lt10Ms',
	'Lt100Ms',
	'Lt1S',
	'Gte1S',
	'Unspecified'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:40
-- QueryLifecycleState
CREATE TYPE QueryLifecycleState AS ENUM (
	'Unspecified',
	'Exact',
	'Indexed',
	'Fallback',
	'IndexNotReady',
	'IndexCorrupt',
	'ArtifactMissing'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:118
-- RecallCheckStatus
CREATE TYPE RecallCheckStatus AS ENUM (
	'Passing',
	'Failing',
	'EmptyExact'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:183
-- TelemetryStatus
CREATE TYPE TelemetryStatus AS ENUM (
	'Active',
	'Empty',
	'MissingArtifacts',
	'StaleCatalog'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sql_enums.rs:153
-- VacuumAdviceStatus
CREATE TYPE VacuumAdviceStatus AS ENUM (
	'Healthy',
	'VacuumRecommended',
	'AnalyzeRecommended',
	'UnsupportedAccessMethod'
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership/persistence.rs:140
-- pgcontext::pgvector_ownership::persistence::_begin_pgvector_ownership_conversion
CREATE  FUNCTION "_begin_pgvector_ownership_conversion"(
	"source_table_oid" oid, /* pg_sys :: Oid */
	"source_column_name" TEXT, /* String */
	"mode" TEXT, /* String */
	"metric" TEXT, /* String */
	"dependency_manifest" TEXT[], /* Vec < String > */
	"validation_attestations" TEXT[] /* Vec < String > */
) RETURNS bigint /* i64 */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'begin_conversion_catalog_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am_compaction.rs:816
-- pgcontext::hnsw_am::_compact_hnsw_segment_pair
CREATE  FUNCTION "_compact_hnsw_segment_pair"(
	"index" regclass, /* PgRelation */
	"expected_directory_epoch" bigint /* i64 */
) RETURNS bool /* bool */
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_compact_segment_pair_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/permit.rs:65
-- pgcontext::document_chunking::permit::_consume_document_chunk_permit
CREATE  FUNCTION "_consume_document_chunk_permit"(
	"operation" INT, /* i32 */
	"identity_a" bigint, /* i64 */
	"identity_b" bigint /* i64 */
) RETURNS bool /* bool */
STRICT 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'consume_document_chunk_permit_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/datum.rs:12
-- pgcontext::document_chunking::datum::_document_chunk_raw_datum_bytes
CREATE  FUNCTION "_document_chunk_raw_datum_bytes"(
	"value" anyelement /* AnyElement */
) RETURNS bigint /* i64 */
STRICT 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'document_chunk_raw_datum_bytes_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:44
-- pgcontext::document_chunking::_document_chunk_source_key_visible
CREATE  FUNCTION "_document_chunk_source_key_visible"(
	"document_source_id" bigint, /* i64 */
	"source_key" TEXT /* String */
) RETURNS bool /* bool */
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'document_chunk_source_key_visible_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_catalog_schema.rs:9
-- requires:
--   document_chunk_source_key_visible
--   create_semantic_rerank_catalog_tables


CREATE TABLE pgcontext._chunking_profiles (
    chunking_profile_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    owner_role oid NOT NULL,
    profile_name text NOT NULL CHECK (pg_catalog.octet_length(profile_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(profile_name) <> '' AND profile_name !~ '[[:cntrl:]]'),
    profile_revision bigint NOT NULL DEFAULT 1 CHECK (profile_revision > 0),
    parser_revision text NOT NULL CHECK (
        parser_revision IN ('plain_text_v1', 'markdown_v1', 'html_v1')),
    tokenizer_revision text NOT NULL DEFAULT 'unicode_words_v1'
        CHECK (tokenizer_revision = 'unicode_words_v1'),
    target_tokens int4 NOT NULL CHECK (target_tokens BETWEEN 1 AND 512),
    max_tokens int4 NOT NULL CHECK (max_tokens BETWEEN target_tokens AND 512),
    min_tokens int4 NOT NULL CHECK (min_tokens BETWEEN 1 AND target_tokens),
    overlap_tokens int4 NOT NULL CHECK (
        overlap_tokens BETWEEN 0 AND 64 AND overlap_tokens < target_tokens),
    max_document_bytes bigint NOT NULL CHECK (max_document_bytes BETWEEN 1 AND 8388608),
    include_structure_context boolean NOT NULL DEFAULT false,
    configuration_sha256 bytea NOT NULL CHECK (
        pg_catalog.octet_length(configuration_sha256) = 32),
    status text NOT NULL DEFAULT 'ready'
        CHECK (status IN ('ready', 'retired')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    retired_at timestamptz,
    UNIQUE (owner_role, profile_name),
    CHECK ((status = 'retired') = (retired_at IS NOT NULL))
);
CREATE TABLE pgcontext._chunking_profile_aliases (
    chunking_profile_alias_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    owner_role oid NOT NULL,
    alias_name text NOT NULL CHECK (pg_catalog.octet_length(alias_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(alias_name) <> '' AND alias_name !~ '[[:cntrl:]]'),
    chunking_profile_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    shadow_chunking_profile_id bigint
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    alias_revision bigint NOT NULL DEFAULT 1 CHECK (alias_revision > 0),
    status text NOT NULL DEFAULT 'ready' CHECK (status IN ('ready','retired')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (owner_role, alias_name)
);
CREATE TABLE pgcontext._chunking_profile_alias_history (
    chunking_profile_alias_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profile_aliases(chunking_profile_alias_id)
        ON DELETE CASCADE,
    alias_revision bigint NOT NULL CHECK (alias_revision > 0),
    chunking_profile_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    promoted_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (chunking_profile_alias_id, alias_revision)
);
CREATE TABLE pgcontext._document_sources (
    document_source_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_name text NOT NULL CHECK (pg_catalog.octet_length(source_name) BETWEEN 1 AND 128
        AND pg_catalog.btrim(source_name) <> '' AND source_name !~ '[[:cntrl:]]'),
    rerank_source_id bigint NOT NULL
        REFERENCES pgcontext._semantic_rerank_sources(rerank_source_id) ON DELETE CASCADE,
    rerank_registration_revision bigint NOT NULL CHECK (rerank_registration_revision > 0),
    chunking_profile_alias_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profile_aliases(chunking_profile_alias_id),
    projection_table_oid oid NOT NULL,
    projection_schema_name text NOT NULL,
    projection_table_name text NOT NULL,
    projection_column_attnums int2[] NOT NULL CHECK (
        pg_catalog.cardinality(projection_column_attnums) = 28),
    projection_column_type_oids oid[] NOT NULL CHECK (
        pg_catalog.cardinality(projection_column_type_oids) = 28),
    projection_column_collation_oids oid[] NOT NULL CHECK (
        pg_catalog.cardinality(projection_column_collation_oids) = 28),
    registration_system_identifier bigint NOT NULL,
    registration_database_oid oid NOT NULL,
    registration_revision bigint NOT NULL DEFAULT 1 CHECK (registration_revision > 0),
    status text NOT NULL DEFAULT 'ready'
        CHECK (status IN ('ready', 'stale', 'retired', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    UNIQUE (collection_id, source_name)
);
CREATE TABLE pgcontext._document_chunk_generations (
    generation_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    document_source_id bigint NOT NULL
        REFERENCES pgcontext._document_sources(document_source_id) ON DELETE CASCADE,
    source_key text NOT NULL CHECK (pg_catalog.octet_length(source_key) BETWEEN 1 AND 1024),
    source_version bigint NOT NULL CHECK (source_version > 0),
    source_sha256 bytea NOT NULL CHECK (pg_catalog.octet_length(source_sha256) = 32),
    chunking_profile_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    source_registration_revision bigint NOT NULL CHECK (source_registration_revision > 0),
    status text NOT NULL DEFAULT 'queued' CHECK (
        status IN ('queued', 'leased', 'parsing', 'chunking', 'embedding',
                   'validating', 'publishing', 'ready', 'cancel_requested',
                   'cancelled', 'failed', 'superseded', 'retired')
    ),
    prior_generation_id bigint
        REFERENCES pgcontext._document_chunk_generations(generation_id),
    chunk_count int4,
    token_count bigint,
    staging_bytes bigint,
    publication_sha256 bytea,
    projection_sha256 bytea,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    published_at timestamptz,
    UNIQUE (document_source_id, source_key, source_version, chunking_profile_id,
        source_registration_revision),
    CHECK (publication_sha256 IS NULL OR pg_catalog.octet_length(publication_sha256) = 32),
    CHECK (projection_sha256 IS NULL OR pg_catalog.octet_length(projection_sha256) = 32),
    CHECK ((status IN ('ready', 'retired')) = (published_at IS NOT NULL))
);
CREATE TABLE pgcontext._document_chunk_jobs (
    job_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    generation_id bigint NOT NULL UNIQUE
        REFERENCES pgcontext._document_chunk_generations(generation_id) ON DELETE CASCADE,
    status text NOT NULL DEFAULT 'queued' CHECK (
        status IN ('queued', 'leased', 'parsing', 'chunking', 'embedding',
                   'validating', 'publishing', 'ready', 'cancel_requested',
                   'cancelled', 'failed', 'superseded', 'retired')
    ),
    attempt int4 NOT NULL DEFAULT 0 CHECK (attempt BETWEEN 0 AND 3),
    lease_worker text,
    lease_token bigint NOT NULL DEFAULT 0 CHECK (lease_token >= 0),
    lease_expires_at timestamptz,
    processed_units bigint NOT NULL DEFAULT 0 CHECK (processed_units >= 0),
    total_units bigint NOT NULL DEFAULT 1 CHECK (total_units > 0),
    error_code text CHECK (error_code IS NULL OR (
        pg_catalog.octet_length(error_code) BETWEEN 1 AND 64
        AND error_code ~ '^[a-z0-9_]+$')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK ((lease_worker IS NULL) = (lease_expires_at IS NULL))
);
CREATE TABLE pgcontext._document_chunk_staging (
    job_id bigint PRIMARY KEY
        REFERENCES pgcontext._document_chunk_jobs(job_id) ON DELETE CASCADE,
    lease_token bigint NOT NULL CHECK (lease_token > 0),
    response_json jsonb NOT NULL,
    response_sha256 bytea NOT NULL CHECK (pg_catalog.octet_length(response_sha256) = 32),
    chunk_count int4 NOT NULL CHECK (chunk_count BETWEEN 0 AND 16384),
    token_count bigint NOT NULL CHECK (token_count >= 0),
    staging_bytes bigint NOT NULL CHECK (staging_bytes BETWEEN 1 AND 33554432),
    staged_at timestamptz NOT NULL DEFAULT pg_catalog.now()
);
CREATE TABLE pgcontext._current_document_chunk_generations (
    document_source_id bigint NOT NULL
        REFERENCES pgcontext._document_sources(document_source_id) ON DELETE CASCADE,
    source_key text NOT NULL,
    chunking_profile_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    generation_id bigint NOT NULL
        REFERENCES pgcontext._document_chunk_generations(generation_id),
    publication_revision bigint NOT NULL DEFAULT 1 CHECK (publication_revision > 0),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (document_source_id, source_key, chunking_profile_id)
);
CREATE TABLE pgcontext._document_embedding_jobs (
    generation_id bigint NOT NULL
        REFERENCES pgcontext._document_chunk_generations(generation_id) ON DELETE CASCADE,
    occurrence_id bigint NOT NULL CHECK (occurrence_id > 0),
    content_hash bigint NOT NULL,
    embedding_profile_id bigint NOT NULL DEFAULT 0 CHECK (embedding_profile_id >= 0),
    status text NOT NULL DEFAULT 'ready' CHECK (status IN ('queued', 'ready', 'failed')),
    fake_embedding jsonb NOT NULL CHECK (pg_catalog.jsonb_typeof(fake_embedding) = 'array'),
    PRIMARY KEY (generation_id, occurrence_id, embedding_profile_id)
);
REVOKE ALL ON TABLE pgcontext._chunking_profiles FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._chunking_profile_aliases FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._chunking_profile_alias_history FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._document_sources FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._document_chunk_generations FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._document_chunk_jobs FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._document_chunk_staging FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._current_document_chunk_generations FROM PUBLIC;
REVOKE ALL ON TABLE pgcontext._document_embedding_jobs FROM PUBLIC;
CREATE VIEW pgcontext._visible_chunking_profiles
WITH (security_barrier = true) AS
SELECT profiles.*
  FROM pgcontext._chunking_profiles AS profiles
 WHERE pg_catalog.pg_has_role(SESSION_USER, profiles.owner_role, 'MEMBER');
CREATE VIEW pgcontext._visible_chunking_profile_aliases
WITH (security_barrier = true) AS
SELECT aliases.*
  FROM pgcontext._chunking_profile_aliases AS aliases
 WHERE pg_catalog.pg_has_role(SESSION_USER, aliases.owner_role, 'MEMBER');
CREATE VIEW pgcontext._visible_document_sources
WITH (security_barrier = true) AS
SELECT sources.document_source_id, sources.collection_id, sources.source_name,
       sources.rerank_source_id, sources.rerank_registration_revision,
       aliases.chunking_profile_id, sources.chunking_profile_alias_id,
       sources.projection_table_oid, sources.projection_schema_name,
       sources.projection_table_name, sources.projection_column_attnums,
       sources.projection_column_type_oids, sources.projection_column_collation_oids,
       sources.registration_revision, sources.status, sources.created_at,
       sources.updated_at
  FROM pgcontext._document_sources AS sources
  JOIN pgcontext._chunking_profile_aliases AS aliases USING (chunking_profile_alias_id)
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');
CREATE VIEW pgcontext._visible_document_chunk_generations
WITH (security_barrier = true) AS
SELECT generations.*
  FROM pgcontext._document_chunk_generations AS generations
 JOIN pgcontext._document_sources AS sources USING (document_source_id)
 JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
   AND pgcontext._document_chunk_source_key_visible(
           generations.document_source_id, generations.source_key
       );
CREATE VIEW pgcontext._visible_document_chunk_jobs
WITH (security_barrier = true) AS
SELECT jobs.job_id, jobs.generation_id, jobs.status, jobs.attempt,
       jobs.processed_units, jobs.total_units, jobs.error_code,
       jobs.created_at, jobs.updated_at,
       generations.document_source_id, generations.source_version,
       generations.chunking_profile_id
  FROM pgcontext._document_chunk_jobs AS jobs
  JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
 JOIN pgcontext._document_sources AS sources USING (document_source_id)
 JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
   AND pgcontext._document_chunk_source_key_visible(
           generations.document_source_id, generations.source_key
       );
CREATE VIEW pgcontext._visible_current_document_chunk_generations
WITH (security_barrier = true) AS
SELECT aliases.*, sources.collection_id, sources.source_name,
       sources.projection_table_oid, sources.projection_schema_name,
       sources.projection_table_name
  FROM pgcontext._current_document_chunk_generations AS aliases
 JOIN pgcontext._document_sources AS sources USING (document_source_id)
 JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
   AND pgcontext._document_chunk_source_key_visible(
           aliases.document_source_id, aliases.source_key
       );
CREATE VIEW pgcontext._visible_document_chunk_staging
WITH (security_barrier = true) AS
SELECT staging.job_id, staging.chunk_count, staging.token_count,
       staging.staging_bytes, staging.staged_at
  FROM pgcontext._document_chunk_staging AS staging
  JOIN pgcontext._document_chunk_jobs AS jobs USING (job_id)
  JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
 JOIN pgcontext._document_sources AS sources USING (document_source_id)
 JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
   AND pgcontext._document_chunk_source_key_visible(
           generations.document_source_id, generations.source_key
       );
CREATE VIEW pgcontext._visible_document_embedding_jobs
WITH (security_barrier = true) AS
SELECT embedding.*
  FROM pgcontext._document_embedding_jobs AS embedding
  JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
 JOIN pgcontext._document_sources AS sources USING (document_source_id)
 JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
   AND pgcontext._document_chunk_source_key_visible(
           generations.document_source_id, generations.source_key
       );
GRANT SELECT ON pgcontext._visible_chunking_profiles,
    pgcontext._visible_chunking_profile_aliases,
    pgcontext._visible_document_sources,
    pgcontext._visible_document_chunk_generations,
    pgcontext._visible_document_chunk_jobs,
    pgcontext._visible_current_document_chunk_generations,
    pgcontext._visible_document_chunk_staging,
    pgcontext._visible_document_embedding_jobs TO PUBLIC;
CREATE FUNCTION pgcontext._register_document_source(
    p_collection_id bigint,
    p_source_name text,
    p_rerank_source_id bigint,
    p_chunking_profile_id bigint,
    p_chunking_profile_alias_id bigint,
    p_projection_table_oid oid,
    p_projection_schema_name text,
    p_projection_table_name text,
    p_projection_column_attnums int2[],
    p_projection_column_type_oids oid[],
    p_projection_column_collation_oids bigint[]
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_id bigint;
    rerank_revision bigint;
    changed boolean;
    projection_collation_oids oid[];
    alias_profile_id bigint;
    origin_system_identifier bigint;
    origin_database_oid oid;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        4, p_collection_id, p_rerank_source_id
    );
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    SELECT pg_catalog.array_agg(value::oid ORDER BY ordinal)
      INTO projection_collation_oids
      FROM pg_catalog.unnest(p_projection_column_collation_oids)
           WITH ORDINALITY AS collations(value, ordinal);
    SELECT system_identifier INTO origin_system_identifier
      FROM pg_catalog.pg_control_system();
    SELECT oid INTO origin_database_oid
      FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database();
    SELECT registration_revision INTO rerank_revision
      FROM pgcontext._semantic_rerank_sources
     WHERE rerank_source_id = p_rerank_source_id
       AND collection_id = p_collection_id
       AND status = 'ready';
    IF rerank_revision IS NULL THEN
        RAISE EXCEPTION 'semantic rerank source does not match the document collection'
            USING ERRCODE = '42704';
    END IF;
    SELECT aliases.chunking_profile_id INTO alias_profile_id
      FROM pgcontext._chunking_profile_aliases AS aliases
      JOIN pgcontext._chunking_profiles AS profiles USING (chunking_profile_id)
     WHERE aliases.chunking_profile_alias_id = p_chunking_profile_alias_id
       AND aliases.status = 'ready' AND profiles.status = 'ready'
       AND pg_catalog.pg_has_role(SESSION_USER, aliases.owner_role, 'MEMBER')
     FOR SHARE OF aliases;
    IF alias_profile_id IS DISTINCT FROM p_chunking_profile_id THEN
        RAISE EXCEPTION 'chunking profile does not exist or is not ready'
            USING ERRCODE = '42704';
    END IF;
    PERFORM pg_catalog.pg_advisory_xact_lock(pg_catalog.hashtextextended(
        p_collection_id::text || E'\x1fdocument\x1f' || p_source_name, 0
    ));
    PERFORM 1
      FROM pgcontext._document_sources AS existing
     WHERE existing.collection_id = p_collection_id
       AND existing.source_name = p_source_name
     FOR UPDATE;
    SELECT EXISTS (
        SELECT 1 FROM pgcontext._document_sources AS existing
         WHERE existing.collection_id = p_collection_id
           AND existing.source_name = p_source_name
           AND (
               existing.rerank_source_id IS DISTINCT FROM p_rerank_source_id
               OR existing.rerank_registration_revision IS DISTINCT FROM rerank_revision
               OR existing.chunking_profile_alias_id IS DISTINCT FROM p_chunking_profile_alias_id
               OR existing.projection_table_oid IS DISTINCT FROM p_projection_table_oid
               OR existing.projection_schema_name IS DISTINCT FROM p_projection_schema_name
               OR existing.projection_table_name IS DISTINCT FROM p_projection_table_name
               OR existing.projection_column_attnums IS DISTINCT FROM p_projection_column_attnums
               OR existing.projection_column_type_oids IS DISTINCT FROM p_projection_column_type_oids
               OR existing.projection_column_collation_oids IS DISTINCT FROM projection_collation_oids
           )
    ) INTO changed;
    INSERT INTO pgcontext._document_sources (
        collection_id, source_name, rerank_source_id, rerank_registration_revision,
        chunking_profile_alias_id,
        projection_table_oid, projection_schema_name, projection_table_name,
        projection_column_attnums, projection_column_type_oids,
        projection_column_collation_oids,
        registration_system_identifier, registration_database_oid
    ) VALUES (
        p_collection_id, p_source_name, p_rerank_source_id, rerank_revision,
        p_chunking_profile_alias_id,
        p_projection_table_oid, p_projection_schema_name, p_projection_table_name,
        p_projection_column_attnums, p_projection_column_type_oids,
        projection_collation_oids, origin_system_identifier, origin_database_oid
    )
    ON CONFLICT (collection_id, source_name) DO UPDATE
       SET rerank_source_id = EXCLUDED.rerank_source_id,
           rerank_registration_revision = EXCLUDED.rerank_registration_revision,
           chunking_profile_alias_id = EXCLUDED.chunking_profile_alias_id,
           projection_table_oid = EXCLUDED.projection_table_oid,
           projection_schema_name = EXCLUDED.projection_schema_name,
           projection_table_name = EXCLUDED.projection_table_name,
           projection_column_attnums = EXCLUDED.projection_column_attnums,
           projection_column_type_oids = EXCLUDED.projection_column_type_oids,
           projection_column_collation_oids = EXCLUDED.projection_column_collation_oids,
           registration_system_identifier = EXCLUDED.registration_system_identifier,
           registration_database_oid = EXCLUDED.registration_database_oid,
           registration_revision = pgcontext._document_sources.registration_revision +
               CASE WHEN changed THEN 1 ELSE 0 END,
           status = 'ready', updated_at = pg_catalog.now()
    RETURNING document_source_id INTO source_id;
    IF changed THEN
        PERFORM 1
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
         WHERE generations.document_source_id = source_id
         ORDER BY jobs.job_id FOR UPDATE OF jobs;
        UPDATE pgcontext._document_chunk_generations
           SET status = 'retired'
         WHERE document_source_id = source_id AND status = 'ready';
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = CASE
                   WHEN generations.status = 'retired' THEN 'retired'
                   ELSE 'superseded'
               END,
               lease_worker = NULL, lease_expires_at = NULL,
               updated_at = pg_catalog.now()
          FROM pgcontext._document_chunk_generations AS generations
         WHERE jobs.generation_id = generations.generation_id
           AND generations.document_source_id = source_id
           AND jobs.status NOT IN ('retired','superseded');
        UPDATE pgcontext._document_chunk_generations
           SET status = 'superseded'
         WHERE document_source_id = source_id
           AND status NOT IN ('ready','retired','superseded');
        DELETE FROM pgcontext._document_chunk_staging AS staging
         USING pgcontext._document_chunk_jobs AS jobs,
               pgcontext._document_chunk_generations AS generations
         WHERE staging.job_id = jobs.job_id AND jobs.generation_id = generations.generation_id
           AND generations.document_source_id = source_id
           AND generations.status = 'superseded';
        DELETE FROM pgcontext._current_document_chunk_generations
         WHERE document_source_id = source_id;
    END IF;
    RETURN source_id;
END;
$$;
CREATE FUNCTION pgcontext._refresh_document_chunk_source(
    p_collection_id bigint,
    p_source_name text
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._document_sources%ROWTYPE;
    current_projection_oid oid;
    current_projection_attnums int2[];
    current_projection_type_oids oid[];
    current_projection_collation_oids oid[];
    current_rerank_revision bigint;
    identity_changed boolean;
    current_system_identifier bigint;
    current_database_oid oid;
    logical_restore boolean;
BEGIN
    PERFORM pgcontext._require_collection_owner(p_collection_id);
    PERFORM pgcontext._refresh_semantic_rerank_source(p_collection_id, p_source_name);
    PERFORM pg_catalog.pg_advisory_xact_lock(pg_catalog.hashtextextended(
        p_collection_id::text || E'\x1fdocument\x1f' || p_source_name, 0
    ));
    SELECT * INTO registration
      FROM pgcontext._document_sources
     WHERE collection_id = p_collection_id AND source_name = p_source_name
     FOR UPDATE;
    IF NOT FOUND THEN
        RETURN;
    END IF;
    SELECT system_identifier INTO current_system_identifier
      FROM pg_catalog.pg_control_system();
    SELECT oid INTO current_database_oid
      FROM pg_catalog.pg_database WHERE datname = pg_catalog.current_database();
    logical_restore := registration.registration_system_identifier IS DISTINCT FROM
            current_system_identifier
        OR registration.registration_database_oid IS DISTINCT FROM current_database_oid;
    SELECT rerank.registration_revision
      INTO current_rerank_revision
      FROM pgcontext._semantic_rerank_sources AS rerank
     WHERE rerank.rerank_source_id = registration.rerank_source_id
       AND rerank.collection_id = p_collection_id
       AND rerank.status = 'ready';
    SELECT relation.oid
      INTO current_projection_oid
      FROM pg_catalog.pg_namespace AS namespace
      JOIN pg_catalog.pg_class AS relation ON relation.relnamespace = namespace.oid
     WHERE namespace.nspname = registration.projection_schema_name
       AND relation.relname = registration.projection_table_name
       AND relation.relkind IN ('r', 'p');
    IF current_projection_oid IS NOT NULL THEN
        SELECT pg_catalog.array_agg(attribute.attnum ORDER BY required.ordinal),
               pg_catalog.array_agg(attribute.atttypid ORDER BY required.ordinal),
               pg_catalog.array_agg(attribute.attcollation ORDER BY required.ordinal)
          INTO current_projection_attnums, current_projection_type_oids,
               current_projection_collation_oids
          FROM pg_catalog.unnest(ARRAY[
              'document_source_id','source_key','source_version','source_sha256',
              'profile_revision','generation_id','occurrence_id','ordinal',
              'original_text','retrieval_text','start_byte','end_byte','start_char',
              'end_char','token_count','structure_kind','structure_path',
              'page_number','region',
              'parent_occurrence_id','previous_occurrence_id','next_occurrence_id',
              'content_hash','context_prefix','context_prefix_hash','fake_embedding',
              'ready','provenance'
          ]::text[]) WITH ORDINALITY AS required(column_name, ordinal)
          LEFT JOIN pg_catalog.pg_attribute AS attribute
            ON attribute.attrelid = current_projection_oid
           AND attribute.attname = required.column_name
           AND attribute.attnum > 0 AND NOT attribute.attisdropped;
    END IF;
    IF current_rerank_revision IS NULL OR current_projection_oid IS NULL
       OR current_projection_attnums IS NULL
       OR pg_catalog.cardinality(current_projection_attnums) <> 28
       OR (NOT logical_restore AND (
           current_projection_attnums IS DISTINCT FROM registration.projection_column_attnums
           OR current_projection_type_oids IS DISTINCT FROM registration.projection_column_type_oids
           OR current_projection_collation_oids IS DISTINCT FROM
              registration.projection_column_collation_oids
       )) THEN
        UPDATE pgcontext._document_sources
           SET status = 'stale', updated_at = pg_catalog.now()
         WHERE document_source_id = registration.document_source_id;
        RETURN;
    END IF;
    identity_changed := NOT logical_restore AND (
        current_projection_oid IS DISTINCT FROM registration.projection_table_oid
        OR current_rerank_revision IS DISTINCT FROM registration.rerank_registration_revision
    );
    UPDATE pgcontext._document_sources AS sources
       SET projection_table_oid = current_projection_oid,
           rerank_registration_revision = current_rerank_revision,
           projection_column_attnums = CASE WHEN logical_restore
               THEN current_projection_attnums ELSE sources.projection_column_attnums END,
           projection_column_type_oids = CASE WHEN logical_restore
               THEN current_projection_type_oids ELSE sources.projection_column_type_oids END,
           projection_column_collation_oids = CASE WHEN logical_restore
               THEN current_projection_collation_oids
               ELSE sources.projection_column_collation_oids END,
           registration_system_identifier = current_system_identifier,
           registration_database_oid = current_database_oid,
           registration_revision = sources.registration_revision +
               CASE WHEN identity_changed THEN 1 ELSE 0 END,
           status = 'ready', updated_at = pg_catalog.now()
     WHERE sources.document_source_id = registration.document_source_id;
    IF identity_changed THEN
        PERFORM 1
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
         WHERE generations.document_source_id = registration.document_source_id
         ORDER BY jobs.job_id FOR UPDATE OF jobs;
        UPDATE pgcontext._document_chunk_generations
           SET status = CASE WHEN status = 'ready' THEN 'retired' ELSE 'superseded' END
         WHERE document_source_id = registration.document_source_id
           AND status NOT IN ('retired','superseded');
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = CASE
                   WHEN generations.status = 'retired' THEN 'retired'
                   ELSE 'superseded'
               END,
               lease_worker = NULL, lease_expires_at = NULL,
               updated_at = pg_catalog.now()
          FROM pgcontext._document_chunk_generations AS generations
         WHERE jobs.generation_id = generations.generation_id
           AND generations.document_source_id = registration.document_source_id
           AND jobs.status NOT IN ('retired','superseded');
        DELETE FROM pgcontext._document_chunk_staging AS staging
         USING pgcontext._document_chunk_jobs AS jobs,
               pgcontext._document_chunk_generations AS generations
         WHERE staging.job_id = jobs.job_id
           AND jobs.generation_id = generations.generation_id
           AND generations.document_source_id = registration.document_source_id;
        DELETE FROM pgcontext._current_document_chunk_generations
         WHERE document_source_id = registration.document_source_id;
    END IF;
END;
$$;
CREATE FUNCTION pgcontext._enqueue_document_chunk_job(
    p_document_source_id bigint,
    p_source_key text,
    p_source_version bigint,
    p_source_sha256 bytea,
    p_chunking_profile_id bigint
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_row pgcontext._document_sources%ROWTYPE;
    v_generation_id bigint;
    v_job_id bigint;
    prior_id bigint;
    current_profile_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        11, p_document_source_id, p_source_version
    );
    SELECT * INTO source_row FROM pgcontext._document_sources
     WHERE document_source_id = p_document_source_id AND status = 'ready'
     FOR SHARE;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'document source does not exist or is not ready'
            USING ERRCODE = '42704';
    END IF;
    SELECT CASE
               WHEN p_chunking_profile_id = aliases.chunking_profile_id
                 OR p_chunking_profile_id = aliases.shadow_chunking_profile_id
               THEN p_chunking_profile_id
           END INTO current_profile_id
      FROM pgcontext._chunking_profile_aliases AS aliases
     WHERE aliases.chunking_profile_alias_id = source_row.chunking_profile_alias_id
       AND aliases.status = 'ready'
     FOR SHARE;
    IF current_profile_id IS NULL THEN
        RAISE EXCEPTION 'chunking profile alias is unavailable' USING ERRCODE = '42704';
    END IF;
    PERFORM pgcontext._require_collection_owner(source_row.collection_id);
    SELECT aliases.generation_id INTO prior_id
      FROM pgcontext._current_document_chunk_generations AS aliases
     WHERE aliases.document_source_id = p_document_source_id
       AND aliases.source_key = p_source_key
       AND aliases.chunking_profile_id = current_profile_id;
    PERFORM 1
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
     WHERE generations.document_source_id = p_document_source_id
       AND generations.source_key = p_source_key
       AND generations.chunking_profile_id = current_profile_id
     ORDER BY jobs.job_id FOR UPDATE OF jobs;
    UPDATE pgcontext._document_chunk_generations
       SET status = 'superseded'
     WHERE document_source_id = p_document_source_id
       AND source_key = p_source_key
       AND chunking_profile_id = current_profile_id
       AND source_version < p_source_version
       AND status NOT IN ('ready', 'retired', 'superseded');
    UPDATE pgcontext._document_chunk_jobs AS jobs
       SET status = 'superseded', lease_worker = NULL, lease_expires_at = NULL,
           updated_at = pg_catalog.now()
      FROM pgcontext._document_chunk_generations AS generations
     WHERE jobs.generation_id = generations.generation_id
       AND generations.document_source_id = p_document_source_id
       AND generations.source_key = p_source_key
       AND generations.chunking_profile_id = current_profile_id
       AND generations.source_version < p_source_version
       AND jobs.status NOT IN ('ready', 'retired', 'superseded');
    INSERT INTO pgcontext._document_chunk_generations (
        document_source_id, source_key, source_version, source_sha256,
        chunking_profile_id, source_registration_revision, prior_generation_id
    ) VALUES (
        p_document_source_id, p_source_key, p_source_version, p_source_sha256,
        current_profile_id, source_row.registration_revision, prior_id
    )
    ON CONFLICT (
        document_source_id, source_key, source_version, chunking_profile_id,
        source_registration_revision
    )
    DO UPDATE SET source_sha256 = pgcontext._document_chunk_generations.source_sha256
      WHERE pgcontext._document_chunk_generations.source_sha256 = EXCLUDED.source_sha256
        AND pgcontext._document_chunk_generations.source_registration_revision =
            EXCLUDED.source_registration_revision
    RETURNING pgcontext._document_chunk_generations.generation_id INTO v_generation_id;
    IF v_generation_id IS NULL THEN
        RAISE EXCEPTION 'document source version identity changed'
            USING ERRCODE = '55000';
    END IF;
    INSERT INTO pgcontext._document_chunk_jobs (generation_id)
    VALUES (v_generation_id)
    ON CONFLICT (generation_id) DO UPDATE SET updated_at = pg_catalog.now()
    RETURNING pgcontext._document_chunk_jobs.job_id INTO v_job_id;
    RETURN v_job_id;
END;
$$;
CREATE FUNCTION pgcontext._claim_document_chunk_jobs(
    p_limit int4,
    p_lease_millis int4,
    p_worker_id text
)
RETURNS TABLE(job_id bigint, lease_token bigint)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        12, p_limit::bigint, p_lease_millis::bigint
    );
    IF p_limit NOT BETWEEN 1 AND 256 OR p_lease_millis NOT BETWEEN 1 AND 60000
       OR pg_catalog.octet_length(p_worker_id) NOT BETWEEN 1 AND 128
       OR p_worker_id ~ '[[:cntrl:]]' THEN
        RAISE EXCEPTION 'invalid document chunk claim bounds' USING ERRCODE = '22023';
    END IF;
    WITH exhausted_ids AS (
        SELECT jobs.job_id
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
          JOIN pgcontext._document_sources AS sources USING (document_source_id)
          JOIN pgcontext._collections AS collections USING (collection_id)
         WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
           AND (jobs.status = 'cancel_requested' OR jobs.attempt >= 3)
           AND jobs.status IN (
               'leased','parsing','chunking','embedding','validating','publishing',
               'cancel_requested'
           )
           AND jobs.lease_expires_at <= pg_catalog.clock_timestamp()
         ORDER BY jobs.updated_at, jobs.job_id
         LIMIT p_limit
         FOR UPDATE OF jobs SKIP LOCKED
    ), exhausted AS (
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = CASE
                   WHEN jobs.status = 'cancel_requested' THEN 'cancelled'
                   ELSE 'failed'
               END,
               lease_worker = NULL, lease_expires_at = NULL,
               error_code = CASE
                   WHEN jobs.status = 'cancel_requested' THEN 'cancelled'
                   ELSE 'attempts_exhausted'
               END,
               updated_at = pg_catalog.now()
          FROM exhausted_ids
         WHERE jobs.job_id = exhausted_ids.job_id
        RETURNING jobs.job_id, jobs.generation_id, jobs.status
    ), updated_generations AS (
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = exhausted.status
          FROM exhausted
         WHERE generations.generation_id = exhausted.generation_id
        RETURNING exhausted.job_id
    )
    DELETE FROM pgcontext._document_chunk_staging AS staging
     USING updated_generations
    WHERE staging.job_id = updated_generations.job_id;
    WITH mismatched_ids AS (
        SELECT jobs.job_id
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
          JOIN pgcontext._document_sources AS sources USING (document_source_id)
          JOIN pgcontext._chunking_profile_aliases AS aliases
            USING (chunking_profile_alias_id)
          JOIN pgcontext._collections AS collections USING (collection_id)
         WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
           AND generations.chunking_profile_id NOT IN (
               aliases.chunking_profile_id,
               COALESCE(aliases.shadow_chunking_profile_id, aliases.chunking_profile_id)
           )
           AND jobs.status NOT IN ('ready','retired','superseded','cancelled','failed')
         ORDER BY jobs.updated_at, jobs.job_id
         LIMIT p_limit
         FOR SHARE OF aliases
         FOR UPDATE OF jobs SKIP LOCKED
    ), mismatched AS (
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = 'superseded', lease_worker = NULL, lease_expires_at = NULL,
               updated_at = pg_catalog.now()
          FROM mismatched_ids
         WHERE jobs.job_id = mismatched_ids.job_id
        RETURNING jobs.job_id, jobs.generation_id
    ), superseded_generations AS (
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = 'superseded'
          FROM mismatched
         WHERE generations.generation_id = mismatched.generation_id
        RETURNING mismatched.job_id
    )
    DELETE FROM pgcontext._document_chunk_staging AS staging
     USING superseded_generations
    WHERE staging.job_id = superseded_generations.job_id;
    /* Cleanup is bounded by p_limit; later claims continue the work. */
    RETURN QUERY
    WITH candidates AS (
        SELECT jobs.job_id
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
          JOIN pgcontext._document_sources AS sources USING (document_source_id)
          JOIN pgcontext._chunking_profile_aliases AS aliases
            USING (chunking_profile_alias_id)
          JOIN pgcontext._collections AS collections USING (collection_id)
         WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
           AND jobs.attempt < 3
           AND generations.chunking_profile_id IN (
               aliases.chunking_profile_id,
               COALESCE(aliases.shadow_chunking_profile_id, aliases.chunking_profile_id)
           )
           AND (
               jobs.status = 'queued'
               OR (jobs.status IN ('leased','parsing','chunking','embedding','validating','publishing')
                   AND jobs.lease_expires_at <= pg_catalog.clock_timestamp())
           )
         ORDER BY jobs.updated_at, jobs.job_id
         LIMIT p_limit
         FOR SHARE OF sources, aliases
         FOR UPDATE OF jobs SKIP LOCKED
    ), claimed AS (
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = 'leased',
               attempt = jobs.attempt + 1,
               lease_worker = p_worker_id,
               lease_token = jobs.lease_token + 1,
               lease_expires_at = pg_catalog.clock_timestamp()
                   + pg_catalog.make_interval(secs => p_lease_millis::double precision / 1000.0),
               processed_units = 0,
               error_code = NULL,
               updated_at = pg_catalog.now()
          FROM candidates
         WHERE jobs.job_id = candidates.job_id
        RETURNING jobs.job_id, jobs.lease_token
    ), reset_generations AS (
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = 'leased'
          FROM pgcontext._document_chunk_jobs AS jobs, claimed
         WHERE jobs.job_id = claimed.job_id
           AND generations.generation_id = jobs.generation_id
        RETURNING claimed.job_id, claimed.lease_token
    )
    SELECT reset_generations.job_id, reset_generations.lease_token
      FROM reset_generations ORDER BY reset_generations.job_id;
END;
$$;
CREATE FUNCTION pgcontext._stage_document_chunk_response(
    p_job_id bigint,
    p_lease_token bigint,
    p_response_json jsonb,
    p_response_sha256 bytea,
    p_chunk_count int4,
    p_token_count bigint,
    p_staging_bytes bigint
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    job_row pgcontext._document_chunk_jobs%ROWTYPE;
    collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        1, p_job_id, p_lease_token
    );
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id
     FOR SHARE OF sources;
    SELECT * INTO job_row FROM pgcontext._document_chunk_jobs WHERE job_id = p_job_id FOR UPDATE;
    IF NOT FOUND OR job_row.lease_token <> p_lease_token
       OR job_row.lease_expires_at <= pg_catalog.clock_timestamp()
       OR job_row.status IN ('cancel_requested','cancelled','failed','superseded','retired','ready') THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    PERFORM pgcontext._require_collection_owner(collection_id);
    INSERT INTO pgcontext._document_chunk_staging (
        job_id, lease_token, response_json, response_sha256,
        chunk_count, token_count, staging_bytes
    ) VALUES (
        p_job_id, p_lease_token, p_response_json, p_response_sha256,
        p_chunk_count, p_token_count, p_staging_bytes
    )
    ON CONFLICT (job_id) DO UPDATE
       SET lease_token = EXCLUDED.lease_token,
           response_json = EXCLUDED.response_json,
           response_sha256 = EXCLUDED.response_sha256,
           chunk_count = EXCLUDED.chunk_count,
           token_count = EXCLUDED.token_count,
           staging_bytes = EXCLUDED.staging_bytes,
           staged_at = pg_catalog.now();
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'validating', processed_units = total_units, updated_at = pg_catalog.now()
     WHERE job_id = p_job_id;
    UPDATE pgcontext._document_chunk_generations AS generations
       SET status = 'validating'
      FROM pgcontext._document_chunk_jobs AS jobs
     WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
END;
$$;
CREATE FUNCTION pgcontext._complete_document_chunk_publication(
    p_job_id bigint,
    p_lease_token bigint,
    p_response_sha256 bytea,
    p_projection_sha256 bytea,
    p_chunk_count int4,
    p_token_count bigint,
    p_staging_bytes bigint
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    job_row pgcontext._document_chunk_jobs%ROWTYPE;
    generation_row pgcontext._document_chunk_generations%ROWTYPE;
    source_row pgcontext._document_sources%ROWTYPE;
    embedding_count bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        2, p_job_id, p_lease_token
    );
    SELECT sources.* INTO source_row
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id
     FOR SHARE OF sources;
    SELECT * INTO job_row FROM pgcontext._document_chunk_jobs
     WHERE job_id = p_job_id FOR UPDATE;
    IF FOUND AND job_row.lease_token = p_lease_token AND job_row.status = 'ready' THEN
        SELECT * INTO generation_row FROM pgcontext._document_chunk_generations
         WHERE generation_id = job_row.generation_id FOR UPDATE;
        IF generation_row.status = 'ready'
           AND generation_row.publication_sha256 = p_response_sha256
           AND generation_row.projection_sha256 = p_projection_sha256
           AND generation_row.chunk_count = p_chunk_count
           AND generation_row.token_count = p_token_count
           AND generation_row.staging_bytes = p_staging_bytes THEN
            RETURN generation_row.generation_id;
        END IF;
        RAISE EXCEPTION 'document chunk publication replay differs from ready generation'
            USING ERRCODE = '55000';
    END IF;
    IF NOT FOUND OR job_row.lease_token <> p_lease_token
       OR job_row.lease_expires_at <= pg_catalog.clock_timestamp()
       OR job_row.status NOT IN ('validating','publishing') THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    SELECT * INTO generation_row FROM pgcontext._document_chunk_generations
     WHERE generation_id = job_row.generation_id FOR UPDATE;
    PERFORM pgcontext._require_collection_owner(source_row.collection_id);
    IF source_row.registration_revision <> generation_row.source_registration_revision
       OR source_row.status <> 'ready' THEN
        RAISE EXCEPTION 'document source registration changed during chunking'
            USING ERRCODE = '55000';
    END IF;
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'publishing', updated_at = pg_catalog.now()
     WHERE job_id = p_job_id;
    UPDATE pgcontext._document_chunk_generations
       SET status = 'publishing'
     WHERE generation_id = generation_row.generation_id;
    INSERT INTO pgcontext._document_embedding_jobs (
        generation_id, occurrence_id, content_hash, embedding_profile_id,
        status, fake_embedding
    )
    SELECT generation_row.generation_id, chunk.occurrence_id,
           chunk.content_hash, 0, 'ready',
           pg_catalog.jsonb_build_array(
               ((chunk.content_hash & 65535)::double precision / 65535.0),
               (((chunk.content_hash >> 16) & 65535)::double precision / 65535.0),
               (((chunk.content_hash >> 32) & 65535)::double precision / 65535.0)
           )
      FROM pgcontext._document_chunk_staging AS staging,
           pg_catalog.jsonb_to_recordset(staging.response_json->'chunks') AS chunk(
               occurrence_id bigint, content_hash bigint
           )
     WHERE staging.job_id = p_job_id AND staging.lease_token = p_lease_token
    ON CONFLICT (generation_id, occurrence_id, embedding_profile_id) DO UPDATE
       SET status = 'ready', fake_embedding = EXCLUDED.fake_embedding
     WHERE pgcontext._document_embedding_jobs.content_hash = EXCLUDED.content_hash;
    GET DIAGNOSTICS embedding_count = ROW_COUNT;
    IF embedding_count <> p_chunk_count THEN
        RAISE EXCEPTION 'document embedding generation is incomplete'
            USING ERRCODE = '55000';
    END IF;
    INSERT INTO pgcontext._current_document_chunk_generations (
        document_source_id, source_key, chunking_profile_id, generation_id
    ) VALUES (
        generation_row.document_source_id, generation_row.source_key,
        generation_row.chunking_profile_id, generation_row.generation_id
    )
    ON CONFLICT (document_source_id, source_key, chunking_profile_id) DO UPDATE
       SET generation_id = EXCLUDED.generation_id,
           publication_revision =
               pgcontext._current_document_chunk_generations.publication_revision + 1,
           updated_at = pg_catalog.now();
    UPDATE pgcontext._document_chunk_generations
       SET status = 'retired'
     WHERE generation_id = generation_row.prior_generation_id
       AND status = 'ready';
    UPDATE pgcontext._document_chunk_jobs AS jobs
       SET status = 'retired', updated_at = pg_catalog.now()
      FROM pgcontext._document_chunk_generations AS generations
     WHERE jobs.generation_id = generations.generation_id
       AND generations.generation_id = generation_row.prior_generation_id
       AND generations.status = 'retired';
    UPDATE pgcontext._document_chunk_generations
       SET status = 'ready', chunk_count = p_chunk_count,
           token_count = p_token_count, staging_bytes = p_staging_bytes,
           publication_sha256 = p_response_sha256,
           projection_sha256 = p_projection_sha256,
           published_at = pg_catalog.now()
     WHERE generation_id = generation_row.generation_id;
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'ready', lease_worker = NULL, lease_expires_at = NULL,
           updated_at = pg_catalog.now()
     WHERE job_id = p_job_id;
    DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
    RETURN generation_row.generation_id;
END;
$$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_rollback_schema.rs:3
-- requires:
--   create_document_chunking_catalog_tables


CREATE FUNCTION pgcontext._rollback_document_chunk_generation(
    p_document_source_id bigint,
    p_source_key text,
    p_generation_id bigint
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_row record;
    target_row pgcontext._document_chunk_generations%ROWTYPE;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        6, p_document_source_id, p_generation_id
    );
    SELECT sources.*, aliases.chunking_profile_id AS current_profile_id
      INTO source_row
      FROM pgcontext._document_sources AS sources
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
     WHERE sources.document_source_id = p_document_source_id
       AND sources.status = 'ready' AND aliases.status = 'ready'
     FOR SHARE OF sources, aliases;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'document source does not exist or is not ready'
            USING ERRCODE = '42704';
    END IF;
    PERFORM pgcontext._require_collection_owner(source_row.collection_id);
    PERFORM 1
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
     WHERE generations.document_source_id = p_document_source_id
       AND generations.source_key = p_source_key
     ORDER BY jobs.job_id FOR UPDATE OF jobs;
    SELECT * INTO target_row FROM pgcontext._document_chunk_generations
     WHERE generation_id = p_generation_id
       AND document_source_id = p_document_source_id
       AND source_key = p_source_key
       AND chunking_profile_id = source_row.current_profile_id
       AND published_at IS NOT NULL
     FOR UPDATE;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'document chunk rollback generation is unavailable'
            USING ERRCODE = '42704';
    END IF;
    UPDATE pgcontext._document_chunk_generations AS generations
       SET status = 'retired'
     WHERE generations.generation_id IN (
        SELECT aliases.generation_id
          FROM pgcontext._current_document_chunk_generations AS aliases
         WHERE aliases.document_source_id = p_document_source_id
           AND aliases.source_key = p_source_key
           AND aliases.chunking_profile_id = target_row.chunking_profile_id
     )
       AND generations.generation_id <> p_generation_id
       AND generations.status = 'ready';
    UPDATE pgcontext._document_chunk_jobs AS jobs
       SET status = 'retired', updated_at = pg_catalog.now()
      FROM pgcontext._document_chunk_generations AS generations
     WHERE jobs.generation_id = generations.generation_id
       AND generations.document_source_id = p_document_source_id
       AND generations.source_key = p_source_key
       AND generations.chunking_profile_id = target_row.chunking_profile_id
       AND generations.status = 'retired'
       AND generations.generation_id <> p_generation_id;
    UPDATE pgcontext._document_chunk_generations
       SET status = 'ready' WHERE generation_id = p_generation_id;
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'ready', updated_at = pg_catalog.now()
     WHERE generation_id = p_generation_id;
    INSERT INTO pgcontext._current_document_chunk_generations (
        document_source_id, source_key, chunking_profile_id, generation_id
    ) VALUES (
        p_document_source_id, p_source_key, target_row.chunking_profile_id,
        p_generation_id
    )
    ON CONFLICT (document_source_id, source_key, chunking_profile_id) DO UPDATE
       SET generation_id = EXCLUDED.generation_id,
           publication_revision =
               pgcontext._current_document_chunk_generations.publication_revision + 1,
           updated_at = pg_catalog.clock_timestamp();
    RETURN p_generation_id;
END;
$$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_profile_state_schema.rs:3
-- requires:
--   create_document_chunking_catalog_tables


CREATE TABLE pgcontext._chunking_profile_alias_retained (
    chunking_profile_alias_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profile_aliases(chunking_profile_alias_id)
        ON DELETE CASCADE,
    chunking_profile_id bigint NOT NULL
        REFERENCES pgcontext._chunking_profiles(chunking_profile_id),
    retained_revision bigint NOT NULL CHECK (retained_revision > 0),
    retained_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    PRIMARY KEY (chunking_profile_alias_id, chunking_profile_id)
);
REVOKE ALL ON TABLE pgcontext._chunking_profile_alias_retained FROM PUBLIC;
CREATE VIEW pgcontext._visible_chunking_profile_alias_retained
WITH (security_barrier = true) AS
SELECT retained.*
  FROM pgcontext._chunking_profile_alias_retained AS retained
  JOIN pgcontext._chunking_profile_aliases AS aliases USING (chunking_profile_alias_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, aliases.owner_role, 'MEMBER');
GRANT SELECT ON pgcontext._visible_chunking_profile_alias_retained TO PUBLIC;
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._chunking_profile_alias_retained', ''
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_profile_schema.rs:3
-- requires:
--   create_document_chunking_profile_state


CREATE FUNCTION pgcontext._register_chunking_profile(
    p_profile_name text,
    p_parser_revision text,
    p_target_tokens int4,
    p_max_tokens int4,
    p_min_tokens int4,
    p_overlap_tokens int4,
    p_max_document_bytes bigint,
    p_include_structure_context boolean,
    p_configuration_sha256 bytea
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    existing pgcontext._chunking_profiles%ROWTYPE;
    profile_id bigint;
    alias_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(3, 0, 0);
    PERFORM pg_catalog.pg_advisory_xact_lock(pg_catalog.hashtextextended(
        SESSION_USER::text || E'\x1fprofile\x1f' || p_profile_name, 0
    ));
    SELECT * INTO existing
      FROM pgcontext._chunking_profiles
     WHERE owner_role = SESSION_USER::pg_catalog.regrole::oid
       AND profile_name = p_profile_name;
    IF FOUND THEN
        IF existing.parser_revision = p_parser_revision
           AND existing.target_tokens = p_target_tokens
           AND existing.max_tokens = p_max_tokens
           AND existing.min_tokens = p_min_tokens
           AND existing.overlap_tokens = p_overlap_tokens
           AND existing.max_document_bytes = p_max_document_bytes
           AND existing.include_structure_context = p_include_structure_context
           AND existing.configuration_sha256 = p_configuration_sha256
           AND existing.status = 'ready' THEN
            profile_id := existing.chunking_profile_id;
        ELSE
            RAISE EXCEPTION 'chunking profile name already identifies a different immutable contract'
                USING ERRCODE = '42710';
        END IF;
    ELSE
        INSERT INTO pgcontext._chunking_profiles (
            owner_role, profile_name, parser_revision, target_tokens, max_tokens,
            min_tokens, overlap_tokens, max_document_bytes,
            include_structure_context, configuration_sha256
        ) VALUES (
            SESSION_USER::pg_catalog.regrole::oid, p_profile_name, p_parser_revision,
            p_target_tokens, p_max_tokens, p_min_tokens, p_overlap_tokens,
            p_max_document_bytes, p_include_structure_context, p_configuration_sha256
        ) RETURNING chunking_profile_id INTO profile_id;
        UPDATE pgcontext._chunking_profiles
           SET profile_revision = profile_id
         WHERE chunking_profile_id = profile_id;
    END IF;
    INSERT INTO pgcontext._chunking_profile_aliases (
        owner_role, alias_name, chunking_profile_id
    ) VALUES (
        SESSION_USER::pg_catalog.regrole::oid, p_profile_name, profile_id
    )
    ON CONFLICT (owner_role, alias_name) DO NOTHING
    RETURNING chunking_profile_alias_id INTO alias_id;
    IF alias_id IS NULL THEN
        SELECT aliases.chunking_profile_alias_id INTO alias_id
          FROM pgcontext._chunking_profile_aliases AS aliases
         WHERE aliases.owner_role = SESSION_USER::pg_catalog.regrole::oid
           AND aliases.alias_name = p_profile_name;
    END IF;
    INSERT INTO pgcontext._chunking_profile_alias_history (
        chunking_profile_alias_id, alias_revision, chunking_profile_id
    ) VALUES (alias_id, 1, profile_id)
    ON CONFLICT DO NOTHING;
    RETURN profile_id;
END;
$$;

CREATE FUNCTION pgcontext._promote_chunking_profile_alias(
    p_alias_id bigint,
    p_profile_id bigint
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    alias_row pgcontext._chunking_profile_aliases%ROWTYPE;
    next_revision bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(20, p_alias_id, p_profile_id);
    SELECT * INTO alias_row FROM pgcontext._chunking_profile_aliases
     WHERE chunking_profile_alias_id = p_alias_id FOR UPDATE;
    IF NOT FOUND OR NOT pg_catalog.pg_has_role(SESSION_USER, alias_row.owner_role, 'MEMBER')
       OR NOT EXISTS (
           SELECT 1 FROM pgcontext._chunking_profiles AS profiles
            WHERE profiles.chunking_profile_id = p_profile_id
              AND profiles.status = 'ready'
              AND pg_catalog.pg_has_role(SESSION_USER, profiles.owner_role, 'MEMBER')
       ) THEN
        RAISE EXCEPTION 'chunking profile alias or target is unavailable'
            USING ERRCODE = '42704';
    END IF;
    IF alias_row.chunking_profile_id = p_profile_id THEN
        RETURN alias_row.alias_revision;
    END IF;
    IF alias_row.shadow_chunking_profile_id IS DISTINCT FROM p_profile_id THEN
        RAISE EXCEPTION 'chunking profile target is not prepared as shadow'
            USING ERRCODE = '55000';
    END IF;
    next_revision := alias_row.alias_revision + 1;
    IF NOT EXISTS (
           SELECT 1 FROM pgcontext._chunking_profile_alias_retained
            WHERE chunking_profile_alias_id = p_alias_id
              AND chunking_profile_id = alias_row.chunking_profile_id
       ) AND (SELECT pg_catalog.count(*)
                FROM pgcontext._chunking_profile_alias_retained
               WHERE chunking_profile_alias_id = p_alias_id
                 AND chunking_profile_id <> p_profile_id) >= 8 THEN
        RAISE EXCEPTION 'chunking profile alias retained-profile limit reached'
            USING ERRCODE = '54000';
    END IF;
    INSERT INTO pgcontext._chunking_profile_alias_retained (
        chunking_profile_alias_id, chunking_profile_id, retained_revision
    ) VALUES (p_alias_id, alias_row.chunking_profile_id, next_revision)
    ON CONFLICT (chunking_profile_alias_id, chunking_profile_id) DO UPDATE
       SET retained_revision = EXCLUDED.retained_revision,
           retained_at = pg_catalog.now();
    DELETE FROM pgcontext._chunking_profile_alias_retained
     WHERE chunking_profile_alias_id = p_alias_id
       AND chunking_profile_id = p_profile_id;
    UPDATE pgcontext._chunking_profile_aliases
       SET chunking_profile_id = p_profile_id,
           shadow_chunking_profile_id = NULL,
           alias_revision = next_revision,
           updated_at = pg_catalog.now()
     WHERE chunking_profile_alias_id = p_alias_id;
    INSERT INTO pgcontext._chunking_profile_alias_history (
        chunking_profile_alias_id, alias_revision, chunking_profile_id
    ) VALUES (p_alias_id, next_revision, p_profile_id);
    RETURN next_revision;
END;
$$;

CREATE FUNCTION pgcontext._rollback_chunking_profile_alias(p_alias_id bigint)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    alias_row pgcontext._chunking_profile_aliases%ROWTYPE;
    target_profile_id bigint;
    next_revision bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(21, p_alias_id, 0);
    SELECT * INTO alias_row FROM pgcontext._chunking_profile_aliases
     WHERE chunking_profile_alias_id = p_alias_id FOR UPDATE;
    IF NOT FOUND OR NOT pg_catalog.pg_has_role(SESSION_USER, alias_row.owner_role, 'MEMBER') THEN
        RAISE EXCEPTION 'chunking profile alias is unavailable' USING ERRCODE = '42704';
    END IF;
    SELECT retained.chunking_profile_id INTO target_profile_id
      FROM pgcontext._chunking_profile_alias_retained AS retained
     WHERE retained.chunking_profile_alias_id = p_alias_id
     ORDER BY retained.retained_revision DESC LIMIT 1;
    IF target_profile_id IS NULL THEN
        RAISE EXCEPTION 'chunking profile alias has no rollback target'
            USING ERRCODE = '55000';
    END IF;
    next_revision := alias_row.alias_revision + 1;
    INSERT INTO pgcontext._chunking_profile_alias_retained (
        chunking_profile_alias_id, chunking_profile_id, retained_revision
    ) VALUES (p_alias_id, alias_row.chunking_profile_id, next_revision)
    ON CONFLICT (chunking_profile_alias_id, chunking_profile_id) DO UPDATE
       SET retained_revision = EXCLUDED.retained_revision,
           retained_at = pg_catalog.now();
    DELETE FROM pgcontext._chunking_profile_alias_retained
     WHERE chunking_profile_alias_id = p_alias_id
       AND chunking_profile_id = target_profile_id;
    UPDATE pgcontext._chunking_profile_aliases
       SET chunking_profile_id = target_profile_id,
           shadow_chunking_profile_id = NULL,
           alias_revision = next_revision,
           updated_at = pg_catalog.now()
     WHERE chunking_profile_alias_id = p_alias_id;
    INSERT INTO pgcontext._chunking_profile_alias_history (
        chunking_profile_alias_id, alias_revision, chunking_profile_id
    ) VALUES (p_alias_id, next_revision, target_profile_id);
    RETURN next_revision;
END;
$$;

CREATE FUNCTION pgcontext._prepare_chunking_profile_alias(
    p_alias_id bigint,
    p_profile_id bigint
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE alias_row pgcontext._chunking_profile_aliases%ROWTYPE;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(22, p_alias_id, p_profile_id);
    SELECT * INTO alias_row FROM pgcontext._chunking_profile_aliases
     WHERE chunking_profile_alias_id = p_alias_id FOR UPDATE;
    IF NOT FOUND OR NOT pg_catalog.pg_has_role(SESSION_USER, alias_row.owner_role, 'MEMBER')
       OR NOT EXISTS (
           SELECT 1 FROM pgcontext._chunking_profiles AS profiles
            WHERE profiles.chunking_profile_id = p_profile_id
              AND profiles.owner_role = alias_row.owner_role
              AND profiles.status = 'ready'
       ) THEN
        RAISE EXCEPTION 'chunking profile alias or shadow target is unavailable'
            USING ERRCODE = '42704';
    END IF;
    IF p_profile_id = alias_row.chunking_profile_id THEN
        RAISE EXCEPTION 'chunking profile shadow must differ from current target'
            USING ERRCODE = '22023';
    END IF;
    UPDATE pgcontext._chunking_profile_aliases
       SET shadow_chunking_profile_id = p_profile_id, updated_at = pg_catalog.now()
     WHERE chunking_profile_alias_id = p_alias_id;
    RETURN alias_row.alias_revision;
END;
$$;

CREATE FUNCTION pgcontext._drain_chunking_profile_alias(
    p_alias_id bigint,
    p_profile_id bigint
)
RETURNS boolean
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE alias_row pgcontext._chunking_profile_aliases%ROWTYPE;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(23, p_alias_id, p_profile_id);
    SELECT * INTO alias_row FROM pgcontext._chunking_profile_aliases
     WHERE chunking_profile_alias_id = p_alias_id FOR UPDATE;
    IF NOT FOUND OR NOT pg_catalog.pg_has_role(SESSION_USER, alias_row.owner_role, 'MEMBER') THEN
        RAISE EXCEPTION 'chunking profile alias is unavailable' USING ERRCODE = '42704';
    END IF;
    IF p_profile_id IN (
        alias_row.chunking_profile_id,
        COALESCE(alias_row.shadow_chunking_profile_id, alias_row.chunking_profile_id)
    ) THEN
        RAISE EXCEPTION 'current or prepared chunking profile cannot be drained'
            USING ERRCODE = '55000';
    END IF;
    DELETE FROM pgcontext._chunking_profile_alias_retained
     WHERE chunking_profile_alias_id = p_alias_id
       AND chunking_profile_id = p_profile_id;
    IF NOT FOUND THEN
        RAISE EXCEPTION 'chunking profile is not retained by this alias'
            USING ERRCODE = '55000';
    END IF;
    RETURN true;
END;
$$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_outbox_schema.rs:3
-- requires:
--   create_document_chunking_profile_state


CREATE FUNCTION pgcontext._document_chunk_outbox_trigger()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_row record;
    v_source_key text;
    old_source_key text;
    new_source_key text;
    v_source_version bigint;
    source_text text;
    source_text_bytes bigint;
    source_digest bytea;
    prior_id bigint;
    v_generation_id bigint;
BEGIN
    SELECT sources.*, aliases.chunking_profile_id AS current_profile_id,
           aliases.shadow_chunking_profile_id,
           rerank.source_table_oid, rerank.text_column_name,
           rerank.source_version_column_name, profiles.max_document_bytes
      INTO source_row
      FROM pgcontext._document_sources AS sources
      JOIN pgcontext._semantic_rerank_sources AS rerank USING (rerank_source_id)
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
      JOIN pgcontext._chunking_profiles AS profiles
        ON profiles.chunking_profile_id = aliases.chunking_profile_id
     WHERE sources.document_source_id = TG_ARGV[0]::bigint
       AND sources.status = 'ready' AND rerank.status = 'ready'
     FOR SHARE OF sources, aliases;
    IF NOT FOUND OR source_row.source_table_oid <> TG_RELID THEN
        RAISE EXCEPTION 'document chunk outbox source identity changed'
            USING ERRCODE = '55000';
    END IF;
    IF TG_OP <> 'INSERT' THEN old_source_key := OLD.id::text; END IF;
    IF TG_OP <> 'DELETE' THEN new_source_key := NEW.id::text; END IF;
    IF TG_OP = 'UPDATE' AND old_source_key IS DISTINCT FROM new_source_key THEN
        v_source_key := old_source_key;
        UPDATE pgcontext._document_chunk_generations SET status = 'retired'
         WHERE generation_id IN (
             SELECT generation_id FROM pgcontext._current_document_chunk_generations
              WHERE document_source_id = source_row.document_source_id
                AND source_key = v_source_key
                AND chunking_profile_id IN (
                    SELECT source_row.current_profile_id
                    UNION ALL
                    SELECT retained.chunking_profile_id
                      FROM pgcontext._chunking_profile_alias_retained AS retained
                     WHERE retained.chunking_profile_alias_id =
                           source_row.chunking_profile_alias_id
                )
         );
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = 'retired',
               lease_worker = NULL, lease_expires_at = NULL, updated_at = pg_catalog.now()
          FROM pgcontext._document_chunk_generations AS generations
         WHERE jobs.generation_id = generations.generation_id
           AND generations.document_source_id = source_row.document_source_id
           AND generations.source_key = v_source_key
           AND generations.status = 'retired';
        WITH target_jobs AS (
            SELECT jobs.job_id, jobs.generation_id
              FROM pgcontext._document_chunk_jobs AS jobs
              JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
             WHERE generations.document_source_id = source_row.document_source_id
               AND generations.source_key = v_source_key
               AND generations.chunking_profile_id IN (
                   source_row.current_profile_id,
                   COALESCE(source_row.shadow_chunking_profile_id,
                            source_row.current_profile_id)
               )
               AND jobs.status IN (
                   'queued','leased','parsing','chunking','embedding','validating',
                   'publishing','cancel_requested'
               )
             ORDER BY jobs.job_id LIMIT 256 FOR UPDATE OF jobs
        ), updated_jobs AS (
            UPDATE pgcontext._document_chunk_jobs AS jobs
               SET status = 'superseded', lease_worker = NULL,
                   lease_expires_at = NULL, updated_at = pg_catalog.now()
              FROM target_jobs
             WHERE jobs.job_id = target_jobs.job_id
            RETURNING jobs.job_id, jobs.generation_id
        ), updated_generations AS (
            UPDATE pgcontext._document_chunk_generations AS generations
               SET status = 'superseded'
              FROM updated_jobs
             WHERE generations.generation_id = updated_jobs.generation_id
            RETURNING updated_jobs.job_id
        )
        DELETE FROM pgcontext._document_chunk_staging AS staging
         USING updated_generations
         WHERE staging.job_id = updated_generations.job_id;
        DELETE FROM pgcontext._current_document_chunk_generations
         WHERE document_source_id = source_row.document_source_id
           AND source_key = v_source_key
           AND chunking_profile_id IN (
               SELECT source_row.current_profile_id
               UNION ALL
               SELECT retained.chunking_profile_id
                 FROM pgcontext._chunking_profile_alias_retained AS retained
                WHERE retained.chunking_profile_alias_id =
                      source_row.chunking_profile_alias_id
           );
    END IF;
    IF TG_OP = 'DELETE' THEN
        v_source_key := old_source_key;
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = 'retired'
         WHERE generations.generation_id IN (
            SELECT aliases.generation_id
              FROM pgcontext._current_document_chunk_generations AS aliases
             WHERE aliases.document_source_id = source_row.document_source_id
               AND aliases.source_key = v_source_key
               AND aliases.chunking_profile_id IN (
                   SELECT source_row.current_profile_id
                   UNION ALL
                   SELECT retained.chunking_profile_id
                     FROM pgcontext._chunking_profile_alias_retained AS retained
                    WHERE retained.chunking_profile_alias_id =
                          source_row.chunking_profile_alias_id
               )
         );
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = 'retired', lease_worker = NULL, lease_expires_at = NULL,
               updated_at = pg_catalog.now()
          FROM pgcontext._document_chunk_generations AS generations
         WHERE jobs.generation_id = generations.generation_id
           AND generations.document_source_id = source_row.document_source_id
           AND generations.source_key = v_source_key
           AND generations.status = 'retired';
        DELETE FROM pgcontext._current_document_chunk_generations
         WHERE document_source_id = source_row.document_source_id
           AND pgcontext._current_document_chunk_generations.source_key = v_source_key
           AND chunking_profile_id IN (
               SELECT source_row.current_profile_id
               UNION ALL
               SELECT retained.chunking_profile_id
                 FROM pgcontext._chunking_profile_alias_retained AS retained
                WHERE retained.chunking_profile_alias_id =
                      source_row.chunking_profile_alias_id
           );
        WITH target_jobs AS (
            SELECT jobs.job_id, jobs.generation_id
              FROM pgcontext._document_chunk_jobs AS jobs
              JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
             WHERE generations.document_source_id = source_row.document_source_id
               AND generations.source_key = v_source_key
               AND generations.chunking_profile_id IN (
                   source_row.current_profile_id,
                   COALESCE(source_row.shadow_chunking_profile_id,
                            source_row.current_profile_id)
               )
               AND jobs.status IN (
                   'queued','leased','parsing','chunking','embedding','validating',
                   'publishing','cancel_requested'
               )
             ORDER BY jobs.job_id LIMIT 256 FOR UPDATE OF jobs
        ), updated_jobs AS (
            UPDATE pgcontext._document_chunk_jobs AS jobs
               SET status = 'superseded', lease_worker = NULL,
                   lease_expires_at = NULL, updated_at = pg_catalog.now()
              FROM target_jobs
             WHERE jobs.job_id = target_jobs.job_id
            RETURNING jobs.job_id, jobs.generation_id
        ), updated_generations AS (
            UPDATE pgcontext._document_chunk_generations AS generations
               SET status = 'superseded'
              FROM updated_jobs
             WHERE generations.generation_id = updated_jobs.generation_id
            RETURNING updated_jobs.job_id
        )
        DELETE FROM pgcontext._document_chunk_staging AS staging
         USING updated_generations
         WHERE staging.job_id = updated_generations.job_id;
        RETURN OLD;
    END IF;
    v_source_key := new_source_key;
    EXECUTE pg_catalog.format(
        'SELECT pg_catalog.octet_length(($1).%1$I), (($1).%2$I)::bigint',
        source_row.text_column_name, source_row.source_version_column_name
    ) INTO source_text_bytes, v_source_version USING NEW;
    IF source_text_bytes IS NULL OR source_text_bytes > source_row.max_document_bytes THEN
        RAISE EXCEPTION 'document source text exceeds the registered profile byte limit'
            USING ERRCODE = '54000';
    END IF;
    EXECUTE pg_catalog.format('SELECT (($1).%I)::text', source_row.text_column_name)
       INTO source_text USING NEW;
    IF v_source_key IS NULL OR source_text IS NULL OR v_source_version IS NULL
       OR v_source_version <= 0 THEN
        RAISE EXCEPTION 'document chunk outbox source row is invalid'
            USING ERRCODE = '22023';
    END IF;
    source_digest := pg_catalog.sha256(pg_catalog.convert_to(source_text, 'UTF8'));
    SELECT aliases.generation_id INTO prior_id
      FROM pgcontext._current_document_chunk_generations AS aliases
     WHERE aliases.document_source_id = source_row.document_source_id
       AND aliases.source_key = v_source_key
       AND aliases.chunking_profile_id = source_row.current_profile_id;
    WITH target_jobs AS (
        SELECT jobs.job_id, jobs.generation_id
          FROM pgcontext._document_chunk_jobs AS jobs
          JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
         WHERE generations.document_source_id = source_row.document_source_id
           AND generations.source_key = v_source_key
           AND generations.chunking_profile_id = source_row.current_profile_id
           AND generations.source_version < v_source_version
           AND jobs.status IN (
               'queued','leased','parsing','chunking','embedding','validating',
               'publishing','cancel_requested'
           )
         ORDER BY jobs.job_id LIMIT 256 FOR UPDATE OF jobs
    ), updated_jobs AS (
        UPDATE pgcontext._document_chunk_jobs AS jobs
           SET status = 'superseded', lease_worker = NULL,
               lease_expires_at = NULL, updated_at = pg_catalog.now()
          FROM target_jobs
         WHERE jobs.job_id = target_jobs.job_id
        RETURNING jobs.job_id, jobs.generation_id
    ), updated_generations AS (
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = 'superseded'
          FROM updated_jobs
         WHERE generations.generation_id = updated_jobs.generation_id
        RETURNING updated_jobs.job_id
    )
    DELETE FROM pgcontext._document_chunk_staging AS staging
     USING updated_generations
     WHERE staging.job_id = updated_generations.job_id;
    INSERT INTO pgcontext._document_chunk_generations (
        document_source_id, source_key, source_version, source_sha256,
        chunking_profile_id, source_registration_revision, prior_generation_id
    ) VALUES (
        source_row.document_source_id, v_source_key, v_source_version, source_digest,
        source_row.current_profile_id, source_row.registration_revision, prior_id
    )
    ON CONFLICT (
        document_source_id, source_key, source_version, chunking_profile_id,
        source_registration_revision
    )
    DO UPDATE SET source_sha256 = pgcontext._document_chunk_generations.source_sha256
      WHERE pgcontext._document_chunk_generations.source_sha256 = EXCLUDED.source_sha256
        AND pgcontext._document_chunk_generations.source_registration_revision =
            EXCLUDED.source_registration_revision
    RETURNING generation_id INTO v_generation_id;
    IF v_generation_id IS NULL THEN
        RAISE EXCEPTION 'document source version identity changed'
            USING ERRCODE = '55000';
    END IF;
    INSERT INTO pgcontext._document_chunk_jobs (generation_id)
    VALUES (v_generation_id)
    ON CONFLICT (generation_id) DO NOTHING;
    RETURN NEW;
END;
$$;

CREATE FUNCTION pgcontext._install_document_chunk_outbox_trigger(p_document_source_id bigint)
RETURNS text
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_row record;
    trigger_name text;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(13, p_document_source_id, 0);
    SELECT sources.collection_id, rerank.source_schema_name, rerank.source_table_name,
           rerank.text_column_name, rerank.source_version_column_name
      INTO source_row
      FROM pgcontext._document_sources AS sources
      JOIN pgcontext._semantic_rerank_sources AS rerank USING (rerank_source_id)
     WHERE sources.document_source_id = p_document_source_id
       AND sources.status = 'ready' AND rerank.status = 'ready';
    IF NOT FOUND THEN
        RAISE EXCEPTION 'document source does not exist or is not ready'
            USING ERRCODE = '42704';
    END IF;
    PERFORM pgcontext._require_collection_owner(source_row.collection_id);
    trigger_name := pg_catalog.format('pgcontext_document_chunk_outbox_%s', p_document_source_id);
    EXECUTE pg_catalog.format(
        'DROP TRIGGER IF EXISTS %I ON %I.%I',
        trigger_name, source_row.source_schema_name, source_row.source_table_name
    );
    EXECUTE pg_catalog.format(
        'CREATE TRIGGER %I AFTER INSERT OR DELETE OR UPDATE OF id, %I, %I ON %I.%I
         FOR EACH ROW EXECUTE FUNCTION pgcontext._document_chunk_outbox_trigger(%L)',
        trigger_name, source_row.text_column_name, source_row.source_version_column_name,
        source_row.source_schema_name, source_row.source_table_name,
        p_document_source_id::text
    );
    RETURN trigger_name;
END;
$$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_dump_schema.rs:3
-- requires:
--   create_document_chunking_catalog_tables


CREATE INDEX _document_chunk_jobs_claimable_idx
    ON pgcontext._document_chunk_jobs (updated_at, job_id)
    WHERE status IN (
        'queued','leased','parsing','chunking','embedding','validating',
        'publishing','cancel_requested'
    );
CREATE INDEX _document_chunk_generations_lifecycle_idx
    ON pgcontext._document_chunk_generations (
        document_source_id, source_key, chunking_profile_id, status, generation_id
    );
SELECT pg_catalog.pg_extension_config_dump('pgcontext._chunking_profiles', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._chunking_profiles_chunking_profile_id_seq', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._chunking_profile_aliases', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._chunking_profile_aliases_chunking_profile_alias_id_seq', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._chunking_profile_alias_history', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._document_sources', '');
SELECT pg_catalog.pg_extension_config_dump('pgcontext._document_sources_document_source_id_seq', '');
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking_lifecycle_schema.rs:3
-- requires:
--   create_document_chunking_catalog_tables
--   create_document_chunking_profile_state


CREATE FUNCTION pgcontext._load_document_chunk_staging(
    p_job_id bigint, p_lease_token bigint
)
RETURNS TABLE(
    response_json jsonb, response_sha256 bytea, chunk_count int4,
    token_count bigint, staging_bytes bigint
)
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(5, p_job_id, p_lease_token);
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token;
    PERFORM pgcontext._require_collection_owner(collection_id);
    RETURN QUERY
    SELECT staging.response_json, staging.response_sha256, staging.chunk_count,
           staging.token_count, staging.staging_bytes
      FROM pgcontext._document_chunk_staging AS staging
     WHERE staging.job_id = p_job_id AND staging.lease_token = p_lease_token;
END;
$$;

CREATE FUNCTION pgcontext._invalidate_document_chunk_aliases(
    p_document_source_id bigint, p_source_keys text[]
)
RETURNS bigint
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint; deleted bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        17, p_document_source_id, pg_catalog.cardinality(p_source_keys)
    );
    SELECT sources.collection_id INTO collection_id FROM pgcontext._document_sources AS sources
     WHERE sources.document_source_id = p_document_source_id FOR SHARE;
    PERFORM pgcontext._require_collection_owner(collection_id);
    PERFORM 1
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
     WHERE generations.document_source_id = p_document_source_id
       AND generations.source_key = ANY(p_source_keys)
     ORDER BY jobs.job_id FOR UPDATE OF jobs;
    UPDATE pgcontext._document_chunk_generations AS generations SET status = 'retired'
     WHERE generations.generation_id IN (
        SELECT aliases.generation_id FROM pgcontext._current_document_chunk_generations AS aliases
         WHERE aliases.document_source_id = p_document_source_id
           AND aliases.source_key = ANY(p_source_keys));
    GET DIAGNOSTICS deleted = ROW_COUNT;
    UPDATE pgcontext._document_chunk_jobs AS jobs
       SET status = 'retired', lease_worker = NULL, lease_expires_at = NULL,
           updated_at = pg_catalog.now()
      FROM pgcontext._document_chunk_generations AS generations
     WHERE jobs.generation_id = generations.generation_id
       AND generations.document_source_id = p_document_source_id
       AND generations.source_key = ANY(p_source_keys) AND generations.status = 'retired';
    UPDATE pgcontext._document_chunk_generations SET status = 'superseded'
     WHERE document_source_id = p_document_source_id AND source_key = ANY(p_source_keys)
       AND status NOT IN ('ready','retired','superseded');
    UPDATE pgcontext._document_chunk_jobs AS jobs
       SET status = 'superseded', lease_worker = NULL, lease_expires_at = NULL,
           updated_at = pg_catalog.now()
      FROM pgcontext._document_chunk_generations AS generations
     WHERE jobs.generation_id = generations.generation_id
       AND generations.document_source_id = p_document_source_id
       AND generations.source_key = ANY(p_source_keys) AND generations.status = 'superseded'
       AND jobs.status NOT IN ('ready','retired','superseded');
    DELETE FROM pgcontext._document_chunk_staging AS staging
     USING pgcontext._document_chunk_jobs AS jobs,
           pgcontext._document_chunk_generations AS generations
     WHERE staging.job_id = jobs.job_id AND jobs.generation_id = generations.generation_id
       AND generations.document_source_id = p_document_source_id
       AND generations.source_key = ANY(p_source_keys);
    DELETE FROM pgcontext._current_document_chunk_generations
     WHERE document_source_id = p_document_source_id AND source_key = ANY(p_source_keys);
    RETURN deleted;
END;
$$;

CREATE FUNCTION pgcontext._release_document_chunk_claim(
    p_job_id bigint, p_lease_token bigint
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(8, p_job_id, p_lease_token);
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'queued', attempt = GREATEST(attempt - 1, 0),
           lease_worker = NULL, lease_expires_at = NULL,
           updated_at = pg_catalog.clock_timestamp()
     WHERE job_id = p_job_id AND lease_token = p_lease_token
       AND status IN ('leased','parsing','chunking','embedding','validating','publishing');
    IF FOUND THEN
        DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
        UPDATE pgcontext._document_chunk_generations AS generations SET status = 'queued'
          FROM pgcontext._document_chunk_jobs AS jobs
         WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
        RETURN true;
    END IF;
    RETURN false;
END;
$$;

CREATE FUNCTION pgcontext._load_document_chunk_lease_expiry(
    p_job_id bigint, p_lease_token bigint
)
RETURNS bigint
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint; expires_micros bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(10, p_job_id, p_lease_token);
    SELECT sources.collection_id,
           COALESCE(
               pg_catalog.floor(pg_catalog.extract('epoch', jobs.lease_expires_at) * 1000000)::bigint,
               9223372036854775807::bigint
           )
      INTO collection_id, expires_micros
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND (jobs.lease_expires_at > pg_catalog.clock_timestamp() OR jobs.status = 'ready');
    IF expires_micros IS NULL THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    PERFORM pgcontext._require_collection_owner(collection_id);
    RETURN expires_micros;
END;
$$;

CREATE FUNCTION pgcontext._load_document_chunk_claim_source(
    p_job_id bigint, p_lease_token bigint
)
RETURNS TABLE(document_source_id bigint, source_table_oid oid, source_key text)
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(24, p_job_id, p_lease_token);
    SELECT sources.collection_id
      INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
      JOIN pgcontext._semantic_rerank_sources AS rerank USING (rerank_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND jobs.lease_expires_at > pg_catalog.clock_timestamp()
       AND jobs.status IN ('leased','parsing','chunking','embedding','validating','publishing');
    IF collection_id IS NULL THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    PERFORM pgcontext._require_collection_owner(collection_id);
    RETURN QUERY
    SELECT generations.document_source_id, rerank.source_table_oid,
           generations.source_key
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
      JOIN pgcontext._semantic_rerank_sources AS rerank USING (rerank_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND jobs.lease_expires_at > pg_catalog.clock_timestamp()
       AND jobs.status IN ('leased','parsing','chunking','embedding','validating','publishing');
END;
$$;

CREATE FUNCTION pgcontext._lock_document_chunk_source(
    p_document_source_id bigint, p_source_key text,
    p_source_version bigint, p_source_bytes bigint,
    p_max_document_bytes bigint
)
RETURNS bytea
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    source_schema text;
    source_table text;
    source_key_column text;
    source_key_type_schema text;
    source_key_type_name text;
    source_text_column text;
    source_version_column text;
    locked_version bigint;
    locked_bytes bigint;
    locked_sha256 bytea;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        25, p_document_source_id, p_source_version
    );
    SELECT rerank.source_schema_name, rerank.source_table_name,
           key_attribute.attname, rerank.source_key_type_schema,
           rerank.source_key_type_name, rerank.text_column_name,
           rerank.source_version_column_name
      INTO source_schema, source_table, source_key_column,
           source_key_type_schema, source_key_type_name,
           source_text_column, source_version_column
      FROM pgcontext._document_sources AS sources
      JOIN pgcontext._semantic_rerank_sources AS rerank USING (rerank_source_id)
      JOIN pg_catalog.pg_attribute AS key_attribute
        ON key_attribute.attrelid = rerank.source_table_oid
       AND key_attribute.attnum = rerank.source_key_attnum
       AND NOT key_attribute.attisdropped
     WHERE sources.document_source_id = p_document_source_id
       AND sources.status = 'ready' AND rerank.status = 'ready';
    IF source_key_column IS NULL THEN
        RETURN NULL;
    END IF;
    IF p_max_document_bytes NOT BETWEEN 1 AND 8388608
       OR p_source_bytes NOT BETWEEN 0 AND p_max_document_bytes THEN
        RETURN NULL;
    END IF;
    EXECUTE pg_catalog.format(
        'SELECT source.%1$I, pg_catalog.octet_length(source.%2$I)::bigint
           FROM %3$I.%4$I AS source
          WHERE source.%5$I = $1::text::%6$I.%7$I
          FOR SHARE OF source',
        source_version_column, source_text_column, source_schema, source_table,
        source_key_column, source_key_type_schema, source_key_type_name
    )
    INTO locked_version, locked_bytes
    USING p_source_key;
    IF locked_version IS DISTINCT FROM p_source_version
       OR locked_bytes IS DISTINCT FROM p_source_bytes
       OR locked_bytes > p_max_document_bytes THEN
        RETURN NULL;
    END IF;
    EXECUTE pg_catalog.format(
        'SELECT pg_catalog.sha256(
                    pg_catalog.convert_to(source.%1$I, ''UTF8'')
                )
           FROM %2$I.%3$I AS source
          WHERE source.%4$I = $1::text::%5$I.%6$I',
        source_text_column, source_schema, source_table, source_key_column,
        source_key_type_schema, source_key_type_name
    )
    INTO locked_sha256
    USING p_source_key;
    RETURN locked_sha256;
END;
$$;

CREATE FUNCTION pgcontext._lock_document_chunk_job_alias(
    p_job_id bigint, p_lease_token bigint, p_allow_ready_retained boolean
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint; alias_matches boolean;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(26, p_job_id, p_lease_token);
    SELECT sources.collection_id,
           generations.chunking_profile_id IN (
               aliases.chunking_profile_id,
               COALESCE(aliases.shadow_chunking_profile_id, aliases.chunking_profile_id)
           ) OR (
               p_allow_ready_retained AND jobs.status = 'ready' AND EXISTS (
                   SELECT 1
                     FROM pgcontext._chunking_profile_alias_retained AS retained
                    WHERE retained.chunking_profile_alias_id =
                              aliases.chunking_profile_alias_id
                      AND retained.chunking_profile_id = generations.chunking_profile_id
               )
           )
      INTO collection_id, alias_matches
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
     WHERE jobs.job_id = p_job_id
       AND (
           p_lease_token = 0
           OR (
               jobs.lease_token = p_lease_token
               AND (
                   jobs.lease_expires_at > pg_catalog.clock_timestamp()
                   OR jobs.status = 'ready'
               )
           )
       )
     FOR SHARE OF aliases;
    IF collection_id IS NULL THEN RETURN false; END IF;
    PERFORM pgcontext._require_collection_owner(collection_id);
    RETURN COALESCE(alias_matches, false);
END;
$$;

CREATE FUNCTION pgcontext._lock_document_chunk_read_alias(
    p_document_source_id bigint
)
RETURNS bigint
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint; profile_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(
        27, p_document_source_id, 0
    );
    SELECT sources.collection_id, aliases.chunking_profile_id
      INTO collection_id, profile_id
      FROM pgcontext._document_sources AS sources
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
     WHERE sources.document_source_id = p_document_source_id
       AND sources.status = 'ready' AND aliases.status = 'ready'
     FOR SHARE OF aliases;
    IF profile_id IS NULL THEN RETURN NULL; END IF;
    PERFORM pgcontext._require_collection_owner(collection_id);
    RETURN profile_id;
END;
$$;

CREATE FUNCTION pgcontext._checkpoint_document_chunk_job(
    p_job_id bigint, p_lease_token bigint, p_status text,
    p_processed_units bigint, p_total_units bigint
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    collection_id bigint;
    current_status text;
    current_processed bigint;
    current_total bigint;
    current_rank int4;
    next_rank int4;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(9, p_job_id, p_lease_token);
    IF p_status NOT IN ('parsing','chunking','embedding')
       OR p_total_units NOT BETWEEN 1 AND 1000000
       OR p_processed_units NOT BETWEEN 0 AND p_total_units THEN
        RAISE EXCEPTION 'invalid document chunk progress checkpoint' USING ERRCODE = '22023';
    END IF;
    SELECT sources.collection_id, jobs.status, jobs.processed_units, jobs.total_units
      INTO collection_id, current_status, current_processed, current_total
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND jobs.lease_expires_at > pg_catalog.clock_timestamp()
     FOR UPDATE OF jobs;
    PERFORM pgcontext._require_collection_owner(collection_id);
    current_rank := CASE current_status WHEN 'leased' THEN 0 WHEN 'parsing' THEN 1
        WHEN 'chunking' THEN 2 WHEN 'embedding' THEN 3 ELSE -1 END;
    next_rank := CASE p_status WHEN 'parsing' THEN 1 WHEN 'chunking' THEN 2 ELSE 3 END;
    IF current_rank < 0 OR next_rank < current_rank OR next_rank > current_rank + 1 THEN
        RAISE EXCEPTION 'invalid document chunk progress transition' USING ERRCODE = '55000';
    END IF;
    IF p_total_units < current_total OR p_processed_units < current_processed THEN
        RAISE EXCEPTION 'document chunk progress cannot regress' USING ERRCODE = '55000';
    END IF;
    UPDATE pgcontext._document_chunk_jobs SET status = p_status,
           processed_units = p_processed_units, total_units = p_total_units,
           updated_at = pg_catalog.now() WHERE job_id = p_job_id;
    UPDATE pgcontext._document_chunk_generations AS generations SET status = p_status
      FROM pgcontext._document_chunk_jobs AS jobs
     WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
    RETURN true;
END;
$$;

CREATE FUNCTION pgcontext._fail_document_chunk_job(
    p_job_id bigint, p_lease_token bigint, p_error_code text
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(7, p_job_id, p_lease_token);
    IF pg_catalog.octet_length(p_error_code) NOT BETWEEN 1 AND 64
       OR p_error_code !~ '^[a-z0-9_]+$' THEN
        RAISE EXCEPTION 'invalid document chunk failure code' USING ERRCODE = '22023';
    END IF;
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND jobs.lease_expires_at > pg_catalog.clock_timestamp()
     FOR UPDATE OF jobs;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs SET status = 'failed', lease_worker = NULL,
           lease_expires_at = NULL, error_code = p_error_code, updated_at = pg_catalog.now()
     WHERE job_id = p_job_id AND lease_token = p_lease_token
       AND status IN ('leased','parsing','chunking','embedding','validating','publishing');
    IF NOT FOUND THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    UPDATE pgcontext._document_chunk_generations AS generations SET status = 'failed'
      FROM pgcontext._document_chunk_jobs AS jobs
     WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
    DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
    RETURN true;
END;
$$;

CREATE FUNCTION pgcontext._retry_document_chunk_job(p_job_id bigint)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(16, p_job_id, 0);
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
     WHERE jobs.job_id = p_job_id
       AND generations.chunking_profile_id IN (
           aliases.chunking_profile_id,
           COALESCE(aliases.shadow_chunking_profile_id, aliases.chunking_profile_id)
       )
     FOR UPDATE OF jobs FOR SHARE OF aliases;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'queued', lease_worker = NULL, lease_expires_at = NULL,
           error_code = NULL, processed_units = 0, updated_at = pg_catalog.now()
     WHERE job_id = p_job_id AND status IN ('cancelled','failed') AND attempt < 3;
    IF FOUND THEN
        DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
        UPDATE pgcontext._document_chunk_generations AS generations
           SET status = 'queued'
          FROM pgcontext._document_chunk_jobs AS jobs
         WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
        RETURN true;
    END IF;
    RETURN false;
END;
$$;

CREATE FUNCTION pgcontext._supersede_document_chunk_claim(
    p_job_id bigint, p_lease_token bigint
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(19, p_job_id, p_lease_token);
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id AND jobs.lease_token = p_lease_token
       AND jobs.lease_expires_at > pg_catalog.clock_timestamp()
     FOR SHARE OF sources;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'superseded', lease_worker = NULL, lease_expires_at = NULL,
           error_code = NULL, updated_at = pg_catalog.now()
     WHERE job_id = p_job_id AND lease_token = p_lease_token
       AND status IN ('leased','parsing','chunking','embedding','validating','publishing');
    IF NOT FOUND THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    UPDATE pgcontext._document_chunk_generations AS generations SET status = 'superseded'
      FROM pgcontext._document_chunk_jobs AS jobs
     WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
    DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
    RETURN true;
END;
$$;

CREATE FUNCTION pgcontext._heartbeat_document_chunk_job(
    p_job_id bigint, p_lease_token bigint, p_lease_millis int4
)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(14, p_job_id, p_lease_token);
    IF p_lease_millis NOT BETWEEN 1 AND 60000 THEN
        RAISE EXCEPTION 'invalid document chunk heartbeat lease' USING ERRCODE = '22023';
    END IF;
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'cancelled', lease_worker = NULL, lease_expires_at = NULL,
           error_code = 'cancelled', updated_at = pg_catalog.now()
     WHERE job_id = p_job_id AND lease_token = p_lease_token
       AND status = 'cancel_requested';
    IF FOUND THEN
        UPDATE pgcontext._document_chunk_generations AS generations SET status = 'cancelled'
          FROM pgcontext._document_chunk_jobs AS jobs
         WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
        RETURN false;
    END IF;
    UPDATE pgcontext._document_chunk_jobs
       SET lease_expires_at = pg_catalog.clock_timestamp()
               + pg_catalog.make_interval(secs => p_lease_millis::double precision / 1000.0),
           updated_at = pg_catalog.now()
     WHERE job_id = p_job_id AND lease_token = p_lease_token
       AND lease_expires_at > pg_catalog.clock_timestamp()
       AND status IN ('leased','parsing','chunking','embedding','validating','publishing');
    IF NOT FOUND THEN
        RAISE EXCEPTION 'stale document chunk job lease' USING ERRCODE = '40001';
    END IF;
    RETURN true;
END;
$$;

CREATE FUNCTION pgcontext._cancel_document_chunk_job(p_job_id bigint)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE collection_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(15, p_job_id, 0);
    SELECT sources.collection_id INTO collection_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
     WHERE jobs.job_id = p_job_id;
    PERFORM pgcontext._require_collection_owner(collection_id);
    UPDATE pgcontext._document_chunk_jobs
       SET status = CASE WHEN status = 'queued' THEN 'cancelled' ELSE 'cancel_requested' END,
           lease_worker = CASE WHEN status = 'queued' THEN NULL ELSE lease_worker END,
           lease_expires_at = CASE WHEN status = 'queued' THEN NULL ELSE lease_expires_at END,
           error_code = 'cancelled', updated_at = pg_catalog.now()
     WHERE job_id = p_job_id
       AND status IN ('queued','leased','parsing','chunking','embedding','validating','publishing');
    IF NOT FOUND THEN RETURN false; END IF;
    DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
    UPDATE pgcontext._document_chunk_generations AS generations SET status = jobs.status
      FROM pgcontext._document_chunk_jobs AS jobs
     WHERE jobs.job_id = p_job_id AND generations.generation_id = jobs.generation_id;
    RETURN true;
END;
$$;

CREATE FUNCTION pgcontext._rebuild_document_chunk_job(p_job_id bigint)
RETURNS boolean
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog, pgcontext
AS $$
DECLARE v_collection_id bigint; v_generation_id bigint;
BEGIN
    PERFORM pgcontext._consume_document_chunk_permit(18, p_job_id, 0);
    SELECT sources.collection_id, jobs.generation_id
      INTO v_collection_id, v_generation_id
      FROM pgcontext._document_chunk_jobs AS jobs
      JOIN pgcontext._document_chunk_generations AS generations USING (generation_id)
      JOIN pgcontext._document_sources AS sources USING (document_source_id)
      JOIN pgcontext._chunking_profile_aliases AS aliases
        USING (chunking_profile_alias_id)
     WHERE jobs.job_id = p_job_id AND jobs.status IN ('ready','retired')
       AND generations.chunking_profile_id IN (
           aliases.chunking_profile_id,
           COALESCE(aliases.shadow_chunking_profile_id, aliases.chunking_profile_id)
       )
     FOR UPDATE OF jobs FOR SHARE OF aliases;
    PERFORM pgcontext._require_collection_owner(v_collection_id);
    IF v_generation_id IS NULL THEN RETURN false; END IF;
    DELETE FROM pgcontext._current_document_chunk_generations
     WHERE generation_id = v_generation_id;
    DELETE FROM pgcontext._document_embedding_jobs
     WHERE generation_id = v_generation_id;
    DELETE FROM pgcontext._document_chunk_staging WHERE job_id = p_job_id;
    UPDATE pgcontext._document_chunk_generations
       SET status = 'queued', chunk_count = NULL, token_count = NULL,
           staging_bytes = NULL, publication_sha256 = NULL,
           projection_sha256 = NULL, published_at = NULL
     WHERE generation_id = v_generation_id;
    UPDATE pgcontext._document_chunk_jobs
       SET status = 'queued', attempt = 0, lease_worker = NULL,
           lease_expires_at = NULL, processed_units = 0, error_code = NULL,
           updated_at = pg_catalog.now()
     WHERE job_id = p_job_id;
    RETURN true;
END;
$$;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:302
-- pgcontext::build_jobs::_enqueue_ivfflat_compaction_debt
CREATE  FUNCTION "_enqueue_ivfflat_compaction_debt"(
	"index_oid" oid, /* pg_sys :: Oid */
	"generation" bigint /* i64 */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_ivfflat_compaction_debt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership/persistence.rs:306
-- pgcontext::pgvector_ownership::persistence::_transition_pgvector_ownership_conversion
CREATE  FUNCTION "_transition_pgvector_ownership_conversion"(
	"conversion_id" bigint, /* i64 */
	"expected_status" TEXT, /* String */
	"new_status" TEXT, /* String */
	"shadow_attnum" smallint, /* Option < i16 > */
	"total_rows" bigint, /* i64 */
	"processed_rows" bigint, /* i64 */
	"mismatch_count" bigint, /* i64 */
	"backfill_cursor" TEXT, /* Option < String > */
	"source_checksum" TEXT, /* Option < String > */
	"shadow_checksum" TEXT, /* Option < String > */
	"attestation" TEXT, /* Option < String > */
	"error_message" TEXT /* Option < String > */
) RETURNS void
SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'transition_conversion_catalog_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:703
-- pgcontext::pgvector_compat::adopt_pgvector
CREATE  FUNCTION "adopt_pgvector"(
	"target" regclass DEFAULT NULL, /* Option < PgRelation > */
	"dry_run" bool DEFAULT true, /* bool */
	"drop_old" bool DEFAULT false /* bool */
) RETURNS TABLE (
	"index_name" TEXT,  /* String */
	"action" TEXT,  /* String */
	"command" TEXT,  /* String */
	"executed" bool  /* bool */
)
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'adopt_pgvector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/apply.rs:28
-- pgcontext::exact_first::apply::apply_exact_first_plan
CREATE  FUNCTION "apply_exact_first_plan"(
	"collection" TEXT, /* String */
	"plan_revision" bigint, /* i64 */
	"policy" TEXT /* String */
) RETURNS TABLE (
	"plan_revision" bigint,  /* i64 */
	"plan_status" TEXT,  /* String */
	"readiness_state" TEXT,  /* String */
	"readiness_reason" TEXT,  /* String */
	"build_job_id" bigint,  /* Option < i64 > */
	"index_oid" oid  /* Option < pg_sys :: Oid > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'apply_exact_first_plan_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:735
-- pgcontext::artifact_segments::artifact_segment_diagnostics
CREATE  FUNCTION "artifact_segment_diagnostics"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"lifecycle_state" TEXT,  /* String */
	"status" TEXT,  /* String */
	"detail" TEXT,  /* String */
	"repair_advice" TEXT,  /* String */
	"cleanup_eligible" bool,  /* bool */
	"relative_path" TEXT,  /* Option < String > */
	"payload_bytes" bigint,  /* i64 */
	"file_payload_bytes" bigint,  /* Option < i64 > */
	"checksum" bigint,  /* i64 */
	"file_checksum" bigint  /* Option < i64 > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'artifact_segment_diagnostics_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:617
-- pgcontext::artifact_segments::artifact_segment_memory
CREATE  FUNCTION "artifact_segment_memory"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"lifecycle_state" TEXT,  /* String */
	"payload_bytes" bigint,  /* i64 */
	"header_bytes" bigint,  /* i64 */
	"mapped_bytes" bigint,  /* i64 */
	"file_materialized" bool  /* bool */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'artifact_segment_memory_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments/serving_readiness.rs:83
-- pgcontext::artifact_segments::serving_readiness::artifact_segment_mmap_payload
CREATE  FUNCTION "artifact_segment_mmap_payload"(
	"collection" TEXT, /* String */
	"artifact_name" TEXT, /* String */
	"max_mapped_bytes" bigint /* i64 */
) RETURNS TABLE (
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"mapped_bytes" bigint,  /* i64 */
	"payload" bytea  /* Vec < u8 > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'artifact_segment_mmap_payload_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments/serving_readiness.rs:52
-- pgcontext::artifact_segments::serving_readiness::artifact_segment_serving_readiness
CREATE  FUNCTION "artifact_segment_serving_readiness"(
	"collection" TEXT, /* String */
	"max_mapped_bytes" bigint /* i64 */
) RETURNS TABLE (
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"lifecycle_state" TEXT,  /* String */
	"status" TEXT,  /* String */
	"serving_ready" bool,  /* bool */
	"mapped_bytes" bigint,  /* i64 */
	"max_mapped_bytes" bigint,  /* i64 */
	"detail" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'artifact_segment_serving_readiness_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:585
-- pgcontext::artifact_segments::artifact_segments
CREATE  FUNCTION "artifact_segments"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"artifact_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"build_job_id" bigint,  /* i64 */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"segment_kind" TEXT,  /* String */
	"format_version" INT,  /* i32 */
	"payload_bytes" bigint,  /* i64 */
	"checksum" bigint,  /* i64 */
	"relative_path" TEXT,  /* Option < String > */
	"lifecycle_state" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'list_artifact_segments_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:274
-- pgcontext::lexical_sql::attach_fuzzy_index
CREATE  FUNCTION "attach_fuzzy_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"index_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'attach_fuzzy_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:180
-- pgcontext::vector_catalog::attach_hnsw_index
CREATE  FUNCTION "attach_hnsw_index"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"index_name" TEXT /* String */
) RETURNS void
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'attach_hnsw_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:172
-- pgcontext::lexical_sql::attach_lexical_index
CREATE  FUNCTION "attach_lexical_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"index_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'attach_lexical_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:221
-- pgcontext::vector_catalog::attach_sparse_hnsw_index
CREATE  FUNCTION "attach_sparse_hnsw_index"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"index_name" TEXT /* String */
) RETURNS void
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'attach_sparse_hnsw_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/points.rs:240
-- pgcontext::points::backfill_points
CREATE  FUNCTION "backfill_points"(
	"collection_name" TEXT, /* String */
	"batch_size" INT /* i32 */
) RETURNS TABLE (
	"batch_number" bigint,  /* i64 */
	"processed_count" bigint,  /* i64 */
	"inserted_count" bigint,  /* i64 */
	"reactivated_count" bigint  /* i64 */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'backfill_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:67
-- BitVec

CREATE TYPE pgcontext.bitvec;
CREATE FUNCTION pgcontext.bitvec_out(input pgcontext.bitvec)
RETURNS cstring IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'bitvec_out_wrapper';
CREATE FUNCTION pgcontext.bitvec_send(input pgcontext.bitvec)
RETURNS bytea IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'bitvec_send_wrapper';
CREATE FUNCTION pgcontext.bitvec_typmod_input(input cstring, _type_oid oid, typmod integer)
RETURNS pgcontext.bitvec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'bitvec_typmod_input_wrapper';
CREATE FUNCTION pgcontext.bitvec_typmod_receive(internal internal, _type_oid oid, typmod integer)
RETURNS pgcontext.bitvec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'bitvec_typmod_receive_wrapper';
CREATE TYPE pgcontext.bitvec (
    INTERNALLENGTH = variable,
    INPUT = pgcontext.bitvec_typmod_input,
    OUTPUT = pgcontext.bitvec_out,
    RECEIVE = pgcontext.bitvec_typmod_receive,
    SEND = pgcontext.bitvec_send,
    STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1447
-- pgcontext::pgcontext::vector_variants::bitvec_hamming_distance
CREATE  FUNCTION "bitvec_hamming_distance"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_hamming_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:343
-- pgcontext::vector_variant_ordering::bitvec_gt
CREATE  FUNCTION "bitvec_gt"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1671
-- pgcontext::pgcontext::vector_variants::bitvec_bits_final
CREATE  FUNCTION "bitvec_bits_final"(
	"state" bool[] /* Vec < bool > */
) RETURNS BitVec /* BitVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_bits_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:313
-- pgcontext::vector_variant_ordering::bitvec_cmp
CREATE  FUNCTION "bitvec_cmp"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:318
-- pgcontext::vector_variant_ordering::bitvec_lt
CREATE  FUNCTION "bitvec_lt"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:868
-- pgcontext::pgcontext::vector_variants::bitvec_from_bool_array
CREATE  FUNCTION "bitvec_from_bool_array"(
	"bits" bool[] /* Vec < bool > */
) RETURNS BitVec /* BitVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_from_bool_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1199
-- pgcontext::pgcontext::vector_variants::bitvec
CREATE  FUNCTION "bitvec"(
	"input" TEXT /* & str */
) RETURNS BitVec /* BitVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1303
-- pgcontext::pgcontext::vector_variants::bitvec_dims
CREATE  FUNCTION "bitvec_dims"(
	"vector" BitVec /* BitVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:225
-- pgcontext::vector_variant_typmods::bitvec_enforce_typmod
CREATE  FUNCTION "bitvec_enforce_typmod"(
	"vector" BitVec, /* BitVec */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS BitVec /* BitVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:338
-- pgcontext::vector_variant_ordering::bitvec_ge
CREATE  FUNCTION "bitvec_ge"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1459
-- pgcontext::pgcontext::vector_variants::bitvec_jaccard_distance
CREATE  FUNCTION "bitvec_jaccard_distance"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_jaccard_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:328
-- pgcontext::vector_variant_ordering::bitvec_eq
CREATE  FUNCTION "bitvec_eq"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:333
-- pgcontext::vector_variant_ordering::bitvec_ne
CREATE  FUNCTION "bitvec_ne"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:886
-- pgcontext::pgcontext::vector_variants::bitvec_from_provider_bytes
CREATE  FUNCTION "bitvec_from_provider_bytes"(
	"collection" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"payload" bytea /* Vec < u8 > */
) RETURNS BitVec /* BitVec */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_from_provider_bytes_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1666
-- pgcontext::pgcontext::vector_variants::bitvec_and_transition
CREATE  FUNCTION "bitvec_and_transition"(
	"state" bool[], /* :: std :: option :: Option < Vec < bool > > */
	"value" BitVec /* Option < BitVec > */
) RETURNS bool[] /* :: std :: option :: Option < Vec < bool > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_and_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1661
-- pgcontext::pgcontext::vector_variants::bitvec_or_transition
CREATE  FUNCTION "bitvec_or_transition"(
	"state" bool[], /* :: std :: option :: Option < Vec < bool > > */
	"value" BitVec /* Option < BitVec > */
) RETURNS bool[] /* :: std :: option :: Option < Vec < bool > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_or_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:323
-- pgcontext::vector_variant_ordering::bitvec_le
CREATE  FUNCTION "bitvec_le"(
	"left" BitVec, /* BitVec */
	"right" BitVec /* BitVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:877
-- pgcontext::pgcontext::vector_variants::bitvec_to_bool_array
CREATE  FUNCTION "bitvec_to_bool_array"(
	"vector" BitVec /* BitVec */
) RETURNS bool[] /* Vec < bool > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_to_bool_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:641
-- requires:
--   BitVec
--   bitvec_from_bool_array
--   bitvec_to_bool_array
--   bitvec_hamming_distance
--   bitvec_jaccard_distance


CREATE CAST (bit AS bitvec) WITH INOUT AS ASSIGNMENT;
CREATE CAST (bit varying AS bitvec) WITH INOUT AS ASSIGNMENT;
CREATE CAST (bitvec AS bit varying) WITH INOUT AS ASSIGNMENT;
CREATE CAST (bitvec AS bit) WITH INOUT;
CREATE CAST (boolean[] AS bitvec) WITH FUNCTION pgcontext.bitvec_from_bool_array(boolean[]) AS ASSIGNMENT;
CREATE CAST (bitvec AS boolean[]) WITH FUNCTION pgcontext.bitvec_to_bool_array(bitvec) AS ASSIGNMENT;
CREATE FUNCTION pgcontext.hamming_distance("left" bit, "right" bit) RETURNS double precision LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS $$
    SELECT pgcontext.bitvec_hamming_distance($1::bitvec, $2::bitvec)::double precision
$$;
CREATE FUNCTION pgcontext.hamming_distance("left" bit varying, "right" bit varying) RETURNS double precision LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS $$
    SELECT pgcontext.bitvec_hamming_distance($1::bitvec, $2::bitvec)::double precision
$$;
CREATE FUNCTION pgcontext.jaccard_distance("left" bit, "right" bit) RETURNS double precision LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS $$
    SELECT pgcontext.bitvec_jaccard_distance($1::bitvec, $2::bitvec)
$$;
CREATE FUNCTION pgcontext.jaccard_distance("left" bit varying, "right" bit varying) RETURNS double precision LANGUAGE sql IMMUTABLE PARALLEL SAFE STRICT AS $$
    SELECT pgcontext.bitvec_jaccard_distance($1::bitvec, $2::bitvec)
$$;
CREATE OPERATOR pgcontext.<~> (LEFTARG = bit, RIGHTARG = bit, FUNCTION = pgcontext.hamming_distance, COMMUTATOR = OPERATOR(pgcontext.<~>));
CREATE OPERATOR pgcontext.<~> (LEFTARG = bit varying, RIGHTARG = bit varying, FUNCTION = pgcontext.hamming_distance, COMMUTATOR = OPERATOR(pgcontext.<~>));
CREATE OPERATOR pgcontext.<%> (LEFTARG = bit, RIGHTARG = bit, FUNCTION = pgcontext.jaccard_distance, COMMUTATOR = OPERATOR(pgcontext.<%>));
CREATE OPERATOR pgcontext.<%> (LEFTARG = bit varying, RIGHTARG = bit varying, FUNCTION = pgcontext.jaccard_distance, COMMUTATOR = OPERATOR(pgcontext.<%>));
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:153
-- pgcontext::vector_variant_typmods::bitvec_typmod_in
CREATE  FUNCTION "bitvec_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:482
-- pgcontext::pgcontext::vector_variants::bitvec_typmod_input
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:160
-- pgcontext::vector_variant_typmods::bitvec_typmod_out
CREATE  FUNCTION "bitvec_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bitvec_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:489
-- pgcontext::pgcontext::vector_variants::bitvec_typmod_receive
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:383
-- pgcontext::build_jobs::build_jobs
CREATE  FUNCTION "build_jobs"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'build_jobs_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:202
-- pgcontext::artifact_segments::build_mmap_hnsw_artifact
CREATE  FUNCTION "build_mmap_hnsw_artifact"(
	"build_job_id" bigint /* i64 */
) RETURNS bytea /* Vec < u8 > */
STRICT VOLATILE
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'build_mmap_hnsw_artifact_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/points.rs:191
-- pgcontext::points::bulk_delete_points
CREATE  FUNCTION "bulk_delete_points"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[], /* Vec < String > */
	"batch_size" INT /* i32 */
) RETURNS TABLE (
	"batch_number" bigint,  /* i64 */
	"processed_count" bigint,  /* i64 */
	"deleted_count" bigint,  /* i64 */
	"missing_count" bigint  /* i64 */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bulk_delete_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/points.rs:139
-- pgcontext::points::bulk_upsert_points
CREATE  FUNCTION "bulk_upsert_points"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[], /* Vec < String > */
	"batch_size" INT /* i32 */
) RETURNS TABLE (
	"batch_number" bigint,  /* i64 */
	"processed_count" bigint,  /* i64 */
	"inserted_count" bigint,  /* i64 */
	"reactivated_count" bigint  /* i64 */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'bulk_upsert_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:698
-- pgcontext::document_chunking::cancel_document_chunk_job
CREATE  FUNCTION "cancel_document_chunk_job"(
	"job_id" bigint /* i64 */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cancel_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:240
-- pgcontext::exact_first::controller::cancel_exact_first_build
CREATE  FUNCTION "cancel_exact_first_build"(
	"collection" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cancel_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:424
-- pgcontext::document_chunking::checkpoint_document_chunk_job
CREATE  FUNCTION "checkpoint_document_chunk_job"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"status" TEXT, /* String */
	"processed_units" bigint, /* i64 */
	"total_units" bigint /* i64 */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'checkpoint_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:350
-- pgcontext::document_chunking::claim_document_chunk_jobs
CREATE  FUNCTION "claim_document_chunk_jobs"(
	"limit" INT, /* i32 */
	"lease_millis" INT, /* i32 */
	"worker_id" TEXT /* String */
) RETURNS TABLE (
	"job_id" bigint,  /* i64 */
	"lease_token" bigint,  /* i64 */
	"request" jsonb  /* JsonB */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'claim_document_chunk_jobs_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:21
-- pgcontext::exact_first::controller::claim_exact_first_build
CREATE  FUNCTION "claim_exact_first_build"(
	"collection" TEXT, /* String */
	"worker_id" TEXT, /* String */
	"lease_millis" INT /* i32 */
) RETURNS TABLE (
	"plan_revision" bigint,  /* i64 */
	"lease_token" bigint,  /* i64 */
	"lease_expires_micros" bigint,  /* i64 */
	"generated_ddl" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'claim_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:690
-- pgcontext::artifact_segments::cleanup_artifact_segments
CREATE  FUNCTION "cleanup_artifact_segments"(
	"collection" TEXT, /* String */
	"dry_run" bool /* bool */
) RETURNS TABLE (
	"artifact_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" TEXT,  /* String */
	"cleanup_action" TEXT,  /* String */
	"relative_path" TEXT,  /* Option < String > */
	"file_removed" bool,  /* bool */
	"lifecycle_state" TEXT  /* String */
)
STRICT VOLATILE SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cleanup_artifact_segments_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/semantic_rerank/api.rs:409
-- pgcontext::semantic_rerank::cleanup_semantic_rerank_requests
CREATE  FUNCTION "cleanup_semantic_rerank_requests"(
	"limit" INT DEFAULT 1000 /* i32 */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cleanup_semantic_rerank_requests_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/payload_mutations.rs:105
-- pgcontext::payload_mutations::clear_payload
CREATE  FUNCTION "clear_payload"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[] /* Vec < String > */
) RETURNS TABLE (
	"source_key" TEXT,  /* String */
	"updated" bool  /* bool */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'clear_payload_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/collection_aliases.rs:56
-- pgcontext::collection_aliases::collection_aliases
CREATE  FUNCTION "collection_aliases"() RETURNS TABLE (
	"alias_name" TEXT,  /* String */
	"collection_name" TEXT  /* String */
)
STRICT STABLE SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'collection_aliases_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:121
-- pgcontext::catalog::collection_info
CREATE  FUNCTION "collection_info"(
	"collection_name" TEXT /* String */
) RETURNS TABLE (
	"collection_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"owner_name" TEXT,  /* String */
	"table_schema" TEXT,  /* Option < String > */
	"table_name" TEXT  /* Option < String > */
)
STRICT STABLE SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'collection_info_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/collection_limits.rs:132
-- pgcontext::collection_limits::collection_limits
CREATE  FUNCTION "collection_limits"(
	"collection_name" TEXT /* String */
) RETURNS TABLE (
	"strict_mode" bool,  /* bool */
	"max_dimensions" INT,  /* Option < i32 > */
	"max_vectors" INT,  /* Option < i32 > */
	"max_points" bigint,  /* Option < i64 > */
	"max_filter_nodes" INT,  /* Option < i32 > */
	"max_search_limit" INT,  /* Option < i32 > */
	"max_candidate_budget" INT,  /* Option < i32 > */
	"query_timeout_ms" INT,  /* Option < i32 > */
	"max_index_memory_bytes" bigint  /* Option < i64 > */
)
STRICT STABLE SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'collection_limits_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:361
-- pgcontext::vector_catalog::collection_sparse_vectors
CREATE  FUNCTION "collection_sparse_vectors"(
	"collection_name" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT,  /* String */
	"storage_options" jsonb,  /* JsonB */
	"index_options" jsonb,  /* JsonB */
	"status" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'collection_sparse_vectors_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:64
-- pgcontext::vector_catalog::collection_vectors
CREATE  FUNCTION "collection_vectors"(
	"collection_name" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT,  /* String */
	"hnsw_options" jsonb,  /* JsonB */
	"quantization_options" jsonb,  /* JsonB */
	"status" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'collection_vectors_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am_compaction.rs:767
-- pgcontext::hnsw_am::compact
CREATE  FUNCTION "compact"(
	"index" regclass /* PgRelation */
) RETURNS TABLE (
	"live_rows" bigint,  /* i64 */
	"base_records_read" bigint,  /* i64 */
	"delta_records_drained" bigint  /* i64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_compact_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/ivfflat_am.rs:2655
-- pgcontext::ivfflat_am::compact_ivfflat
CREATE  FUNCTION "compact_ivfflat"(
	"index" regclass /* UnlockedRegclass */
) RETURNS jsonb /* JsonB */
STRICT 
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'compact_ivfflat_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:1617
-- pgcontext::pgvector_compat::compare_indexes
CREATE  FUNCTION "compare_indexes"(
	"table_name" TEXT, /* String */
	"column_name" TEXT, /* String */
	"queries" INT DEFAULT 20 /* i32 */
) RETURNS TABLE (
	"index_name" TEXT,  /* String */
	"access_method" TEXT,  /* String */
	"operator" TEXT,  /* Option < String > */
	"p50_ms" double precision,  /* Option < f64 > */
	"p95_ms" double precision,  /* Option < f64 > */
	"recall_at_10" double precision  /* Option < f64 > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'compare_indexes_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/collection_limits.rs:45
-- pgcontext::collection_limits::configure_collection_limits
CREATE  FUNCTION "configure_collection_limits"(
	"collection_name" TEXT, /* String */
	"strict_mode" bool, /* bool */
	"max_dimensions" INT, /* Option < i32 > */
	"max_vectors" INT, /* Option < i32 > */
	"max_points" bigint, /* Option < i64 > */
	"max_filter_nodes" INT, /* Option < i32 > */
	"max_search_limit" INT, /* Option < i32 > */
	"max_candidate_budget" INT, /* Option < i32 > */
	"query_timeout_ms" INT, /* Option < i32 > */
	"max_index_memory_bytes" bigint /* Option < i64 > */
) RETURNS TABLE (
	"strict_mode" bool,  /* bool */
	"max_dimensions" INT,  /* Option < i32 > */
	"max_vectors" INT,  /* Option < i32 > */
	"max_points" bigint,  /* Option < i64 > */
	"max_filter_nodes" INT,  /* Option < i32 > */
	"max_search_limit" INT,  /* Option < i32 > */
	"max_candidate_budget" INT,  /* Option < i32 > */
	"query_timeout_ms" INT,  /* Option < i32 > */
	"max_index_memory_bytes" bigint  /* Option < i64 > */
)
SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'configure_collection_limits_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:396
-- pgcontext::vector_catalog::configure_sparse_vector
CREATE  FUNCTION "configure_sparse_vector"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"storage_options" jsonb, /* JsonB */
	"index_options" jsonb, /* JsonB */
	"status" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT,  /* String */
	"storage_options" jsonb,  /* JsonB */
	"index_options" jsonb,  /* JsonB */
	"status" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'configure_sparse_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:104
-- pgcontext::vector_catalog::configure_vector
CREATE  FUNCTION "configure_vector"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"hnsw_options" jsonb, /* JsonB */
	"quantization_options" jsonb, /* JsonB */
	"status" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT,  /* String */
	"hnsw_options" jsonb,  /* JsonB */
	"quantization_options" jsonb,  /* JsonB */
	"status" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'configure_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:155
-- pgcontext::table_search::count
CREATE  FUNCTION "count"(
	"collection" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'count_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:161
-- pgcontext::table_search::count
CREATE  FUNCTION "count"(
	"collection" TEXT, /* String */
	"filter" TEXT /* Option < String > */
) RETURNS bigint /* i64 */

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'count_collection_filtered_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:59
-- pgcontext::catalog::create_collection
CREATE  FUNCTION "create_collection"(
	"collection_name" TEXT /* String */
) RETURNS TABLE (
	"collection_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"owner_name" TEXT,  /* String */
	"table_schema" TEXT,  /* Option < String > */
	"table_name" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:90
-- pgcontext::catalog::create_collection
CREATE  FUNCTION "create_collection"(
	"collection_name" TEXT, /* String */
	"table_name" TEXT /* String */
) RETURNS TABLE (
	"collection_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"owner_name" TEXT,  /* String */
	"table_schema" TEXT,  /* Option < String > */
	"table_name" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_collection_for_table_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/collection_aliases.rs:21
-- pgcontext::collection_aliases::create_collection_alias
CREATE  FUNCTION "create_collection_alias"(
	"alias_name" TEXT, /* String */
	"target_collection_name" TEXT /* String */
) RETURNS TABLE (
	"alias_name" TEXT,  /* String */
	"collection_name" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_collection_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:101
-- pgcontext::document_chunking::create_document_chunk_projection
CREATE  FUNCTION "create_document_chunk_projection"(
	"table_name" TEXT /* String */
) RETURNS TEXT /* String */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_document_chunk_projection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_migrations.rs:51
-- pgcontext::embedding_migrations::create_embedding_migration
CREATE  FUNCTION "create_embedding_migration"(
	"collection" TEXT, /* String */
	"source_profile" TEXT, /* String */
	"target_profile" TEXT, /* String */
	"total_points" bigint /* i64 */
) RETURNS TABLE (
	"migration_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"source_profile" TEXT,  /* String */
	"target_profile" TEXT,  /* String */
	"status" EmbeddingMigrationStatus,  /* EmbeddingMigrationStatus */
	"total_points" bigint,  /* i64 */
	"processed_points" bigint  /* i64 */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_embedding_migration_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:238
-- pgcontext::lexical_sql::create_fuzzy_index
CREATE  FUNCTION "create_fuzzy_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"method" TEXT DEFAULT 'gin' /* String */
) RETURNS TEXT /* String */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_fuzzy_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:138
-- pgcontext::lexical_sql::create_lexical_index
CREATE  FUNCTION "create_lexical_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"method" TEXT DEFAULT 'gin' /* String */
) RETURNS TEXT /* String */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'create_lexical_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/query.rs:101
-- pgcontext::document_chunking::query::current_document_chunks
CREATE  FUNCTION "current_document_chunks"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"source_keys" text[] /* BoundedSourceKeys */
) RETURNS TABLE (
	"source_key" TEXT,  /* String */
	"source_version" bigint,  /* i64 */
	"profile_revision" bigint,  /* i64 */
	"generation_id" bigint,  /* i64 */
	"occurrence_id" bigint,  /* i64 */
	"ordinal" INT,  /* i32 */
	"original_text" TEXT,  /* String */
	"retrieval_text" TEXT,  /* String */
	"start_byte" bigint,  /* i64 */
	"end_byte" bigint,  /* i64 */
	"start_char" bigint,  /* i64 */
	"end_char" bigint,  /* i64 */
	"token_count" INT,  /* i32 */
	"structure_kind" TEXT,  /* String */
	"structure_path" TEXT[],  /* Vec < String > */
	"page_number" INT,  /* Option < i32 > */
	"region" jsonb,  /* Option < JsonB > */
	"parent_occurrence_id" bigint,  /* Option < i64 > */
	"previous_occurrence_id" bigint,  /* Option < i64 > */
	"next_occurrence_id" bigint,  /* Option < i64 > */
	"content_hash" bigint,  /* i64 */
	"context_prefix" TEXT,  /* Option < String > */
	"fake_embedding" jsonb  /* JsonB */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'current_document_chunks_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:232
-- pgcontext::pgvector_ownership::cutover_pgvector_ownership_conversion
CREATE  FUNCTION "cutover_pgvector_ownership_conversion"(
	"conversion_id" bigint, /* i64 */
	"sessions_drained" bool DEFAULT false /* bool */
) RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cutover_pgvector_ownership_conversion_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/payload_mutations.rs:79
-- pgcontext::payload_mutations::delete_payload
CREATE  FUNCTION "delete_payload"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[], /* Vec < String > */
	"payload_keys" TEXT[] /* Vec < String > */
) RETURNS TABLE (
	"source_key" TEXT,  /* String */
	"updated" bool  /* bool */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'delete_payload_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/points.rs:106
-- pgcontext::points::delete_points
CREATE  FUNCTION "delete_points"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[] /* Vec < String > */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'delete_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:295
-- pgcontext::lexical_sql::detach_fuzzy_index
CREATE  FUNCTION "detach_fuzzy_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'detach_fuzzy_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:192
-- pgcontext::lexical_sql::detach_lexical_index
CREATE  FUNCTION "detach_lexical_index"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'detach_lexical_index_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:1177
-- pgcontext::pgvector_compat::disable_pgvector_binding
CREATE  FUNCTION "disable_pgvector_binding"() RETURNS void
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'disable_pgvector_binding_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:1481
-- pgcontext::pgvector_compat::disable_pgvector_name_facade
CREATE  FUNCTION "disable_pgvector_name_facade"() RETURNS void
STRICT
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'disable_pgvector_name_facade_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/recommend.rs:132
-- pgcontext::table_search::recommend::discover
CREATE  FUNCTION "discover"(
	"collection" TEXT, /* String */
	"context_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'discover_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/query.rs:8
-- pgcontext::document_chunking::query::document_chunking_progress
CREATE  FUNCTION "document_chunking_progress"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'document_chunking_progress_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/profile_api.rs:129
-- pgcontext::document_chunking::profile_api::drain_chunking_profile_alias
CREATE  FUNCTION "drain_chunking_profile_alias"(
	"alias_name" TEXT, /* String */
	"profile_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'drain_chunking_profile_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:301
-- pgcontext::catalog::drop_collection
CREATE  FUNCTION "drop_collection"(
	"collection_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'drop_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/collection_aliases.rs:110
-- pgcontext::collection_aliases::drop_collection_alias
CREATE  FUNCTION "drop_collection_alias"(
	"alias_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'drop_collection_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:309
-- pgcontext::lexical_sql::drop_fuzzy_source
CREATE  FUNCTION "drop_fuzzy_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'drop_fuzzy_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:205
-- pgcontext::lexical_sql::drop_lexical_source
CREATE  FUNCTION "drop_lexical_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'drop_lexical_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_migrations.rs:137
-- pgcontext::embedding_migrations::embedding_migrations
CREATE  FUNCTION "embedding_migrations"() RETURNS TABLE (
	"migration_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"source_profile" TEXT,  /* String */
	"target_profile" TEXT,  /* String */
	"status" EmbeddingMigrationStatus,  /* EmbeddingMigrationStatus */
	"total_points" bigint,  /* i64 */
	"processed_points" bigint  /* i64 */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'embedding_migrations_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_profiles.rs:1279
-- pgcontext::embedding_profiles::embedding_profile_coverage
CREATE  FUNCTION "embedding_profile_coverage"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"profile_name" TEXT,  /* String */
	"lifecycle" TEXT,  /* String */
	"serves_queries" bool,  /* bool */
	"source_column" TEXT,  /* String */
	"covered_points" bigint,  /* i64 */
	"stale_points" bigint,  /* i64 */
	"active_points" bigint  /* i64 */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'embedding_profile_coverage_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_profiles.rs:182
-- pgcontext::embedding_profiles::embedding_profile_explain
CREATE  FUNCTION "embedding_profile_explain"(
	"collection" TEXT, /* String */
	"profile_name" TEXT /* String */
) RETURNS jsonb /* JsonB */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'embedding_profile_explain_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_profiles.rs:116
-- pgcontext::embedding_profiles::embedding_profiles
CREATE  FUNCTION "embedding_profiles"() RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"profile_name" TEXT,  /* String */
	"source_column" TEXT,  /* String */
	"hnsw_index" TEXT,  /* String */
	"profile" jsonb  /* JsonB */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'embedding_profiles_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:1148
-- pgcontext::pgvector_compat::enable_pgvector_binding
CREATE  FUNCTION "enable_pgvector_binding"() RETURNS void
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enable_pgvector_binding_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:1439
-- pgcontext::pgvector_compat::enable_pgvector_name_facade
CREATE  FUNCTION "enable_pgvector_name_facade"() RETURNS void
STRICT
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enable_pgvector_name_facade_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:192
-- pgcontext::artifact_segments::encode_artifact_segment
CREATE  FUNCTION "encode_artifact_segment"(
	"kind" TEXT, /* String */
	"payload" bytea /* Vec < u8 > */
) RETURNS bytea /* Vec < u8 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'encode_artifact_segment_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:161
-- pgcontext::build_jobs::enqueue_build_job
CREATE  FUNCTION "enqueue_build_job"(
	"collection" TEXT, /* String */
	"job_kind" TEXT, /* String */
	"publication_alias" TEXT /* String */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_build_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/enqueue_api.rs:6
-- pgcontext::document_chunking::enqueue_api::enqueue_document_chunking
CREATE  FUNCTION "enqueue_document_chunking"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"source_keys" text[] /* BoundedSourceKeys */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_document_chunking_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/enqueue_api.rs:19
-- pgcontext::document_chunking::enqueue_api::enqueue_document_chunking_profile
CREATE  FUNCTION "enqueue_document_chunking_profile"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"source_keys" text[] /* BoundedSourceKeys */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_document_chunking_profile_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:221
-- pgcontext::build_jobs::enqueue_hnsw_compaction
CREATE  FUNCTION "enqueue_hnsw_compaction"(
	"collection" TEXT, /* String */
	"index" regclass /* PgRelation */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_hnsw_compaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:264
-- pgcontext::build_jobs::enqueue_ivfflat_compaction
CREATE  FUNCTION "enqueue_ivfflat_compaction"(
	"collection" TEXT, /* String */
	"index" regclass /* PgRelation */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'enqueue_ivfflat_compaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:188
-- pgcontext::operations::estimate_index_memory
CREATE  FUNCTION "estimate_index_memory"(
	"index_name" TEXT /* String */
) RETURNS TABLE (
	"index_schema" TEXT,  /* String */
	"index_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"access_method" TEXT,  /* String */
	"estimated_rows" bigint,  /* i64 */
	"dimensions" INT,  /* i32 */
	"vector_bytes" bigint,  /* i64 */
	"link_bytes" bigint,  /* i64 */
	"total_bytes" bigint,  /* i64 */
	"status" IndexMemoryEstimateStatus  /* IndexMemoryEstimateStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'estimate_index_memory_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/advisor.rs:77
-- pgcontext::exact_first::advisor::exact_first_advisor
CREATE  FUNCTION "exact_first_advisor"(
	"collection" TEXT, /* String */
	"objectives" jsonb /* BoundedExactFirstObjectives */
) RETURNS TABLE (
	"plan_revision" bigint,  /* i64 */
	"recommendation" TEXT,  /* String */
	"precision" TEXT,  /* String */
	"reason" TEXT,  /* String */
	"evidence" jsonb,  /* JsonB */
	"generated_ddl" TEXT,  /* Option < String > */
	"plan_sha256" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'exact_first_advisor_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:355
-- pgcontext::exact_first::controller::exact_first_progress
CREATE  FUNCTION "exact_first_progress"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"plan_revision" bigint,  /* Option < i64 > */
	"plan_status" TEXT,  /* Option < String > */
	"build_job_id" bigint,  /* Option < i64 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"invalid_samples" bigint,  /* i64 */
	"error_code" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'exact_first_progress_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first.rs:225
-- pgcontext::exact_first::exact_first_readiness
CREATE  FUNCTION "exact_first_readiness"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"registration_revision" bigint,  /* i64 */
	"readiness_state" TEXT,  /* String */
	"readiness_reason" TEXT,  /* String */
	"plan_revision" bigint,  /* Option < i64 > */
	"build_job_id" bigint,  /* Option < i64 > */
	"repair_advice" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'exact_first_readiness_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:372
-- pgcontext::query_builders::execute_query
CREATE  FUNCTION "execute_query"(
	"collection" TEXT, /* String */
	"plan" jsonb /* JsonB */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'execute_query_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query.rs:206
-- pgcontext::hybrid_query::explain
CREATE  FUNCTION "explain"(
	"collection" TEXT, /* String */
	"lexical_source" TEXT /* String */
) RETURNS TABLE (
	"stage" TEXT,  /* String */
	"detail" TEXT,  /* String */
	"branch" TEXT,  /* Option < String > */
	"strategy" TEXT,  /* String */
	"status" QueryExplainStatus,  /* QueryExplainStatus */
	"estimated_candidates" bigint,  /* Option < i64 > */
	"candidate_budget" bigint  /* Option < i64 > */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explain_collection_query_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/recommend.rs:151
-- pgcontext::table_search::recommend::explore
CREATE  FUNCTION "explore"(
	"collection" TEXT, /* String */
	"context_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explore_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:177
-- pgcontext::table_search::facet
CREATE  FUNCTION "facet"(
	"collection" TEXT, /* String */
	"field" TEXT, /* String */
	"filter" TEXT, /* Option < String > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"value" TEXT,  /* String */
	"count" bigint  /* i64 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'facet_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:465
-- pgcontext::document_chunking::fail_document_chunk_job
CREATE  FUNCTION "fail_document_chunk_job"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"error_code" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'fail_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:332
-- pgcontext::exact_first::controller::fail_exact_first_build
CREATE  FUNCTION "fail_exact_first_build"(
	"collection" TEXT, /* String */
	"plan_revision" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"error_code" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'fail_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:666
-- pgcontext::document_chunking::fake_process_document_chunk_job
CREATE  FUNCTION "fake_process_document_chunk_job"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint /* i64 */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'fake_process_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:277
-- pgcontext::pgvector_ownership::finalize_pgvector_ownership_conversion
CREATE  FUNCTION "finalize_pgvector_ownership_conversion"(
	"conversion_id" bigint /* i64 */
) RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'finalize_pgvector_ownership_conversion_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/semantic_rerank/api.rs:249
-- pgcontext::semantic_rerank::finalize_semantic_rerank
CREATE  FUNCTION "finalize_semantic_rerank"(
	"request_id" bigint, /* i64 */
	"response" jsonb DEFAULT NULL, /* Option < BoundedResponseJson > */
	"failure_reason" text DEFAULT NULL /* Option < BoundedFailureReason > */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'finalize_semantic_rerank_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:403
-- pgcontext::lexical_sql::fuzzy_sources
CREATE  FUNCTION "fuzzy_sources"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"source_name" TEXT,  /* String */
	"text_column" TEXT,  /* String */
	"trgm_schema" TEXT,  /* String */
	"index_name" TEXT,  /* Option < String > */
	"index_method" TEXT,  /* Option < String > */
	"registration_revision" bigint,  /* i64 */
	"status" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'fuzzy_sources_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:45
-- HalfVec
CREATE TYPE HalfVec;

-- crates/context-pg/src/vector_variants.rs:45
-- pgcontext::pgcontext::vector_variants::halfvec_in
CREATE  FUNCTION "halfvec_in"(
	"input" cstring /* Option < & :: core :: ffi :: CStr > */
) RETURNS HalfVec /* Option < HalfVec > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_in_wrapper';

-- crates/context-pg/src/vector_variants.rs:45
-- pgcontext::pgcontext::vector_variants::halfvec_out
CREATE  FUNCTION "halfvec_out"(
	"input" HalfVec /* HalfVec */
) RETURNS cstring /* :: pgrx :: ffi :: CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_out_wrapper';

-- crates/context-pg/src/vector_variants.rs:45
-- HalfVec
CREATE TYPE HalfVec (
	INTERNALLENGTH = variable,
	INPUT = halfvec_in, /* pgcontext::pgcontext::vector_variants::halfvec_in */
	OUTPUT = halfvec_out, /* pgcontext::pgcontext::vector_variants::halfvec_out */
	STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:845
-- pgcontext::pgcontext::vector_variants::halfvec_from_double_array
CREATE  FUNCTION "halfvec_from_double_array"(
	"values" double precision[] /* Vec < f64 > */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_from_double_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:246
-- pgcontext::vector_variant_ordering::halfvec_lt
CREATE  FUNCTION "halfvec_lt"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:271
-- pgcontext::vector_variant_ordering::halfvec_gt
CREATE  FUNCTION "halfvec_gt"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1411
-- pgcontext::pgcontext::vector_variants::halfvec_l1_distance
CREATE  FUNCTION "halfvec_l1_distance"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_l1_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1135
-- pgcontext::pgcontext::vector_variants::halfvec
CREATE  FUNCTION "halfvec"(
	"input" TEXT /* & str */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1603
-- pgcontext::pgcontext::vector_variants::halfvec_avg_final
CREATE  FUNCTION "halfvec_avg_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_avg_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:256
-- pgcontext::vector_variant_ordering::halfvec_eq
CREATE  FUNCTION "halfvec_eq"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:241
-- pgcontext::vector_variant_ordering::halfvec_cmp
CREATE  FUNCTION "halfvec_cmp"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1405
-- pgcontext::pgcontext::vector_variants::halfvec_cosine_distance
CREATE  FUNCTION "halfvec_cosine_distance"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_cosine_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:266
-- pgcontext::vector_variant_ordering::halfvec_ge
CREATE  FUNCTION "halfvec_ge"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:251
-- pgcontext::vector_variant_ordering::halfvec_le
CREATE  FUNCTION "halfvec_le"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1393
-- pgcontext::pgcontext::vector_variants::halfvec_inner_product
CREATE  FUNCTION "halfvec_inner_product"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1399
-- pgcontext::pgcontext::vector_variants::halfvec_negative_inner_product
CREATE  FUNCTION "halfvec_negative_inner_product"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_negative_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1387
-- pgcontext::pgcontext::vector_variants::halfvec_l2_distance
CREATE  FUNCTION "halfvec_l2_distance"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:829
-- pgcontext::pgcontext::vector_variants::halfvec_from_real_array
CREATE  FUNCTION "halfvec_from_real_array"(
	"values" real[] /* Vec < f32 > */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_from_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:195
-- pgcontext::vector_variant_typmods::halfvec_enforce_typmod
CREATE  FUNCTION "halfvec_enforce_typmod"(
	"vector" HalfVec, /* HalfVec */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1263
-- pgcontext::pgcontext::vector_variants::halfvec_dims
CREATE  FUNCTION "halfvec_dims"(
	"vector" HalfVec /* HalfVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:837
-- pgcontext::pgcontext::vector_variants::halfvec_from_integer_array
CREATE  FUNCTION "halfvec_from_integer_array"(
	"values" INT[] /* Vec < i32 > */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_from_integer_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:261
-- pgcontext::vector_variant_ordering::halfvec_ne
CREATE  FUNCTION "halfvec_ne"(
	"left" HalfVec, /* HalfVec */
	"right" HalfVec /* HalfVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1597
-- pgcontext::pgcontext::vector_variants::halfvec_sum_final
CREATE  FUNCTION "halfvec_sum_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS HalfVec /* HalfVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_sum_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1556
-- pgcontext::pgcontext::vector_variants::halfvec_sum_transition
CREATE  FUNCTION "halfvec_sum_transition"(
	"state" real[], /* :: std :: option :: Option < Vec < f32 > > */
	"value" HalfVec /* Option < HalfVec > */
) RETURNS real[] /* :: std :: option :: Option < Vec < f32 > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_sum_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:851
-- pgcontext::pgcontext::vector_variants::halfvec_to_real_array
CREATE  FUNCTION "halfvec_to_real_array"(
	"vector" HalfVec /* HalfVec */
) RETURNS real[] /* Vec < f32 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_to_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:125
-- pgcontext::vector_variant_typmods::halfvec_typmod_in
CREATE  FUNCTION "halfvec_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:132
-- pgcontext::vector_variant_typmods::halfvec_typmod_out
CREATE  FUNCTION "halfvec_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:679
-- pgcontext::document_chunking::heartbeat_document_chunk_job
CREATE  FUNCTION "heartbeat_document_chunk_job"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"lease_millis" INT /* i32 */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'heartbeat_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:143
-- pgcontext::exact_first::controller::heartbeat_exact_first_build
CREATE  FUNCTION "heartbeat_exact_first_build"(
	"collection" TEXT, /* String */
	"plan_revision" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"lease_millis" INT /* i32 */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'heartbeat_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:922
-- pgcontext::operations::hnsw_build_stats
CREATE  FUNCTION "hnsw_build_stats"() RETURNS TABLE (
	"last_build_tuples" bigint,  /* i64 */
	"graph_millis" bigint,  /* i64 */
	"write_millis" bigint  /* i64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_build_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:622
-- pgcontext::hnsw_am::hnsw_last_scan_work
CREATE  FUNCTION "hnsw_last_scan_work"() RETURNS TABLE (
	"page_visits" bigint,  /* i64 */
	"node_reads" bigint,  /* i64 */
	"candidates" bigint,  /* i64 */
	"rechecks" bigint,  /* i64 */
	"exact_strategy" bool  /* bool */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_last_scan_work_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am_compaction.rs:858
-- pgcontext::hnsw_am::hnsw_segment_stats
CREATE  FUNCTION "hnsw_segment_stats"(
	"index" regclass /* PgRelation */
) RETURNS TABLE (
	"segment_count" INT,  /* i32 */
	"active_delta_records" bigint,  /* i64 */
	"immutable_rows" bigint,  /* i64 */
	"smallest_pair_rows" bigint,  /* Option < i64 > */
	"compaction_debt" bool,  /* bool */
	"parallel_eligible" bool,  /* bool */
	"serving_mode" TEXT,  /* String */
	"frozen_mutation_records" bigint,  /* i64 */
	"active_delta_blocks" bigint,  /* i64 */
	"directory_epoch" bigint,  /* i64 */
	"codec" TEXT,  /* String */
	"codec_revision" TEXT,  /* Option < String > */
	"codec_code_width" INT,  /* Option < i32 > */
	"candidate_budget" INT,  /* i32 */
	"exact_source_rerank" bool,  /* bool */
	"codec_serving_capability" TEXT  /* String */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_segment_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:845
-- pgcontext::operations::hnsw_serving_stats
CREATE  FUNCTION "hnsw_serving_stats"() RETURNS TABLE (
	"pack_builds" bigint,  /* i64 */
	"pack_reuses" bigint,  /* i64 */
	"last_pack_bytes" bigint,  /* i64 */
	"last_pack_millis" bigint,  /* i64 */
	"total_pack_millis" bigint,  /* i64 */
	"shared_attaches" bigint,  /* i64 */
	"shared_publishes" bigint,  /* i64 */
	"shared_publish_skips" bigint,  /* i64 */
	"mapped_attaches" bigint,  /* i64 */
	"mapped_publishes" bigint,  /* i64 */
	"mapped_publish_skips" bigint,  /* i64 */
	"page_native_fallbacks" bigint,  /* i64 */
	"delta_segment_records" bigint,  /* i64 */
	"delta_segment_scans" bigint,  /* i64 */
	"segment_rotations" bigint,  /* i64 */
	"multi_segment_scans" bigint,  /* i64 */
	"parallel_segment_scans" bigint,  /* i64 */
	"serial_segment_degradations" bigint,  /* i64 */
	"max_segments_observed" bigint,  /* i64 */
	"segment_compactions" bigint,  /* i64 */
	"parallel_admission_denials" bigint,  /* i64 */
	"segment_merge_candidates" bigint,  /* i64 */
	"frozen_mutation_records_scanned" bigint,  /* i64 */
	"compaction_input_rows" bigint,  /* i64 */
	"compaction_output_rows" bigint,  /* i64 */
	"compaction_wal_pages" bigint,  /* i64 */
	"compaction_peak_projected_bytes" bigint  /* i64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_serving_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations/advisor.rs:52
-- pgcontext::operations::advisor::index_advisor
CREATE  FUNCTION "index_advisor"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"filter_key" TEXT,  /* Option < String > */
	"column_name" TEXT,  /* Option < String > */
	"recommendation" IndexAdvisorRecommendation,  /* IndexAdvisorRecommendation */
	"detail" TEXT,  /* String */
	"suggested_sql" TEXT  /* Option < String > */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'index_advisor_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:138
-- pgcontext::operations::index_diagnostics
CREATE  FUNCTION "index_diagnostics"(
	"index_name" TEXT /* String */
) RETURNS TABLE (
	"index_schema" TEXT,  /* String */
	"index_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"access_method" TEXT,  /* String */
	"status" IndexDiagnosticStatus,  /* IndexDiagnosticStatus */
	"context_error" TEXT,  /* Option < String > */
	"sqlstate" TEXT,  /* Option < String > */
	"repair_advice" TEXT  /* String */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'index_diagnostics_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:92
-- pgcontext::operations::index_status
CREATE  FUNCTION "index_status"(
	"index_name" TEXT /* String */
) RETURNS TABLE (
	"index_schema" TEXT,  /* String */
	"index_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"access_method" TEXT,  /* String */
	"is_valid" bool,  /* bool */
	"is_ready" bool,  /* bool */
	"is_live" bool,  /* bool */
	"status" IndexLifecycleStatus  /* IndexLifecycleStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'index_status_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first.rs:82
-- pgcontext::exact_first::inspect_exact_first_source
CREATE  FUNCTION "inspect_exact_first_source"(
	"source_table" TEXT, /* String */
	"options" jsonb DEFAULT '{}'::jsonb /* BoundedExactFirstObjectives */
) RETURNS TABLE (
	"ordinal_position" smallint,  /* i16 */
	"column_name" TEXT,  /* String */
	"type_schema" TEXT,  /* String */
	"type_name" TEXT,  /* String */
	"formatted_type" TEXT,  /* String */
	"nullable" bool,  /* bool */
	"support_family" TEXT,  /* Option < String > */
	"supported" bool,  /* bool */
	"reason" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'inspect_exact_first_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:320
-- pgcontext::document_chunking::install_document_chunk_trigger
CREATE  FUNCTION "install_document_chunk_trigger"(
	"collection" TEXT, /* String */
	"source_name" TEXT /* String */
) RETURNS TEXT /* String */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'install_document_chunk_trigger_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:104
-- Int8Vec

CREATE TYPE pgcontext.int8vec;
CREATE FUNCTION pgcontext.int8vec_out(input pgcontext.int8vec)
RETURNS cstring IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'int8vec_out_wrapper';
CREATE FUNCTION pgcontext.int8vec_send(input pgcontext.int8vec)
RETURNS bytea IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'int8vec_send_wrapper';
CREATE FUNCTION pgcontext.int8vec_typmod_input(input cstring, _type_oid oid, typmod integer)
RETURNS pgcontext.int8vec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'int8vec_typmod_input_wrapper';
CREATE FUNCTION pgcontext.int8vec_typmod_receive(internal internal, _type_oid oid, typmod integer)
RETURNS pgcontext.int8vec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'int8vec_typmod_receive_wrapper';
CREATE TYPE pgcontext.int8vec (
    INTERNALLENGTH = variable,
    INPUT = pgcontext.int8vec_typmod_input,
    OUTPUT = pgcontext.int8vec_out,
    RECEIVE = pgcontext.int8vec_typmod_receive,
    SEND = pgcontext.int8vec_send,
    STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:977
-- pgcontext::pgcontext::vector_variants::int8vec_from_smallint_array
CREATE  FUNCTION "int8vec_from_smallint_array"(
	"values" smallint[] /* Vec < i16 > */
) RETURNS Int8Vec /* Int8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_from_smallint_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:379
-- pgcontext::vector_variant_ordering::int8vec_gt
CREATE  FUNCTION "int8vec_gt"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:921
-- pgcontext::pgcontext::vector_variants::int8vec_from_profile
CREATE  FUNCTION "int8vec_from_profile"(
	"collection" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"values" smallint[] /* Vec < i16 > */
) RETURNS Int8Vec /* Int8Vec */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_from_profile_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:369
-- pgcontext::vector_variant_ordering::int8vec_ne
CREATE  FUNCTION "int8vec_ne"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1313
-- pgcontext::pgcontext::vector_variants::int8vec_dims
CREATE  FUNCTION "int8vec_dims"(
	"vector" Int8Vec /* Int8Vec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1208
-- pgcontext::pgcontext::vector_variants::int8vec
CREATE  FUNCTION "int8vec"(
	"input" TEXT /* & str */
) RETURNS Int8Vec /* Int8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:359
-- pgcontext::vector_variant_ordering::int8vec_le
CREATE  FUNCTION "int8vec_le"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1351
-- pgcontext::pgcontext::vector_variants::int8vec_l1_distance
CREATE  FUNCTION "int8vec_l1_distance"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_l1_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:983
-- pgcontext::pgcontext::vector_variants::int8vec_from_integer_array
CREATE  FUNCTION "int8vec_from_integer_array"(
	"values" INT[] /* Vec < i32 > */
) RETURNS Int8Vec /* Int8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_from_integer_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1327
-- pgcontext::pgcontext::vector_variants::int8vec_l2_distance
CREATE  FUNCTION "int8vec_l2_distance"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1339
-- pgcontext::pgcontext::vector_variants::int8vec_negative_inner_product
CREATE  FUNCTION "int8vec_negative_inner_product"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_negative_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1345
-- pgcontext::pgcontext::vector_variants::int8vec_cosine_distance
CREATE  FUNCTION "int8vec_cosine_distance"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_cosine_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:354
-- pgcontext::vector_variant_ordering::int8vec_lt
CREATE  FUNCTION "int8vec_lt"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:240
-- pgcontext::vector_variant_typmods::int8vec_enforce_typmod
CREATE  FUNCTION "int8vec_enforce_typmod"(
	"vector" Int8Vec, /* Int8Vec */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS Int8Vec /* Int8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:364
-- pgcontext::vector_variant_ordering::int8vec_eq
CREATE  FUNCTION "int8vec_eq"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:349
-- pgcontext::vector_variant_ordering::int8vec_cmp
CREATE  FUNCTION "int8vec_cmp"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:374
-- pgcontext::vector_variant_ordering::int8vec_ge
CREATE  FUNCTION "int8vec_ge"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1333
-- pgcontext::pgcontext::vector_variants::int8vec_inner_product
CREATE  FUNCTION "int8vec_inner_product"(
	"left" Int8Vec, /* Int8Vec */
	"right" Int8Vec /* Int8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1471
-- pgcontext::pgcontext::vector_variants::int8vec_sum_transition
CREATE  FUNCTION "int8vec_sum_transition"(
	"state" bigint[], /* :: std :: option :: Option < Vec < i64 > > */
	"value" Int8Vec /* Option < Int8Vec > */
) RETURNS bigint[] /* :: std :: option :: Option < Vec < i64 > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_sum_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1001
-- pgcontext::pgcontext::vector_variants::int8vec_to_smallint_array
CREATE  FUNCTION "int8vec_to_smallint_array"(
	"vector" Int8Vec /* Int8Vec */
) RETURNS smallint[] /* Vec < i16 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_to_smallint_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:167
-- pgcontext::vector_variant_typmods::int8vec_typmod_in
CREATE  FUNCTION "int8vec_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:500
-- pgcontext::pgcontext::vector_variants::int8vec_typmod_input
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:174
-- pgcontext::vector_variant_typmods::int8vec_typmod_out
CREATE  FUNCTION "int8vec_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:507
-- pgcontext::pgcontext::vector_variants::int8vec_typmod_receive
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1510
-- pgcontext::pgcontext::vector_variants::integer_vector_avg_final
CREATE  FUNCTION "integer_vector_avg_final"(
	"state" bigint[] /* Vec < i64 > */
) RETURNS double precision[] /* Vec < f64 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'integer_vector_avg_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1498
-- pgcontext::pgcontext::vector_variants::integer_vector_sum_final
CREATE  FUNCTION "integer_vector_sum_final"(
	"state" bigint[] /* Vec < i64 > */
) RETURNS bigint[] /* Vec < i64 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'integer_vector_sum_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:737
-- pgcontext::document_chunking::invalidate_document_chunks
CREATE  FUNCTION "invalidate_document_chunks"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"source_keys" text[] /* BoundedSourceKeys */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'invalidate_document_chunks_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/ivfflat_am.rs:2526
-- pgcontext::ivfflat_am::ivfflat_index_info
CREATE  FUNCTION "ivfflat_index_info"(
	"index" regclass /* PgRelation */
) RETURNS jsonb /* JsonB */
STRICT PARALLEL SAFE 
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'ivfflat_index_info_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/ivfflat_am.rs:2476
-- pgcontext::ivfflat_am::ivfflat_last_scan_work
CREATE  FUNCTION "ivfflat_last_scan_work"() RETURNS TABLE (
	"requested_probes" bigint,  /* i64 */
	"visited_lists" bigint,  /* i64 */
	"visited_postings" bigint,  /* i64 */
	"delta_records" bigint,  /* i64 */
	"candidates" bigint,  /* i64 */
	"exact_rerank_candidates" bigint,  /* i64 */
	"widening_rounds" bigint,  /* i64 */
	"codec" TEXT,  /* & '_ str */
	"completion_reason" TEXT,  /* & '_ str */
	"generation" bigint  /* i64 */
)
STRICT PARALLEL SAFE 
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'ivfflat_last_scan_work_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:465
-- pgcontext::lexical_sql::lexical_headline
CREATE  FUNCTION "lexical_headline"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"point_ids" bigint[], /* Vec < Option < i64 > > */
	"query" jsonb, /* JsonB */
	"options" TEXT DEFAULT '' /* String */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"headline" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'lexical_headline_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:341
-- pgcontext::lexical_sql::lexical_sources
CREATE  FUNCTION "lexical_sources"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"source_name" TEXT,  /* String */
	"document_mode" TEXT,  /* String */
	"text_configuration" TEXT,  /* String */
	"ranker" TEXT,  /* String */
	"normalization" INT,  /* i32 */
	"index_name" TEXT,  /* Option < String > */
	"index_method" TEXT,  /* Option < String > */
	"registration_revision" bigint,  /* i64 */
	"status" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'lexical_sources_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:493
-- pgcontext::pgvector_compat::migration_report
CREATE  FUNCTION "migration_report"() RETURNS TABLE (
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"type_name" TEXT,  /* String */
	"dimensions" INT,  /* Option < i32 > */
	"pgvector_indexes" TEXT[],  /* Vec < String > */
	"pgcontext_indexes" TEXT[],  /* Vec < String > */
	"conversion_supported" bool,  /* bool */
	"blockers" TEXT[],  /* Vec < String > */
	"suggested_command" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'migration_report_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:241
-- pgcontext::operations::optimization_status
CREATE  FUNCTION "optimization_status"(
	"collection" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"table_schema" TEXT,  /* Option < String > */
	"table_name" TEXT,  /* Option < String > */
	"has_source_table" bool,  /* bool */
	"source_table_exists" bool,  /* bool */
	"registered_vectors" bigint,  /* i64 */
	"active_points" bigint,  /* i64 */
	"filter_fields" bigint,  /* i64 */
	"hnsw_indexes" bigint,  /* i64 */
	"status" OptimizationStatus  /* OptimizationStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'optimization_status_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_compat.rs:133
-- pgcontext::pgvector_compat::pgvector_compatibility_inventory
CREATE  FUNCTION "pgvector_compatibility_inventory"() RETURNS TABLE (
	"category" TEXT,  /* String */
	"pgvector_surface" TEXT,  /* String */
	"status" TEXT,  /* String */
	"pgcontext_surface" TEXT,  /* String */
	"notes" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'pgvector_compatibility_inventory_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:352
-- pgcontext::pgvector_ownership::pgvector_ownership_conversions
CREATE  FUNCTION "pgvector_ownership_conversions"() RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'pgvector_ownership_conversions_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/profile_api.rs:33
-- pgcontext::document_chunking::profile_api::prepare_chunking_profile_alias
CREATE  FUNCTION "prepare_chunking_profile_alias"(
	"alias_name" TEXT, /* String */
	"profile_name" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'prepare_chunking_profile_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/semantic_rerank/api.rs:126
-- pgcontext::semantic_rerank::prepare_semantic_rerank
CREATE  FUNCTION "prepare_semantic_rerank"(
	"collection" text, /* BoundedCollectionName */
	"source_name" text, /* BoundedRerankSourceName */
	"query" text, /* BoundedRerankQuery */
	"candidates" jsonb, /* BoundedCandidatesJson */
	"model" text, /* BoundedRerankModel */
	"model_revision" bigint, /* i64 */
	"ttl_millis" bigint DEFAULT 5000, /* i64 */
	"failure_policy" text DEFAULT 'require_reranker', /* BoundedFailurePolicy */
	"filter" jsonb DEFAULT NULL, /* Option < BoundedFilterJson > */
	"allow_partial" bool DEFAULT false /* bool */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'prepare_semantic_rerank_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/profile_api.rs:62
-- pgcontext::document_chunking::profile_api::promote_chunking_profile_alias
CREATE  FUNCTION "promote_chunking_profile_alias"(
	"alias_name" TEXT, /* String */
	"profile_name" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'promote_chunking_profile_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:394
-- pgcontext::artifact_segments::publish_artifact_segment
CREATE  FUNCTION "publish_artifact_segment"(
	"build_job_id" bigint, /* i64 */
	"segment" bytea /* Vec < u8 > */
) RETURNS TABLE (
	"artifact_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"build_job_id" bigint,  /* i64 */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"segment_kind" TEXT,  /* String */
	"format_version" INT,  /* i32 */
	"payload_bytes" bigint,  /* i64 */
	"checksum" bigint,  /* i64 */
	"lifecycle_state" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'publish_artifact_segment_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:431
-- pgcontext::artifact_segments::publish_artifact_segment_file
CREATE  FUNCTION "publish_artifact_segment_file"(
	"build_job_id" bigint, /* i64 */
	"segment" bytea /* Vec < u8 > */
) RETURNS TABLE (
	"artifact_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"build_job_id" bigint,  /* i64 */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"segment_kind" TEXT,  /* String */
	"format_version" INT,  /* i32 */
	"payload_bytes" bigint,  /* i64 */
	"checksum" bigint,  /* i64 */
	"relative_path" TEXT,  /* Option < String > */
	"lifecycle_state" TEXT  /* String */
)
STRICT VOLATILE SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'publish_artifact_segment_file_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:584
-- pgcontext::document_chunking::publish_document_chunk_generation
CREATE  FUNCTION "publish_document_chunk_generation"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint /* i64 */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'publish_document_chunk_generation_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:184
-- pgcontext::exact_first::controller::publish_exact_first_build
CREATE  FUNCTION "publish_exact_first_build"(
	"collection" TEXT, /* String */
	"plan_revision" bigint, /* i64 */
	"lease_token" bigint /* i64 */
) RETURNS TABLE (
	"plan_status" TEXT,  /* String */
	"readiness_state" TEXT,  /* String */
	"index_oid" oid  /* pg_sys :: Oid */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'publish_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_stats.rs:361
-- pgcontext::query_stats::query_cohort_stats
CREATE  FUNCTION "query_cohort_stats"() RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"cohort" TEXT,  /* String */
	"query_kind" TEXT,  /* String */
	"query_count" bigint,  /* i64 */
	"total_results" bigint,  /* i64 */
	"total_candidates" bigint,  /* Option < i64 > */
	"total_rows_rechecked" bigint,  /* i64 */
	"total_rows_pruned" bigint,  /* i64 */
	"avg_recall_threshold" double precision,  /* Option < f64 > */
	"avg_recall_achieved" double precision,  /* Option < f64 > */
	"latency_bucket" QueryLatencyBucket,  /* QueryLatencyBucket */
	"lifecycle_state" QueryLifecycleState,  /* QueryLifecycleState */
	"avg_latency_ms" double precision,  /* f64 */
	"status" QueryCohortStatus  /* QueryCohortStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_cohort_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:214
-- pgcontext::query_builders::query_discover
CREATE  FUNCTION "query_discover"(
	"context_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_discover_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_stats.rs:390
-- pgcontext::query_stats::query_execution_stats
CREATE  FUNCTION "query_execution_stats"() RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"query_kind" TEXT,  /* String */
	"strategy" TEXT,  /* String */
	"query_count" bigint,  /* i64 */
	"total_visits" bigint,  /* i64 */
	"total_filter_candidates" bigint,  /* i64 */
	"total_candidates" bigint,  /* i64 */
	"total_rechecks" bigint,  /* i64 */
	"total_stages" bigint,  /* i64 */
	"total_expansions" bigint,  /* i64 */
	"adaptive_prefix_dimensions" INT,  /* Option < i32 > */
	"adaptive_termination" TEXT,  /* Option < String > */
	"completion" TEXT,  /* String */
	"latency_bucket" QueryLatencyBucket,  /* QueryLatencyBucket */
	"lifecycle_state" QueryLifecycleState,  /* QueryLifecycleState */
	"avg_latency_ms" double precision  /* f64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_execution_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:338
-- pgcontext::query_builders::query_external_rerank
CREATE  FUNCTION "query_external_rerank"(
	"branch" jsonb, /* JsonB */
	"model_revision" bigint, /* i64 */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_external_rerank_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:306
-- pgcontext::query_builders::query_formula
CREATE  FUNCTION "query_formula"(
	"branch" jsonb, /* JsonB */
	"formula" TEXT /* String */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_formula_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:129
-- pgcontext::query_builders::query_fuzzy
CREATE  FUNCTION "query_fuzzy"(
	"source" TEXT, /* String */
	"query" TEXT, /* String */
	"mode" TEXT DEFAULT 'similarity', /* String */
	"threshold" double precision DEFAULT 0.3, /* f64 */
	"filter" jsonb DEFAULT NULL, /* Option < JsonB > */
	"limit" INT DEFAULT 10 /* i32 */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_fuzzy_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:101
-- pgcontext::query_builders::query_lexical
CREATE  FUNCTION "query_lexical"(
	"source" TEXT, /* String */
	"query" jsonb, /* JsonB */
	"filter" jsonb DEFAULT NULL, /* Option < JsonB > */
	"limit" INT DEFAULT 10 /* i32 */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_lexical_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:225
-- pgcontext::query_builders::query_lookup
CREATE  FUNCTION "query_lookup"(
	"point_ids" bigint[] /* Vec < i64 > */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_lookup_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/multi_model.rs:147
-- pgcontext::multi_model::query_multi_model
CREATE  FUNCTION "query_multi_model"(
	"collection" TEXT, /* String */
	"branches" jsonb, /* JsonB */
	"filter" jsonb, /* Option < JsonB > */
	"limit" INT, /* i32 */
	"rrf_k" INT, /* i32 */
	"unique_candidate_budget" INT, /* i32 */
	"require_all_profiles" bool /* bool */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_multi_model_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:235
-- pgcontext::query_builders::query_prefetch
CREATE  FUNCTION "query_prefetch"(
	"branches" jsonb[] /* Vec < JsonB > */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_prefetch_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:250
-- pgcontext::query_builders::query_prefetch
CREATE  FUNCTION "query_prefetch"(
	"branches" jsonb[], /* Vec < JsonB > */
	"fusion" TEXT, /* String */
	"rank_constant" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_prefetch_configured_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:195
-- pgcontext::query_builders::query_recommend
CREATE  FUNCTION "query_recommend"(
	"positive_point_ids" bigint[], /* Vec < i64 > */
	"negative_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_recommend_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:325
-- pgcontext::query_builders::query_rerank
CREATE  FUNCTION "query_rerank"(
	"branch" jsonb, /* JsonB */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_rerank_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:288
-- pgcontext::query_builders::query_score_threshold
CREATE  FUNCTION "query_score_threshold"(
	"branch" jsonb, /* JsonB */
	"min_score" double precision, /* Option < f64 > */
	"max_score" double precision /* Option < f64 > */
) RETURNS jsonb /* JsonB */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_score_threshold_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_stats.rs:421
-- pgcontext::query_stats::query_telemetry_queue_stats
CREATE  FUNCTION "query_telemetry_queue_stats"() RETURNS TABLE (
	"transport" TEXT,  /* String */
	"delivery" TEXT,  /* String */
	"enqueued" bigint,  /* i64 */
	"persisted" bigint,  /* i64 */
	"dropped_contention" bigint,  /* i64 */
	"dropped_full" bigint,  /* i64 */
	"dropped_orphaned" bigint,  /* i64 */
	"database_slot_exhausted" bigint,  /* i64 */
	"worker_launch_failures" bigint,  /* i64 */
	"pending" bigint,  /* i64 */
	"worker_pid" INT  /* Option < i32 > */
)
STRICT 
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_telemetry_queue_stats_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:358
-- pgcontext::query_builders::query_topology_expand
CREATE  FUNCTION "query_topology_expand"(
	"branch" jsonb, /* JsonB */
	"max_depth" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_topology_expand_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:275
-- pgcontext::query_builders::query_weight
CREATE  FUNCTION "query_weight"(
	"branch" jsonb, /* JsonB */
	"weight" double precision /* f64 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_weight_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/lifecycle_api.rs:6
-- pgcontext::document_chunking::lifecycle_api::rebuild_document_chunk_job
CREATE  FUNCTION "rebuild_document_chunk_job"(
	"job_id" bigint /* i64 */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rebuild_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:340
-- pgcontext::operations::recall_check
CREATE  FUNCTION "recall_check"(
	"exact_point_ids" bigint[], /* Vec < i64 > */
	"candidate_point_ids" bigint[], /* Vec < i64 > */
	"min_recall" double precision /* f64 */
) RETURNS TABLE (
	"exact_count" bigint,  /* i64 */
	"candidate_count" bigint,  /* i64 */
	"intersection_count" bigint,  /* i64 */
	"recall" double precision,  /* f64 */
	"status" RecallCheckStatus  /* RecallCheckStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'recall_check_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/recommend.rs:17
-- pgcontext::table_search::recommend::recommend
CREATE  FUNCTION "recommend"(
	"collection" TEXT, /* String */
	"positive_point_ids" bigint[], /* Vec < i64 > */
	"negative_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'recommend_collection_from_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_stats.rs:251
-- pgcontext::query_stats::record_query_stat
CREATE  FUNCTION "record_query_stat"(
	"collection" TEXT, /* String */
	"cohort" TEXT, /* String */
	"query_kind" TEXT, /* String */
	"result_count" bigint, /* i64 */
	"candidate_count" bigint, /* Option < i64 > */
	"latency_ms" double precision /* f64 */
) RETURNS bool /* bool */
SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'record_query_stat_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_stats.rs:302
-- pgcontext::query_stats::record_query_stat
CREATE  FUNCTION "record_query_stat"(
	"collection" TEXT, /* String */
	"cohort" TEXT, /* String */
	"query_kind" TEXT, /* String */
	"result_count" bigint, /* i64 */
	"candidates_considered" bigint, /* Option < i64 > */
	"rows_rechecked" bigint, /* i64 */
	"rows_pruned" bigint, /* i64 */
	"recall_threshold" double precision, /* Option < f64 > */
	"recall_achieved" double precision, /* Option < f64 > */
	"latency_ms" double precision, /* f64 */
	"lifecycle_state" QueryLifecycleState /* QueryLifecycleState */
) RETURNS bool /* bool */
SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'record_query_stat_detailed_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:328
-- pgcontext::lexical_sql::refresh_lexical_catalog
CREATE  FUNCTION "refresh_lexical_catalog"(
	"collection" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'refresh_lexical_catalog_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:150
-- pgcontext::document_chunking::register_chunking_profile
CREATE  FUNCTION "register_chunking_profile"(
	"profile_name" TEXT, /* String */
	"parser" TEXT, /* String */
	"target_tokens" INT, /* i32 */
	"max_tokens" INT, /* i32 */
	"min_tokens" INT, /* i32 */
	"overlap_tokens" INT, /* i32 */
	"max_document_bytes" bigint, /* i64 */
	"include_structure_context" bool /* bool */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_chunking_profile_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:223
-- pgcontext::document_chunking::register_document_source
CREATE  FUNCTION "register_document_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"text_column" TEXT, /* String */
	"source_version_column" TEXT, /* String */
	"projection_table" TEXT, /* String */
	"profile_name" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_document_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_profiles.rs:77
-- pgcontext::embedding_profiles::register_embedding_profile
CREATE  FUNCTION "register_embedding_profile"(
	"collection" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"source_column" TEXT, /* String */
	"hnsw_index" TEXT, /* String */
	"profile" jsonb, /* JsonB */
	"lifecycle" TEXT DEFAULT 'active' /* String */
) RETURNS jsonb /* JsonB */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_embedding_profile_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first.rs:132
-- pgcontext::exact_first::register_exact_first
CREATE  FUNCTION "register_exact_first"(
	"collection" TEXT, /* String */
	"source_table" TEXT, /* String */
	"specification" jsonb, /* BoundedExactFirstSpecification */
	"apply_policy" TEXT DEFAULT 'recommend_only' /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"registration_revision" bigint,  /* i64 */
	"specification_sha256" TEXT,  /* String */
	"readiness_state" TEXT,  /* String */
	"readiness_reason" TEXT,  /* String */
	"plan_revision" bigint  /* Option < i64 > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_exact_first_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:237
-- pgcontext::catalog::register_filter_column
CREATE  FUNCTION "register_filter_column"(
	"collection_name" TEXT, /* String */
	"filter_key" TEXT, /* String */
	"column_name" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"filter_key" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_filter_column_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:219
-- pgcontext::lexical_sql::register_fuzzy_source
CREATE  FUNCTION "register_fuzzy_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"text_column" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_fuzzy_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/payload_catalog.rs:39
-- pgcontext::payload_catalog::register_jsonb_path
CREATE  FUNCTION "register_jsonb_path"(
	"collection_name" TEXT, /* String */
	"filter_key" TEXT, /* String */
	"column_name" TEXT, /* String */
	"path" TEXT[] /* Vec < String > */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"filter_key" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"jsonb_path" TEXT[]  /* Vec < String > */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_jsonb_path_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/late_interaction_catalog.rs:57
-- pgcontext::late_interaction_catalog::register_late_interaction
CREATE  FUNCTION "register_late_interaction"(
	"collection" TEXT, /* String */
	"source_table" TEXT, /* String */
	"token_source" TEXT /* String */
) RETURNS TABLE (
	"collection" TEXT,  /* String */
	"source_table" TEXT,  /* String */
	"token_source" TEXT,  /* String */
	"dimensions" INT,  /* Option < i32 > */
	"point_count" bigint,  /* i64 */
	"token_count" bigint,  /* i64 */
	"status" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:75
-- pgcontext::lexical_sql::register_lexical_document_source
CREATE  FUNCTION "register_lexical_document_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"document_column" TEXT, /* String */
	"text_configuration" TEXT DEFAULT 'pg_catalog.english', /* String */
	"ranker" TEXT DEFAULT 'ts_rank_cd', /* String */
	"normalization" INT DEFAULT 0, /* i32 */
	"rank_weights" real[] DEFAULT NULL /* :: std :: option :: Option < Vec < Option < f32 > > > */
) RETURNS bigint /* i64 */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_lexical_document_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:31
-- pgcontext::lexical_sql::register_lexical_source
CREATE  FUNCTION "register_lexical_source"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"text_columns" TEXT[], /* Vec < Option < String > > */
	"text_configuration" TEXT DEFAULT 'pg_catalog.english', /* String */
	"field_weights" TEXT[] DEFAULT NULL, /* :: std :: option :: Option < Vec < Option < String > > > */
	"json_paths" TEXT[] DEFAULT NULL, /* :: std :: option :: Option < Vec < Option < String > > > */
	"ranker" TEXT DEFAULT 'ts_rank_cd', /* String */
	"normalization" INT DEFAULT 0, /* i32 */
	"rank_weights" real[] DEFAULT NULL /* :: std :: option :: Option < Vec < Option < f32 > > > */
) RETURNS bigint /* i64 */
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_lexical_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/lexical_sql.rs:110
-- pgcontext::lexical_sql::register_lexical_tsquery
CREATE  FUNCTION "register_lexical_tsquery"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"tsquery_name" TEXT, /* String */
	"tsquery_column" TEXT /* String */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_lexical_tsquery_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/semantic_rerank/api.rs:2
-- pgcontext::semantic_rerank::register_semantic_rerank_source
CREATE  FUNCTION "register_semantic_rerank_source"(
	"collection" text, /* BoundedCollectionName */
	"source_name" text, /* BoundedRerankSourceName */
	"text_column" text, /* BoundedColumnName */
	"source_version_column" text /* BoundedColumnName */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_semantic_rerank_source_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_catalog.rs:292
-- pgcontext::vector_catalog::register_sparse_vector
CREATE  FUNCTION "register_sparse_vector"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector_column" TEXT, /* String */
	"dimensions" INT, /* i32 */
	"metric" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT,  /* String */
	"storage_options" jsonb,  /* JsonB */
	"index_options" jsonb,  /* JsonB */
	"status" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_sparse_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/catalog.rs:163
-- pgcontext::catalog::register_vector
CREATE  FUNCTION "register_vector"(
	"collection_name" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector_column" TEXT, /* String */
	"dimensions" INT, /* i32 */
	"metric" TEXT /* String */
) RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"vector_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"vector_column" TEXT,  /* String */
	"dimensions" INT,  /* i32 */
	"metric" TEXT  /* String */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'register_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/late_interaction_catalog.rs:113
-- pgcontext::late_interaction_catalog::repair_late_interaction
CREATE  FUNCTION "repair_late_interaction"(
	"collection" TEXT, /* String */
	"batch_size" INT /* i32 */
) RETURNS TABLE (
	"collection" TEXT,  /* String */
	"batch_count" bigint,  /* i64 */
	"point_count" bigint,  /* i64 */
	"token_count" bigint,  /* i64 */
	"dimensions" INT,  /* Option < i32 > */
	"status" TEXT  /* String */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'repair_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:510
-- pgcontext::build_jobs::request_build_cancel
CREATE  FUNCTION "request_build_cancel"(
	"build_job_id" bigint /* i64 */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'request_build_cancel_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:645
-- pgcontext::artifact_segments::retire_artifact_segment
CREATE  FUNCTION "retire_artifact_segment"(
	"artifact_id" bigint /* i64 */
) RETURNS TABLE (
	"artifact_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"previous_relative_path" TEXT,  /* Option < String > */
	"file_removed" bool,  /* bool */
	"lifecycle_state" TEXT  /* String */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'retire_artifact_segment_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:559
-- pgcontext::build_jobs::retry_build_job
CREATE  FUNCTION "retry_build_job"(
	"build_job_id" bigint /* i64 */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'retry_build_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:717
-- pgcontext::document_chunking::retry_document_chunk_job
CREATE  FUNCTION "retry_document_chunk_job"(
	"job_id" bigint /* i64 */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'retry_document_chunk_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/controller.rs:290
-- pgcontext::exact_first::controller::retry_exact_first_build
CREATE  FUNCTION "retry_exact_first_build"(
	"collection" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'retry_exact_first_build_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking/profile_api.rs:91
-- pgcontext::document_chunking::profile_api::rollback_chunking_profile_alias
CREATE  FUNCTION "rollback_chunking_profile_alias"(
	"alias_name" TEXT /* String */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rollback_chunking_profile_alias_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:767
-- pgcontext::document_chunking::rollback_document_chunk_generation
CREATE  FUNCTION "rollback_document_chunk_generation"(
	"collection" TEXT, /* String */
	"source_name" TEXT, /* String */
	"source_key" TEXT, /* String */
	"generation_id" bigint /* i64 */
) RETURNS bigint /* i64 */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rollback_document_chunk_generation_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:313
-- pgcontext::pgvector_ownership::rollback_pgvector_ownership_conversion
CREATE  FUNCTION "rollback_pgvector_ownership_conversion"(
	"conversion_id" bigint /* i64 */
) RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rollback_pgvector_ownership_conversion_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:638
-- pgcontext::build_jobs::run_build_job
CREATE  FUNCTION "run_build_job"(
	"build_job_id" bigint, /* i64 */
	"units_per_step" bigint DEFAULT 1 /* i64 */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'run_build_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:163
-- pgcontext::pgvector_ownership::run_pgvector_ownership_conversion
CREATE  FUNCTION "run_pgvector_ownership_conversion"(
	"conversion_id" bigint, /* i64 */
	"batch_size" INT DEFAULT 1000, /* i32 */
	"sessions_drained" bool DEFAULT false /* bool */
) RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'run_pgvector_ownership_conversion_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:126
-- pgcontext::table_search::scroll
CREATE  FUNCTION "scroll"(
	"collection" TEXT, /* String */
	"cursor" TEXT, /* Option < String > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"next_cursor" TEXT  /* String */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'scroll_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_profiles.rs:1208
-- pgcontext::embedding_profiles::set_embedding_profile_lifecycle
CREATE  FUNCTION "set_embedding_profile_lifecycle"(
	"collection" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"lifecycle" TEXT /* String */
) RETURNS TEXT /* String */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'set_embedding_profile_lifecycle_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/payload_mutations.rs:43
-- pgcontext::payload_mutations::set_payload
CREATE  FUNCTION "set_payload"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[], /* Vec < String > */
	"payload" jsonb /* JsonB */
) RETURNS TABLE (
	"source_key" TEXT,  /* String */
	"updated" bool  /* bool */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'set_payload_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:53
-- SparseVec
CREATE TYPE SparseVec;

-- crates/context-pg/src/vector_variants.rs:53
-- pgcontext::pgcontext::vector_variants::sparsevec_in
CREATE  FUNCTION "sparsevec_in"(
	"input" cstring /* Option < & :: core :: ffi :: CStr > */
) RETURNS SparseVec /* Option < SparseVec > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_in_wrapper';

-- crates/context-pg/src/vector_variants.rs:53
-- pgcontext::pgcontext::vector_variants::sparsevec_out
CREATE  FUNCTION "sparsevec_out"(
	"input" SparseVec /* SparseVec */
) RETURNS cstring /* :: pgrx :: ffi :: CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_out_wrapper';

-- crates/context-pg/src/vector_variants.rs:53
-- SparseVec
CREATE TYPE SparseVec (
	INTERNALLENGTH = variable,
	INPUT = sparsevec_in, /* pgcontext::pgcontext::vector_variants::sparsevec_in */
	OUTPUT = sparsevec_out, /* pgcontext::pgcontext::vector_variants::sparsevec_out */
	STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:783
-- pgcontext::hnsw_am::_hnsw_sparse_masked_candidates
CREATE  FUNCTION "_hnsw_sparse_masked_candidates"(
	"index_relation" regclass, /* PgRelation */
	"query" SparseVec, /* SparseVec */
	"allowed_heap_tids" anyarray, /* AnyArray */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"heap_tid" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_sparse_masked_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:210
-- pgcontext::vector_variant_typmods::sparsevec_enforce_typmod
CREATE  FUNCTION "sparsevec_enforce_typmod"(
	"vector" SparseVec, /* SparseVec */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1088
-- pgcontext::pgcontext::vector_variants::sparsevec_from_real_array
CREATE  FUNCTION "sparsevec_from_real_array"(
	"values" real[] /* Vec < f32 > */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_from_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:297
-- pgcontext::vector_variant_ordering::sparsevec_ne
CREATE  FUNCTION "sparsevec_ne"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sparse_search.rs:19
-- pgcontext::sparse_search::search_sparse
CREATE  FUNCTION "search_sparse"(
	"query" SparseVec, /* SparseVec */
	"point_ids" bigint[], /* Vec < i64 > */
	"vectors" SparseVec[], /* Vec < SparseVec > */
	"metric" TEXT, /* String */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"score" real  /* f32 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_sparse_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1273
-- pgcontext::pgcontext::vector_variants::sparsevec_dims
CREATE  FUNCTION "sparsevec_dims"(
	"vector" SparseVec /* SparseVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:695
-- pgcontext::hnsw_am::_hnsw_sparse_candidates
CREATE  FUNCTION "_hnsw_sparse_candidates"(
	"index_relation" regclass, /* PgRelation */
	"query" SparseVec, /* SparseVec */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"heap_tid" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_sparse_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1283
-- pgcontext::pgcontext::vector_variants::sparsevec_indices
CREATE  FUNCTION "sparsevec_indices"(
	"vector" SparseVec /* SparseVec */
) RETURNS INT[] /* Vec < i32 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_indices_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:292
-- pgcontext::vector_variant_ordering::sparsevec_eq
CREATE  FUNCTION "sparsevec_eq"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:277
-- pgcontext::vector_variant_ordering::sparsevec_cmp
CREATE  FUNCTION "sparsevec_cmp"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1144
-- pgcontext::pgcontext::vector_variants::sparsevec
CREATE  FUNCTION "sparsevec"(
	"input" TEXT /* & str */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:282
-- pgcontext::vector_variant_ordering::sparsevec_lt
CREATE  FUNCTION "sparsevec_lt"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:53
-- pgcontext::query_builders::query_sparse_nearest
CREATE  FUNCTION "query_sparse_nearest"(
	"vector_name" TEXT, /* String */
	"vector" SparseVec, /* SparseVec */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_sparse_nearest_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1429
-- pgcontext::pgcontext::vector_variants::sparsevec_negative_inner_product
CREATE  FUNCTION "sparsevec_negative_inner_product"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_negative_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1656
-- pgcontext::pgcontext::vector_variants::sparsevec_avg_final
CREATE  FUNCTION "sparsevec_avg_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_avg_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:307
-- pgcontext::vector_variant_ordering::sparsevec_gt
CREATE  FUNCTION "sparsevec_gt"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1441
-- pgcontext::pgcontext::vector_variants::sparsevec_l1_distance
CREATE  FUNCTION "sparsevec_l1_distance"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_l1_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sparse_search.rs:115
-- pgcontext::sparse_search::search_sparse
CREATE  FUNCTION "search_sparse"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"query" SparseVec, /* SparseVec */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_sparse_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1435
-- pgcontext::pgcontext::vector_variants::sparsevec_cosine_distance
CREATE  FUNCTION "sparsevec_cosine_distance"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_cosine_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:302
-- pgcontext::vector_variant_ordering::sparsevec_ge
CREATE  FUNCTION "sparsevec_ge"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1153
-- pgcontext::pgcontext::vector_variants::sparsevec_from_arrays
CREATE  FUNCTION "sparsevec_from_arrays"(
	"indices" INT[], /* Vec < i32 > */
	"values" real[], /* Vec < f32 > */
	"dimensions" INT /* i32 */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_from_arrays_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sparse_search.rs:54
-- pgcontext::sparse_search::explain_sparse
CREATE  FUNCTION "explain_sparse"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"query" SparseVec, /* SparseVec */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"strategy" TEXT,  /* String */
	"active_points" bigint,  /* i64 */
	"scored_count" bigint,  /* i64 */
	"candidate_count" bigint,  /* i64 */
	"recheck_count" bigint  /* i64 */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explain_sparse_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1417
-- pgcontext::pgcontext::vector_variants::sparsevec_l2_distance
CREATE  FUNCTION "sparsevec_l2_distance"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:287
-- pgcontext::vector_variant_ordering::sparsevec_le
CREATE  FUNCTION "sparsevec_le"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:11
-- requires:
--   HalfVec
--   SparseVec
--   BitVec
--   halfvec_lt
--   halfvec_le
--   halfvec_eq
--   halfvec_ne
--   halfvec_ge
--   halfvec_gt
--   halfvec_cmp
--   sparsevec_lt
--   sparsevec_le
--   sparsevec_eq
--   sparsevec_ne
--   sparsevec_ge
--   sparsevec_gt
--   sparsevec_cmp
--   bitvec_lt
--   bitvec_le
--   bitvec_eq
--   bitvec_ne
--   bitvec_ge
--   bitvec_gt
--   bitvec_cmp


CREATE OPERATOR pgcontext.< (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_lt,
    COMMUTATOR = OPERATOR(pgcontext.>),
    NEGATOR = OPERATOR(pgcontext.>=)
);
CREATE OPERATOR pgcontext.<= (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_le,
    COMMUTATOR = OPERATOR(pgcontext.>=),
    NEGATOR = OPERATOR(pgcontext.>)
);
CREATE OPERATOR pgcontext.= (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_eq,
    COMMUTATOR = OPERATOR(pgcontext.=),
    NEGATOR = OPERATOR(pgcontext.<>)
);
CREATE OPERATOR pgcontext.<> (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_ne,
    COMMUTATOR = OPERATOR(pgcontext.<>),
    NEGATOR = OPERATOR(pgcontext.=)
);
CREATE OPERATOR pgcontext.>= (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_ge,
    COMMUTATOR = OPERATOR(pgcontext.<=),
    NEGATOR = OPERATOR(pgcontext.<)
);
CREATE OPERATOR pgcontext.> (
    LEFTARG = halfvec,
    RIGHTARG = halfvec,
    FUNCTION = pgcontext.halfvec_gt,
    COMMUTATOR = OPERATOR(pgcontext.<),
    NEGATOR = OPERATOR(pgcontext.<=)
);
CREATE OPERATOR CLASS pgcontext.halfvec_ops
    DEFAULT FOR TYPE halfvec USING btree AS
    OPERATOR 1 pgcontext.< (halfvec, halfvec),
    OPERATOR 2 pgcontext.<= (halfvec, halfvec),
    OPERATOR 3 pgcontext.= (halfvec, halfvec),
    OPERATOR 4 pgcontext.>= (halfvec, halfvec),
    OPERATOR 5 pgcontext.> (halfvec, halfvec),
    FUNCTION 1 pgcontext.halfvec_cmp(halfvec, halfvec);

CREATE OPERATOR pgcontext.< (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_lt,
    COMMUTATOR = OPERATOR(pgcontext.>),
    NEGATOR = OPERATOR(pgcontext.>=)
);
CREATE OPERATOR pgcontext.<= (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_le,
    COMMUTATOR = OPERATOR(pgcontext.>=),
    NEGATOR = OPERATOR(pgcontext.>)
);
CREATE OPERATOR pgcontext.= (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_eq,
    COMMUTATOR = OPERATOR(pgcontext.=),
    NEGATOR = OPERATOR(pgcontext.<>)
);
CREATE OPERATOR pgcontext.<> (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_ne,
    COMMUTATOR = OPERATOR(pgcontext.<>),
    NEGATOR = OPERATOR(pgcontext.=)
);
CREATE OPERATOR pgcontext.>= (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_ge,
    COMMUTATOR = OPERATOR(pgcontext.<=),
    NEGATOR = OPERATOR(pgcontext.<)
);
CREATE OPERATOR pgcontext.> (
    LEFTARG = sparsevec,
    RIGHTARG = sparsevec,
    FUNCTION = pgcontext.sparsevec_gt,
    COMMUTATOR = OPERATOR(pgcontext.<),
    NEGATOR = OPERATOR(pgcontext.<=)
);
CREATE OPERATOR CLASS pgcontext.sparsevec_ops
    DEFAULT FOR TYPE sparsevec USING btree AS
    OPERATOR 1 pgcontext.< (sparsevec, sparsevec),
    OPERATOR 2 pgcontext.<= (sparsevec, sparsevec),
    OPERATOR 3 pgcontext.= (sparsevec, sparsevec),
    OPERATOR 4 pgcontext.>= (sparsevec, sparsevec),
    OPERATOR 5 pgcontext.> (sparsevec, sparsevec),
    FUNCTION 1 pgcontext.sparsevec_cmp(sparsevec, sparsevec);

CREATE OPERATOR pgcontext.< (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_lt,
    COMMUTATOR = OPERATOR(pgcontext.>),
    NEGATOR = OPERATOR(pgcontext.>=)
);
CREATE OPERATOR pgcontext.<= (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_le,
    COMMUTATOR = OPERATOR(pgcontext.>=),
    NEGATOR = OPERATOR(pgcontext.>)
);
CREATE OPERATOR pgcontext.= (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_eq,
    COMMUTATOR = OPERATOR(pgcontext.=),
    NEGATOR = OPERATOR(pgcontext.<>)
);
CREATE OPERATOR pgcontext.<> (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_ne,
    COMMUTATOR = OPERATOR(pgcontext.<>),
    NEGATOR = OPERATOR(pgcontext.=)
);
CREATE OPERATOR pgcontext.>= (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_ge,
    COMMUTATOR = OPERATOR(pgcontext.<=),
    NEGATOR = OPERATOR(pgcontext.<)
);
CREATE OPERATOR pgcontext.> (
    LEFTARG = bitvec,
    RIGHTARG = bitvec,
    FUNCTION = pgcontext.bitvec_gt,
    COMMUTATOR = OPERATOR(pgcontext.<),
    NEGATOR = OPERATOR(pgcontext.<=)
);
CREATE OPERATOR CLASS pgcontext.bitvec_ops
    DEFAULT FOR TYPE bitvec USING btree AS
    OPERATOR 1 pgcontext.< (bitvec, bitvec),
    OPERATOR 2 pgcontext.<= (bitvec, bitvec),
    OPERATOR 3 pgcontext.= (bitvec, bitvec),
    OPERATOR 4 pgcontext.>= (bitvec, bitvec),
    OPERATOR 5 pgcontext.> (bitvec, bitvec),
    FUNCTION 1 pgcontext.bitvec_cmp(bitvec, bitvec);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/sparse_search.rs:159
-- pgcontext::sparse_search::search_sparse
CREATE  FUNCTION "search_sparse"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"query" SparseVec, /* SparseVec */
	"filter" TEXT, /* Option < String > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_sparse_collection_filtered_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1423
-- pgcontext::pgcontext::vector_variants::sparsevec_inner_product
CREATE  FUNCTION "sparsevec_inner_product"(
	"left" SparseVec, /* SparseVec */
	"right" SparseVec /* SparseVec */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:68
-- pgcontext::query_builders::query_sparse_nearest
CREATE  FUNCTION "query_sparse_nearest"(
	"vector_name" TEXT, /* String */
	"vector" SparseVec, /* SparseVec */
	"filter" jsonb, /* Option < JsonB > */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_sparse_nearest_filtered_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1650
-- pgcontext::pgcontext::vector_variants::sparsevec_sum_final
CREATE  FUNCTION "sparsevec_sum_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_sum_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1609
-- pgcontext::pgcontext::vector_variants::sparsevec_sum_transition
CREATE  FUNCTION "sparsevec_sum_transition"(
	"state" real[], /* :: std :: option :: Option < Vec < f32 > > */
	"value" SparseVec /* Option < SparseVec > */
) RETURNS real[] /* :: std :: option :: Option < Vec < f32 > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_sum_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:761
-- requires:
--   HalfVec
--   SparseVec
--   BitVec
--   halfvec_sum_transition
--   halfvec_sum_final
--   halfvec_avg_final
--   sparsevec_sum_transition
--   sparsevec_sum_final
--   sparsevec_avg_final
--   bitvec_or_transition
--   bitvec_and_transition
--   bitvec_bits_final


CREATE AGGREGATE pgcontext.sum(halfvec) (
    SFUNC = pgcontext.halfvec_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.halfvec_sum_final
);

CREATE AGGREGATE pgcontext.avg(halfvec) (
    SFUNC = pgcontext.halfvec_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.halfvec_avg_final
);

CREATE AGGREGATE pgcontext.sum(sparsevec) (
    SFUNC = pgcontext.sparsevec_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.sparsevec_sum_final
);

CREATE AGGREGATE pgcontext.avg(sparsevec) (
    SFUNC = pgcontext.sparsevec_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.sparsevec_avg_final
);

CREATE AGGREGATE pgcontext.bit_or(bitvec) (
    SFUNC = pgcontext.bitvec_or_transition,
    STYPE = boolean[],
    FINALFUNC = pgcontext.bitvec_bits_final
);

CREATE AGGREGATE pgcontext.bit_and(bitvec) (
    SFUNC = pgcontext.bitvec_and_transition,
    STYPE = boolean[],
    FINALFUNC = pgcontext.bitvec_bits_final
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1106
-- pgcontext::pgcontext::vector_variants::sparsevec_to_real_array
CREATE  FUNCTION "sparsevec_to_real_array"(
	"vector" SparseVec /* SparseVec */
) RETURNS real[] /* Vec < f32 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_to_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:139
-- pgcontext::vector_variant_typmods::sparsevec_typmod_in
CREATE  FUNCTION "sparsevec_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:146
-- pgcontext::vector_variant_typmods::sparsevec_typmod_out
CREATE  FUNCTION "sparsevec_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1293
-- pgcontext::pgcontext::vector_variants::sparsevec_values
CREATE  FUNCTION "sparsevec_values"(
	"vector" SparseVec /* SparseVec */
) RETURNS real[] /* Vec < f32 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_values_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/document_chunking.rs:495
-- pgcontext::document_chunking::stage_document_chunks
CREATE  FUNCTION "stage_document_chunks"(
	"job_id" bigint, /* i64 */
	"lease_token" bigint, /* i64 */
	"response" jsonb /* BoundedChunkResponse */
) RETURNS bool /* bool */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'stage_document_chunks_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:102
-- pgcontext::build_jobs::start_build_job
CREATE  FUNCTION "start_build_job"(
	"collection" TEXT, /* String */
	"artifact_kind" TEXT, /* String */
	"artifact_name" TEXT, /* String */
	"target_name" TEXT, /* String */
	"total_units" bigint /* i64 */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'start_build_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership.rs:54
-- pgcontext::pgvector_ownership::start_pgvector_ownership_conversion
CREATE  FUNCTION "start_pgvector_ownership_conversion"(
	"target" regclass, /* PgRelation */
	"column_name" TEXT, /* String */
	"mode" TEXT DEFAULT 'fast', /* String */
	"metric" TEXT DEFAULT 'cosine', /* String */
	"application_uses_column_lists" bool DEFAULT false, /* bool */
	"application_dependencies_reviewed" bool DEFAULT false /* bool */
) RETURNS TABLE (
	"conversion_id" bigint,  /* i64 */
	"mode" TEXT,  /* String */
	"status" TEXT,  /* String */
	"schema_name" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"column_name" TEXT,  /* String */
	"target_type" TEXT,  /* String */
	"total_rows" bigint,  /* i64 */
	"processed_rows" bigint,  /* i64 */
	"mismatch_count" bigint,  /* i64 */
	"validation_attestations" TEXT[],  /* Vec < String > */
	"next_command" TEXT,  /* Option < String > */
	"error_message" TEXT  /* Option < String > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'start_pgvector_ownership_conversion_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/telemetry.rs:30
-- pgcontext::telemetry::telemetry
CREATE  FUNCTION "telemetry"() RETURNS TABLE (
	"collection_name" TEXT,  /* String */
	"table_schema" TEXT,  /* Option < String > */
	"table_name" TEXT,  /* Option < String > */
	"has_source_table" bool,  /* bool */
	"source_table_exists" bool,  /* bool */
	"registered_vectors" bigint,  /* i64 */
	"active_points" bigint,  /* i64 */
	"deleted_points" bigint,  /* i64 */
	"filter_fields" bigint,  /* i64 */
	"hnsw_indexes" bigint,  /* i64 */
	"status" TelemetryStatus  /* TelemetryStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'telemetry_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:141
-- UInt8Vec

CREATE TYPE pgcontext.uint8vec;
CREATE FUNCTION pgcontext.uint8vec_out(input pgcontext.uint8vec)
RETURNS cstring IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'uint8vec_out_wrapper';
CREATE FUNCTION pgcontext.uint8vec_send(input pgcontext.uint8vec)
RETURNS bytea IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'uint8vec_send_wrapper';
CREATE FUNCTION pgcontext.uint8vec_typmod_input(input cstring, _type_oid oid, typmod integer)
RETURNS pgcontext.uint8vec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'uint8vec_typmod_input_wrapper';
CREATE FUNCTION pgcontext.uint8vec_typmod_receive(internal internal, _type_oid oid, typmod integer)
RETURNS pgcontext.uint8vec IMMUTABLE STRICT PARALLEL SAFE LANGUAGE c
AS 'MODULE_PATHNAME', 'uint8vec_typmod_receive_wrapper';
CREATE TYPE pgcontext.uint8vec (
    INTERNALLENGTH = variable,
    INPUT = pgcontext.uint8vec_typmod_input,
    OUTPUT = pgcontext.uint8vec_out,
    RECEIVE = pgcontext.uint8vec_typmod_receive,
    SEND = pgcontext.uint8vec_send,
    STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1363
-- pgcontext::pgcontext::vector_variants::uint8vec_inner_product
CREATE  FUNCTION "uint8vec_inner_product"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1369
-- pgcontext::pgcontext::vector_variants::uint8vec_negative_inner_product
CREATE  FUNCTION "uint8vec_negative_inner_product"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_negative_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1357
-- pgcontext::pgcontext::vector_variants::uint8vec_l2_distance
CREATE  FUNCTION "uint8vec_l2_distance"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:995
-- pgcontext::pgcontext::vector_variants::uint8vec_from_integer_array
CREATE  FUNCTION "uint8vec_from_integer_array"(
	"values" INT[] /* Vec < i32 > */
) RETURNS UInt8Vec /* UInt8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_from_integer_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:251
-- pgcontext::vector_variant_typmods::uint8vec_enforce_typmod
CREATE  FUNCTION "uint8vec_enforce_typmod"(
	"vector" UInt8Vec, /* UInt8Vec */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS UInt8Vec /* UInt8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1375
-- pgcontext::pgcontext::vector_variants::uint8vec_cosine_distance
CREATE  FUNCTION "uint8vec_cosine_distance"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_cosine_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:405
-- pgcontext::vector_variant_ordering::uint8vec_ne
CREATE  FUNCTION "uint8vec_ne"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:410
-- pgcontext::vector_variant_ordering::uint8vec_ge
CREATE  FUNCTION "uint8vec_ge"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1381
-- pgcontext::pgcontext::vector_variants::uint8vec_l1_distance
CREATE  FUNCTION "uint8vec_l1_distance"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_l1_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:676
-- requires:
--   Int8Vec
--   UInt8Vec
--   int8vec_l2_distance
--   int8vec_negative_inner_product
--   int8vec_cosine_distance
--   int8vec_l1_distance
--   uint8vec_l2_distance
--   uint8vec_negative_inner_product
--   uint8vec_cosine_distance
--   uint8vec_l1_distance


CREATE OPERATOR pgcontext.<-> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_l2_distance, COMMUTATOR = OPERATOR(pgcontext.<->));
CREATE OPERATOR pgcontext.<#> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_negative_inner_product, COMMUTATOR = OPERATOR(pgcontext.<#>));
CREATE OPERATOR pgcontext.<=> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_cosine_distance, COMMUTATOR = OPERATOR(pgcontext.<=>));
CREATE OPERATOR pgcontext.<+> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_l1_distance, COMMUTATOR = OPERATOR(pgcontext.<+>));
CREATE OPERATOR pgcontext.<-> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_l2_distance, COMMUTATOR = OPERATOR(pgcontext.<->));
CREATE OPERATOR pgcontext.<#> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_negative_inner_product, COMMUTATOR = OPERATOR(pgcontext.<#>));
CREATE OPERATOR pgcontext.<=> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_cosine_distance, COMMUTATOR = OPERATOR(pgcontext.<=>));
CREATE OPERATOR pgcontext.<+> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_l1_distance, COMMUTATOR = OPERATOR(pgcontext.<+>));
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1320
-- pgcontext::pgcontext::vector_variants::uint8vec_dims
CREATE  FUNCTION "uint8vec_dims"(
	"vector" UInt8Vec /* UInt8Vec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:400
-- pgcontext::vector_variant_ordering::uint8vec_eq
CREATE  FUNCTION "uint8vec_eq"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1214
-- pgcontext::pgcontext::vector_variants::uint8vec
CREATE  FUNCTION "uint8vec"(
	"input" TEXT /* & str */
) RETURNS UInt8Vec /* UInt8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:395
-- pgcontext::vector_variant_ordering::uint8vec_le
CREATE  FUNCTION "uint8vec_le"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:949
-- pgcontext::pgcontext::vector_variants::uint8vec_from_profile
CREATE  FUNCTION "uint8vec_from_profile"(
	"collection" TEXT, /* String */
	"profile_name" TEXT, /* String */
	"values" smallint[] /* Vec < i16 > */
) RETURNS UInt8Vec /* UInt8Vec */
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_from_profile_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:989
-- pgcontext::pgcontext::vector_variants::uint8vec_from_smallint_array
CREATE  FUNCTION "uint8vec_from_smallint_array"(
	"values" smallint[] /* Vec < i16 > */
) RETURNS UInt8Vec /* UInt8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_from_smallint_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:385
-- pgcontext::vector_variant_ordering::uint8vec_cmp
CREATE  FUNCTION "uint8vec_cmp"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:415
-- pgcontext::vector_variant_ordering::uint8vec_gt
CREATE  FUNCTION "uint8vec_gt"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:390
-- pgcontext::vector_variant_ordering::uint8vec_lt
CREATE  FUNCTION "uint8vec_lt"(
	"left" UInt8Vec, /* UInt8Vec */
	"right" UInt8Vec /* UInt8Vec */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_ordering.rs:195
-- requires:
--   Int8Vec
--   UInt8Vec
--   int8vec_lt
--   int8vec_le
--   int8vec_eq
--   int8vec_ne
--   int8vec_ge
--   int8vec_gt
--   int8vec_cmp
--   uint8vec_lt
--   uint8vec_le
--   uint8vec_eq
--   uint8vec_ne
--   uint8vec_ge
--   uint8vec_gt
--   uint8vec_cmp


CREATE OPERATOR pgcontext.< (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_lt, COMMUTATOR = OPERATOR(pgcontext.>), NEGATOR = OPERATOR(pgcontext.>=));
CREATE OPERATOR pgcontext.<= (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_le, COMMUTATOR = OPERATOR(pgcontext.>=), NEGATOR = OPERATOR(pgcontext.>));
CREATE OPERATOR pgcontext.= (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_eq, COMMUTATOR = OPERATOR(pgcontext.=), NEGATOR = OPERATOR(pgcontext.<>));
CREATE OPERATOR pgcontext.<> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_ne, COMMUTATOR = OPERATOR(pgcontext.<>), NEGATOR = OPERATOR(pgcontext.=));
CREATE OPERATOR pgcontext.>= (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_ge, COMMUTATOR = OPERATOR(pgcontext.<=), NEGATOR = OPERATOR(pgcontext.<));
CREATE OPERATOR pgcontext.> (LEFTARG = int8vec, RIGHTARG = int8vec, FUNCTION = pgcontext.int8vec_gt, COMMUTATOR = OPERATOR(pgcontext.<), NEGATOR = OPERATOR(pgcontext.<=));
CREATE OPERATOR CLASS pgcontext.int8vec_ops DEFAULT FOR TYPE int8vec USING btree AS
    OPERATOR 1 pgcontext.< (int8vec, int8vec), OPERATOR 2 pgcontext.<= (int8vec, int8vec),
    OPERATOR 3 pgcontext.= (int8vec, int8vec), OPERATOR 4 pgcontext.>= (int8vec, int8vec),
    OPERATOR 5 pgcontext.> (int8vec, int8vec), FUNCTION 1 pgcontext.int8vec_cmp(int8vec, int8vec);

CREATE OPERATOR pgcontext.< (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_lt, COMMUTATOR = OPERATOR(pgcontext.>), NEGATOR = OPERATOR(pgcontext.>=));
CREATE OPERATOR pgcontext.<= (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_le, COMMUTATOR = OPERATOR(pgcontext.>=), NEGATOR = OPERATOR(pgcontext.>));
CREATE OPERATOR pgcontext.= (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_eq, COMMUTATOR = OPERATOR(pgcontext.=), NEGATOR = OPERATOR(pgcontext.<>));
CREATE OPERATOR pgcontext.<> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_ne, COMMUTATOR = OPERATOR(pgcontext.<>), NEGATOR = OPERATOR(pgcontext.=));
CREATE OPERATOR pgcontext.>= (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_ge, COMMUTATOR = OPERATOR(pgcontext.<=), NEGATOR = OPERATOR(pgcontext.<));
CREATE OPERATOR pgcontext.> (LEFTARG = uint8vec, RIGHTARG = uint8vec, FUNCTION = pgcontext.uint8vec_gt, COMMUTATOR = OPERATOR(pgcontext.<), NEGATOR = OPERATOR(pgcontext.<=));
CREATE OPERATOR CLASS pgcontext.uint8vec_ops DEFAULT FOR TYPE uint8vec USING btree AS
    OPERATOR 1 pgcontext.< (uint8vec, uint8vec), OPERATOR 2 pgcontext.<= (uint8vec, uint8vec),
    OPERATOR 3 pgcontext.= (uint8vec, uint8vec), OPERATOR 4 pgcontext.>= (uint8vec, uint8vec),
    OPERATOR 5 pgcontext.> (uint8vec, uint8vec), FUNCTION 1 pgcontext.uint8vec_cmp(uint8vec, uint8vec);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1483
-- pgcontext::pgcontext::vector_variants::uint8vec_sum_transition
CREATE  FUNCTION "uint8vec_sum_transition"(
	"state" bigint[], /* :: std :: option :: Option < Vec < i64 > > */
	"value" UInt8Vec /* Option < UInt8Vec > */
) RETURNS bigint[] /* :: std :: option :: Option < Vec < i64 > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_sum_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:566
-- requires:
--   Int8Vec
--   UInt8Vec
--   int8vec_sum_transition
--   uint8vec_sum_transition
--   integer_vector_sum_final
--   integer_vector_avg_final


CREATE AGGREGATE pgcontext.sum(int8vec) (
    SFUNC = pgcontext.int8vec_sum_transition,
    STYPE = bigint[],
    FINALFUNC = pgcontext.integer_vector_sum_final
);
CREATE AGGREGATE pgcontext.avg(int8vec) (
    SFUNC = pgcontext.int8vec_sum_transition,
    STYPE = bigint[],
    FINALFUNC = pgcontext.integer_vector_avg_final
);
CREATE AGGREGATE pgcontext.sum(uint8vec) (
    SFUNC = pgcontext.uint8vec_sum_transition,
    STYPE = bigint[],
    FINALFUNC = pgcontext.integer_vector_sum_final
);
CREATE AGGREGATE pgcontext.avg(uint8vec) (
    SFUNC = pgcontext.uint8vec_sum_transition,
    STYPE = bigint[],
    FINALFUNC = pgcontext.integer_vector_avg_final
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1007
-- pgcontext::pgcontext::vector_variants::uint8vec_to_smallint_array
CREATE  FUNCTION "uint8vec_to_smallint_array"(
	"vector" UInt8Vec /* UInt8Vec */
) RETURNS smallint[] /* Vec < i16 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_to_smallint_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:181
-- pgcontext::vector_variant_typmods::uint8vec_typmod_in
CREATE  FUNCTION "uint8vec_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:518
-- pgcontext::pgcontext::vector_variants::uint8vec_typmod_input
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:188
-- pgcontext::vector_variant_typmods::uint8vec_typmod_out
CREATE  FUNCTION "uint8vec_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:525
-- pgcontext::pgcontext::vector_variants::uint8vec_typmod_receive
-- Skipped due to `#[pgrx(sql = false)]`
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:430
-- pgcontext::build_jobs::update_build_job
CREATE  FUNCTION "update_build_job"(
	"build_job_id" bigint, /* i64 */
	"processed_units" bigint, /* i64 */
	"status" TEXT, /* String */
	"error_message" TEXT DEFAULT NULL /* Option < String > */
) RETURNS TABLE (
	"build_job_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"artifact_kind" TEXT,  /* String */
	"artifact_name" TEXT,  /* String */
	"target_name" TEXT,  /* String */
	"status" BuildJobStatus,  /* BuildJobStatus */
	"backend_pid" INT,  /* Option < i32 > */
	"attempt" INT,  /* i32 */
	"processed_units" bigint,  /* i64 */
	"total_units" bigint,  /* i64 */
	"cancel_requested" bool,  /* bool */
	"error_message" TEXT  /* Option < String > */
)
SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'update_build_job_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/embedding_migrations.rs:106
-- pgcontext::embedding_migrations::update_embedding_migration
CREATE  FUNCTION "update_embedding_migration"(
	"migration_id" bigint, /* i64 */
	"processed_points" bigint, /* i64 */
	"status" TEXT /* String */
) RETURNS TABLE (
	"migration_id" bigint,  /* i64 */
	"collection_name" TEXT,  /* String */
	"source_profile" TEXT,  /* String */
	"target_profile" TEXT,  /* String */
	"status" EmbeddingMigrationStatus,  /* EmbeddingMigrationStatus */
	"total_points" bigint,  /* i64 */
	"processed_points" bigint  /* i64 */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'update_embedding_migration_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/points.rs:59
-- pgcontext::points::upsert_points
CREATE  FUNCTION "upsert_points"(
	"collection_name" TEXT, /* String */
	"source_keys" TEXT[] /* Vec < String > */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"inserted" bool  /* bool */
)
STRICT SECURITY DEFINER
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'upsert_points_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/operations.rs:291
-- pgcontext::operations::vacuum_advice
CREATE  FUNCTION "vacuum_advice"(
	"index_name" TEXT /* String */
) RETURNS TABLE (
	"index_schema" TEXT,  /* String */
	"index_name" TEXT,  /* String */
	"table_schema" TEXT,  /* String */
	"table_name" TEXT,  /* String */
	"access_method" TEXT,  /* String */
	"estimated_index_tuples" bigint,  /* i64 */
	"index_pages" bigint,  /* i64 */
	"dead_table_tuples" bigint,  /* i64 */
	"status" VacuumAdviceStatus  /* VacuumAdviceStatus */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vacuum_advice_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:307
-- pgcontext::artifact_segments::validate_artifact_segment
CREATE  FUNCTION "validate_artifact_segment"(
	"segment" bytea /* Vec < u8 > */
) RETURNS TABLE (
	"kind" TEXT,  /* String */
	"payload_bytes" bigint,  /* i64 */
	"checksum" bigint  /* i64 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'validate_artifact_segment_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/artifact_segments.rs:337
-- pgcontext::artifact_segments::validate_hnsw_graph_artifact
CREATE  FUNCTION "validate_hnsw_graph_artifact"(
	"segment" bytea /* Vec < u8 > */
) RETURNS TABLE (
	"record_count" bigint,  /* i64 */
	"dimensions" INT,  /* i32 */
	"base_neighbor_count" bigint  /* i64 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'validate_hnsw_graph_artifact_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:91
-- Vector
CREATE TYPE Vector;

-- crates/context-pg/src/vector.rs:91
-- pgcontext::pgcontext::vector::vector_in
CREATE  FUNCTION "vector_in"(
	"input" cstring /* Option < & :: core :: ffi :: CStr > */
) RETURNS Vector /* Option < Vector > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_in_wrapper';

-- crates/context-pg/src/vector.rs:91
-- pgcontext::pgcontext::vector::vector_out
CREATE  FUNCTION "vector_out"(
	"input" Vector /* Vector */
) RETURNS cstring /* :: pgrx :: ffi :: CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_out_wrapper';

-- crates/context-pg/src/vector.rs:91
-- Vector
CREATE TYPE Vector (
	INTERNALLENGTH = variable,
	INPUT = vector_in, /* pgcontext::pgcontext::vector::vector_in */
	OUTPUT = vector_out, /* pgcontext::pgcontext::vector::vector_out */
	STORAGE = extended
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/late_interaction_catalog_schema.rs:9
-- requires:
--   Vector
--   create_catalog_tables


CREATE TABLE pgcontext._collection_late_interaction (
    collection_id bigint PRIMARY KEY
        REFERENCES pgcontext._collections(collection_id) ON DELETE CASCADE,
    source_table_oid oid NOT NULL,
    source_schema_name text NOT NULL,
    source_table_name text NOT NULL,
    token_column_name text NOT NULL,
    token_attnum int2 NOT NULL,
    dimensions int4,
    hnsw_index_oid oid,
    point_count bigint NOT NULL DEFAULT 0 CHECK (point_count >= 0),
    token_count bigint NOT NULL DEFAULT 0 CHECK (token_count >= 0),
    status text NOT NULL DEFAULT 'building'
        CHECK (status IN ('building', 'ready', 'stale', 'failed')),
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    CHECK (dimensions IS NULL OR dimensions > 0),
    CHECK ((status = 'ready') = (dimensions IS NOT NULL AND hnsw_index_oid IS NOT NULL))
);

ALTER TABLE pgcontext._collection_points
    ADD CONSTRAINT pgcontext_collection_points_collection_point_unique
    UNIQUE (collection_id, point_id);

CREATE TABLE pgcontext._collection_late_interaction_tokens (
    token_id bigint GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    collection_id bigint NOT NULL,
    point_id bigint NOT NULL,
    token_ordinal int4 NOT NULL CHECK (token_ordinal > 0),
    token_vector vector NOT NULL,
    created_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    updated_at timestamptz NOT NULL DEFAULT pg_catalog.now(),
    FOREIGN KEY (collection_id, point_id)
        REFERENCES pgcontext._collection_points(collection_id, point_id)
        ON DELETE CASCADE,
    UNIQUE (collection_id, point_id, token_ordinal)
);

CREATE VIEW pgcontext._visible_collection_late_interaction
WITH (security_barrier = true) AS
SELECT registrations.*
  FROM pgcontext._collection_late_interaction AS registrations
  JOIN pgcontext._collections AS collections USING (collection_id)
 WHERE pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');

GRANT SELECT ON pgcontext._visible_collection_late_interaction TO PUBLIC;

CREATE FUNCTION pgcontext._capture_late_interaction_tokens()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._collection_late_interaction%ROWTYPE;
    selected_record record;
    current_source_key text;
    previous_source_key text;
    token_vectors pgcontext.vector[];
    point bigint;
    minimum_dimensions int4;
    maximum_dimensions int4;
    deleted_token_count bigint;
    replacement_token_count bigint;
BEGIN
    SELECT *
      INTO registration
      FROM pgcontext._collection_late_interaction
     WHERE collection_id = TG_ARGV[0]::bigint;

    IF NOT FOUND OR registration.source_table_oid <> TG_RELID THEN
        RAISE EXCEPTION 'late-interaction source trigger binding is stale for relation %', TG_RELID
            USING ERRCODE = '55000';
    END IF;

    IF TG_OP IN ('UPDATE', 'DELETE') THEN
        previous_source_key := pg_catalog.to_jsonb(OLD)->>'id';
        IF previous_source_key IS NULL OR previous_source_key = '' THEN
            RAISE EXCEPTION 'late-interaction source key id must not be null or empty'
                USING ERRCODE = '22023';
        END IF;
    END IF;

    IF TG_OP = 'DELETE' THEN
        DELETE FROM pgcontext._collection_late_interaction_tokens AS tokens
         USING pgcontext._collection_points AS points
         WHERE tokens.collection_id = registration.collection_id
           AND tokens.point_id = points.point_id
           AND points.collection_id = registration.collection_id
           AND points.source_key = previous_source_key;
        GET DIAGNOSTICS deleted_token_count = ROW_COUNT;

        IF deleted_token_count > 0 THEN
            UPDATE pgcontext._collection_late_interaction
               SET point_count = point_count - 1,
                   token_count = token_count - deleted_token_count,
                   updated_at = pg_catalog.now()
             WHERE collection_id = registration.collection_id;
        END IF;

        UPDATE pgcontext._collection_points
           SET deleted_at = coalesce(deleted_at, pg_catalog.now()),
               updated_at = pg_catalog.now()
         WHERE collection_id = registration.collection_id
           AND source_key = previous_source_key;
        RETURN OLD;
    END IF;

    current_source_key := pg_catalog.to_jsonb(NEW)->>'id';
    IF current_source_key IS NULL OR current_source_key = '' THEN
        RAISE EXCEPTION 'late-interaction source key id must not be null or empty'
            USING ERRCODE = '22023';
    END IF;

    EXECUTE pg_catalog.format(
        'SELECT ($1).%I::pgcontext.vector[] AS token_vectors',
        registration.token_column_name
    )
    INTO selected_record
    USING NEW;
    token_vectors := selected_record.token_vectors;

    IF token_vectors IS NULL
       OR pg_catalog.cardinality(token_vectors) = 0
       OR pg_catalog.array_position(token_vectors, NULL) IS NOT NULL THEN
        RAISE EXCEPTION 'late-interaction token source must contain at least one non-null vector for source key %', current_source_key
            USING ERRCODE = '22023';
    END IF;
    IF pg_catalog.cardinality(token_vectors) > 16384 THEN
        RAISE EXCEPTION 'late-interaction token count exceeds per-point limit 16384 for source key %', current_source_key
            USING ERRCODE = '54000';
    END IF;

    SELECT pg_catalog.min(pgcontext.vector_dims(token)),
           pg_catalog.max(pgcontext.vector_dims(token))
      INTO minimum_dimensions, maximum_dimensions
      FROM pg_catalog.unnest(token_vectors) AS token;
    IF minimum_dimensions IS NULL OR minimum_dimensions <> maximum_dimensions THEN
        RAISE EXCEPTION 'late-interaction token dimensions must be uniform for source key %', current_source_key
            USING ERRCODE = '22023';
    END IF;
    IF registration.dimensions IS NOT NULL
       AND registration.dimensions <> minimum_dimensions THEN
        RAISE EXCEPTION 'late-interaction token dimension mismatch: expected %, found % for source key %',
            registration.dimensions,
            minimum_dimensions,
            current_source_key
            USING ERRCODE = '22023';
    END IF;

    IF TG_OP = 'UPDATE' AND previous_source_key <> current_source_key THEN
        DELETE FROM pgcontext._collection_late_interaction_tokens AS tokens
         USING pgcontext._collection_points AS points
         WHERE tokens.collection_id = registration.collection_id
           AND tokens.point_id = points.point_id
           AND points.collection_id = registration.collection_id
           AND points.source_key = previous_source_key;
        GET DIAGNOSTICS deleted_token_count = ROW_COUNT;
        IF deleted_token_count > 0 THEN
            UPDATE pgcontext._collection_late_interaction
               SET point_count = point_count - 1,
                   token_count = token_count - deleted_token_count,
                   updated_at = pg_catalog.now()
             WHERE collection_id = registration.collection_id;
        END IF;
        UPDATE pgcontext._collection_points
           SET deleted_at = coalesce(deleted_at, pg_catalog.now()),
               updated_at = pg_catalog.now()
         WHERE collection_id = registration.collection_id
           AND source_key = previous_source_key;
    END IF;

    INSERT INTO pgcontext._collection_points (collection_id, source_key)
    VALUES (registration.collection_id, current_source_key)
    ON CONFLICT (collection_id, source_key) DO UPDATE
        SET deleted_at = NULL,
            updated_at = pg_catalog.now()
    RETURNING point_id INTO point;

    DELETE FROM pgcontext._collection_late_interaction_tokens
     WHERE collection_id = registration.collection_id
       AND point_id = point;
    GET DIAGNOSTICS replacement_token_count = ROW_COUNT;
    INSERT INTO pgcontext._collection_late_interaction_tokens (
        collection_id,
        point_id,
        token_ordinal,
        token_vector
    )
    SELECT registration.collection_id,
           point,
           ordinal::int4,
           token
      FROM pg_catalog.unnest(token_vectors) WITH ORDINALITY AS expanded(token, ordinal);

    UPDATE pgcontext._collection_late_interaction
       SET dimensions = coalesce(dimensions, minimum_dimensions),
           point_count = point_count + CASE WHEN replacement_token_count = 0 THEN 1 ELSE 0 END,
           token_count = token_count
               - replacement_token_count
               + pg_catalog.cardinality(token_vectors),
           updated_at = pg_catalog.now()
     WHERE collection_id = registration.collection_id;
    RETURN NEW;
END;
$$;

CREATE FUNCTION pgcontext._begin_late_interaction_registration(
    p_collection_id bigint,
    p_source_table_oid oid,
    p_source_schema_name text,
    p_source_table_name text,
    p_token_column_name text,
    p_token_attnum int2
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    trigger_name text;
BEGIN
    IF NOT EXISTS (
        SELECT 1
          FROM pgcontext._collections AS collections
          JOIN pg_catalog.pg_class AS source_class
            ON source_class.oid = collections.source_table_oid
          JOIN pg_catalog.pg_namespace AS source_namespace
            ON source_namespace.oid = source_class.relnamespace
          JOIN pg_catalog.pg_attribute AS token_attribute
            ON token_attribute.attrelid = source_class.oid
           AND token_attribute.attname = p_token_column_name
           AND token_attribute.attnum = p_token_attnum
           AND token_attribute.attnum > 0
           AND NOT token_attribute.attisdropped
         WHERE collections.collection_id = p_collection_id
           AND pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
           AND source_class.oid = p_source_table_oid
           AND source_namespace.nspname = p_source_schema_name
           AND source_class.relname = p_source_table_name
           AND source_class.relkind = 'r'
           AND token_attribute.atttypid = 'pgcontext.vector[]'::pg_catalog.regtype
    ) THEN
        RAISE EXCEPTION 'invalid or unauthorized late-interaction registration for collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;
    IF NOT pg_catalog.has_table_privilege(SESSION_USER, p_source_table_oid, 'SELECT') THEN
        RAISE EXCEPTION 'permission denied for late-interaction source table %.%',
            p_source_schema_name,
            p_source_table_name
            USING ERRCODE = '42501';
    END IF;

    INSERT INTO pgcontext._collection_late_interaction (
        collection_id,
        source_table_oid,
        source_schema_name,
        source_table_name,
        token_column_name,
        token_attnum
    )
    VALUES (
        p_collection_id,
        p_source_table_oid,
        p_source_schema_name,
        p_source_table_name,
        p_token_column_name,
        p_token_attnum
    );

    trigger_name := pg_catalog.format('pgcontext_late_interaction_%s', p_collection_id);
    EXECUTE pg_catalog.format(
        'CREATE TRIGGER %I AFTER INSERT OR UPDATE OF id, %I OR DELETE ON %I.%I '
        'FOR EACH ROW EXECUTE FUNCTION pgcontext._capture_late_interaction_tokens(%L)',
        trigger_name,
        p_token_column_name,
        p_source_schema_name,
        p_source_table_name,
        p_collection_id::text
    );
END;
$$;

CREATE FUNCTION pgcontext._store_late_interaction_tokens(
    p_collection_id bigint,
    p_source_key text
)
RETURNS bigint
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._collection_late_interaction%ROWTYPE;
    point bigint;
    minimum_dimensions int4;
    maximum_dimensions int4;
    replacement_token_count bigint;
    token_vectors pgcontext.vector[];
    loaded_row_count bigint;
BEGIN
    SELECT registrations.*
      INTO registration
      FROM pgcontext._collection_late_interaction AS registrations
      JOIN pgcontext._collections AS collections USING (collection_id)
     WHERE registrations.collection_id = p_collection_id
       AND pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER');
    IF NOT FOUND
       OR NOT pg_catalog.has_table_privilege(
           SESSION_USER,
           registration.source_table_oid,
           'SELECT'
       ) THEN
        RAISE EXCEPTION 'permission denied for late-interaction collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;
    IF p_source_key IS NULL OR p_source_key = '' THEN
        RAISE EXCEPTION 'late-interaction source key must not be null or empty'
            USING ERRCODE = '22023';
    END IF;

    EXECUTE pg_catalog.format(
        'SELECT source.%I::pgcontext.vector[]
           FROM %I.%I AS source
          WHERE source.id::text = $1
          LIMIT 1',
        registration.token_column_name,
        registration.source_schema_name,
        registration.source_table_name
    ) INTO token_vectors USING p_source_key;
    GET DIAGNOSTICS loaded_row_count = ROW_COUNT;
    IF loaded_row_count = 0 THEN
        RAISE EXCEPTION 'late-interaction source row does not exist for source key %', p_source_key
            USING ERRCODE = '42704';
    END IF;
    IF token_vectors IS NULL
       OR pg_catalog.cardinality(token_vectors) = 0
       OR pg_catalog.array_position(token_vectors, NULL) IS NOT NULL THEN
        RAISE EXCEPTION 'late-interaction token source must contain at least one non-null vector for source key %', p_source_key
            USING ERRCODE = '22023';
    END IF;
    IF pg_catalog.cardinality(token_vectors) > 16384 THEN
        RAISE EXCEPTION 'late-interaction token count exceeds per-point limit 16384 for source key %', p_source_key
            USING ERRCODE = '54000';
    END IF;

    SELECT pg_catalog.min(pgcontext.vector_dims(token)),
           pg_catalog.max(pgcontext.vector_dims(token))
      INTO minimum_dimensions, maximum_dimensions
      FROM pg_catalog.unnest(token_vectors) AS token;
    IF minimum_dimensions IS NULL OR minimum_dimensions <> maximum_dimensions THEN
        RAISE EXCEPTION 'late-interaction token dimensions must be uniform for source key %', p_source_key
            USING ERRCODE = '22023';
    END IF;
    IF registration.dimensions IS NOT NULL
       AND registration.dimensions <> minimum_dimensions THEN
        RAISE EXCEPTION 'late-interaction token dimension mismatch: expected %, found % for source key %',
            registration.dimensions,
            minimum_dimensions,
            p_source_key
            USING ERRCODE = '22023';
    END IF;

    INSERT INTO pgcontext._collection_points (collection_id, source_key)
    VALUES (p_collection_id, p_source_key)
    ON CONFLICT (collection_id, source_key) DO UPDATE
        SET updated_at = pg_catalog.now()
    RETURNING point_id INTO point;

    DELETE FROM pgcontext._collection_late_interaction_tokens
     WHERE collection_id = p_collection_id
       AND point_id = point;
    GET DIAGNOSTICS replacement_token_count = ROW_COUNT;
    INSERT INTO pgcontext._collection_late_interaction_tokens (
        collection_id,
        point_id,
        token_ordinal,
        token_vector
    )
    SELECT p_collection_id,
           point,
           ordinal::int4,
           token
      FROM pg_catalog.unnest(token_vectors) WITH ORDINALITY AS expanded(token, ordinal);

    UPDATE pgcontext._collection_late_interaction
       SET dimensions = coalesce(dimensions, minimum_dimensions),
           point_count = point_count + CASE WHEN replacement_token_count = 0 THEN 1 ELSE 0 END,
           token_count = token_count
               - replacement_token_count
               + pg_catalog.cardinality(token_vectors),
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id;
    RETURN point;
END;
$$;

CREATE FUNCTION pgcontext._finish_late_interaction_registration(
    p_collection_id bigint,
    p_dimensions int4
)
RETURNS oid
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    index_name text;
    index_oid oid;
BEGIN
    IF p_dimensions <= 0 OR NOT EXISTS (
        SELECT 1
          FROM pgcontext._collection_late_interaction AS registrations
          JOIN pgcontext._collections AS collections USING (collection_id)
         WHERE registrations.collection_id = p_collection_id
           AND registrations.dimensions = p_dimensions
           AND pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
    ) THEN
        RAISE EXCEPTION 'invalid or unauthorized late-interaction finalization for collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    index_name := pg_catalog.format('pgcontext_late_interaction_%s_hnsw', p_collection_id);
    EXECUTE pg_catalog.format(
        'CREATE INDEX %I ON pgcontext._collection_late_interaction_tokens '
        'USING pgcontext_hnsw ((token_vector::pgcontext.vector(%s)) pgcontext.vector_hnsw_ip_ops) '
        'WHERE collection_id = %s',
        index_name,
        p_dimensions,
        p_collection_id
    );
    index_oid := pg_catalog.to_regclass(
        pg_catalog.format('pgcontext.%I', index_name)
    )::oid;
    UPDATE pgcontext._collection_late_interaction
       SET hnsw_index_oid = index_oid,
           status = 'ready',
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id;
    RETURN index_oid;
END;
$$;

CREATE FUNCTION pgcontext._late_interaction_ann_candidate_points(
    p_collection_id bigint,
    p_query vector,
    p_limit int4
)
RETURNS TABLE (point_id bigint)
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._collection_late_interaction%ROWTYPE;
    previous_enable_seqscan text;
BEGIN
    IF p_limit IS NULL OR p_limit <= 0 THEN
        RAISE EXCEPTION 'late-interaction ANN candidate limit must be positive'
            USING ERRCODE = '22023';
    END IF;

    SELECT registrations.*
      INTO registration
      FROM pgcontext._collection_late_interaction AS registrations
      JOIN pgcontext._collections AS collections USING (collection_id)
      JOIN pg_catalog.pg_index AS index_metadata
        ON index_metadata.indexrelid = registrations.hnsw_index_oid
      JOIN pg_catalog.pg_class AS index_class
        ON index_class.oid = index_metadata.indexrelid
      JOIN pg_catalog.pg_am AS access_method
        ON access_method.oid = index_class.relam
      JOIN pg_catalog.pg_opclass AS operator_class
        ON operator_class.oid = index_metadata.indclass[0]
      JOIN pg_catalog.pg_namespace AS operator_namespace
        ON operator_namespace.oid = operator_class.opcnamespace
     WHERE registrations.collection_id = p_collection_id
       AND pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
       AND registrations.status = 'ready'
       AND registrations.dimensions IS NOT NULL
       AND index_metadata.indrelid = 'pgcontext._collection_late_interaction_tokens'::regclass
       AND index_metadata.indisvalid
       AND index_metadata.indisready
       AND access_method.amname = 'pgcontext_hnsw'
       AND index_class.relname = pg_catalog.format(
           'pgcontext_late_interaction_%s_hnsw',
           registrations.collection_id
       )
       AND index_metadata.indnkeyatts = 1
       AND index_metadata.indnatts = 1
       AND operator_namespace.nspname = 'pgcontext'
       AND operator_class.opcname = 'vector_hnsw_ip_ops'
       AND pg_catalog.regexp_replace(
           pg_catalog.pg_get_expr(
               index_metadata.indpred,
               index_metadata.indrelid,
               true
           ),
           '[()[:space:]]',
           '',
           'g'
       ) = pg_catalog.format('collection_id=%s', registrations.collection_id)
       AND pg_catalog.regexp_replace(
           pg_catalog.pg_get_indexdef(index_metadata.indexrelid, 1, true),
           '[()[:space:]]',
           '',
           'g'
       ) IN (
           pg_catalog.format('token_vector::vector%s', registrations.dimensions),
           pg_catalog.format('token_vector::pgcontext.vector%s', registrations.dimensions)
       );
    IF NOT FOUND THEN
        RAISE EXCEPTION 'late-interaction ANN generation is not ready or is unauthorized for collection %', p_collection_id
            USING ERRCODE = '55000';
    END IF;
    IF pgcontext.vector_dims(p_query) <> registration.dimensions THEN
        RAISE EXCEPTION 'late-interaction query dimension mismatch: expected %, found %',
            registration.dimensions,
            pgcontext.vector_dims(p_query)
            USING ERRCODE = '22023';
    END IF;

    previous_enable_seqscan := pg_catalog.current_setting('enable_seqscan');
    PERFORM pg_catalog.set_config('enable_seqscan', 'off', true);
    BEGIN
        RETURN QUERY EXECUTE pg_catalog.format(
            'SELECT tokens.point_id
               FROM pgcontext._collection_late_interaction_tokens AS tokens
              WHERE tokens.collection_id = $1
              ORDER BY (tokens.token_vector::pgcontext.vector(%s)) OPERATOR(pgcontext.<#>) $2
              LIMIT $3',
            registration.dimensions
        ) USING p_collection_id, p_query, p_limit;
    EXCEPTION WHEN others THEN
        PERFORM pg_catalog.set_config('enable_seqscan', previous_enable_seqscan, true);
        RAISE;
    END;
    PERFORM pg_catalog.set_config('enable_seqscan', previous_enable_seqscan, true);
END;
$$;

CREATE FUNCTION pgcontext._prepare_late_interaction_repair(
    p_collection_id bigint,
    p_source_table_oid oid,
    p_token_attnum int2
)
RETURNS void
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._collection_late_interaction%ROWTYPE;
    trigger_name text;
    index_name text;
BEGIN
    SELECT registrations.*
      INTO registration
      FROM pgcontext._collection_late_interaction AS registrations
      JOIN pgcontext._collections AS collections USING (collection_id)
      JOIN pg_catalog.pg_class AS source_class
        ON source_class.oid = p_source_table_oid
      JOIN pg_catalog.pg_namespace AS source_namespace
        ON source_namespace.oid = source_class.relnamespace
      JOIN pg_catalog.pg_attribute AS token_attribute
        ON token_attribute.attrelid = source_class.oid
       AND token_attribute.attname = registrations.token_column_name
       AND token_attribute.attnum = p_token_attnum
       AND token_attribute.attnum > 0
       AND NOT token_attribute.attisdropped
     WHERE registrations.collection_id = p_collection_id
       AND collections.source_table_oid = p_source_table_oid
       AND pg_catalog.pg_has_role(SESSION_USER, collections.owner_role, 'MEMBER')
       AND source_namespace.nspname = registrations.source_schema_name
       AND source_class.relname = registrations.source_table_name
       AND source_class.relkind = 'r'
       AND token_attribute.atttypid = 'pgcontext.vector[]'::pg_catalog.regtype;
    IF NOT FOUND OR NOT pg_catalog.has_table_privilege(
        SESSION_USER,
        p_source_table_oid,
        'SELECT'
    ) THEN
        RAISE EXCEPTION 'invalid or unauthorized late-interaction repair for collection %', p_collection_id
            USING ERRCODE = '42501';
    END IF;

    trigger_name := pg_catalog.format('pgcontext_late_interaction_%s', p_collection_id);
    EXECUTE pg_catalog.format(
        'DROP TRIGGER IF EXISTS %I ON %I.%I',
        trigger_name,
        registration.source_schema_name,
        registration.source_table_name
    );
    index_name := pg_catalog.format('pgcontext_late_interaction_%s_hnsw', p_collection_id);
    EXECUTE pg_catalog.format('DROP INDEX IF EXISTS pgcontext.%I', index_name);

    DELETE FROM pgcontext._collection_late_interaction_tokens
     WHERE collection_id = p_collection_id;
    UPDATE pgcontext._collection_late_interaction
       SET source_table_oid = p_source_table_oid,
           token_attnum = p_token_attnum,
           dimensions = NULL,
           hnsw_index_oid = NULL,
           point_count = 0,
           token_count = 0,
           status = 'building',
           updated_at = pg_catalog.now()
     WHERE collection_id = p_collection_id;

    EXECUTE pg_catalog.format(
        'CREATE TRIGGER %I AFTER INSERT OR UPDATE OF id, %I OR DELETE ON %I.%I '
        'FOR EACH ROW EXECUTE FUNCTION pgcontext._capture_late_interaction_tokens(%L)',
        trigger_name,
        registration.token_column_name,
        registration.source_schema_name,
        registration.source_table_name,
        p_collection_id::text
    );
END;
$$;

CREATE FUNCTION pgcontext._cleanup_late_interaction_registration()
RETURNS trigger
LANGUAGE plpgsql
SECURITY DEFINER
SET search_path = pg_catalog, pgcontext
AS $$
DECLARE
    registration pgcontext._collection_late_interaction%ROWTYPE;
    trigger_name text;
    index_name text;
    current_schema_name text;
    current_table_name text;
BEGIN
    SELECT *
      INTO registration
      FROM pgcontext._collection_late_interaction
     WHERE collection_id = OLD.collection_id;
    IF NOT FOUND THEN
        RETURN OLD;
    END IF;

    trigger_name := pg_catalog.format(
        'pgcontext_late_interaction_%s',
        OLD.collection_id
    );
    SELECT namespace.nspname, source_class.relname
      INTO current_schema_name, current_table_name
      FROM pg_catalog.pg_class AS source_class
      JOIN pg_catalog.pg_namespace AS namespace
        ON namespace.oid = source_class.relnamespace
     WHERE source_class.oid = registration.source_table_oid;
    IF FOUND THEN
        EXECUTE pg_catalog.format(
            'DROP TRIGGER IF EXISTS %I ON %I.%I',
            trigger_name,
            current_schema_name,
            current_table_name
        );
    END IF;

    index_name := pg_catalog.format(
        'pgcontext_late_interaction_%s_hnsw',
        OLD.collection_id
    );
    EXECUTE pg_catalog.format('DROP INDEX IF EXISTS pgcontext.%I', index_name);
    RETURN OLD;
END;
$$;

CREATE TRIGGER pgcontext_cleanup_late_interaction_registration
BEFORE DELETE ON pgcontext._collections
FOR EACH ROW
EXECUTE FUNCTION pgcontext._cleanup_late_interaction_registration();

SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_late_interaction',
    ''
);
SELECT pg_catalog.pg_extension_config_dump(
    'pgcontext._collection_late_interaction_tokens',
    ''
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:731
-- requires:
--   Vector
--   HalfVec
--   SparseVec
--   BitVec
--   halfvec_l2_distance
--   halfvec_negative_inner_product
--   halfvec_cosine_distance
--   halfvec_l1_distance
--   sparsevec_l2_distance
--   sparsevec_negative_inner_product
--   sparsevec_cosine_distance
--   sparsevec_l1_distance
--   bitvec_hamming_distance
--   bitvec_jaccard_distance


CREATE OPERATOR pgcontext.<#> (LEFTARG = halfvec, RIGHTARG = halfvec, FUNCTION = pgcontext.halfvec_negative_inner_product, COMMUTATOR = OPERATOR(pgcontext.<#>));
CREATE OPERATOR pgcontext.<=> (LEFTARG = halfvec, RIGHTARG = halfvec, FUNCTION = pgcontext.halfvec_cosine_distance, COMMUTATOR = OPERATOR(pgcontext.<=>));
CREATE OPERATOR pgcontext.<+> (LEFTARG = halfvec, RIGHTARG = halfvec, FUNCTION = pgcontext.halfvec_l1_distance, COMMUTATOR = OPERATOR(pgcontext.<+>));
CREATE OPERATOR pgcontext.<#> (LEFTARG = sparsevec, RIGHTARG = sparsevec, FUNCTION = pgcontext.sparsevec_negative_inner_product, COMMUTATOR = OPERATOR(pgcontext.<#>));
CREATE OPERATOR pgcontext.<=> (LEFTARG = sparsevec, RIGHTARG = sparsevec, FUNCTION = pgcontext.sparsevec_cosine_distance, COMMUTATOR = OPERATOR(pgcontext.<=>));
CREATE OPERATOR pgcontext.<+> (LEFTARG = sparsevec, RIGHTARG = sparsevec, FUNCTION = pgcontext.sparsevec_l1_distance, COMMUTATOR = OPERATOR(pgcontext.<+>));
CREATE OPERATOR pgcontext.<%> (LEFTARG = bitvec, RIGHTARG = bitvec, FUNCTION = pgcontext.bitvec_jaccard_distance, COMMUTATOR = OPERATOR(pgcontext.<%>));
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_datum.rs:209
-- requires:
--   pgcontext_bootstrap
--   Vector


CREATE FUNCTION pgcontext._l2_distance_fast(pgcontext.vector, pgcontext.vector)
RETURNS real
AS 'MODULE_PATHNAME', 'pgcontext_l2_distance_fast'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION pgcontext._l2_distance_fast8(pgcontext.vector, pgcontext.vector)
RETURNS double precision
AS 'MODULE_PATHNAME', 'pgcontext_l2_distance_fast8'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION pgcontext._negative_inner_product_fast(pgcontext.vector, pgcontext.vector)
RETURNS real
AS 'MODULE_PATHNAME', 'pgcontext_negative_inner_product_fast'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION pgcontext._cosine_distance_fast(pgcontext.vector, pgcontext.vector)
RETURNS real
AS 'MODULE_PATHNAME', 'pgcontext_cosine_distance_fast'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE FUNCTION pgcontext._l1_distance_fast(pgcontext.vector, pgcontext.vector)
RETURNS real
AS 'MODULE_PATHNAME', 'pgcontext_l1_distance_fast'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:183
-- requires:
--   Vector
--   create_vector_fast_distance_functions


CREATE OPERATOR pgcontext.<#> (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext._negative_inner_product_fast,
    COMMUTATOR = OPERATOR(pgcontext.<#>)
);

CREATE OPERATOR pgcontext.<=> (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext._cosine_distance_fast,
    COMMUTATOR = OPERATOR(pgcontext.<=>)
);

CREATE OPERATOR pgcontext.<+> (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext._l1_distance_fast,
    COMMUTATOR = OPERATOR(pgcontext.<+>)
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:585
-- pgcontext::pgcontext::vector::l2_distance
CREATE  FUNCTION "l2_distance"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:462
-- pgcontext::pgcontext::vector::vector_gt
CREATE  FUNCTION "vector_gt"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_gt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/grouped.rs:68
-- pgcontext::table_search::grouped::grouped_search
CREATE  FUNCTION "grouped_search"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"group_by" TEXT, /* String */
	"group_limit" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"group_value" TEXT,  /* String */
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'grouped_search_collection_named_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:603
-- pgcontext::pgcontext::vector::cosine_distance
CREATE  FUNCTION "cosine_distance"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'cosine_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1025
-- pgcontext::pgcontext::vector_variants::int8vec_from_vector
CREATE  FUNCTION "int8vec_from_vector"(
	"vector" Vector /* Vector */
) RETURNS Int8Vec /* Int8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_from_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:456
-- pgcontext::pgcontext::vector::vector_ge
CREATE  FUNCTION "vector_ge"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_ge_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction_ann.rs:351
-- pgcontext::hybrid_query::late_interaction_ann::search_late_interaction_ann
CREATE  FUNCTION "search_late_interaction_ann"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"candidates_per_query" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" double precision  /* f64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_owned_late_interaction_ann_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/grouped.rs:17
-- pgcontext::table_search::grouped::grouped_search
CREATE  FUNCTION "grouped_search"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"group_by" TEXT, /* String */
	"group_limit" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"group_value" TEXT,  /* String */
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'grouped_search_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction_ann.rs:1317
-- pgcontext::hybrid_query::late_interaction_ann::explain_late_interaction_ann
CREATE  FUNCTION "explain_late_interaction_ann"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"vector_column" TEXT, /* String */
	"token_table" TEXT, /* String */
	"token_source_key_column" TEXT, /* String */
	"token_vector_column" TEXT, /* String */
	"candidates_per_query" INT /* i32 */
) RETURNS TABLE (
	"stage" TEXT,  /* String */
	"detail" TEXT,  /* String */
	"branch" TEXT,  /* Option < String > */
	"strategy" TEXT,  /* String */
	"status" QueryExplainStatus,  /* QueryExplainStatus */
	"estimated_candidates" bigint,  /* Option < i64 > */
	"candidate_budget" bigint  /* Option < i64 > */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explain_late_interaction_ann_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:657
-- pgcontext::pgcontext::vector::rerank_quantized_candidates
CREATE  FUNCTION "rerank_quantized_candidates"(
	"query" Vector, /* Vector */
	"point_ids" bigint[], /* Vec < i64 > */
	"original_vectors" Vector[], /* Vec < Vector > */
	"metric" TEXT, /* String */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"score" real  /* f32 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rerank_quantized_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1019
-- pgcontext::pgcontext::vector_variants::uint8vec_to_vector
CREATE  FUNCTION "uint8vec_to_vector"(
	"vector" UInt8Vec /* UInt8Vec */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_to_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:597
-- pgcontext::pgcontext::vector::negative_inner_product
CREATE  FUNCTION "negative_inner_product"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'negative_inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:860
-- pgcontext::pgcontext::vector_variants::halfvec_to_vector
CREATE  FUNCTION "halfvec_to_vector"(
	"vector" HalfVec /* HalfVec */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'halfvec_to_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:535
-- requires:
--   Vector
--   HalfVec
--   halfvec_from_real_array
--   halfvec_from_integer_array
--   halfvec_from_double_array
--   halfvec_to_real_array
--   halfvec_to_vector


CREATE CAST (real[] AS halfvec)
    WITH FUNCTION pgcontext.halfvec_from_real_array(real[]);

CREATE CAST (integer[] AS halfvec)
    WITH FUNCTION pgcontext.halfvec_from_integer_array(integer[]);

CREATE CAST (double precision[] AS halfvec)
    WITH FUNCTION pgcontext.halfvec_from_double_array(double precision[]);

CREATE CAST (halfvec AS real[])
    WITH FUNCTION pgcontext.halfvec_to_real_array(halfvec)
    AS ASSIGNMENT;

CREATE CAST (halfvec AS vector)
    WITH FUNCTION pgcontext.halfvec_to_vector(halfvec)
    AS ASSIGNMENT;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/exact_first/search.rs:22
-- pgcontext::exact_first::search::exact_first_search
CREATE  FUNCTION "exact_first_search"(
	"collection" TEXT, /* String */
	"binding" TEXT, /* String */
	"vector" Vector, /* Vector */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'exact_first_search_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/quantization_sql.rs:27
-- pgcontext::quantization_sql::scalar_quantize
CREATE  FUNCTION "scalar_quantize"(
	"vector" Vector, /* Vector */
	"min" real, /* f32 */
	"max" real, /* f32 */
	"levels" INT /* i32 */
) RETURNS bytea /* Vec < u8 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'scalar_quantize_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/quantization_sql.rs:39
-- pgcontext::quantization_sql::scalar_reconstruct
CREATE  FUNCTION "scalar_reconstruct"(
	"codes" bytea, /* Vec < u8 > */
	"min" real, /* f32 */
	"max" real, /* f32 */
	"levels" INT /* i32 */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'scalar_reconstruct_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:444
-- pgcontext::pgcontext::vector::vector_eq
CREATE  FUNCTION "vector_eq"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_eq_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:729
-- pgcontext::hnsw_am::_hnsw_masked_candidates
CREATE  FUNCTION "_hnsw_masked_candidates"(
	"index_relation" regclass, /* PgRelation */
	"query" Vector, /* Vector */
	"allowed_heap_tids" anyarray, /* AnyArray */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"heap_tid" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_masked_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/quantization_sql.rs:66
-- pgcontext::quantization_sql::product_reconstruct
CREATE  FUNCTION "product_reconstruct"(
	"codes" bytea, /* Vec < u8 > */
	"subvector_dimensions" INT, /* i32 */
	"codebooks" jsonb /* JsonB */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'product_reconstruct_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:299
-- pgcontext::pgcontext::vector::vector_from_real_array
CREATE  FUNCTION "vector_from_real_array"(
	"values" real[] /* Vec < f32 > */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_from_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:434
-- pgcontext::table_search::candidate_recheck::_mmap_hnsw_artifact_candidates
CREATE  FUNCTION "_mmap_hnsw_artifact_candidates"(
	"collection" TEXT, /* String */
	"artifact_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"max_mapped_bytes" bigint, /* i64 */
	"candidate_limit" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"score" real,  /* f32 */
	"generation_high_water" bigint  /* i64 */
)
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'mmap_hnsw_artifact_candidates_internal_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:84
-- pgcontext::table_search::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"filter" TEXT, /* Option < String > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_filtered_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1117
-- pgcontext::pgcontext::vector_variants::sparsevec_from_vector
CREATE  FUNCTION "sparsevec_from_vector"(
	"vector" Vector /* Vector */
) RETURNS SparseVec /* SparseVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_from_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:237
-- pgcontext::table_search::candidate_recheck::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"filter" TEXT, /* Option < String > */
	"candidate_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_named_vector_filtered_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/quantization_sql.rs:54
-- pgcontext::quantization_sql::product_quantize
CREATE  FUNCTION "product_quantize"(
	"vector" Vector, /* Vector */
	"subvector_dimensions" INT, /* i32 */
	"codebooks" jsonb /* JsonB */
) RETURNS bytea /* Vec < u8 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'product_quantize_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:657
-- pgcontext::hnsw_am::_hnsw_candidates
CREATE  FUNCTION "_hnsw_candidates"(
	"index_relation" regclass, /* PgRelation */
	"query" Vector, /* Vector */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"heap_tid" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:136
-- pgcontext::table_search::candidate_recheck::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"candidate_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_named_vector_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction_ann.rs:1225
-- pgcontext::hybrid_query::late_interaction_ann::search_late_interaction_ann
CREATE  FUNCTION "search_late_interaction_ann"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"vector_column" TEXT, /* String */
	"token_table" TEXT, /* String */
	"token_source_key_column" TEXT, /* String */
	"token_vector_column" TEXT, /* String */
	"candidates_per_query" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" double precision  /* f64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_late_interaction_ann_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am.rs:358
-- pgcontext::hnsw_am::hnsw_l2_distance
CREATE  FUNCTION "hnsw_l2_distance"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS double precision /* f64 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'hnsw_l2_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query.rs:70
-- pgcontext::hybrid_query::query
CREATE  FUNCTION "query"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"text_query" TEXT, /* String */
	"lexical_source" TEXT, /* String */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" double precision  /* f64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:186
-- pgcontext::table_search::candidate_recheck::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"filter" TEXT, /* Option < String > */
	"candidate_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_filtered_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1032
-- pgcontext::pgcontext::vector_variants::uint8vec_from_vector
CREATE  FUNCTION "uint8vec_from_vector"(
	"vector" Vector /* Vector */
) RETURNS UInt8Vec /* UInt8Vec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'uint8vec_from_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:569
-- pgcontext::pgcontext::vector::vector_dims
CREATE  FUNCTION "vector_dims"(
	"vector" Vector /* Vector */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_dims_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:114
-- pgcontext::vector_variant_typmods::vector_enforce_typmod
CREATE  FUNCTION "vector_enforce_typmod"(
	"vector" Vector, /* Vector */
	"typmod" INT, /* i32 */
	"_explicit" bool /* bool */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_enforce_typmod_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:308
-- pgcontext::pgcontext::vector::vector_from_integer_array
CREATE  FUNCTION "vector_from_integer_array"(
	"values" INT[] /* Vec < i32 > */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_from_integer_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:320
-- pgcontext::pgcontext::vector::vector_from_double_array
CREATE  FUNCTION "vector_from_double_array"(
	"values" double precision[] /* Vec < f64 > */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_from_double_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/recommend.rs:109
-- pgcontext::table_search::recommend::recommend
CREATE  FUNCTION "recommend"(
	"collection" TEXT, /* String */
	"positive_vectors" Vector[], /* Vec < Vector > */
	"negative_vectors" Vector[], /* Vec < Vector > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'recommend_collection_from_vectors_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1127
-- pgcontext::pgcontext::vector_variants::sparsevec_to_vector
CREATE  FUNCTION "sparsevec_to_vector"(
	"vector" SparseVec /* SparseVec */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'sparsevec_to_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:702
-- requires:
--   Vector
--   SparseVec
--   sparsevec_from_real_array
--   sparsevec_to_real_array
--   sparsevec_from_vector
--   sparsevec_to_vector


CREATE CAST (real[] AS sparsevec)
    WITH FUNCTION pgcontext.sparsevec_from_real_array(real[])
    AS ASSIGNMENT;

CREATE CAST (sparsevec AS real[])
    WITH FUNCTION pgcontext.sparsevec_to_real_array(sparsevec)
    AS ASSIGNMENT;

CREATE CAST (vector AS sparsevec)
    WITH FUNCTION pgcontext.sparsevec_from_vector(vector)
    AS ASSIGNMENT;

CREATE CAST (sparsevec AS vector)
    WITH FUNCTION pgcontext.sparsevec_to_vector(sparsevec)
    AS ASSIGNMENT;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction_ann.rs:431
-- pgcontext::hybrid_query::late_interaction_ann::explain_late_interaction_ann
CREATE  FUNCTION "explain_late_interaction_ann"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"candidates_per_query" INT /* i32 */
) RETURNS TABLE (
	"stage" TEXT,  /* String */
	"detail" TEXT,  /* String */
	"branch" TEXT,  /* Option < String > */
	"strategy" TEXT,  /* String */
	"status" QueryExplainStatus,  /* QueryExplainStatus */
	"estimated_candidates" bigint,  /* Option < i64 > */
	"candidate_budget" bigint  /* Option < i64 > */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explain_owned_late_interaction_ann_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:1013
-- pgcontext::pgcontext::vector_variants::int8vec_to_vector
CREATE  FUNCTION "int8vec_to_vector"(
	"vector" Int8Vec /* Int8Vec */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'int8vec_to_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variants.rs:600
-- requires:
--   Vector
--   Int8Vec
--   UInt8Vec
--   int8vec_from_smallint_array
--   int8vec_from_integer_array
--   uint8vec_from_smallint_array
--   uint8vec_from_integer_array
--   int8vec_to_smallint_array
--   uint8vec_to_smallint_array
--   int8vec_to_vector
--   uint8vec_to_vector
--   int8vec_from_vector
--   uint8vec_from_vector


CREATE CAST (smallint[] AS int8vec)
    WITH FUNCTION pgcontext.int8vec_from_smallint_array(smallint[]);
CREATE CAST (integer[] AS int8vec)
    WITH FUNCTION pgcontext.int8vec_from_integer_array(integer[]);
CREATE CAST (smallint[] AS uint8vec)
    WITH FUNCTION pgcontext.uint8vec_from_smallint_array(smallint[]);
CREATE CAST (integer[] AS uint8vec)
    WITH FUNCTION pgcontext.uint8vec_from_integer_array(integer[]);
CREATE CAST (int8vec AS smallint[])
    WITH FUNCTION pgcontext.int8vec_to_smallint_array(int8vec) AS ASSIGNMENT;
CREATE CAST (uint8vec AS smallint[])
    WITH FUNCTION pgcontext.uint8vec_to_smallint_array(uint8vec) AS ASSIGNMENT;
CREATE CAST (int8vec AS vector)
    WITH FUNCTION pgcontext.int8vec_to_vector(int8vec) AS ASSIGNMENT;
CREATE CAST (uint8vec AS vector)
    WITH FUNCTION pgcontext.uint8vec_to_vector(uint8vec) AS ASSIGNMENT;
CREATE CAST (vector AS int8vec)
    WITH FUNCTION pgcontext.int8vec_from_vector(vector);
CREATE CAST (vector AS uint8vec)
    WITH FUNCTION pgcontext.uint8vec_from_vector(vector);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search.rs:47
-- pgcontext::table_search::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:618
-- pgcontext::pgcontext::vector::search
CREATE  FUNCTION "search"(
	"query" Vector, /* Vector */
	"point_ids" bigint[], /* Vec < i64 > */
	"vectors" Vector[], /* Vec < Vector > */
	"metric" TEXT, /* String */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"score" real  /* f32 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction.rs:80
-- pgcontext::hybrid_query::late_interaction::explain_late_interaction
CREATE  FUNCTION "explain_late_interaction"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"vector_column" TEXT /* String */
) RETURNS TABLE (
	"stage" TEXT,  /* String */
	"detail" TEXT,  /* String */
	"branch" TEXT,  /* Option < String > */
	"strategy" TEXT,  /* String */
	"status" QueryExplainStatus,  /* QueryExplainStatus */
	"estimated_candidates" bigint,  /* Option < i64 > */
	"candidate_budget" bigint  /* Option < i64 > */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'explain_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:15
-- pgcontext::query_builders::query_nearest
CREATE  FUNCTION "query_nearest"(
	"vector" Vector, /* Vector */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_nearest_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:609
-- pgcontext::pgcontext::vector::l1_distance
CREATE  FUNCTION "l1_distance"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'l1_distance_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hnsw_am/sql_contract.rs:4
-- requires:
--   pgcontext_bootstrap
--   Vector
--   HalfVec
--   SparseVec
--   BitVec
--   Int8Vec
--   UInt8Vec
--   create_vector_distance_operators
--   create_vector_variant_distance_operators
--   create_vector_fast_distance_functions
--   hnsw_l2_distance
--   negative_inner_product
--   cosine_distance
--   l1_distance
--   halfvec_l2_distance
--   halfvec_negative_inner_product
--   halfvec_cosine_distance
--   halfvec_l1_distance
--   sparsevec_l2_distance
--   sparsevec_negative_inner_product
--   sparsevec_cosine_distance
--   sparsevec_l1_distance
--   bitvec_hamming_distance
--   bitvec_jaccard_distance
--   int8vec_l2_distance
--   int8vec_negative_inner_product
--   int8vec_cosine_distance
--   int8vec_l1_distance
--   uint8vec_l2_distance
--   uint8vec_negative_inner_product
--   uint8vec_cosine_distance
--   uint8vec_l1_distance


CREATE FUNCTION pgcontext.hnsw_handler(internal)
RETURNS index_am_handler
AS 'MODULE_PATHNAME', 'pgcontext_hnsw_handler'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE OPERATOR pgcontext.<-> (
    LEFTARG = pgcontext.vector,
    RIGHTARG = pgcontext.vector,
    FUNCTION = pgcontext._l2_distance_fast8,
    COMMUTATOR = OPERATOR(pgcontext.<->)
);

CREATE ACCESS METHOD pgcontext_hnsw
    TYPE INDEX
    HANDLER pgcontext.hnsw_handler;

CREATE OPERATOR CLASS pgcontext.vector_hnsw_ops
    DEFAULT FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.hnsw_l2_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_hnsw_ip_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.negative_inner_product(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_hnsw_cosine_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.cosine_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_hnsw_l1_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.l1_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR pgcontext.<-> (
    LEFTARG = pgcontext.halfvec,
    RIGHTARG = pgcontext.halfvec,
    FUNCTION = pgcontext.halfvec_l2_distance,
    COMMUTATOR = OPERATOR(pgcontext.<->)
);

CREATE OPERATOR CLASS pgcontext.halfvec_hnsw_ops
    DEFAULT FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l2_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.halfvec_hnsw_ip_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_negative_inner_product(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.halfvec_hnsw_cosine_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_cosine_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.halfvec_hnsw_l1_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l1_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR pgcontext.<-> (
    LEFTARG = pgcontext.sparsevec,
    RIGHTARG = pgcontext.sparsevec,
    FUNCTION = pgcontext.sparsevec_l2_distance,
    COMMUTATOR = OPERATOR(pgcontext.<->)
);

CREATE OPERATOR CLASS pgcontext.sparsevec_hnsw_ops
    DEFAULT FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_l2_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.sparsevec_hnsw_ip_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_negative_inner_product(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.sparsevec_hnsw_cosine_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_cosine_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.sparsevec_hnsw_l1_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_l1_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;

CREATE OPERATOR pgcontext.<~> (
    LEFTARG = pgcontext.bitvec,
    RIGHTARG = pgcontext.bitvec,
    FUNCTION = pgcontext.bitvec_hamming_distance,
    COMMUTATOR = OPERATOR(pgcontext.<~>)
);

CREATE OPERATOR CLASS pgcontext.bitvec_hnsw_hamming_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<~> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.integer_ops,
    FUNCTION 1 pgcontext.bitvec_hamming_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.bitvec_hnsw_jaccard_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<%> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.bitvec_jaccard_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.int8vec_hnsw_ops
    DEFAULT FOR TYPE pgcontext.int8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_l2_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.int8vec_hnsw_ip_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_negative_inner_product(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.int8vec_hnsw_cosine_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_cosine_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.int8vec_hnsw_l1_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_l1_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.uint8vec_hnsw_ops
    DEFAULT FOR TYPE pgcontext.uint8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_l2_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.uint8vec_hnsw_ip_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_negative_inner_product(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.uint8vec_hnsw_cosine_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_cosine_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.uint8vec_hnsw_l1_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_l1_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;

-- Pgvector-spelled opclass aliases for clean installations that put
-- pgcontext on search_path. The access method remains explicitly native.
CREATE OPERATOR CLASS pgcontext.vector_l2_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.hnsw_l2_distance(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_ip_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.negative_inner_product(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_cosine_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.cosine_distance(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_l1_ops
    FOR TYPE pgcontext.vector USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.l1_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.halfvec_l2_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l2_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_ip_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_negative_inner_product(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_cosine_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_cosine_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_l1_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l1_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.sparsevec_l2_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<-> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_l2_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.sparsevec_ip_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<#> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_negative_inner_product(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.sparsevec_cosine_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<=> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_cosine_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.sparsevec_l1_ops
    FOR TYPE pgcontext.sparsevec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<+> (pgcontext.sparsevec, pgcontext.sparsevec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.sparsevec_l1_distance(pgcontext.sparsevec, pgcontext.sparsevec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.bit_hamming_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<~> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.integer_ops,
    FUNCTION 1 pgcontext.bitvec_hamming_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.bit_jaccard_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_hnsw AS
    OPERATOR 1 pgcontext.<%> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.bitvec_jaccard_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/ivfflat_am.rs:2900
-- requires:
--   pgcontext_bootstrap
--   create_hnsw_access_method


CREATE FUNCTION pgcontext.ivfflat_handler(internal)
RETURNS index_am_handler
AS 'MODULE_PATHNAME', 'pgcontext_ivfflat_handler'
LANGUAGE C IMMUTABLE STRICT PARALLEL SAFE;

CREATE ACCESS METHOD pgcontext_ivfflat
    TYPE INDEX
    HANDLER pgcontext.ivfflat_handler;

CREATE OPERATOR CLASS pgcontext.vector_ivfflat_ops
    DEFAULT FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.hnsw_l2_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_ivfflat_ip_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.negative_inner_product(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_ivfflat_cosine_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.cosine_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.vector_ivfflat_l1_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.l1_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.halfvec_ivfflat_ops
    DEFAULT FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l2_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_ivfflat_ip_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_negative_inner_product(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_ivfflat_cosine_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_cosine_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_ivfflat_l1_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l1_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.int8vec_ivfflat_ops
    DEFAULT FOR TYPE pgcontext.int8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_l2_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.int8vec_ivfflat_ip_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_negative_inner_product(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.int8vec_ivfflat_cosine_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_cosine_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.int8vec_ivfflat_l1_ops
    FOR TYPE pgcontext.int8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.int8vec, pgcontext.int8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.int8vec_l1_distance(pgcontext.int8vec, pgcontext.int8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.uint8vec_ivfflat_ops
    DEFAULT FOR TYPE pgcontext.uint8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_l2_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.uint8vec_ivfflat_ip_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_negative_inner_product(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.uint8vec_ivfflat_cosine_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_cosine_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.uint8vec_ivfflat_l1_ops
    FOR TYPE pgcontext.uint8vec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.uint8vec, pgcontext.uint8vec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.uint8vec_l1_distance(pgcontext.uint8vec, pgcontext.uint8vec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.bitvec_ivfflat_hamming_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<~> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.integer_ops,
    FUNCTION 1 pgcontext.bitvec_hamming_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.bitvec_ivfflat_jaccard_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<%> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.bitvec_jaccard_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;

-- Pgvector-spelled aliases are scoped by access method and schema, so the
-- same names coexist with the HNSW aliases without changing native ownership.
CREATE OPERATOR CLASS pgcontext.vector_l2_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.hnsw_l2_distance(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_ip_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.negative_inner_product(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_cosine_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.cosine_distance(pgcontext.vector, pgcontext.vector);
CREATE OPERATOR CLASS pgcontext.vector_l1_ops
    FOR TYPE pgcontext.vector USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.vector, pgcontext.vector) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.l1_distance(pgcontext.vector, pgcontext.vector);

CREATE OPERATOR CLASS pgcontext.halfvec_l2_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<-> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l2_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_ip_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<#> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_negative_inner_product(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_cosine_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<=> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_cosine_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.halfvec_l1_ops
    FOR TYPE pgcontext.halfvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<+> (pgcontext.halfvec, pgcontext.halfvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.halfvec_l1_distance(pgcontext.halfvec, pgcontext.halfvec),
    STORAGE pgcontext.vector;

CREATE OPERATOR CLASS pgcontext.bit_hamming_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<~> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.integer_ops,
    FUNCTION 1 pgcontext.bitvec_hamming_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;
CREATE OPERATOR CLASS pgcontext.bit_jaccard_ops
    FOR TYPE pgcontext.bitvec USING pgcontext_ivfflat AS
    OPERATOR 1 pgcontext.<%> (pgcontext.bitvec, pgcontext.bitvec) FOR ORDER BY pg_catalog.float_ops,
    FUNCTION 1 pgcontext.bitvec_jaccard_distance(pgcontext.bitvec, pgcontext.bitvec),
    STORAGE pgcontext.vector;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:701
-- pgcontext::pgcontext::vector::rerank_late_interaction
CREATE  FUNCTION "rerank_late_interaction"(
	"query_vectors" Vector[], /* Vec < Vector > */
	"point_ids" bigint[], /* Vec < i64 > */
	"candidate_vectors" Vector[], /* Vec < Vector > */
	"candidate_offsets" INT[], /* Vec < i32 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"score" real  /* f32 */
)
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'rerank_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/quantization_sql.rs:17
-- pgcontext::quantization_sql::binary_quantize
CREATE  FUNCTION "binary_quantize"(
	"vector" Vector /* Vector */
) RETURNS BitVec /* BitVec */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'binary_quantize_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/named.rs:16
-- pgcontext::table_search::named::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_named_vector_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:432
-- pgcontext::pgcontext::vector::vector_lt
CREATE  FUNCTION "vector_lt"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_lt_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:26
-- pgcontext::query_builders::query_nearest
CREATE  FUNCTION "query_nearest"(
	"vector_name" TEXT, /* Option < String > */
	"vector" Vector, /* Vector */
	"filter" jsonb, /* Option < JsonB > */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_nearest_configured_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:450
-- pgcontext::pgcontext::vector::vector_ne
CREATE  FUNCTION "vector_ne"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_ne_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:438
-- pgcontext::pgcontext::vector::vector_le
CREATE  FUNCTION "vector_le"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS bool /* bool */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_le_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query.rs:138
-- pgcontext::hybrid_query::query
CREATE  FUNCTION "query"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"sparse_vector_name" TEXT, /* String */
	"sparse_query" SparseVec, /* SparseVec */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" double precision  /* f64 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_collection_dense_sparse_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:422
-- pgcontext::pgcontext::vector::vector_cmp
CREATE  FUNCTION "vector_cmp"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_cmp_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:210
-- requires:
--   Vector
--   vector_lt
--   vector_le
--   vector_eq
--   vector_ne
--   vector_ge
--   vector_gt
--   vector_cmp


CREATE OPERATOR pgcontext.< (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_lt,
    COMMUTATOR = OPERATOR(pgcontext.>),
    NEGATOR = OPERATOR(pgcontext.>=)
);

CREATE OPERATOR pgcontext.<= (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_le,
    COMMUTATOR = OPERATOR(pgcontext.>=),
    NEGATOR = OPERATOR(pgcontext.>)
);

CREATE OPERATOR pgcontext.= (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_eq,
    COMMUTATOR = OPERATOR(pgcontext.=),
    NEGATOR = OPERATOR(pgcontext.<>)
);

CREATE OPERATOR pgcontext.<> (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_ne,
    COMMUTATOR = OPERATOR(pgcontext.<>),
    NEGATOR = OPERATOR(pgcontext.=)
);

CREATE OPERATOR pgcontext.>= (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_ge,
    COMMUTATOR = OPERATOR(pgcontext.<=),
    NEGATOR = OPERATOR(pgcontext.<)
);

CREATE OPERATOR pgcontext.> (
    LEFTARG = vector,
    RIGHTARG = vector,
    FUNCTION = pgcontext.vector_gt,
    COMMUTATOR = OPERATOR(pgcontext.<),
    NEGATOR = OPERATOR(pgcontext.<=)
);

CREATE OPERATOR CLASS pgcontext.vector_ops
    DEFAULT FOR TYPE vector USING btree AS
    OPERATOR 1 pgcontext.< (vector, vector),
    OPERATOR 2 pgcontext.<= (vector, vector),
    OPERATOR 3 pgcontext.= (vector, vector),
    OPERATOR 4 pgcontext.>= (vector, vector),
    OPERATOR 5 pgcontext.> (vector, vector),
    FUNCTION 1 pgcontext.vector_cmp(vector, vector);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:88
-- pgcontext::table_search::candidate_recheck::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector" Vector, /* Vector */
	"candidate_point_ids" bigint[], /* Vec < i64 > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT 
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_candidates_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:416
-- pgcontext::pgcontext::vector::vector_avg_final
CREATE  FUNCTION "vector_avg_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_avg_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:591
-- pgcontext::pgcontext::vector::inner_product
CREATE  FUNCTION "inner_product"(
	"left" Vector, /* Vector */
	"right" Vector /* Vector */
) RETURNS real /* f32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'inner_product_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/query_builders.rs:163
-- pgcontext::query_builders::query_late_interaction
CREATE  FUNCTION "query_late_interaction"(
	"query_vectors" Vector[], /* Vec < Vector > */
	"candidates_per_query" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS jsonb /* JsonB */
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'query_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/named.rs:50
-- pgcontext::table_search::named::search
CREATE  FUNCTION "search"(
	"collection" TEXT, /* String */
	"vector_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"filter" TEXT, /* Option < String > */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)

SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_collection_named_vector_filtered_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/hybrid_query/late_interaction.rs:40
-- pgcontext::hybrid_query::late_interaction::search_late_interaction
CREATE  FUNCTION "search_late_interaction"(
	"collection" TEXT, /* String */
	"query_vectors" Vector[], /* Vec < Vector > */
	"vector_column" TEXT, /* String */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" double precision  /* f64 */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_late_interaction_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/table_search/candidate_recheck.rs:290
-- pgcontext::table_search::candidate_recheck::search_mmap_hnsw_artifact
CREATE  FUNCTION "search_mmap_hnsw_artifact"(
	"collection" TEXT, /* String */
	"artifact_name" TEXT, /* String */
	"vector" Vector, /* Vector */
	"max_mapped_bytes" bigint, /* i64 */
	"candidate_limit" INT, /* i32 */
	"limit" INT /* i32 */
) RETURNS TABLE (
	"point_id" bigint,  /* i64 */
	"source_key" TEXT,  /* String */
	"score" real  /* f32 */
)
STRICT
SET search_path TO pg_catalog, pgcontext, public
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'search_mmap_hnsw_artifact_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:536
-- pgcontext::pgcontext::vector::vector_prefix
CREATE  FUNCTION "vector_prefix"(
	"vector" Vector, /* Vector */
	"dimensions" INT /* i32 */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_prefix_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:410
-- pgcontext::pgcontext::vector::vector_sum_final
CREATE  FUNCTION "vector_sum_final"(
	"state" real[] /* Vec < f32 > */
) RETURNS Vector /* Vector */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_sum_final_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:369
-- pgcontext::pgcontext::vector::vector_sum_transition
CREATE  FUNCTION "vector_sum_transition"(
	"state" real[], /* :: std :: option :: Option < Vec < f32 > > */
	"value" Vector /* Option < Vector > */
) RETURNS real[] /* :: std :: option :: Option < Vec < f32 > > */
IMMUTABLE PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_sum_transition_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:275
-- requires:
--   Vector
--   vector_sum_transition
--   vector_sum_final
--   vector_avg_final


CREATE AGGREGATE pgcontext.sum(vector) (
    SFUNC = pgcontext.vector_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.vector_sum_final
);

CREATE AGGREGATE pgcontext.avg(vector) (
    SFUNC = pgcontext.vector_sum_transition,
    STYPE = real[],
    FINALFUNC = pgcontext.vector_avg_final
);
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:332
-- pgcontext::pgcontext::vector::vector_to_real_array
CREATE  FUNCTION "vector_to_real_array"(
	"vector" Vector /* Vector */
) RETURNS real[] /* Vec < f32 > */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_to_real_array_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector.rs:157
-- requires:
--   Vector
--   vector_from_real_array
--   vector_from_integer_array
--   vector_from_double_array
--   vector_to_real_array


CREATE CAST (real[] AS vector)
    WITH FUNCTION pgcontext.vector_from_real_array(real[])
    AS ASSIGNMENT;

CREATE CAST (integer[] AS vector)
    WITH FUNCTION pgcontext.vector_from_integer_array(integer[]);

CREATE CAST (double precision[] AS vector)
    WITH FUNCTION pgcontext.vector_from_double_array(double precision[]);

CREATE CAST (vector AS real[])
    WITH FUNCTION pgcontext.vector_to_real_array(vector)
    AS ASSIGNMENT;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:100
-- pgcontext::vector_variant_typmods::vector_typmod_in
CREATE  FUNCTION "vector_typmod_in"(
	"modifiers" cstring[] /* Array < '_, & CStr > */
) RETURNS INT /* i32 */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_typmod_in_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:107
-- pgcontext::vector_variant_typmods::vector_typmod_out
CREATE  FUNCTION "vector_typmod_out"(
	"typmod" INT /* i32 */
) RETURNS cstring /* CString */
IMMUTABLE STRICT PARALLEL SAFE
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'vector_typmod_out_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/vector_variant_typmods.rs:14
-- requires:
--   Vector
--   HalfVec
--   SparseVec
--   BitVec
--   Int8Vec
--   UInt8Vec
--   vector_typmod_in
--   vector_typmod_out
--   vector_enforce_typmod
--   halfvec_typmod_in
--   halfvec_typmod_out
--   sparsevec_typmod_in
--   sparsevec_typmod_out
--   bitvec_typmod_in
--   bitvec_typmod_out
--   int8vec_typmod_in
--   int8vec_typmod_out
--   uint8vec_typmod_in
--   uint8vec_typmod_out
--   halfvec_enforce_typmod
--   sparsevec_enforce_typmod
--   bitvec_enforce_typmod
--   int8vec_enforce_typmod
--   uint8vec_enforce_typmod


ALTER TYPE vector SET (
    TYPMOD_IN = pgcontext.vector_typmod_in,
    TYPMOD_OUT = pgcontext.vector_typmod_out
);

ALTER TYPE halfvec SET (
    TYPMOD_IN = pgcontext.halfvec_typmod_in,
    TYPMOD_OUT = pgcontext.halfvec_typmod_out
);

ALTER TYPE sparsevec SET (
    TYPMOD_IN = pgcontext.sparsevec_typmod_in,
    TYPMOD_OUT = pgcontext.sparsevec_typmod_out
);

ALTER TYPE bitvec SET (
    TYPMOD_IN = pgcontext.bitvec_typmod_in,
    TYPMOD_OUT = pgcontext.bitvec_typmod_out
);

ALTER TYPE int8vec SET (
    TYPMOD_IN = pgcontext.int8vec_typmod_in,
    TYPMOD_OUT = pgcontext.int8vec_typmod_out
);

ALTER TYPE uint8vec SET (
    TYPMOD_IN = pgcontext.uint8vec_typmod_in,
    TYPMOD_OUT = pgcontext.uint8vec_typmod_out
);

CREATE CAST (halfvec AS halfvec)
    WITH FUNCTION pgcontext.halfvec_enforce_typmod(halfvec, integer, boolean)
    AS IMPLICIT;

CREATE CAST (sparsevec AS sparsevec)
    WITH FUNCTION pgcontext.sparsevec_enforce_typmod(sparsevec, integer, boolean)
    AS IMPLICIT;

CREATE CAST (bitvec AS bitvec)
    WITH FUNCTION pgcontext.bitvec_enforce_typmod(bitvec, integer, boolean)
    AS IMPLICIT;

CREATE CAST (int8vec AS int8vec)
    WITH FUNCTION pgcontext.int8vec_enforce_typmod(int8vec, integer, boolean)
    AS IMPLICIT;

CREATE CAST (uint8vec AS uint8vec)
    WITH FUNCTION pgcontext.uint8vec_enforce_typmod(uint8vec, integer, boolean)
    AS IMPLICIT;

CREATE CAST (vector AS vector)
    WITH FUNCTION pgcontext.vector_enforce_typmod(vector, integer, boolean)
    AS IMPLICIT;
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/build_jobs.rs:350
-- pgcontext::build_jobs::wake_build_jobs
CREATE  FUNCTION "wake_build_jobs"(
	"collection" TEXT /* String */
) RETURNS bool /* bool */
STRICT SECURITY DEFINER 
SET search_path TO pg_catalog, pgcontext
LANGUAGE c /* Rust */
AS 'MODULE_PATHNAME', 'wake_build_jobs_wrapper';
/* </end connected objects> */

/* <begin connected objects> */
-- crates/context-pg/src/pgvector_ownership/trigger.rs:26
-- pgcontext::pgvector_ownership::trigger::_sync_pgvector_ownership_columns
CREATE FUNCTION "_sync_pgvector_ownership_columns"()
	RETURNS TRIGGER
	LANGUAGE c
	AS 'MODULE_PATHNAME', '_sync_pgvector_ownership_columns_wrapper';
/* </end connected objects> */
