labcardai / scripts /create_tables.sql
ayush712145's picture
Upload folder using huggingface_hub
769bf77 verified
Raw
History Blame Contribute Delete
6.97 kB
-- ─────────────────────────────────────────────────────────────────────────────
-- LabCard AI β€” Supabase Schema
-- Run this once in Supabase SQL Editor:
-- https://supabase.com β†’ Your project β†’ SQL Editor β†’ New query
-- ─────────────────────────────────────────────────────────────────────────────
-- ── Extensions ────────────────────────────────────────────────────────────────
create extension if not exists "uuid-ossp";
create extension if not exists vector; -- for future RAG embeddings
-- ── Users (extends Supabase auth.users) ──────────────────────────────────────
create table if not exists public.profiles (
id uuid primary key references auth.users(id) on delete cascade,
name text,
age int,
gender text,
city text,
phone text,
created_at timestamptz default now(),
updated_at timestamptz default now()
);
-- ── Reports ───────────────────────────────────────────────────────────────────
create table if not exists public.reports (
id uuid primary key default gen_random_uuid(),
user_id uuid references public.profiles(id) on delete cascade,
lab_name text,
report_date date,
health_score int check (health_score between 0 and 100),
biological_age int,
grade text,
summary_en text,
summary_hi text,
doctor_note text,
top_priority text,
has_critical boolean default false,
raw_text_hash text, -- SHA-256 of raw text β€” dedup without storing PII
created_at timestamptz default now()
);
create index if not exists idx_reports_user_date
on public.reports (user_id, created_at desc);
-- ── Biomarkers ────────────────────────────────────────────────────────────────
create table if not exists public.biomarkers (
id bigserial primary key,
report_id uuid references public.reports(id) on delete cascade,
name text not null,
std_name text,
value numeric,
unit text,
normal_low numeric,
normal_high numeric,
status text,
category text,
explanation_en text,
explanation_hi text,
advice text,
foods jsonb default '[]',
created_at timestamptz default now()
);
create index if not exists idx_biomarkers_report
on public.biomarkers (report_id);
create index if not exists idx_biomarkers_trend
on public.biomarkers (report_id, std_name, created_at);
-- ── Reference Ranges ─────────────────────────────────────────────────────────
create table if not exists public.reference_ranges (
id bigserial primary key,
biomarker text not null,
std_name text,
gender text default 'A',
age_min int default 0,
age_max int default 120,
normal_low numeric,
normal_high numeric,
critical_low numeric,
critical_high numeric,
unit text,
category text,
notes text,
updated_at timestamptz default now(),
unique (biomarker, gender)
);
-- ── Chat Messages ─────────────────────────────────────────────────────────────
create table if not exists public.chat_messages (
id bigserial primary key,
report_id uuid references public.reports(id) on delete cascade,
role text not null check (role in ('user','assistant')),
content text not null,
lang text default 'en',
created_at timestamptz default now()
);
create index if not exists idx_chat_report
on public.chat_messages (report_id, created_at);
-- ── Medical Knowledge (for future RAG) ───────────────────────────────────────
create table if not exists public.medical_knowledge (
id bigserial primary key,
content text not null,
embedding vector(1536),
metadata jsonb default '{}',
source text,
created_at timestamptz default now()
);
create index if not exists idx_medical_knowledge_embedding
on public.medical_knowledge
using hnsw (embedding vector_cosine_ops)
with (m = 16, ef_construction = 64);
-- Similarity search function
create or replace function match_medical_knowledge (
query_embedding vector(1536),
match_threshold float default 0.75,
match_count int default 5
)
returns table (id bigint, content text, metadata jsonb, similarity float)
language sql stable as $$
select id, content, metadata,
1 - (embedding <=> query_embedding) as similarity
from public.medical_knowledge
where 1 - (embedding <=> query_embedding) > match_threshold
order by embedding <=> query_embedding
limit match_count;
$$;
-- ── Row Level Security ────────────────────────────────────────────────────────
alter table public.profiles enable row level security;
alter table public.reports enable row level security;
alter table public.biomarkers enable row level security;
alter table public.chat_messages enable row level security;
-- Profiles: users can only see/edit their own profile
create policy "profiles_own" on public.profiles
for all using (auth.uid() = id);
-- Reports: users can only see their own reports
create policy "reports_own" on public.reports
for all using (auth.uid() = user_id);
-- Biomarkers: accessible through report ownership
create policy "biomarkers_own" on public.biomarkers
for all using (
report_id in (
select id from public.reports where user_id = auth.uid()
)
);
-- Chat: accessible through report ownership
create policy "chat_own" on public.chat_messages
for all using (
report_id in (
select id from public.reports where user_id = auth.uid()
)
);
-- Reference ranges: public read
create policy "ref_ranges_read" on public.reference_ranges
for select using (true);