\set ON_ERROR_STOP on
begin transaction isolation level repeatable read read only;
\if :{?snapshot_id}
set transaction snapshot :'snapshot_id';
\endif
set local statement_timeout = '30s';

select jsonb_build_object(
  'kind', 'identity',
  'database', current_database(),
  'current_user', current_user,
  'server_version_num', current_setting('server_version_num')::integer,
  'server_encoding', current_setting('server_encoding'),
  'database_collation', (select datcollate from pg_database where datname = current_database()),
  'database_ctype', (select datctype from pg_database where datname = current_database()),
  'transaction_read_only', current_setting('transaction_read_only'),
  'server_address', host(inet_server_addr()),
  'server_port', inet_server_port(),
  'ssl', coalesce((select ssl from pg_stat_ssl where pid = pg_backend_pid()), false),
  'ssl_version', (select version from pg_stat_ssl where pid = pg_backend_pid()),
  'captured_at', clock_timestamp()
)::text;

select jsonb_build_object(
  'kind', 'schemas',
  'items', coalesce(
    (select jsonb_agg(nspname order by nspname)
       from pg_namespace
      where nspname in ('public', 'kb_stage')),
    '[]'::jsonb
  )
)::text;

select jsonb_build_object(
  'kind', 'extensions',
  'items', coalesce(
    (select jsonb_agg(jsonb_build_object('name', extname, 'version', extversion) order by extname)
       from pg_extension),
    '[]'::jsonb
  )
)::text;

select jsonb_build_object(
  'kind', 'application_roles',
  'items', coalesce(
    (select jsonb_agg(
       jsonb_build_object(
         'name', rolname,
         'can_login', rolcanlogin,
         'superuser', rolsuper,
         'create_db', rolcreatedb,
         'create_role', rolcreaterole,
         'inherit', rolinherit,
         'replication', rolreplication,
         'bypass_rls', rolbypassrls
       ) order by rolname)
       from pg_roles
      where rolname in ('kb_apply', 'kb_review')),
    '[]'::jsonb
  )
)::text;

select jsonb_build_object(
  'kind', 'columns',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', table_schema,
        'table', table_name,
        'position', ordinal_position,
        'name', column_name,
        'data_type', data_type,
        'udt_name', udt_name,
        'nullable', is_nullable,
        'default', column_default
      ) order by table_schema, table_name, ordinal_position
    ),
    '[]'::jsonb
  )
)::text
from information_schema.columns
where table_schema in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'constraints',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', namespace.nspname,
        'table', relation.relname,
        'name', constraint_row.conname,
        'type', constraint_row.contype,
        'definition', pg_get_constraintdef(constraint_row.oid, true),
        'validated', constraint_row.convalidated,
        'deferrable', constraint_row.condeferrable,
        'initially_deferred', constraint_row.condeferred
      ) order by namespace.nspname, relation.relname, constraint_row.conname
    ),
    '[]'::jsonb
  )
)::text
from pg_constraint constraint_row
join pg_class relation on relation.oid = constraint_row.conrelid
join pg_namespace namespace on namespace.oid = relation.relnamespace
where namespace.nspname in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'indexes',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', schemaname,
        'table', tablename,
        'name', indexname,
        'definition', indexdef
      ) order by schemaname, tablename, indexname
    ),
    '[]'::jsonb
  )
)::text
from pg_indexes
where schemaname in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'sequences',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', schemaname,
        'name', sequencename,
        'data_type', data_type,
        'start_value', start_value,
        'min_value', min_value,
        'max_value', max_value,
        'increment_by', increment_by,
        'cycle', cycle,
        'cache_size', cache_size,
        'last_value', last_value
      ) order by schemaname, sequencename
    ),
    '[]'::jsonb
  )
)::text
from pg_sequences
where schemaname in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'views',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', schemaname,
        'name', viewname,
        'definition', definition
      ) order by schemaname, viewname
    ),
    '[]'::jsonb
  )
)::text
from pg_views
where schemaname in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'functions',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', namespace.nspname,
        'name', procedure.proname,
        'identity_arguments', pg_get_function_identity_arguments(procedure.oid),
        'result', pg_get_function_result(procedure.oid),
        'language', language.lanname,
        'volatility', procedure.provolatile,
        'security_definer', procedure.prosecdef,
        'definition', pg_get_functiondef(procedure.oid)
      ) order by namespace.nspname, procedure.proname, pg_get_function_identity_arguments(procedure.oid)
    ),
    '[]'::jsonb
  )
)::text
from pg_proc procedure
join pg_namespace namespace on namespace.oid = procedure.pronamespace
join pg_language language on language.oid = procedure.prolang
where namespace.nspname in ('public', 'kb_stage');

