Initial commit
This commit is contained in:
@@ -0,0 +1,979 @@
|
||||
-- =============================================================================
|
||||
-- Life OS - Release 1 COMPLETE Schema
|
||||
-- Self-hosted PostgreSQL 16 on defiant-01 (Hetzner)
|
||||
-- Database: lifeos_dev
|
||||
-- Generated from Architecture Design Document v2.0
|
||||
-- =============================================================================
|
||||
|
||||
-- Extensions
|
||||
CREATE EXTENSION IF NOT EXISTS "pgcrypto";
|
||||
|
||||
-- =============================================================================
|
||||
-- LOOKUP TABLE: Context Types
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE context_types (
|
||||
id SERIAL PRIMARY KEY,
|
||||
value TEXT NOT NULL UNIQUE,
|
||||
label TEXT NOT NULL,
|
||||
description TEXT,
|
||||
is_system BOOLEAN NOT NULL DEFAULT true,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- CORE HIERARCHY
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE domains (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
color TEXT,
|
||||
description TEXT,
|
||||
icon TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE areas (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
icon TEXT,
|
||||
color TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE projects (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
|
||||
area_id UUID REFERENCES areas(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'active',
|
||||
priority INTEGER NOT NULL DEFAULT 3,
|
||||
start_date DATE,
|
||||
target_date DATE,
|
||||
completed_at TIMESTAMPTZ,
|
||||
color TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Forward-declare releases for tasks.release_id FK
|
||||
CREATE TABLE releases (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
version_label TEXT,
|
||||
description TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'planned',
|
||||
target_date DATE,
|
||||
released_at DATE,
|
||||
release_notes TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Forward-declare contacts for tasks.waiting_for_contact_id FK
|
||||
CREATE TABLE contacts (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
first_name TEXT NOT NULL,
|
||||
last_name TEXT,
|
||||
company TEXT,
|
||||
role TEXT,
|
||||
email TEXT,
|
||||
phone TEXT,
|
||||
notes TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE tasks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
|
||||
area_id UUID REFERENCES areas(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
release_id UUID REFERENCES releases(id) ON DELETE SET NULL,
|
||||
parent_id UUID REFERENCES tasks(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
priority INTEGER NOT NULL DEFAULT 3,
|
||||
status TEXT NOT NULL DEFAULT 'open',
|
||||
due_date DATE,
|
||||
deadline TIMESTAMPTZ,
|
||||
recurrence TEXT,
|
||||
estimated_minutes INTEGER,
|
||||
energy_required TEXT,
|
||||
context TEXT,
|
||||
is_custom_context BOOLEAN NOT NULL DEFAULT false,
|
||||
waiting_for_contact_id UUID REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
waiting_since DATE,
|
||||
import_batch_id UUID,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- KNOWLEDGE MANAGEMENT
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE note_folders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
parent_id UUID REFERENCES note_folders(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
auto_generated BOOLEAN NOT NULL DEFAULT false,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- Forward-declare meetings for notes.meeting_id FK
|
||||
CREATE TABLE meetings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
parent_id UUID REFERENCES meetings(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
meeting_date DATE NOT NULL,
|
||||
start_at TIMESTAMPTZ,
|
||||
end_at TIMESTAMPTZ,
|
||||
location TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'scheduled',
|
||||
priority INTEGER,
|
||||
recurrence TEXT,
|
||||
agenda TEXT,
|
||||
transcript TEXT,
|
||||
notes_body TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE notes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
folder_id UUID REFERENCES note_folders(id) ON DELETE SET NULL,
|
||||
meeting_id UUID REFERENCES meetings(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
body TEXT,
|
||||
content_format TEXT NOT NULL DEFAULT 'rich',
|
||||
is_meeting_note BOOLEAN NOT NULL DEFAULT false,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE decisions (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
title TEXT NOT NULL,
|
||||
rationale TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'proposed',
|
||||
impact TEXT NOT NULL DEFAULT 'medium',
|
||||
decided_at DATE,
|
||||
meeting_id UUID REFERENCES meetings(id) ON DELETE SET NULL,
|
||||
superseded_by_id UUID REFERENCES decisions(id) ON DELETE SET NULL,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE lists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
|
||||
area_id UUID REFERENCES areas(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
list_type TEXT NOT NULL DEFAULT 'checklist',
|
||||
description TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE list_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
list_id UUID NOT NULL REFERENCES lists(id) ON DELETE CASCADE,
|
||||
parent_item_id UUID REFERENCES list_items(id) ON DELETE SET NULL,
|
||||
content TEXT NOT NULL,
|
||||
completed BOOLEAN NOT NULL DEFAULT false,
|
||||
completed_at TIMESTAMPTZ,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE links (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID REFERENCES domains(id) ON DELETE CASCADE,
|
||||
area_id UUID REFERENCES areas(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
label TEXT NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
description TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE files (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
filename TEXT NOT NULL,
|
||||
original_filename TEXT NOT NULL,
|
||||
storage_path TEXT NOT NULL,
|
||||
mime_type TEXT,
|
||||
size_bytes INTEGER,
|
||||
description TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Appointments
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE appointments (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
title TEXT NOT NULL,
|
||||
description TEXT,
|
||||
location TEXT,
|
||||
start_at TIMESTAMPTZ NOT NULL,
|
||||
end_at TIMESTAMPTZ,
|
||||
all_day BOOLEAN NOT NULL DEFAULT false,
|
||||
recurrence TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Milestones
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE milestones (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
release_id UUID REFERENCES releases(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
name TEXT NOT NULL,
|
||||
target_date DATE NOT NULL,
|
||||
completed_at DATE,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Processes
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE processes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
process_type TEXT NOT NULL DEFAULT 'checklist',
|
||||
category TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'draft',
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE process_steps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
process_id UUID NOT NULL REFERENCES processes(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
instructions TEXT,
|
||||
expected_output TEXT,
|
||||
estimated_days INTEGER,
|
||||
context TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE process_runs (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
process_id UUID NOT NULL REFERENCES processes(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'not_started',
|
||||
process_type TEXT NOT NULL,
|
||||
task_generation TEXT NOT NULL DEFAULT 'all_at_once',
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
contact_id UUID REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
started_at TIMESTAMPTZ,
|
||||
completed_at TIMESTAMPTZ,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE process_run_steps (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
run_id UUID NOT NULL REFERENCES process_runs(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
instructions TEXT,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
completed_by_id UUID REFERENCES contacts(id) ON DELETE SET NULL,
|
||||
completed_at TIMESTAMPTZ,
|
||||
notes TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Daily Focus
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE daily_focus (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
focus_date DATE NOT NULL,
|
||||
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
slot INTEGER,
|
||||
completed BOOLEAN NOT NULL DEFAULT false,
|
||||
note TEXT,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Capture Queue
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE capture (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
raw_text TEXT NOT NULL,
|
||||
processed BOOLEAN NOT NULL DEFAULT false,
|
||||
converted_to_type TEXT,
|
||||
converted_to_id UUID,
|
||||
area_id UUID REFERENCES areas(id) ON DELETE SET NULL,
|
||||
project_id UUID REFERENCES projects(id) ON DELETE SET NULL,
|
||||
list_id UUID REFERENCES lists(id) ON DELETE SET NULL,
|
||||
import_batch_id UUID,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Task Templates
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE task_templates (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
priority INTEGER,
|
||||
estimated_minutes INTEGER,
|
||||
energy_required TEXT,
|
||||
context TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE task_template_items (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
template_id UUID NOT NULL REFERENCES task_templates(id) ON DELETE CASCADE,
|
||||
title TEXT NOT NULL,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- TIME MANAGEMENT
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE time_entries (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
start_at TIMESTAMPTZ NOT NULL,
|
||||
end_at TIMESTAMPTZ,
|
||||
duration_minutes INTEGER,
|
||||
notes TEXT,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE time_blocks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
task_id UUID REFERENCES tasks(id) ON DELETE SET NULL,
|
||||
title TEXT NOT NULL,
|
||||
context TEXT,
|
||||
energy TEXT,
|
||||
start_at TIMESTAMPTZ NOT NULL,
|
||||
end_at TIMESTAMPTZ NOT NULL,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE time_budgets (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
domain_id UUID NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
|
||||
weekly_hours DECIMAL NOT NULL,
|
||||
effective_from DATE NOT NULL,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Weblink Directory
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE weblink_folders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
parent_id UUID REFERENCES weblink_folders(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
auto_generated BOOLEAN NOT NULL DEFAULT false,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE weblinks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
label TEXT NOT NULL,
|
||||
url TEXT NOT NULL,
|
||||
description TEXT,
|
||||
tags TEXT[],
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
search_vector TSVECTOR,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- SYSTEM LEVEL: Reminders (polymorphic)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE reminders (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
entity_type TEXT NOT NULL,
|
||||
entity_id UUID NOT NULL,
|
||||
remind_at TIMESTAMPTZ NOT NULL,
|
||||
note TEXT,
|
||||
delivered BOOLEAN NOT NULL DEFAULT false,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now()
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- UNIVERSAL: Dependencies (polymorphic DAG)
|
||||
-- =============================================================================
|
||||
|
||||
CREATE TABLE dependencies (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
blocker_type TEXT NOT NULL,
|
||||
blocker_id UUID NOT NULL,
|
||||
dependent_type TEXT NOT NULL,
|
||||
dependent_id UUID NOT NULL,
|
||||
dependency_type TEXT NOT NULL DEFAULT 'finish_to_start',
|
||||
lag_days INTEGER NOT NULL DEFAULT 0,
|
||||
note TEXT,
|
||||
is_deleted BOOLEAN NOT NULL DEFAULT false,
|
||||
deleted_at TIMESTAMPTZ,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (blocker_type, blocker_id, dependent_type, dependent_id, dependency_type),
|
||||
CHECK (NOT (blocker_type = dependent_type AND blocker_id = dependent_id))
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- JUNCTION TABLES
|
||||
-- =============================================================================
|
||||
|
||||
-- Notes <-> Projects (M2M)
|
||||
CREATE TABLE note_projects (
|
||||
note_id UUID NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
is_primary BOOLEAN NOT NULL DEFAULT false,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (note_id, project_id)
|
||||
);
|
||||
|
||||
-- Notes <-> Notes (wiki graph)
|
||||
CREATE TABLE note_links (
|
||||
source_note_id UUID NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
target_note_id UUID NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (source_note_id, target_note_id)
|
||||
);
|
||||
|
||||
-- Files <-> any entity (polymorphic M2M)
|
||||
CREATE TABLE file_mappings (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
file_id UUID NOT NULL REFERENCES files(id) ON DELETE CASCADE,
|
||||
context_type TEXT NOT NULL,
|
||||
context_id UUID NOT NULL,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
UNIQUE (file_id, context_type, context_id)
|
||||
);
|
||||
|
||||
-- Releases <-> Projects (M2M)
|
||||
CREATE TABLE release_projects (
|
||||
release_id UUID NOT NULL REFERENCES releases(id) ON DELETE CASCADE,
|
||||
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (release_id, project_id)
|
||||
);
|
||||
|
||||
-- Releases <-> Domains (M2M)
|
||||
CREATE TABLE release_domains (
|
||||
release_id UUID NOT NULL REFERENCES releases(id) ON DELETE CASCADE,
|
||||
domain_id UUID NOT NULL REFERENCES domains(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (release_id, domain_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> Tasks
|
||||
CREATE TABLE contact_tasks (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, task_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> Projects
|
||||
CREATE TABLE contact_projects (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, project_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> Lists
|
||||
CREATE TABLE contact_lists (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
list_id UUID NOT NULL REFERENCES lists(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, list_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> List Items
|
||||
CREATE TABLE contact_list_items (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
list_item_id UUID NOT NULL REFERENCES list_items(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, list_item_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> Appointments
|
||||
CREATE TABLE contact_appointments (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
appointment_id UUID NOT NULL REFERENCES appointments(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, appointment_id)
|
||||
);
|
||||
|
||||
-- Contacts <-> Meetings
|
||||
CREATE TABLE contact_meetings (
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
meeting_id UUID NOT NULL REFERENCES meetings(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (contact_id, meeting_id)
|
||||
);
|
||||
|
||||
-- Decisions <-> Projects
|
||||
CREATE TABLE decision_projects (
|
||||
decision_id UUID NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||
project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (decision_id, project_id)
|
||||
);
|
||||
|
||||
-- Decisions <-> Contacts
|
||||
CREATE TABLE decision_contacts (
|
||||
decision_id UUID NOT NULL REFERENCES decisions(id) ON DELETE CASCADE,
|
||||
contact_id UUID NOT NULL REFERENCES contacts(id) ON DELETE CASCADE,
|
||||
role TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (decision_id, contact_id)
|
||||
);
|
||||
|
||||
-- Meetings <-> Tasks
|
||||
CREATE TABLE meeting_tasks (
|
||||
meeting_id UUID NOT NULL REFERENCES meetings(id) ON DELETE CASCADE,
|
||||
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
source TEXT,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (meeting_id, task_id)
|
||||
);
|
||||
|
||||
-- Process Run Steps <-> Tasks
|
||||
CREATE TABLE process_run_tasks (
|
||||
run_step_id UUID NOT NULL REFERENCES process_run_steps(id) ON DELETE CASCADE,
|
||||
task_id UUID NOT NULL REFERENCES tasks(id) ON DELETE CASCADE,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (run_step_id, task_id)
|
||||
);
|
||||
|
||||
-- Weblinks <-> Folders (M2M)
|
||||
CREATE TABLE folder_weblinks (
|
||||
folder_id UUID NOT NULL REFERENCES weblink_folders(id) ON DELETE CASCADE,
|
||||
weblink_id UUID NOT NULL REFERENCES weblinks(id) ON DELETE CASCADE,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
|
||||
PRIMARY KEY (folder_id, weblink_id)
|
||||
);
|
||||
|
||||
-- =============================================================================
|
||||
-- INDEXES
|
||||
-- =============================================================================
|
||||
|
||||
-- Sort order indexes
|
||||
CREATE INDEX idx_domains_sort ON domains(sort_order);
|
||||
CREATE INDEX idx_areas_sort ON areas(domain_id, sort_order);
|
||||
CREATE INDEX idx_projects_sort ON projects(domain_id, sort_order);
|
||||
CREATE INDEX idx_projects_area_sort ON projects(area_id, sort_order);
|
||||
CREATE INDEX idx_tasks_project_sort ON tasks(project_id, sort_order);
|
||||
CREATE INDEX idx_tasks_parent_sort ON tasks(parent_id, sort_order);
|
||||
CREATE INDEX idx_tasks_domain_sort ON tasks(domain_id, sort_order);
|
||||
CREATE INDEX idx_list_items_sort ON list_items(list_id, sort_order);
|
||||
CREATE INDEX idx_list_items_parent_sort ON list_items(parent_item_id, sort_order);
|
||||
CREATE INDEX idx_weblink_folders_sort ON weblink_folders(parent_id, sort_order);
|
||||
|
||||
-- Lookup indexes
|
||||
CREATE INDEX idx_tasks_status ON tasks(status);
|
||||
CREATE INDEX idx_tasks_due_date ON tasks(due_date);
|
||||
CREATE INDEX idx_tasks_priority ON tasks(priority);
|
||||
CREATE INDEX idx_projects_status ON projects(status);
|
||||
CREATE INDEX idx_daily_focus_date ON daily_focus(focus_date);
|
||||
CREATE INDEX idx_appointments_start ON appointments(start_at);
|
||||
CREATE INDEX idx_capture_processed ON capture(processed);
|
||||
CREATE INDEX idx_file_mappings_context ON file_mappings(context_type, context_id);
|
||||
CREATE INDEX idx_dependencies_blocker ON dependencies(blocker_type, blocker_id);
|
||||
CREATE INDEX idx_dependencies_dependent ON dependencies(dependent_type, dependent_id);
|
||||
CREATE INDEX idx_reminders_entity ON reminders(entity_type, entity_id);
|
||||
CREATE INDEX idx_time_entries_task ON time_entries(task_id);
|
||||
CREATE INDEX idx_meetings_date ON meetings(meeting_date);
|
||||
|
||||
-- Full-text search GIN indexes
|
||||
CREATE INDEX idx_domains_search ON domains USING GIN(search_vector);
|
||||
CREATE INDEX idx_areas_search ON areas USING GIN(search_vector);
|
||||
CREATE INDEX idx_projects_search ON projects USING GIN(search_vector);
|
||||
CREATE INDEX idx_tasks_search ON tasks USING GIN(search_vector);
|
||||
CREATE INDEX idx_notes_search ON notes USING GIN(search_vector);
|
||||
CREATE INDEX idx_contacts_search ON contacts USING GIN(search_vector);
|
||||
CREATE INDEX idx_meetings_search ON meetings USING GIN(search_vector);
|
||||
CREATE INDEX idx_decisions_search ON decisions USING GIN(search_vector);
|
||||
CREATE INDEX idx_lists_search ON lists USING GIN(search_vector);
|
||||
CREATE INDEX idx_links_search ON links USING GIN(search_vector);
|
||||
CREATE INDEX idx_files_search ON files USING GIN(search_vector);
|
||||
CREATE INDEX idx_weblinks_search ON weblinks USING GIN(search_vector);
|
||||
CREATE INDEX idx_processes_search ON processes USING GIN(search_vector);
|
||||
CREATE INDEX idx_appointments_search ON appointments USING GIN(search_vector);
|
||||
|
||||
-- =============================================================================
|
||||
-- SEARCH VECTOR TRIGGERS
|
||||
-- =============================================================================
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_search_vector() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' ||
|
||||
coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(NEW.name, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), '')
|
||||
);
|
||||
RETURN NEW;
|
||||
EXCEPTION WHEN undefined_column THEN
|
||||
-- Fallback for tables with different column names
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
-- Per-table triggers with correct columns
|
||||
CREATE OR REPLACE FUNCTION update_domains_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english', coalesce(NEW.name, ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_domains_search BEFORE INSERT OR UPDATE ON domains
|
||||
FOR EACH ROW EXECUTE FUNCTION update_domains_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_areas_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.name, '') || ' ' || coalesce(NEW.description, ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_areas_search BEFORE INSERT OR UPDATE ON areas
|
||||
FOR EACH ROW EXECUTE FUNCTION update_areas_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_projects_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.name, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_projects_search BEFORE INSERT OR UPDATE ON projects
|
||||
FOR EACH ROW EXECUTE FUNCTION update_projects_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_tasks_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_tasks_search BEFORE INSERT OR UPDATE ON tasks
|
||||
FOR EACH ROW EXECUTE FUNCTION update_tasks_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_notes_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' || coalesce(NEW.body, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_notes_search BEFORE INSERT OR UPDATE ON notes
|
||||
FOR EACH ROW EXECUTE FUNCTION update_notes_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_contacts_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.first_name, '') || ' ' || coalesce(NEW.last_name, '') || ' ' ||
|
||||
coalesce(NEW.company, '') || ' ' || coalesce(NEW.email, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_contacts_search BEFORE INSERT OR UPDATE ON contacts
|
||||
FOR EACH ROW EXECUTE FUNCTION update_contacts_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_meetings_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' || coalesce(NEW.agenda, '') || ' ' ||
|
||||
coalesce(NEW.notes_body, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_meetings_search BEFORE INSERT OR UPDATE ON meetings
|
||||
FOR EACH ROW EXECUTE FUNCTION update_meetings_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_decisions_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' || coalesce(NEW.rationale, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_decisions_search BEFORE INSERT OR UPDATE ON decisions
|
||||
FOR EACH ROW EXECUTE FUNCTION update_decisions_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_lists_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.name, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_lists_search BEFORE INSERT OR UPDATE ON lists
|
||||
FOR EACH ROW EXECUTE FUNCTION update_lists_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_links_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.label, '') || ' ' || coalesce(NEW.url, '') || ' ' ||
|
||||
coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_links_search BEFORE INSERT OR UPDATE ON links
|
||||
FOR EACH ROW EXECUTE FUNCTION update_links_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_files_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.original_filename, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_files_search BEFORE INSERT OR UPDATE ON files
|
||||
FOR EACH ROW EXECUTE FUNCTION update_files_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_weblinks_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.label, '') || ' ' || coalesce(NEW.url, '') || ' ' ||
|
||||
coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_weblinks_search BEFORE INSERT OR UPDATE ON weblinks
|
||||
FOR EACH ROW EXECUTE FUNCTION update_weblinks_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_processes_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.name, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_processes_search BEFORE INSERT OR UPDATE ON processes
|
||||
FOR EACH ROW EXECUTE FUNCTION update_processes_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_appointments_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.title, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(NEW.location, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_appointments_search BEFORE INSERT OR UPDATE ON appointments
|
||||
FOR EACH ROW EXECUTE FUNCTION update_appointments_search();
|
||||
|
||||
CREATE OR REPLACE FUNCTION update_releases_search() RETURNS trigger AS $$
|
||||
BEGIN
|
||||
NEW.search_vector := to_tsvector('pg_catalog.english',
|
||||
coalesce(NEW.name, '') || ' ' || coalesce(NEW.description, '') || ' ' ||
|
||||
coalesce(NEW.version_label, '') || ' ' ||
|
||||
coalesce(array_to_string(NEW.tags, ' '), ''));
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
CREATE TRIGGER trg_releases_search BEFORE INSERT OR UPDATE ON releases
|
||||
FOR EACH ROW EXECUTE FUNCTION update_releases_search();
|
||||
|
||||
-- =============================================================================
|
||||
-- SEED DATA: Context Types
|
||||
-- =============================================================================
|
||||
|
||||
INSERT INTO context_types (value, label, is_system, sort_order) VALUES
|
||||
('deep_work', 'Deep Work', true, 10),
|
||||
('quick', 'Quick', true, 20),
|
||||
('waiting', 'Waiting', true, 30),
|
||||
('someday', 'Someday', true, 40),
|
||||
('meeting', 'Meeting', true, 50),
|
||||
('errand', 'Errand', true, 60);
|
||||
Reference in New Issue
Block a user