270 lines
8.5 KiB
PL/PgSQL
270 lines
8.5 KiB
PL/PgSQL
create table if not exists public.document_tables (
|
|
id uuid primary key default gen_random_uuid(),
|
|
workspace_id uuid not null references public.workspaces(id) on delete cascade,
|
|
document_id uuid not null references public.documents(id) on delete cascade,
|
|
title text not null default '未命名表格',
|
|
schema jsonb not null default '{}'::jsonb,
|
|
view_preferences jsonb not null default '{}'::jsonb,
|
|
is_archived boolean not null default false,
|
|
snapshot jsonb,
|
|
last_synced_at timestamptz,
|
|
created_by uuid references public.profiles(id) on delete set null,
|
|
updated_by uuid references public.profiles(id) on delete set null,
|
|
created_at timestamptz not null default timezone('utc', now()),
|
|
updated_at timestamptz not null default timezone('utc', now())
|
|
);
|
|
|
|
create index if not exists document_tables_workspace_idx
|
|
on public.document_tables (workspace_id, updated_at desc);
|
|
|
|
create index if not exists document_tables_document_idx
|
|
on public.document_tables (document_id, updated_at desc);
|
|
|
|
create index if not exists document_tables_archived_idx
|
|
on public.document_tables (workspace_id, is_archived, updated_at desc);
|
|
|
|
create or replace function public.set_document_tables_updated_at()
|
|
returns trigger
|
|
language plpgsql
|
|
security invoker
|
|
as $$
|
|
begin
|
|
new.updated_at := timezone('utc', now());
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
drop trigger if exists set_document_tables_updated_at on public.document_tables;
|
|
create trigger set_document_tables_updated_at
|
|
before update on public.document_tables
|
|
for each row
|
|
execute procedure public.set_document_tables_updated_at();
|
|
|
|
create or replace function public.ensure_document_table_workspace()
|
|
returns trigger
|
|
language plpgsql
|
|
security invoker
|
|
as $$
|
|
declare
|
|
v_workspace uuid;
|
|
begin
|
|
select workspace_id
|
|
into v_workspace
|
|
from public.documents
|
|
where id = new.document_id;
|
|
|
|
if not found then
|
|
raise exception 'Document % not found when creating document table', new.document_id;
|
|
end if;
|
|
|
|
if new.workspace_id is null then
|
|
new.workspace_id := v_workspace;
|
|
elsif new.workspace_id <> v_workspace then
|
|
raise exception 'Workspace mismatch between document table and document %', new.document_id;
|
|
end if;
|
|
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
drop trigger if exists ensure_document_table_workspace on public.document_tables;
|
|
create trigger ensure_document_table_workspace
|
|
before insert or update on public.document_tables
|
|
for each row
|
|
execute procedure public.ensure_document_table_workspace();
|
|
|
|
alter table public.document_tables enable row level security;
|
|
|
|
drop policy if exists "Select tables within workspace" on public.document_tables;
|
|
create policy "Select tables within workspace"
|
|
on public.document_tables
|
|
for select
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_tables.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Insert tables within workspace" on public.document_tables;
|
|
create policy "Insert tables within workspace"
|
|
on public.document_tables
|
|
for insert
|
|
with check (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_tables.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Update tables within workspace" on public.document_tables;
|
|
create policy "Update tables within workspace"
|
|
on public.document_tables
|
|
for update
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_tables.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
)
|
|
with check (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_tables.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Delete tables within workspace" on public.document_tables;
|
|
create policy "Delete tables within workspace"
|
|
on public.document_tables
|
|
for delete
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_tables.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
create table if not exists public.document_table_rows (
|
|
id uuid primary key default gen_random_uuid(),
|
|
workspace_id uuid not null references public.workspaces(id) on delete cascade,
|
|
document_id uuid not null references public.documents(id) on delete cascade,
|
|
table_id uuid not null references public.document_tables(id) on delete cascade,
|
|
row_index integer not null,
|
|
row_data jsonb not null default '{}'::jsonb,
|
|
row_hash text,
|
|
is_deleted boolean not null default false,
|
|
updated_by uuid references public.profiles(id) on delete set null,
|
|
created_at timestamptz not null default timezone('utc', now()),
|
|
updated_at timestamptz not null default timezone('utc', now())
|
|
);
|
|
|
|
create unique index if not exists document_table_rows_unique_row
|
|
on public.document_table_rows (table_id, row_index)
|
|
where is_deleted = false;
|
|
|
|
create index if not exists document_table_rows_workspace_idx
|
|
on public.document_table_rows (workspace_id, updated_at desc);
|
|
|
|
create index if not exists document_table_rows_table_idx
|
|
on public.document_table_rows (table_id, row_index);
|
|
|
|
create or replace function public.set_document_table_rows_updated_at()
|
|
returns trigger
|
|
language plpgsql
|
|
security invoker
|
|
as $$
|
|
begin
|
|
new.updated_at := timezone('utc', now());
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
drop trigger if exists set_document_table_rows_updated_at on public.document_table_rows;
|
|
create trigger set_document_table_rows_updated_at
|
|
before update on public.document_table_rows
|
|
for each row
|
|
execute procedure public.set_document_table_rows_updated_at();
|
|
|
|
create or replace function public.sync_document_table_row_meta()
|
|
returns trigger
|
|
language plpgsql
|
|
security invoker
|
|
as $$
|
|
declare
|
|
v_table record;
|
|
begin
|
|
select workspace_id, document_id
|
|
into v_table
|
|
from public.document_tables
|
|
where id = new.table_id;
|
|
|
|
if not found then
|
|
raise exception 'Document table % not found when creating row', new.table_id;
|
|
end if;
|
|
|
|
new.workspace_id := v_table.workspace_id;
|
|
new.document_id := v_table.document_id;
|
|
|
|
return new;
|
|
end;
|
|
$$;
|
|
|
|
drop trigger if exists sync_document_table_row_meta on public.document_table_rows;
|
|
create trigger sync_document_table_row_meta
|
|
before insert or update on public.document_table_rows
|
|
for each row
|
|
execute procedure public.sync_document_table_row_meta();
|
|
|
|
alter table public.document_table_rows enable row level security;
|
|
|
|
drop policy if exists "Select table rows within workspace" on public.document_table_rows;
|
|
create policy "Select table rows within workspace"
|
|
on public.document_table_rows
|
|
for select
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_table_rows.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Insert table rows within workspace" on public.document_table_rows;
|
|
create policy "Insert table rows within workspace"
|
|
on public.document_table_rows
|
|
for insert
|
|
with check (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_table_rows.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Update table rows within workspace" on public.document_table_rows;
|
|
create policy "Update table rows within workspace"
|
|
on public.document_table_rows
|
|
for update
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_table_rows.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
)
|
|
with check (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_table_rows.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|
|
|
|
drop policy if exists "Delete table rows within workspace" on public.document_table_rows;
|
|
create policy "Delete table rows within workspace"
|
|
on public.document_table_rows
|
|
for delete
|
|
using (
|
|
exists (
|
|
select 1
|
|
from public.workspace_members wm
|
|
where wm.workspace_id = document_table_rows.workspace_id
|
|
and wm.user_id = auth.uid()
|
|
)
|
|
);
|