select jsonb_build_object(
  'kind', 'triggers',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', namespace.nspname,
        'table', relation.relname,
        'name', trigger_row.tgname,
        'enabled', trigger_row.tgenabled,
        'definition', pg_get_triggerdef(trigger_row.oid, true)
      ) order by namespace.nspname, relation.relname, trigger_row.tgname
    ),
    '[]'::jsonb
  )
)::text
from pg_trigger trigger_row
join pg_class relation on relation.oid = trigger_row.tgrelid
join pg_namespace namespace on namespace.oid = relation.relnamespace
where namespace.nspname in ('public', 'kb_stage')
  and not trigger_row.tgisinternal;

select jsonb_build_object(
  'kind', 'types',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', namespace.nspname,
        'name', type_row.typname,
        'kind', type_row.typtype,
        'category', type_row.typcategory,
        'base_type', case when type_row.typbasetype = 0 then null else format_type(type_row.typbasetype, null) end,
        'not_null', type_row.typnotnull,
        'default', type_row.typdefault,
        'enum_values', (
          select coalesce(jsonb_agg(enum_row.enumlabel order by enum_row.enumsortorder), '[]'::jsonb)
          from pg_enum enum_row
          where enum_row.enumtypid = type_row.oid
        )
      ) order by namespace.nspname, type_row.typname
    ),
    '[]'::jsonb
  )
)::text
from pg_type type_row
join pg_namespace namespace on namespace.oid = type_row.typnamespace
where namespace.nspname in ('public', 'kb_stage')
  and type_row.typtype in ('d', 'e');

select jsonb_build_object(
  'kind', 'policies',
  'items', coalesce(
    jsonb_agg(
      jsonb_build_object(
        'schema', schemaname,
        'table', tablename,
        'name', policyname,
        'permissive', permissive,
        'roles', roles,
        'command', cmd,
        'using', qual,
        'check', with_check
      ) order by schemaname, tablename, policyname
    ),
    '[]'::jsonb
  )
)::text
from pg_policies
where schemaname in ('public', 'kb_stage');

select format(
  $manifest$
  select jsonb_build_object(
    'kind', 'table',
    'schema', %L,
    'table', %L,
    'row_count', count(*)::bigint,
    'rowset_md5', md5(coalesce(string_agg(to_jsonb(row_value)::text, E'\n'
      order by (to_jsonb(row_value)::text) collate "C"), ''))
  )::text
  from %I.%I row_value;
  $manifest$,
  schemaname,
  tablename,
  schemaname,
  tablename
)
from pg_tables
where schemaname in ('public', 'kb_stage')
order by schemaname, tablename
\gexec

with started as materialized (
  select clock_timestamp() as at
), observed as materialized (
  select count(*)::bigint as row_count, min(started.at) as started_at
  from public.claims cross join started
), finished as materialized (
  select clock_timestamp() as finished_at, max(row_count) as row_count, min(started_at) as started_at
  from observed
)
select jsonb_build_object(
  'kind', 'performance',
  'query', 'count_claims',
  'elapsed_ms', extract(epoch from (finished_at - started_at)) * 1000,
  'observed_rows', row_count
)::text
from finished;

with started as materialized (
  select clock_timestamp() as at
), candidate as materialized (
  select id from public.claims order by id limit 1
), observed as materialized (
  select count(*)::bigint as row_count, min(started.at) as started_at
  from public.claim_evidence evidence
  join candidate on candidate.id = evidence.claim_id
  cross join started
), finished as materialized (
  select clock_timestamp() as finished_at, max(row_count) as row_count, min(started_at) as started_at
  from observed
)
select jsonb_build_object(
  'kind', 'performance',
  'query', 'claim_evidence_by_claim_id',
  'elapsed_ms', extract(epoch from (finished_at - started_at)) * 1000,
  'observed_rows', row_count
)::text
from finished;

with started as materialized (
  select clock_timestamp() as at
), candidate as materialized (
  select id from public.claims order by id limit 1
), observed as materialized (
  select count(*)::bigint as row_count, min(started.at) as started_at
  from public.claim_edges edge_row
  join candidate on candidate.id in (edge_row.from_claim, edge_row.to_claim)
  cross join started
), finished as materialized (
  select clock_timestamp() as finished_at, max(row_count) as row_count, min(started_at) as started_at
  from observed
)
select jsonb_build_object(
  'kind', 'performance',
  'query', 'claim_edges_by_claim_id',
  'elapsed_ms', extract(epoch from (finished_at - started_at)) * 1000,
  'observed_rows', row_count
)::text
from finished;

with started as materialized (
  select clock_timestamp() as at
), observed as materialized (
  select count(*)::bigint as row_count, min(started.at) as started_at
  from (
    select id from kb_stage.kb_proposals
    where status = 'pending_review'
    order by created_at desc
    limit 25
  ) proposal_row
  cross join started
), finished as materialized (
  select clock_timestamp() as finished_at, max(row_count) as row_count, min(started_at) as started_at
  from observed
)
select jsonb_build_object(
  'kind', 'performance',
  'query', 'pending_proposals_latest',
  'elapsed_ms', extract(epoch from (finished_at - started_at)) * 1000,
  'observed_rows', row_count
)::text
from finished;

rollback;
