From 779ac57f5097166c3660374e2a10acfe2045dc8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=A7=CE=B3=CF=86=CF=84=20Kompanion?= Date: Wed, 15 Oct 2025 10:39:44 +1300 Subject: [PATCH] Add Schema files --- db/init/001_roles.sql | 2 ++ db/init/002_extensions.sql | 2 ++ db/init/010_schema.sql | 39 ++++++++++++++++++++++++++++++++++++ db/init/020_indexes.sql | 15 ++++++++++++++ db/scripts/create-prod-db.sh | 22 ++++++++++++++++++++ db/scripts/create-test-db.sh | 17 ++++++++++++++++ 6 files changed, 97 insertions(+) create mode 100644 db/init/001_roles.sql create mode 100644 db/init/002_extensions.sql create mode 100644 db/init/010_schema.sql create mode 100644 db/init/020_indexes.sql create mode 100755 db/scripts/create-prod-db.sh create mode 100755 db/scripts/create-test-db.sh diff --git a/db/init/001_roles.sql b/db/init/001_roles.sql new file mode 100644 index 0000000..540b47b --- /dev/null +++ b/db/init/001_roles.sql @@ -0,0 +1,2 @@ +CREATE ROLE kompanion LOGIN PASSWORD 'komp'; +CREATE DATABASE kompanion OWNER kompanion; diff --git a/db/init/002_extensions.sql b/db/init/002_extensions.sql new file mode 100644 index 0000000..6aa6c6f --- /dev/null +++ b/db/init/002_extensions.sql @@ -0,0 +1,2 @@ +CREATE EXTENSION IF NOT EXISTS vector; +CREATE EXTENSION IF NOT EXISTS pg_trgm; diff --git a/db/init/010_schema.sql b/db/init/010_schema.sql new file mode 100644 index 0000000..6ec8c21 --- /dev/null +++ b/db/init/010_schema.sql @@ -0,0 +1,39 @@ +CREATE TABLE IF NOT EXISTS namespaces ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + name TEXT UNIQUE NOT NULL +); + +CREATE TABLE IF NOT EXISTS memory_items ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + namespace_id UUID NOT NULL REFERENCES namespaces(id) ON DELETE CASCADE, + key TEXT, + content TEXT NOT NULL, + metadata JSONB NOT NULL DEFAULT '{}', + tags TEXT[] NOT NULL DEFAULT '{}', + revision INT NOT NULL DEFAULT 1, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + updated_at TIMESTAMPTZ NOT NULL DEFAULT now(), + expires_at TIMESTAMPTZ, + deleted_at TIMESTAMPTZ, + last_accessed_at TIMESTAMPTZ +); + +CREATE TABLE IF NOT EXISTS memory_chunks ( + id UUID PRIMARY KEY DEFAULT gen_random_uuid(), + item_id UUID NOT NULL REFERENCES memory_items(id) ON DELETE CASCADE, + seq INT NOT NULL, + content TEXT NOT NULL, + expires_at TIMESTAMPTZ, + deleted_at TIMESTAMPTZ, + content_tsv tsvector GENERATED ALWAYS AS (to_tsvector('english', content)) STORED +); + +CREATE TABLE IF NOT EXISTS embeddings ( + id BIGSERIAL PRIMARY KEY, + chunk_id UUID NOT NULL REFERENCES memory_chunks(id) ON DELETE CASCADE, + model TEXT NOT NULL, + dim INT NOT NULL, + vector VECTOR(1536), + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + UNIQUE(chunk_id, model) +); diff --git a/db/init/020_indexes.sql b/db/init/020_indexes.sql new file mode 100644 index 0000000..9336d13 --- /dev/null +++ b/db/init/020_indexes.sql @@ -0,0 +1,15 @@ +CREATE UNIQUE INDEX IF NOT EXISTS ux_items_ns_key + ON memory_items(namespace_id, key) + WHERE key IS NOT NULL; + +CREATE INDEX IF NOT EXISTS ix_chunks_item ON memory_chunks(item_id); + +CREATE INDEX IF NOT EXISTS idx_chunks_content_tsv + ON memory_chunks USING GIN(content_tsv); + +CREATE INDEX IF NOT EXISTS ix_embed_model_dim ON embeddings(model, dim); + +-- per-model ANN index (duplicate with each concrete model name) +CREATE INDEX IF NOT EXISTS ix_embed_vec_model_default + ON embeddings USING ivfflat (vector vector_cosine_ops) + WHERE model = 'default-emb'; diff --git a/db/scripts/create-prod-db.sh b/db/scripts/create-prod-db.sh new file mode 100755 index 0000000..6652a42 --- /dev/null +++ b/db/scripts/create-prod-db.sh @@ -0,0 +1,22 @@ +#!/usr/bin/env bash +set -euo pipefail +DB_NAME=${1:-kompanion} +ROLE=${ROLE:-kompanion} +PASS=${PASS:-komp} + +psql -v ON_ERROR_STOP=1 <