Changeset 0.22.8 (#150)
This commit is contained in:
75
server/database/migrations/007_notes.sql
Normal file
75
server/database/migrations/007_notes.sql
Normal file
@@ -0,0 +1,75 @@
|
||||
-- ==========================================
|
||||
-- Chat Switchboard — 007 Notes & Links
|
||||
-- ==========================================
|
||||
-- Notes with full-text search, wikilink graph edges.
|
||||
-- ICD §6 (Notes)
|
||||
-- ==========================================
|
||||
|
||||
-- =========================================
|
||||
-- NOTES
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS notes (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
title VARCHAR(500) NOT NULL,
|
||||
content TEXT DEFAULT '',
|
||||
folder_path TEXT DEFAULT '/',
|
||||
tags TEXT[] DEFAULT '{}',
|
||||
metadata JSONB DEFAULT '{}',
|
||||
source_channel_id UUID REFERENCES channels(id) ON DELETE SET NULL,
|
||||
source_message_id UUID,
|
||||
team_id UUID REFERENCES teams(id) ON DELETE SET NULL,
|
||||
search_vector TSVECTOR,
|
||||
embedding VECTOR(3072),
|
||||
created_at TIMESTAMPTZ DEFAULT NOW(),
|
||||
updated_at TIMESTAMPTZ DEFAULT NOW()
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_user ON notes(user_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_search ON notes USING GIN(search_vector);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_folder ON notes(user_id, folder_path);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_tags ON notes USING GIN(tags);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_updated ON notes(user_id, updated_at DESC);
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_team ON notes(team_id) WHERE team_id IS NOT NULL;
|
||||
CREATE INDEX IF NOT EXISTS idx_notes_source_msg ON notes(source_message_id)
|
||||
WHERE source_message_id IS NOT NULL;
|
||||
|
||||
CREATE OR REPLACE FUNCTION notes_search_update_fn()
|
||||
RETURNS TRIGGER AS $$
|
||||
BEGIN
|
||||
NEW.search_vector :=
|
||||
setweight(to_tsvector('pg_catalog.english', COALESCE(NEW.title, '')), 'A') ||
|
||||
setweight(to_tsvector('pg_catalog.english', COALESCE(NEW.content, '')), 'B');
|
||||
NEW.updated_at := NOW();
|
||||
RETURN NEW;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
|
||||
DROP TRIGGER IF EXISTS notes_search_update ON notes;
|
||||
CREATE TRIGGER notes_search_update
|
||||
BEFORE INSERT OR UPDATE OF title, content ON notes
|
||||
FOR EACH ROW EXECUTE FUNCTION notes_search_update_fn();
|
||||
|
||||
|
||||
-- =========================================
|
||||
-- NOTE LINKS (v0.17.3 — wikilink graph)
|
||||
-- =========================================
|
||||
|
||||
CREATE TABLE IF NOT EXISTS note_links (
|
||||
source_note_id UUID NOT NULL REFERENCES notes(id) ON DELETE CASCADE,
|
||||
target_note_id UUID REFERENCES notes(id) ON DELETE CASCADE,
|
||||
target_title TEXT NOT NULL,
|
||||
display_text TEXT,
|
||||
is_transclusion BOOLEAN NOT NULL DEFAULT FALSE,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
PRIMARY KEY (source_note_id, target_title)
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_note_links_target ON note_links(target_note_id)
|
||||
WHERE target_note_id IS NOT NULL;
|
||||
|
||||
COMMENT ON TABLE note_links IS 'Directed links between notes, extracted from [[wikilink]] syntax on save';
|
||||
COMMENT ON COLUMN note_links.target_note_id IS 'NULL for unresolved links (target note does not exist yet)';
|
||||
COMMENT ON COLUMN note_links.target_title IS 'Raw [[title]] text — preserved for re-resolution after renames';
|
||||
COMMENT ON COLUMN note_links.is_transclusion IS 'true for ![[embed]] syntax, false for regular [[link]]';
|
||||
Reference in New Issue
Block a user