Files

40 lines
2.4 KiB
SQL
Raw Permalink Normal View History

-- Migration: 000036_kb_vector_store_id
-- Description: Add vector_store_id column to knowledge_bases for per-KB VectorStore binding.
-- NULL means "use tenant's effective engines" (env store derived from RETRIEVE_DRIVER),
-- which preserves existing behavior for all pre-existing rows.
-- No foreign key: env store IDs are virtual (not present in vector_stores), and
-- VectorStore soft-delete must not cascade into KB references. Referential integrity is
-- enforced at the application layer.
-- On PostgreSQL 11+ this ALTER runs as metadata-only (O(1), no row rewrite) because the
-- column is nullable with no DEFAULT. PostgreSQL 10 and earlier are not supported.
DO $$ BEGIN RAISE NOTICE '[Migration 000036] Adding vector_store_id column to knowledge_bases'; END $$;
ALTER TABLE knowledge_bases ADD COLUMN IF NOT EXISTS vector_store_id VARCHAR(36);
COMMENT ON COLUMN knowledge_bases.vector_store_id IS
'References vector_stores.id. NULL means tenant default (env store derived from RETRIEVE_DRIVER). '
'Immutable after creation (enforced at ORM and service layer). No FK by design.';
-- Composite index: tenant_id first to align with the dominant query pattern. All KB queries
-- start with `WHERE tenant_id = $1`, so the composite index enforces tenant-scoped plans and
-- hardens against accidental cross-tenant access. A full (non-partial) index is used because
-- the target end-state has most KBs bound to a store, making a partial index short-lived.
-- Storage cost is negligible at typical KB row counts.
CREATE INDEX IF NOT EXISTS idx_knowledge_bases_tenant_vector_store
ON knowledge_bases(tenant_id, vector_store_id);
-- Note: CREATE INDEX here holds a SHARE lock briefly. For very large knowledge_bases tables
-- (hundreds of thousands of rows or more), operators may prefer CREATE INDEX CONCURRENTLY.
-- This requires running the statement outside a transaction, which the standard migration
-- runner does not support; execute the CONCURRENTLY variant from a separate operational
-- script in that case. Simply replacing the statement below with CONCURRENTLY inside this
-- file will cause the migration to fail and leave schema_migrations in a dirty state.
DO $$
DECLARE non_null_count BIGINT;
BEGIN
SELECT COUNT(*) INTO non_null_count
FROM knowledge_bases WHERE vector_store_id IS NOT NULL;
RAISE NOTICE '[Migration 000036] knowledge_bases.vector_store_id added (% non-NULL rows)', non_null_count;
END $$;