Files
RolemasterDB/docs/critical_tables_schema.sql
2026-03-14 00:32:26 +01:00

143 lines
5.1 KiB
SQL

-- PostgreSQL-oriented schema for Rolemaster critical tables.
-- It is intentionally hybrid: relational axes + raw text + parsed JSON.
create table critical_table (
id bigint generated always as identity primary key,
slug text not null unique,
display_name text not null,
family text not null check (family in ('standard', 'variant_column', 'grouped_variant')),
source_pdf text not null,
source_page integer not null default 1,
extraction_method text not null check (extraction_method in ('text', 'ocr', 'manual')),
notes text,
created_at timestamptz not null default now()
);
create table critical_group (
id bigint generated always as identity primary key,
critical_table_id bigint not null references critical_table(id) on delete cascade,
group_key text not null,
label text not null,
sort_order integer not null,
unique (critical_table_id, group_key)
);
create table critical_column (
id bigint generated always as identity primary key,
critical_table_id bigint not null references critical_table(id) on delete cascade,
column_key text not null,
label text not null,
role text not null default 'severity' check (role in ('severity', 'variant', 'other')),
sort_order integer not null,
unique (critical_table_id, column_key)
);
create table critical_roll_band (
id bigint generated always as identity primary key,
critical_table_id bigint not null references critical_table(id) on delete cascade,
label text not null,
min_roll integer not null,
max_roll integer,
sort_order integer not null,
check (max_roll is null or max_roll >= min_roll),
unique (critical_table_id, label)
);
create index critical_roll_band_lookup_idx
on critical_roll_band (critical_table_id, min_roll, max_roll);
create table critical_result (
id bigint generated always as identity primary key,
critical_table_id bigint not null references critical_table(id) on delete cascade,
critical_group_id bigint references critical_group(id) on delete cascade,
critical_column_id bigint not null references critical_column(id) on delete cascade,
critical_roll_band_id bigint not null references critical_roll_band(id) on delete cascade,
raw_cell_text text not null,
description_text text,
raw_affix_text text,
parsed_json jsonb not null default '{}'::jsonb,
parse_status text not null default 'raw' check (parse_status in ('raw', 'partial', 'parsed', 'verified')),
source_bbox jsonb,
created_at timestamptz not null default now()
);
create unique index critical_result_lookup_uidx
on critical_result (
critical_table_id,
coalesce(critical_group_id, 0),
critical_column_id,
critical_roll_band_id
);
create table critical_branch (
id bigint generated always as identity primary key,
critical_result_id bigint not null references critical_result(id) on delete cascade,
branch_kind text not null default 'conditional' check (branch_kind in ('conditional', 'note', 'override')),
condition_key text,
condition_text text not null,
condition_json jsonb not null default '{}'::jsonb,
raw_text text not null,
description_text text,
raw_affix_text text,
parsed_json jsonb not null default '{}'::jsonb,
sort_order integer not null default 1
);
create table critical_effect (
id bigint generated always as identity primary key,
critical_result_id bigint references critical_result(id) on delete cascade,
critical_branch_id bigint references critical_branch(id) on delete cascade,
effect_code text not null,
target text,
value_integer integer,
value_decimal numeric(10, 2),
duration_rounds integer,
per_round integer,
modifier integer,
body_part text,
is_permanent boolean not null default false,
source_type text not null default 'symbol' check (source_type in ('symbol', 'prose', 'manual')),
source_text text,
check ((critical_result_id is not null) <> (critical_branch_id is not null))
);
create index critical_effect_lookup_idx
on critical_effect (effect_code, target);
create index critical_effect_result_idx
on critical_effect (critical_result_id);
create index critical_effect_branch_idx
on critical_effect (critical_branch_id);
create index critical_result_parsed_json_gin
on critical_result using gin (parsed_json);
create index critical_branch_parsed_json_gin
on critical_branch using gin (parsed_json);
-- Example lookup pattern:
--
-- select
-- t.slug as critical_type,
-- t.display_name as table_name,
-- g.group_key,
-- c.column_key,
-- rb.label as roll_band,
-- rb.min_roll,
-- rb.max_roll,
-- r.description_text,
-- r.raw_affix_text,
-- r.raw_cell_text,
-- r.parsed_json
-- from critical_result r
-- join critical_table t on t.id = r.critical_table_id
-- left join critical_group g on g.id = r.critical_group_id
-- join critical_column c on c.id = r.critical_column_id
-- join critical_roll_band rb on rb.id = r.critical_roll_band_id
-- where t.slug = 'slash'
-- and c.column_key = 'C'
-- and 38 >= rb.min_roll
-- and (rb.max_roll is null or 38 <= rb.max_roll);