40 lines
2.4 KiB
SQL
40 lines
2.4 KiB
SQL
-- 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 $$;
|