teleo-infrastructure/ops/postgres_parity_manifest.sql

644 lines
19 KiB
SQL

\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_gate_owner', 'kb_apply', 'kb_review')),
'[]'::jsonb
)
)::text;
select jsonb_build_object(
'kind', 'role_memberships',
'items', coalesce(
(select jsonb_agg(
jsonb_build_object(
'role', role_row.rolname,
'member', member_row.rolname,
'grantor', grantor_row.rolname,
'admin_option', membership.admin_option,
'inherit_option', membership.inherit_option,
'set_option', membership.set_option
) order by role_row.rolname, member_row.rolname, grantor_row.rolname)
from pg_auth_members membership
join pg_roles role_row on role_row.oid = membership.roleid
join pg_roles member_row on member_row.oid = membership.member
join pg_roles grantor_row on grantor_row.oid = membership.grantor
where role_row.rolname in ('kb_gate_owner', 'kb_apply', 'kb_review')
or member_row.rolname in ('kb_gate_owner', 'kb_apply', 'kb_review')),
'[]'::jsonb
)
)::text;
with ownership as (
select
'database:canonical_database'::text as sort_key,
'database'::text as object_type,
null::text as schema,
'canonical_database'::text as name,
null::text as identity_arguments,
pg_get_userbyid(database_row.datdba) as owner
from pg_database database_row
where database_row.datname = current_database()
union all
select
format('schema:%s', namespace.nspname),
'schema',
namespace.nspname,
namespace.nspname,
null::text,
pg_get_userbyid(namespace.nspowner)
from pg_namespace namespace
where namespace.nspname in ('public', 'kb_stage')
union all
select
format('relation:%s.%s', namespace.nspname, relation.relname),
case relation.relkind
when 'r' then 'table'
when 'p' then 'partitioned_table'
when 'v' then 'view'
when 'm' then 'materialized_view'
when 'S' then 'sequence'
when 'f' then 'foreign_table'
end,
namespace.nspname,
relation.relname,
null::text,
pg_get_userbyid(relation.relowner)
from pg_class relation
join pg_namespace namespace on namespace.oid = relation.relnamespace
where namespace.nspname in ('public', 'kb_stage')
and relation.relkind in ('r', 'p', 'v', 'm', 'S', 'f')
union all
select
format(
'function:%s.%s(%s)',
namespace.nspname,
procedure.proname,
pg_get_function_identity_arguments(procedure.oid)
),
'function',
namespace.nspname,
procedure.proname,
pg_get_function_identity_arguments(procedure.oid),
pg_get_userbyid(procedure.proowner)
from pg_proc procedure
join pg_namespace namespace on namespace.oid = procedure.pronamespace
where namespace.nspname in ('public', 'kb_stage')
union all
select
format('type:%s.%s', namespace.nspname, type_row.typname),
case type_row.typtype when 'd' then 'domain' else 'enum' end,
namespace.nspname,
type_row.typname,
null::text,
pg_get_userbyid(type_row.typowner)
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', 'object_ownership',
'items', coalesce(
jsonb_agg(to_jsonb(ownership) - 'sort_key' order by sort_key),
'[]'::jsonb
)
)::text
from ownership;
with acl_rows as (
select
format(
'database:canonical_database:%s:%s:%s',
acl.grantee,
acl.privilege_type,
acl.is_grantable
) as sort_key,
'database'::text as object_type,
null::text as schema,
'canonical_database'::text as name,
null::text as column_name,
null::text as identity_arguments,
pg_get_userbyid(acl.grantor) as grantor,
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end as grantee,
acl.privilege_type,
acl.is_grantable
from pg_database database_row
cross join lateral aclexplode(coalesce(database_row.datacl, acldefault('d', database_row.datdba))) acl
where database_row.datname = current_database()
union all
select
format(
'schema:%s:%s:%s:%s',
namespace.nspname,
acl.grantee,
acl.privilege_type,
acl.is_grantable
),
'schema',
namespace.nspname,
namespace.nspname,
null::text,
null::text,
pg_get_userbyid(acl.grantor),
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end,
acl.privilege_type,
acl.is_grantable
from pg_namespace namespace
cross join lateral aclexplode(coalesce(namespace.nspacl, acldefault('n', namespace.nspowner))) acl
where namespace.nspname in ('public', 'kb_stage')
union all
select
format(
'relation:%s.%s:%s:%s:%s',
namespace.nspname,
relation.relname,
acl.grantee,
acl.privilege_type,
acl.is_grantable
),
case when relation.relkind = 'S' then 'sequence' else 'relation' end,
namespace.nspname,
relation.relname,
null::text,
null::text,
pg_get_userbyid(acl.grantor),
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end,
acl.privilege_type,
acl.is_grantable
from pg_class relation
join pg_namespace namespace on namespace.oid = relation.relnamespace
cross join lateral aclexplode(
coalesce(
relation.relacl,
acldefault(case when relation.relkind = 'S' then 'S'::"char" else 'r'::"char" end, relation.relowner)
)
) acl
where namespace.nspname in ('public', 'kb_stage')
and relation.relkind in ('r', 'p', 'v', 'm', 'S', 'f')
union all
select
format(
'column:%s.%s.%s:%s:%s:%s',
namespace.nspname,
relation.relname,
attribute.attname,
acl.grantee,
acl.privilege_type,
acl.is_grantable
),
'column',
namespace.nspname,
relation.relname,
attribute.attname,
null::text,
pg_get_userbyid(acl.grantor),
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end,
acl.privilege_type,
acl.is_grantable
from pg_attribute attribute
join pg_class relation on relation.oid = attribute.attrelid
join pg_namespace namespace on namespace.oid = relation.relnamespace
cross join lateral aclexplode(attribute.attacl) acl
where namespace.nspname in ('public', 'kb_stage')
and relation.relkind in ('r', 'p', 'v', 'm', 'f')
and attribute.attnum > 0
and not attribute.attisdropped
union all
select
format(
'function:%s.%s(%s):%s:%s:%s',
namespace.nspname,
procedure.proname,
pg_get_function_identity_arguments(procedure.oid),
acl.grantee,
acl.privilege_type,
acl.is_grantable
),
'function',
namespace.nspname,
procedure.proname,
null::text,
pg_get_function_identity_arguments(procedure.oid),
pg_get_userbyid(acl.grantor),
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end,
acl.privilege_type,
acl.is_grantable
from pg_proc procedure
join pg_namespace namespace on namespace.oid = procedure.pronamespace
cross join lateral aclexplode(coalesce(procedure.proacl, acldefault('f', procedure.proowner))) acl
where namespace.nspname in ('public', 'kb_stage')
union all
select
format(
'type:%s.%s:%s:%s:%s',
namespace.nspname,
type_row.typname,
acl.grantee,
acl.privilege_type,
acl.is_grantable
),
'type',
namespace.nspname,
type_row.typname,
null::text,
null::text,
pg_get_userbyid(acl.grantor),
case when acl.grantee = 0 then 'PUBLIC' else pg_get_userbyid(acl.grantee) end,
acl.privilege_type,
acl.is_grantable
from pg_type type_row
join pg_namespace namespace on namespace.oid = type_row.typnamespace
cross join lateral aclexplode(coalesce(type_row.typacl, acldefault('T', type_row.typowner))) acl
where namespace.nspname in ('public', 'kb_stage')
and type_row.typtype in ('d', 'e')
)
select jsonb_build_object(
'kind', 'object_acl',
'items', coalesce(
jsonb_agg(
to_jsonb(acl_rows) - 'sort_key'
order by
object_type,
schema nulls first,
name,
column_name nulls first,
identity_arguments nulls first,
grantor,
grantee,
privilege_type,
is_grantable
),
'[]'::jsonb
)
)::text
from acl_rows;
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;