-- Unified Search: Document chunks table for RAG indexing -- Creates document_chunks table with HNSW index on embedding, -- and adds content_text/content_tsv columns to files if missing. CREATE EXTENSION IF NOT EXISTS vector; -- ─── Document Chunks Table ─── CREATE TABLE IF NOT EXISTS document_chunks ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), tenant_id UUID NOT NULL, file_id UUID NOT NULL REFERENCES files(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, chunk_text TEXT NOT NULL, chunk_hash VARCHAR(64) NOT NULL, embedding vector(768), deleted_at TIMESTAMPTZ, created_at TIMESTAMPTZ NOT NULL DEFAULT now(), updated_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX IF NOT EXISTS ix_document_chunks_tenant ON document_chunks(tenant_id); CREATE INDEX IF NOT EXISTS ix_document_chunks_file ON document_chunks(file_id); CREATE INDEX IF NOT EXISTS ix_document_chunks_tenant_file ON document_chunks(tenant_id, file_id); -- HNSW index for fast cosine similarity search on chunk embeddings CREATE INDEX IF NOT EXISTS ix_document_chunks_embedding ON document_chunks USING hnsw(embedding vector_cosine_ops); -- ─── Files: content_text and content_tsv (idempotent) ─── DO $$ BEGIN IF EXISTS (SELECT 1 FROM information_schema.tables WHERE table_name = 'files') THEN ALTER TABLE files ADD COLUMN IF NOT EXISTS content_text text; ALTER TABLE files ADD COLUMN IF NOT EXISTS content_tsv tsvector; -- GIN index for full-text search on file content CREATE INDEX IF NOT EXISTS ix_files_content_tsv ON files USING gin(content_tsv); END IF; END $$;