inou/docs/schema.sql

90 lines
3.1 KiB
SQL

-- ============================================================================
-- Inou Database Schema (inou.db)
-- ============================================================================
-- Three core tables + two reference tables.
-- Tables are NOT auto-created from Go. Run this manually.
-- OAuth tables are in separate auth.db (see schema-auth.sql).
-- ============================================================================
-- Everything: dossier profiles (cat 0), imaging, labs, genome, docs, ...
-- String fields are BLOB (compress→encrypt via Pack/Unpack).
-- Integer/bool fields are plain INTEGER.
-- IDs are plain TEXT (not packed).
CREATE TABLE IF NOT EXISTS entries (
EntryID TEXT PRIMARY KEY,
DossierID TEXT NOT NULL,
ParentID TEXT DEFAULT '',
Category INTEGER DEFAULT 0,
Type BLOB,
Value BLOB,
Summary BLOB,
Ordinal INTEGER DEFAULT 0,
Timestamp INTEGER DEFAULT 0,
TimestampEnd INTEGER DEFAULT 0,
Status INTEGER DEFAULT 0,
Tags BLOB,
Data BLOB,
SearchKey BLOB
);
CREATE INDEX IF NOT EXISTS idx_entries_dossier ON entries(DossierID);
CREATE INDEX IF NOT EXISTS idx_entries_parent ON entries(DossierID, ParentID);
CREATE INDEX IF NOT EXISTS idx_entries_category ON entries(DossierID, Category);
CREATE INDEX IF NOT EXISTS idx_entries_searchkey ON entries(SearchKey);
-- RBAC grants: who (GranteeID) can access whose (DossierID) data.
-- All columns plain text/int — no packing.
CREATE TABLE IF NOT EXISTS access (
AccessID TEXT PRIMARY KEY,
DossierID TEXT NOT NULL,
GranteeID TEXT NOT NULL,
EntryID TEXT DEFAULT '',
Relation INTEGER DEFAULT 0,
Ops INTEGER DEFAULT 0,
CreatedAt INTEGER DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_access_grantee ON access(GranteeID);
CREATE INDEX IF NOT EXISTS idx_access_dossier ON access(DossierID);
-- Immutable audit log. String fields are packed.
CREATE TABLE IF NOT EXISTS audit (
AuditID TEXT PRIMARY KEY,
Actor1ID TEXT,
Actor2ID TEXT,
TargetID TEXT,
Action BLOB,
Details BLOB,
RelationID INTEGER DEFAULT 0,
Timestamp INTEGER DEFAULT 0
);
CREATE INDEX IF NOT EXISTS idx_audit_actor ON audit(Actor1ID);
CREATE INDEX IF NOT EXISTS idx_audit_target ON audit(TargetID);
-- Lab test properties (per LOINC code)
-- Public reference data (not PII). Plain text.
-- Values stored as int64 with x1,000,000 scaling for float precision.
CREATE TABLE IF NOT EXISTS lab_test (
loinc_id TEXT PRIMARY KEY,
name TEXT NOT NULL,
si_unit TEXT NOT NULL,
direction TEXT NOT NULL DEFAULT 'range',
si_factor INTEGER NOT NULL DEFAULT 1000000
);
-- Lab reference ranges (always in SI units)
CREATE TABLE IF NOT EXISTS lab_reference (
ref_id TEXT PRIMARY KEY,
loinc_id TEXT NOT NULL,
source TEXT NOT NULL,
sex TEXT NOT NULL DEFAULT '',
age_days INTEGER NOT NULL DEFAULT 0,
age_end INTEGER NOT NULL,
ref_low INTEGER NOT NULL DEFAULT -1,
ref_high INTEGER NOT NULL DEFAULT -1,
unit TEXT NOT NULL
);
CREATE INDEX IF NOT EXISTS idx_lab_reference_loinc ON lab_reference(loinc_id);